int verbose = 0;
int version = 0;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+int chaining = 0;
+static int chainingResolve = -1;
+static int chainingContinuation = -1;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
/* Set in main() */
char *prog = NULL;
#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
N_(" ppolicy\n")
#endif
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+N_(" [!]chaining[=<resolveBehavior>[/<continuationBehavior>]]\n")
+N_(" one of \"chainingPreferred\", \"chainingRequired\",\n")
+N_(" \"referralsPreferred\", \"referralsRequired\"\n")
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
N_(" [!]postread[=<attrs>] (a comma-separated attribute list)\n")
N_(" [!]preread[=<attrs>] (a comma-separated attribute list)\n"),
N_(" -f file read operations from `file'\n"),
postread = 1 + crit;
postread_attrs = cvalue;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ } else if ( strcasecmp( control, "chaining" ) == 0 ) {
+ chaining = 1 + crit;
+
+ if ( cvalue != NULL ) {
+ char *continuation;
+
+ continuation = strchr( cvalue, '/' );
+ if ( continuation ) {
+ /* FIXME: this makes sense only in searches */
+ *continuation++ = '\0';
+ if ( strcasecmp( continuation, "chainingPreferred" ) == 0 ) {
+ chainingContinuation = LDAP_CHAINING_PREFERRED;
+ } else if ( strcasecmp( continuation, "chainingRequired" ) == 0 ) {
+ chainingContinuation = LDAP_CHAINING_REQUIRED;
+ } else if ( strcasecmp( continuation, "referralsPreferred" ) == 0 ) {
+ chainingContinuation = LDAP_REFERRALS_PREFERRED;
+ } else if ( strcasecmp( continuation, "referralsRequired" ) == 0 ) {
+ chainingContinuation = LDAP_REFERRALS_REQUIRED;
+ } else {
+ fprintf( stderr,
+ "chaining behavior control "
+ "continuation value \"%s\" invalid\n",
+ continuation );
+ exit( EXIT_FAILURE );
+ }
+ }
+
+ if ( strcasecmp( cvalue, "chainingPreferred" ) == 0 ) {
+ chainingResolve = LDAP_CHAINING_PREFERRED;
+ } else if ( strcasecmp( cvalue, "chainingRequired" ) == 0 ) {
+ chainingResolve = LDAP_CHAINING_REQUIRED;
+ } else if ( strcasecmp( cvalue, "referralsPreferred" ) == 0 ) {
+ chainingResolve = LDAP_REFERRALS_PREFERRED;
+ } else if ( strcasecmp( cvalue, "referralsRequired" ) == 0 ) {
+ chainingResolve = LDAP_REFERRALS_REQUIRED;
+ } else {
+ fprintf( stderr,
+ "chaining behavior control "
+ "resolve value \"%s\" invalid\n",
+ cvalue);
+ exit( EXIT_FAILURE );
+ }
+ }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
} else {
fprintf( stderr, "Invalid general control name: %s\n",
control );
tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count )
{
int i = 0, j, crit = 0, err;
- LDAPControl c[8], **ctrls;
+ LDAPControl c[9], **ctrls;
ctrls = (LDAPControl**) malloc(sizeof(c) + (count+1)*sizeof(LDAPControl*));
if ( ctrls == NULL ) {
if ( manageDSAit ) {
c[i].ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
- c[i].ldctl_value.bv_val = NULL;
- c[i].ldctl_value.bv_len = 0;
+ BER_BVZERO( &c[i].ldctl_value );
c[i].ldctl_iscritical = manageDSAit > 1;
ctrls[i] = &c[i];
i++;
if ( noop ) {
c[i].ldctl_oid = LDAP_CONTROL_NOOP;
- c[i].ldctl_value.bv_val = NULL;
- c[i].ldctl_value.bv_len = 0;
+ BER_BVZERO( &c[i].ldctl_value );
c[i].ldctl_iscritical = noop > 1;
ctrls[i] = &c[i];
i++;
if( attrs ) ldap_charray_free( attrs );
}
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ if ( chaining ) {
+ if ( chainingResolve > -1 ) {
+ BerElementBuffer berbuf;
+ BerElement *ber = (BerElement *)&berbuf;
+
+ ber_init2( ber, NULL, LBER_USE_DER );
+
+ err = ber_printf( ber, "{e" /* } */, chainingResolve );
+ if ( err == -1 ) {
+ ber_free( ber, 1 );
+ fprintf( stderr, _("Chaining behavior control encoding error!\n") );
+ exit( EXIT_FAILURE );
+ }
+
+ if ( chainingContinuation > -1 ) {
+ err = ber_printf( ber, "e", chainingContinuation );
+ if ( err == -1 ) {
+ ber_free( ber, 1 );
+ fprintf( stderr, _("Chaining behavior control encoding error!\n") );
+ exit( EXIT_FAILURE );
+ }
+ }
+
+ err = ber_printf( ber, /* { */ "N}" );
+ if ( err == -1 ) {
+ ber_free( ber, 1 );
+ fprintf( stderr, _("Chaining behavior control encoding error!\n") );
+ exit( EXIT_FAILURE );
+ }
+
+ if ( ber_flatten2( ber, &c[i].ldctl_value, 0 ) == -1 ) {
+ exit( EXIT_FAILURE );
+ }
+
+ } else {
+ BER_BVZERO( &c[i].ldctl_value );
+ }
+
+ c[i].ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR;
+ c[i].ldctl_iscritical = chaining > 1;
+ ctrls[i] = &c[i];
+ i++;
+ }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
while ( count-- ) {
ctrls[i++] = extra_c++;
}
extern int noop;
extern int ppolicy;
extern int preread, postread;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+extern int chaining;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
extern int not;
extern int want_bindpw;
if( crit ) subentries *= -1;
#endif
- } else if ( strcasecmp( control, "sync" ) == 0 ) {
+ } else if ( strcasecmp( control, "sync" ) == 0 ) {
char *cookiep;
char *slimitp;
if ( ldapsync ) {
#ifdef LDAP_CONTROL_PAGEDRESULTS
|| pagedResults
#endif
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ || chaining
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
|| ldapsync
|| subentries || valuesReturnFilter )
{
int err;
int i=0;
- LDAPControl c[6];
+ LDAPControl c[10];
#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
- if ( domainScope ) {
- c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
- c[i].ldctl_value.bv_val = NULL;
- c[i].ldctl_value.bv_len = 0;
- c[i].ldctl_iscritical = domainScope > 1;
- i++;
- }
+ if ( domainScope ) {
+ c[i].ldctl_oid = LDAP_CONTROL_X_DOMAIN_SCOPE;
+ c[i].ldctl_value.bv_val = NULL;
+ c[i].ldctl_value.bv_len = 0;
+ c[i].ldctl_iscritical = domainScope > 1;
+ i++;
+ }
#endif
#ifdef LDAP_CONTROL_SUBENTRIES
if ( subentries ) {
- if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
+ if (( seber = ber_alloc_t(LBER_USE_DER)) == NULL ) {
return EXIT_FAILURE;
}
err = ber_printf( seber, "b", abs(subentries) == 1 ? 0 : 1 );
- if ( err == -1 ) {
+ if ( err == -1 ) {
ber_free( seber, 1 );
fprintf( stderr, _("Subentries control encoding error!\n") );
return EXIT_FAILURE;
In this case, the modified data is discarded and a subsequent search
will return a different result.
.TP
-.B fasttool
-Disables transaction logging when using the slapadd/slapindex tools,
-using the DB_TXN_NOT_DURABLE flag. Does not affect normal slapd operation,
-but will improve the performance of slapadd/slapindex.
-See the Berkeley DB reference guide for more details.
-.TP
.B idlcachesize <integer>
Specify the size of the in-memory index cache, in index slots. The
default is zero. A larger value will speed up frequent searches of
#define LDAP_SEARCH_FLAG_DOMAIN_SCOPE 1 /* do not generate referrals */
#define LDAP_SEARCH_FLAG_PHANTOM_ROOT 2 /* search all NCs subordinate to base */
+/* LDAP Chaining Behavior Control *//* work in progress */
+/* <draft-sermersheim-ldap-chaining>;
+ * see also LDAP_REQUIRES_CHAINING, LDAP_CANNOT_CHAIN */
+#ifdef LDAP_DEVEL
+#define LDAP_CONTROL_X_CHAINING_BEHAVIOR "1.3.6.1.4.1.4203.666.11.3"
+
+#define LDAP_CHAINING_PREFERRED 0
+#define LDAP_CHAINING_REQUIRED 1
+#define LDAP_REFERRALS_PREFERRED 2
+#define LDAP_REFERRALS_REQUIRED 3
+#endif
+
/* LDAP Unsolicited Notifications */
#define LDAP_NOTICE_OF_DISCONNECTION "1.3.6.1.4.1.1466.20036" /* RFC 2251 */
#define LDAP_NOTICE_DISCONNECT LDAP_NOTICE_OF_DISCONNECTION
/* for the Assertion control */
#define LDAP_ASSERTION_FAILED 0x410f
+/* for the Chaining Behavior control (consecutive result codes requested;
+ * see <draft-sermersheim-ldap-chaining> ) */
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+#define LDAP_REQUIRES_CHAINING 0x4110
+#define LDAP_CANNOT_CHAIN 0x4111
+#endif
+
/* API Error Codes
*
* Based on draft-ietf-ldap-c-api-xx
void slapi_set_object_extension(int objecttype, void *object,
int extensionhandle, void *extension);
+int slapi_x_backend_get_flags( const Slapi_Backend *be, unsigned long *flags );
+
/* parameters currently supported */
/*
#define SLAPI_ATTR_FLAG_COLLECTIVE 0x0080
#define SLAPI_ATTR_FLAG_NOUSERMOD 0x0100
+/*
+ * Backend flags returned by slapi_x_backend_get_flags()
+ */
+#define SLAPI_BACKEND_FLAG_NOLASTMOD 0x0001U
+#define SLAPI_BACKEND_FLAG_NO_SCHEMA_CHECK 0x0002U
+#define SLAPI_BACKEND_FLAG_GLUE_INSTANCE 0x0010U /* a glue backend */
+#define SLAPI_BACKEND_FLAG_GLUE_SUBORDINATE 0x0020U /* child of a glue hierarchy */
+#define SLAPI_BACKEND_FLAG_GLUE_LINKED 0x0040U /* child is connected to parent */
+#define SLAPI_BACKEND_FLAG_OVERLAY 0x0080U /* this db struct is an overlay */
+#define SLAPI_BACKEND_FLAG_GLOBAL_OVERLAY 0x0100U /* this db struct is a global overlay */
+#define SLAPI_BACKEND_FLAG_SHADOW 0x8000U /* a shadow */
+#define SLAPI_BACKEND_FLAG_SYNC_SHADOW 0x1000U /* a sync shadow */
+#define SLAPI_BACKEND_FLAG_SLURP_SHADOW 0x2000U /* a slurp shadow */
+
/*
* ACL levels
*/
scope = LDAP_SCOPE_BASE;
break;
case LDAP_SCOPE_SUBTREE:
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
case LDAP_SCOPE_SUBORDINATE:
#endif
scope = LDAP_SCOPE_SUBTREE;
case LDAP_SCOPE_BASE:
case LDAP_SCOPE_ONELEVEL:
case LDAP_SCOPE_SUBTREE:
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
case LDAP_SCOPE_SUBORDINATE:
#endif
switch ( u->lud_scope ) {
len += STRLENOF( "sub" );
break;
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
case LDAP_SCOPE_SUBORDINATE:
len += STRLENOF( "subordinate" );
break;
case LDAP_SCOPE_BASE:
case LDAP_SCOPE_ONELEVEL:
case LDAP_SCOPE_SUBTREE:
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
case LDAP_SCOPE_SUBORDINATE:
#endif
gotscope = 1;
len -= STRLENOF("sub");
break;
-#ifdef LDAP_FEATURE_SUBORDINATE_SCOPE
+#ifdef LDAP_SCOPE_SUBORDINATE
case LDAP_SCOPE_SUBORDINATE:
strcpy( &s[sofar], "children" );
sofar += STRLENOF("children");
} else if ( strcasecmp( argv[0], "dbnosync" ) == 0 ) {
bdb->bi_dbenv_xflags |= DB_TXN_NOSYNC;
- /* slapadd/slapindex logging configuration */
- } else if ( strcasecmp( argv[0], "fasttool" ) == 0 ) {
- if ( slapMode & SLAP_TOOL_MODE )
-#if DB_VERSION_FULL >= 0x04030015
- bdb->bi_dbenv_xflags |= DB_LOG_INMEMORY;
-#else
- bdb->bi_dbenv_xflags |= DB_TXN_NOT_DURABLE;
-#endif
-
/* slapindex algorithm tuning */
} else if ( strcasecmp( argv[0], "linearindex" ) == 0 ) {
bdb->bi_linear_index = 1;
typedef void * db_malloc(size_t);
typedef void * db_realloc(void *, size_t);
-#if 0
-static int
-bdb_open( BackendInfo *bi )
-{
- return 0;
-}
-
-static int
-bdb_destroy( BackendInfo *bi )
-{
- return 0;
-}
-
-static int
-bdb_close( BackendInfo *bi )
-{
- /* terminate the underlying database system */
- return 0;
-}
-#endif
-
static int
bdb_db_init( BackendDB *be )
{
flags = DB_INIT_MPOOL | DB_THREAD | DB_CREATE;
-if ( !( slapMode & SLAP_TOOL_QUICK ))
+ if ( !( slapMode & SLAP_TOOL_QUICK ))
flags |= DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN;
#if 0
ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
}
- /* <insert> open (and create) index databases */
return 0;
}
bi->bi_op_unbind = 0;
-#if 0 /* DELETE ME */
- bi->bi_op_abandon = bdb_abandon;
- bi->bi_op_cancel = bdb_cancel;
-#endif
-
bi->bi_extended = bdb_extended;
bi->bi_chk_referrals = bdb_referrals;
ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
if ( !lc->lc_bound ) {
+ struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+
/*
* FIXME: we need to let clients use proxyAuthz
* otherwise we cannot do symmetric pools of servers;
/*
* if no bind took place yet, but the connection is bound
* and the "idassert-authcDN" (or other ID) is set,
- * then bind as the asserting ideintity and explicitly
+ * then bind as the asserting identity and explicitly
* add the proxyAuthz control to every operation with the
* dn bound to the connection as control value.
+ * This is done also if this is the authrizing backend,
+ * but the "override" flag is given to idassert.
+ * It allows to use SASL bind and yet proxyAuthz users
*/
- if ( op->o_conn != NULL && BER_BVISNULL( &lc->lc_bound_ndn ) ) {
+ if ( op->o_conn != NULL &&
+ ( BER_BVISNULL( &lc->lc_bound_ndn ) ||
+ ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
+ {
(void)ldap_back_proxy_authz_bind( lc, op, rs );
goto done;
}
#include "slap.h"
#include "back-ldap.h"
-static BackendInfo *lback;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+#define SLAP_CH_RESOLVE_SHIFT SLAP_CONTROL_SHIFT
+#define SLAP_CH_RESOLVE_MASK (0x3 << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_CHAINING_PREFERRED (LDAP_CHAINING_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_CHAINING_REQUIRED (LDAP_CHAINING_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_REFERRALS_PREFERRED (LDAP_REFERRALS_PREFERRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_REFERRALS_REQUIRED (LDAP_REFERRALS_REQUIRED << SLAP_CH_RESOLVE_SHIFT)
+#define SLAP_CH_RESOLVE_DEFAULT SLAP_CH_RESOLVE_CHAINING_PREFERRED
+#define SLAP_CH_CONTINUATION_SHIFT (SLAP_CH_RESOLVE_SHIFT + 2)
+#define SLAP_CH_CONTINUATION_MASK (0x3 << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_CHAINING_PREFERRED (LDAP_CHAINING_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_CHAINING_REQUIRED (LDAP_CHAINING_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_REFERRALS_PREFERRED (LDAP_REFERRALS_PREFERRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_REFERRALS_REQUIRED (LDAP_REFERRALS_REQUIRED << SLAP_CH_CONTINUATION_SHIFT)
+#define SLAP_CH_CONTINUATION_DEFAULT SLAP_CH_CONTINUATION_CHAINING_PREFERRED
+
+#define o_chaining o_ctrlflag[sc_chainingBehavior]
+#define get_chaining(op) ((op)->o_chaining & SLAP_CONTROL_MASK)
+#define get_chainingBehavior(op) ((op)->o_chaining & (SLAP_CH_RESOLVE_MASK|SLAP_CH_CONTINUATION_MASK))
+#define get_resolveBehavior(op) ((op)->o_chaining & SLAP_CH_RESOLVE_MASK)
+#define get_continuationBehavior(op) ((op)->o_chaining & SLAP_CH_CONTINUATION_MASK)
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
+#define LDAP_CH_NONE ((void *)(0))
+#define LDAP_CH_RES ((void *)(1))
+#define LDAP_CH_ERR ((void *)(2))
+
+static int sc_chainingBehavior;
+static BackendInfo *lback;
static int
ldap_chain_operational( Operation *op, SlapReply *rs )
{
assert( op->o_tag == LDAP_REQ_SEARCH );
+ /* if in error, don't proceed any further */
+ if ( op->o_callback->sc_private == LDAP_CH_ERR ) {
+ return 0;
+ }
+
if ( rs->sr_type == REP_SEARCH ) {
Attribute **ap = &rs->sr_entry->e_attrs;
return SLAP_CB_CONTINUE;
+ } else if ( rs->sr_type == REP_SEARCHREF ) {
+ /* if we get it here, it means the library was unable
+ * to chase the referral... */
+
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ if ( get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
+ switch ( get_continuationBehavior( op ) ) {
+ case SLAP_CH_RESOLVE_CHAINING_REQUIRED:
+ op->o_callback->sc_private = LDAP_CH_ERR;
+ return -1;
+
+ default:
+ break;
+ }
+ }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+ return SLAP_CB_CONTINUE;
+
} else if ( rs->sr_type == REP_RESULT ) {
/* back-ldap tried to send result */
- op->o_callback->sc_private = (void *)(1);
+ op->o_callback->sc_private = LDAP_CH_RES;
}
return 0;
static int
ldap_chain_cb_response( Operation *op, SlapReply *rs )
{
+ /* if in error, don't proceed any further */
+ if ( op->o_callback->sc_private == LDAP_CH_ERR ) {
+ return 0;
+ }
+
if ( rs->sr_type == REP_RESULT ) {
- op->o_callback->sc_private = (void *)(1);
+ op->o_callback->sc_private = LDAP_CH_RES;
} else if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH )
{
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
- int rc;
+
+ /* NOTE: returned if ref is empty... */
+ int rc = LDAP_OTHER;
if ( lip->url != NULL ) {
op->o_bd->be_private = on->on_bi.bi_private;
struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ int sr_err = rs->sr_err;
+ slap_reply_t sr_type = rs->sr_type;
+ slap_mask_t chain_mask = 0;
+ ber_len_t chain_shift = 0;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF ) {
return SLAP_CB_CONTINUE;
}
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ if ( rs->sr_err == LDAP_REFERRAL && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
+ switch ( get_resolveBehavior( op ) ) {
+ case SLAP_CH_RESOLVE_REFERRALS_PREFERRED:
+ case SLAP_CH_RESOLVE_REFERRALS_REQUIRED:
+ return SLAP_CB_CONTINUE;
+
+ default:
+ chain_mask = SLAP_CH_RESOLVE_MASK;
+ chain_shift = SLAP_CH_RESOLVE_SHIFT;
+ break;
+ }
+
+ } else if ( rs->sr_type == REP_SEARCHREF && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {
+ switch ( get_continuationBehavior( op ) ) {
+ case SLAP_CH_CONTINUATION_REFERRALS_PREFERRED:
+ case SLAP_CH_CONTINUATION_REFERRALS_REQUIRED:
+ return SLAP_CB_CONTINUE;
+
+ default:
+ chain_mask = SLAP_CH_CONTINUATION_MASK;
+ chain_shift = SLAP_CH_CONTINUATION_SHIFT;
+ break;
+ }
+ }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
/*
* TODO: add checks on who/when chain operations; e.g.:
* a) what identities are authorized
char textbuf[ SLAP_TEXT_BUFLEN ];
size_t textlen = sizeof( textbuf );
+#if 0
+ /* FIXME: op->o_bd is still set to the BackendDB
+ * structure of the database that tried to handle
+ * the operation and actually returned a referral
+ * ... */
+ assert( SLAP_DBFLAGS( op->o_bd ) & SLAP_DBFLAG_GLOBAL_OVERLAY );
+#endif
+
/* global overlay: create entry */
/* NOTE: this is a hack to use the chain overlay
* as global. I expect to be able to remove this
if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
break;
}
+
+ rc = rs->sr_err;
}
op->o_req_dn = odn;
break;
}
- if ( sc2.sc_private == NULL ) {
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ if ( rc != LDAP_SUCCESS || sc2.sc_private == LDAP_CH_ERR ) {
+ if ( rs->sr_err == LDAP_CANNOT_CHAIN ) {
+ goto cannot_chain;
+ }
+
+ switch ( ( get_chainingBehavior( op ) & chain_mask ) >> chain_shift ) {
+ case LDAP_CHAINING_REQUIRED:
+cannot_chain:;
+ op->o_callback = NULL;
+ send_ldap_error( op, rs, LDAP_CANNOT_CHAIN, "operation cannot be completed without chaining" );
+ break;
+
+ default:
+ rc = SLAP_CB_CONTINUE;
+ rs->sr_err = sr_err;
+ rs->sr_type = sr_type;
+ break;
+ }
+ goto dont_chain;
+ }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
+ if ( sc2.sc_private == LDAP_CH_NONE ) {
op->o_callback = NULL;
rc = rs->sr_err = slap_map_api2result( rs );
send_ldap_result( op, rs );
}
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+dont_chain:;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
op->o_do_not_cache = cache;
op->o_bd->be_private = private;
op->o_callback = sc;
int rc;
be->be_private = on->on_bi.bi_private;
- if ( strncasecmp( argv[ 0 ], "chain-", sizeof( "chain-" ) - 1 ) == 0 ) {
+ if ( strncasecmp( argv[ 0 ], "chain-", STRLENOF( "chain-" ) ) == 0 ) {
argv0 = argv[ 0 ];
- argv[ 0 ] = &argv[ 0 ][ sizeof( "chain-" ) - 1 ];
+ argv[ 0 ] = &argv[ 0 ][ STRLENOF( "chain-" ) ];
}
rc = lback->bi_db_config( be, fname, lineno, argc, argv );
if ( argv0 ) {
return rc;
}
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+static int
+ldap_chain_db_open(
+ BackendDB *be
+)
+{
+ return overlay_register_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR );
+}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
static int
ldap_chain_db_destroy(
BackendDB *be
return rc;
}
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+static int
+ldap_chain_parse_ctrl(
+ Operation *op,
+ SlapReply *rs,
+ LDAPControl *ctrl )
+{
+ ber_tag_t tag;
+ BerElement *ber;
+ ber_int_t mode,
+ behavior;
+
+ if ( get_chaining( op ) != SLAP_CONTROL_NONE ) {
+ rs->sr_text = "Chaining behavior control specified multiple times";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( op->o_pagedresults != SLAP_CONTROL_NONE ) {
+ rs->sr_text = "Chaining behavior control specified with pagedResults control";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) {
+ mode = (SLAP_CH_RESOLVE_DEFAULT|SLAP_CH_CONTINUATION_DEFAULT);
+
+ } else {
+ ber_len_t len;
+
+ /* Parse the control value
+ * ChainingBehavior ::= SEQUENCE {
+ * resolveBehavior Behavior OPTIONAL,
+ * continuationBehavior Behavior OPTIONAL }
+ *
+ * Behavior :: = ENUMERATED {
+ * chainingPreferred (0),
+ * chainingRequired (1),
+ * referralsPreferred (2),
+ * referralsRequired (3) }
+ */
+
+ ber = ber_init( &ctrl->ldctl_value );
+ if( ber == NULL ) {
+ rs->sr_text = "internal error";
+ return LDAP_OTHER;
+ }
+
+ tag = ber_scanf( ber, "{e" /* } */, &behavior );
+ /* FIXME: since the whole SEQUENCE is optional,
+ * should we accept no enumerations at all? */
+ if ( tag != LBER_ENUMERATED ) {
+ rs->sr_text = "Chaining behavior control: resolveBehavior decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ switch ( behavior ) {
+ case LDAP_CHAINING_PREFERRED:
+ mode = SLAP_CH_RESOLVE_CHAINING_PREFERRED;
+ break;
+
+ case LDAP_CHAINING_REQUIRED:
+ mode = SLAP_CH_RESOLVE_CHAINING_REQUIRED;
+ break;
+
+ case LDAP_REFERRALS_PREFERRED:
+ mode = SLAP_CH_RESOLVE_REFERRALS_PREFERRED;
+ break;
+
+ case LDAP_REFERRALS_REQUIRED:
+ mode = SLAP_CH_RESOLVE_REFERRALS_REQUIRED;
+ break;
+
+ default:
+ rs->sr_text = "Chaining behavior control: unknown resolveBehavior";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ tag = ber_peek_tag( ber, &len );
+ if ( tag == LBER_ENUMERATED ) {
+ tag = ber_scanf( ber, "e", &behavior );
+ if ( tag == LBER_ERROR ) {
+ rs->sr_text = "Chaining behavior control: continuationBehavior decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+ }
+
+ if ( tag == LBER_DEFAULT ) {
+ mode |= SLAP_CH_CONTINUATION_DEFAULT;
+
+ } else {
+ switch ( behavior ) {
+ case LDAP_CHAINING_PREFERRED:
+ mode |= SLAP_CH_CONTINUATION_CHAINING_PREFERRED;
+ break;
+
+ case LDAP_CHAINING_REQUIRED:
+ mode |= SLAP_CH_CONTINUATION_CHAINING_REQUIRED;
+ break;
+
+ case LDAP_REFERRALS_PREFERRED:
+ mode |= SLAP_CH_CONTINUATION_REFERRALS_PREFERRED;
+ break;
+
+ case LDAP_REFERRALS_REQUIRED:
+ mode |= SLAP_CH_CONTINUATION_REFERRALS_REQUIRED;
+ break;
+
+ default:
+ rs->sr_text = "Chaining behavior control: unknown continuationBehavior";
+ return LDAP_PROTOCOL_ERROR;
+ }
+ }
+
+ if ( ( ber_scanf( ber, /* { */ "}") ) == LBER_ERROR ) {
+ rs->sr_text = "Chaining behavior control: decoding error";
+ return LDAP_PROTOCOL_ERROR;
+ }
+
+ (void) ber_free( ber, 1 );
+ }
+
+ op->o_chaining = mode | ( ctrl->ldctl_iscritical
+ ? SLAP_CONTROL_CRITICAL
+ : SLAP_CONTROL_NONCRITICAL );
+
+ return LDAP_SUCCESS;
+}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
static slap_overinst ldapchain;
int
chain_init( void )
{
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ int rc;
+
+ rc = register_supported_control( LDAP_CONTROL_X_CHAINING_BEHAVIOR,
+ /* SLAP_CTRL_GLOBAL| */ SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE, NULL,
+ ldap_chain_parse_ctrl, &sc_chainingBehavior );
+ if ( rc != LDAP_SUCCESS ) {
+ fprintf( stderr, "Failed to register chaining behavior control: %d\n", rc );
+ return rc;
+ }
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
ldapchain.on_bi.bi_type = "chain";
ldapchain.on_bi.bi_db_init = ldap_chain_db_init;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+ ldapchain.on_bi.bi_db_open = ldap_chain_db_open;
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
ldapchain.on_bi.bi_db_config = ldap_chain_db_config;
ldapchain.on_bi.bi_db_destroy = ldap_chain_db_destroy;
}
} else {
+ char **references = NULL;
+
rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
&match.bv_val, (char **)&rs->sr_text,
- NULL, &rs->sr_ctrls, 1 );
- if (rc != LDAP_SUCCESS ) {
+ &references, &rs->sr_ctrls, 1 );
+ if ( rc != LDAP_SUCCESS ) {
rs->sr_err = rc;
}
rs->sr_err = slap_map_api2result( rs );
+
+ if ( references ) {
+ int cnt;
+
+ for ( cnt = 0; references[ cnt ]; cnt++ )
+ /* NO OP */ ;
+
+ rs->sr_ref = ch_calloc( cnt + 1, sizeof( struct berval ) );
+
+ for ( cnt = 0; references[ cnt ]; cnt++ ) {
+ ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
+ }
+
+ /* cleanup */
+ if ( references ) {
+ ldap_value_free( references );
+ }
+ }
+
rc = 0;
break;
}
rs->sr_matched = NULL;
LDAP_FREE( match.bv_val );
}
+
if ( rs->sr_text ) {
if ( !dontfreetext ) {
LDAP_FREE( (char *)rs->sr_text );
}
rs->sr_text = NULL;
}
+
+ if ( rs->sr_ref ) {
+ ber_bvarray_free( rs->sr_ref );
+ rs->sr_ref = NULL;
+ }
+
if ( attrs ) {
ch_free( attrs );
}
attrs[ i ] = NULL;
rs->sr_err = ldap_add_ext_s( lc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
- attrs, NULL, NULL );
+ attrs, op->o_ctrls, NULL );
for ( --i; i >= 0; --i ) {
free( attrs[ i ]->mod_bvalues );
free( attrs[ i ] );
return -1;
}
- if ( op->o_ctrls ) {
- rs->sr_err = ldap_set_option( lsc->msc_ld,
- LDAP_OPT_SERVER_CONTROLS, op->o_ctrls );
- if ( rs->sr_err != LDAP_SUCCESS ) {
- rs->sr_err = slap_map_api2result( rs );
- goto return_results;
- }
- }
-
/* FIXME: this fixes the bind problem right now; we need
* to use the asynchronous version to get the "matched"
* and more in case of failure ... */
+ /* FIXME: should be check if at least some of the op->o_ctrls
+ * can/should be passed? */
rs->sr_err = ldap_sasl_bind( lsc->msc_ld, mdn.bv_val,
LDAP_SASL_SIMPLE, &op->orb_cred,
op->o_ctrls, NULL, &msgid );
continue;
}
- /*
- * If required, set controls
- */
- if ( op->o_ctrls ) {
- if ( ldap_set_option( lsc->msc_ld, LDAP_OPT_SERVER_CONTROLS,
- op->o_ctrls ) != LDAP_SUCCESS ) {
- ( void )meta_clear_one_candidate( lsc, 1 );
- continue;
- }
- }
-
/*
* If the target is already bound it is skipped
*/
BER_BVZERO( &lsc->msc_cred );
}
+ /* FIXME: should be check if at least some of the op->o_ctrls
+ * can/should be passed? */
rc = ldap_sasl_bind( lsc->msc_ld, "", LDAP_SASL_SIMPLE, &cred,
- op->o_ctrls, NULL, &msgid );
+ NULL, NULL, &msgid );
if ( rc == LDAP_SUCCESS ) {
LDAPMessage *res;
struct timeval tv = { 0, 0 };
*/
rc = ldap_compare_ext( lc->mc_conns[ i ].msc_ld, mdn.bv_val,
mapped_attr.bv_val, &mapped_value,
- NULL, NULL, &msgid[ i ] );
+ op->o_ctrls, NULL, &msgid[ i ] );
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
ludp->lud_dn[ 0 ] = '\0';
- for ( tmpludp = ludp->lud_next; tmpludp; tmpludp = tmpludp->lud_next ) {
+ /* check all, to apply the scope check on the first one */
+ for ( tmpludp = ludp; tmpludp; tmpludp = tmpludp->lud_next ) {
if ( tmpludp->lud_dn != NULL && tmpludp->lud_dn[ 0 ] != '\0' ) {
fprintf( stderr, "%s: line %d: "
"multiple URIs must have "
return( 1 );
}
+
+ if ( tmpludp->lud_scope == LDAP_SCOPE_BASE ) {
+ tmpludp->lud_scope = LDAP_SCOPE_DEFAULT;
+ }
}
li->targets[ i ]->mt_uri = ldap_url_list2urls( ludp );
}
(void)ldap_delete_ext_s( lc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
- NULL, NULL );
+ op->o_ctrls, NULL );
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
modv[ i ] = 0;
rs->sr_err = ldap_modify_ext_s( lc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
- modv, NULL, NULL );
+ modv, op->o_ctrls, NULL );
cleanup:;
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
op->orr_newrdn.bv_val,
mnewSuperior.bv_val,
op->orr_deleteoldrdn,
- NULL, NULL ) != LDAP_SUCCESS;
+ op->o_ctrls, NULL ) != LDAP_SUCCESS;
cleanup:;
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
rc = ldap_search_ext( lsc->msc_ld,
mbase.bv_val, realscope, mfilter.bv_val,
mapped_attrs, op->ors_attrsonly,
- NULL, NULL,
+ op->o_ctrls, NULL,
NULL, op->ors_slimit, &msgid[ i ] );
if ( mapped_attrs ) {
free( mapped_attrs );
if ( !BER_BVISNULL( &ri->ri_realsuffix ) ) {
ri->ri_bd = select_backend( &ri->ri_realsuffix, 0, 1 );
+
/* must be there: it was during config! */
assert( ri->ri_bd );
- /* FIXME: (somehow) copy supported controls ? */
+ /* inherit controls */
+ if ( ri->ri_bd->be_controls ) {
+ be->be_controls = ldap_charray_dup( ri->ri_bd->be_controls );
+ }
+
+ } else {
+ /* inherit all? */
+ if ( frontendDB->be_controls ) {
+ be->be_controls = ldap_charray_dup( frontendDB->be_controls );
+ }
}
return 0;
if((nBackendInfo != 0) || (backendInfo != NULL)) {
/* already initialized */
Debug( LDAP_DEBUG_ANY,
- "backend_init: already initialized.\n", 0, 0, 0 );
+ "backend_init: already initialized\n", 0, 0, 0 );
return -1;
}
/* startup a specific backend database */
int backend_startup_one(Backend *be)
{
- int rc = 0;
+ int rc = 0;
+ BackendInfo *bi = be->bd_info;
assert(be);
LDAP_TAILQ_INIT( be->be_pending_csn_list );
+ /* back-relay takes care of itself; so may do other */
+ if ( be->be_controls == NULL ) {
+ if ( overlay_is_over( be ) ) {
+ bi = ((slap_overinfo *)be->bd_info->bi_private)->oi_orig;
+ }
+
+ if ( bi->bi_controls ) {
+ be->be_controls = ldap_charray_dup( bi->bi_controls );
+ }
+ }
+
Debug( LDAP_DEBUG_TRACE,
"backend_startup: starting \"%s\"\n",
be->be_suffix ? be->be_suffix[0].bv_val : "(unknown)",
rc, 0, 0 );
}
}
+
+ /* back-relay takes care of itself; so may do other */
+ bi = be->bd_info;
+ if ( overlay_is_over( be ) ) {
+ bi = ((slap_overinfo *)be->bd_info->bi_private)->oi_orig;
+ }
+
+ if ( bi->bi_controls ) {
+ if ( be->be_controls == NULL ) {
+ be->be_controls = ldap_charray_dup( bi->bi_controls );
+
+ } else {
+ int i;
+
+ /* maybe not efficient, but it's startup and few dozens of controls... */
+ for ( i = 0; bi->bi_controls[ i ]; i++ ) {
+ if ( !ldap_charray_inlist( be->be_controls, bi->bi_controls[ i ] ) ) {
+ rc = ldap_charray_add( &be->be_controls, bi->bi_controls[ i ] );
+ if ( rc != 0 ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
return rc;
}
free( bd->be_rootpw.bv_val );
}
acl_destroy( bd->be_acl, frontendDB->be_acl );
+ if ( bd->be_controls ) {
+ ldap_charray_free( bd->be_controls );
+ }
}
free( backendDB );
be = &backends[nbackends++];
be->bd_info = bi;
+
be->be_def_limit = frontendDB->be_def_limit;
be->be_dfltaccess = frontendDB->be_dfltaccess;
/* assign a default depth limit for alias deref */
be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;
- if(bi->bi_db_init) {
+ if ( bi->bi_db_init ) {
rc = bi->bi_db_init( be );
}
- if(rc != 0) {
+ if ( rc != 0 ) {
fprintf( stderr, "database init failed (%s)\n", type );
nbackends--;
return NULL;
if ( frontendDB->bd_info->bi_db_close ) {
(*frontendDB->bd_info->bi_db_close)( frontendDB );
}
+
}
Backend *
if( ctrls ) {
for( ; *ctrls != NULL ; ctrls++ ) {
- if( (*ctrls)->ldctl_iscritical && !ldap_charray_inlist(
- op->o_bd->be_controls, (*ctrls)->ldctl_oid ) )
+ int cid;
+ if( slap_find_control_id( (*ctrls)->ldctl_oid, &cid ) ==
+ LDAP_CONTROL_NOT_FOUND )
+ {
+ /* unrecognized control */
+ if ( (*ctrls)->ldctl_iscritical ) {
+ /* should not be reachable */
+ Debug( LDAP_DEBUG_ANY,
+ "backend_check_controls: unrecognized control: %s\n",
+ (*ctrls)->ldctl_oid, 0, 0 );
+ assert( 0 );
+ }
+
+ } else if ( !slap_global_control( op, (*ctrls)->ldctl_oid ) &&
+ !ldap_charray_inlist( op->o_bd->be_controls,
+ (*ctrls)->ldctl_oid ) )
{
- /* FIXME: standards compliance issue
- *
- * Per RFC 2251 (and LDAPBIS discussions), if the control
+ /* Per RFC 2251 (and LDAPBIS discussions), if the control
* is recognized and appropriate for the operation (which
* we've already verified), then the server should make
- * use of the control when performing the operation
- * (without regard to criticality). This code is incorrect
- * on two counts.
- * 1) a service error (e.g., unwillingToPerform) should be
- * returned where a particular backend cannot service the
- * operation,
- * 2) this error should be returned irregardless of the
- * criticality of the control.
+ * use of the control when performing the operation.
+ *
+ * Here we find that operation extended by the control
+ * is not unavailable in a particular context, hence the
+ * return of unwillingToPerform.
*/
rs->sr_text = "control unavailable in context";
- rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
+ rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
break;
}
}
BER_BVZERO( &anlist[ 1 ].an_name );
rs.sr_attrs = anlist;
- rs.sr_attr_flags = slap_attr_flags( rs.sr_attrs );
-
- rc = backend_operational( op, &rs );
+ /* NOTE: backend_operational() is also called
+ * when returning results, so it's supposed
+ * to do no harm to entries */
+ rs.sr_entry = e;
+ rc = backend_operational( op, &rs );
+ rs.sr_entry = NULL;
+
+ if ( rc == LDAP_SUCCESS ) {
+ if ( rs.sr_operational_attrs ) {
+ freeattr = 1;
+ a = rs.sr_operational_attrs;
- if ( rc == LDAP_SUCCESS && rs.sr_operational_attrs ) {
- freeattr = 1;
- a = rs.sr_operational_attrs;
+ } else {
+ rc = LDAP_NO_SUCH_ATTRIBUTE;
+ }
}
}
return rc;
}
+#ifdef LDAP_SLAPI
+static int backend_compute_output_attr_access(computed_attr_context *c, Slapi_Attr *a, Slapi_Entry *e)
+{
+ struct berval *nval = (struct berval *)c->cac_private;
+ Operation *op = NULL;
+
+ slapi_pblock_get( c->cac_pb, SLAPI_OPERATION, &op );
+ if ( op == NULL ) {
+ return 1;
+ }
+
+ return access_allowed( op, e, a->a_desc, nval, ACL_AUTH, NULL ) == 0;
+}
+#endif /* LDAP_SLAPI */
+
+int
+backend_access(
+ Operation *op,
+ Entry *target,
+ struct berval *edn,
+ AttributeDescription *entry_at,
+ struct berval *nval,
+ slap_access_t access,
+ slap_mask_t *mask )
+{
+ Entry *e = NULL;
+ int rc = LDAP_INSUFFICIENT_ACCESS;
+ Backend *be = op->o_bd;
+
+ /* pedantic */
+ assert( op );
+ assert( op->o_conn );
+ assert( edn );
+ assert( access > ACL_NONE );
+
+ op->o_bd = select_backend( edn, 0, 0 );
+
+ if ( target && dn_match( &target->e_nname, edn ) ) {
+ e = target;
+
+ } else {
+ rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e );
+ }
+
+ if ( e ) {
+ Attribute *a = NULL;
+ int freeattr = 0;
+
+ if ( entry_at == NULL ) {
+ entry_at = slap_schema.si_ad_entry;
+ }
+
+ if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children )
+ {
+ if ( access_allowed_mask( op, e, entry_at,
+ NULL, access, NULL, mask ) == 0 )
+ {
+ rc = LDAP_INSUFFICIENT_ACCESS;
+
+ } else {
+ rc = LDAP_SUCCESS;
+ }
+
+ } else {
+ a = attr_find( e->e_attrs, entry_at );
+ if ( a == NULL ) {
+ SlapReply rs = { 0 };
+ AttributeName anlist[ 2 ];
+
+ anlist[ 0 ].an_name = entry_at->ad_cname;
+ anlist[ 0 ].an_desc = entry_at;
+ BER_BVZERO( &anlist[ 1 ].an_name );
+ rs.sr_attrs = anlist;
+
+ rs.sr_attr_flags = slap_attr_flags( rs.sr_attrs );
+
+ /* NOTE: backend_operational() is also called
+ * when returning results, so it's supposed
+ * to do no harm to entries */
+ rs.sr_entry = e;
+ rc = backend_operational( op, &rs );
+ rs.sr_entry = NULL;
+
+ if ( rc == LDAP_SUCCESS ) {
+ if ( rs.sr_operational_attrs ) {
+ freeattr = 1;
+ a = rs.sr_operational_attrs;
+
+ } else {
+ rc = LDAP_NO_SUCH_OBJECT;
+ }
+ }
+ }
+
+ if ( a ) {
+ if ( access_allowed_mask( op, e, entry_at,
+ nval, access, NULL, mask ) == 0 )
+ {
+ rc = LDAP_INSUFFICIENT_ACCESS;
+ goto freeit;
+ }
+ rc = LDAP_SUCCESS;
+ }
+#ifdef LDAP_SLAPI
+ else if ( op->o_pb ) {
+ /* try any computed attributes */
+ computed_attr_context ctx;
+
+ slapi_int_pblock_set_operation( op->o_pb, op );
+
+ ctx.cac_pb = op->o_pb;
+ ctx.cac_attrs = NULL;
+ ctx.cac_userattrs = 0;
+ ctx.cac_opattrs = 0;
+ ctx.cac_private = (void *)nval;
+
+ rc = compute_evaluator( &ctx, entry_at->ad_cname.bv_val, e, backend_compute_output_attr_access );
+ if ( rc == 1 ) {
+ rc = LDAP_INSUFFICIENT_ACCESS;
+
+ } else {
+ rc = LDAP_SUCCESS;
+ }
+ }
+#endif /* LDAP_SLAPI */
+ }
+freeit: if ( e != target ) {
+ be_entry_release_r( op, e );
+ }
+ if ( freeattr ) {
+ attr_free( a );
+ }
+ }
+
+ op->o_bd = be;
+ return rc;
+}
+
int backend_operational(
Operation *op,
SlapReply *rs )
* and the backend supports specific operational attributes,
* add them to the attribute list
*/
- if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( op->ors_attrs &&
- ad_inlist( slap_schema.si_ad_entryDN, op->ors_attrs )))
+ if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
+ ad_inlist( slap_schema.si_ad_entryDN, rs->sr_attrs )))
{
*ap = slap_operational_entryDN( rs->sr_entry );
ap = &(*ap)->a_next;
}
- if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( op->ors_attrs &&
- ad_inlist( slap_schema.si_ad_subschemaSubentry, op->ors_attrs )))
+ if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs &&
+ ad_inlist( slap_schema.si_ad_subschemaSubentry, rs->sr_attrs )))
{
*ap = slap_operational_subschemaSubentry( op->o_bd );
ap = &(*ap)->a_next;
if ( SLAP_ISOVERLAY( be_orig ))
op->o_bd = select_backend( be_orig->be_nsuffix, 0, 0 );
- if (( SLAP_OPATTRS( rs->sr_attr_flags ) || op->ors_attrs ) &&
+ if (( SLAP_OPATTRS( rs->sr_attr_flags ) || rs->sr_attrs ) &&
op->o_bd && op->o_bd->be_operational != NULL )
{
Attribute *a;
return 0;
}
+int
+overlay_register_control( BackendDB *be, const char *oid )
+{
+ int rc = 0;
+ int gotit = 0;
+
+ if ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_GLOBAL_OVERLAY ) {
+ int i;
+
+ /* add to all backends... */
+ for ( i = 0; i < nBackendDB; i++ ) {
+ BackendDB *bd = &backendDB[i];
+
+ if ( be == bd ) {
+ gotit = 1;
+ }
+
+ if ( bd->be_controls == NULL ||
+ !ldap_charray_inlist( bd->be_controls, oid ) )
+ {
+ rc = ldap_charray_add( &bd->be_controls, oid );
+ if ( rc ) {
+ break;
+ }
+ }
+ }
+
+ }
+
+ if ( rc == 0 && !gotit && !ldap_charray_inlist( be->be_controls, oid ) ) {
+ rc = ldap_charray_add( &be->be_controls, oid );
+ if ( rc ) {
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
/* add an overlay to a particular backend. */
int
overlay_config( BackendDB *be, const char *ov )
oi->oi_orig = be->bd_info;
oi->oi_bi = *be->bd_info;
+ /* NOTE: the first time a global overlay is configured,
+ * frontendDB gets this flag; it is used later by overlays
+ * to determine if they're stacked on top of the frontendDB */
+ if ( oi->oi_orig == frontendDB->bd_info ) {
+ SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
+ }
+
/* Save a pointer to ourself in bi_private.
*/
oi->oi_bi.bi_private = oi;
send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
"subschemaSubentry compare not supported" );
+#ifndef SLAP_COMPARE_IN_FRONTEND
} else if ( ava.aa_desc == slap_schema.si_ad_hasSubordinates
&& op->o_bd->be_has_subordinates )
{
rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry );
if ( rc == 0 && entry ) {
- rc = op->o_bd->be_has_subordinates( op, entry,
- &hasSubordinates );
- be_entry_release_r( op, entry );
+ if ( ! access_allowed( op, entry,
+ ava.aa_desc, &ava.aa_value, ACL_COMPARE, NULL ) )
+ {
+ rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+
+ } else {
+ rc = rs->sr_err = op->o_bd->be_has_subordinates( op,
+ entry, &hasSubordinates );
+ be_entry_release_r( op, entry );
+ }
}
if ( rc == 0 ) {
? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
if ( hasSubordinates == asserted ) {
rs->sr_err = LDAP_COMPARE_TRUE;
+
} else {
rs->sr_err = LDAP_COMPARE_FALSE;
}
+
+ } else {
+#ifdef SLAP_ACL_HONOR_DISCLOSE
+ /* return error only if "disclose"
+ * is granted on the object */
+ if ( backend_access( op, NULL, &op->o_req_ndn,
+ slap_schema.si_ad_entry,
+ NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS )
+ {
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ }
+#endif /* SLAP_ACL_HONOR_DISCLOSE */
}
+
send_ldap_result( op, rs );
- if( rc == 0 ) rs->sr_err = LDAP_SUCCESS;
+ if ( rc == 0 ) {
+ rs->sr_err = LDAP_SUCCESS;
+ }
} else if ( op->o_bd->be_compare ) {
op->o_bd->be_compare( op, rs );
+#endif /* ! SLAP_COMPARE_IN_FRONTEND */
} else {
- send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
- "operation not supported within namingContext" );
+ /* do our best to compare that AVA
+ *
+ * NOTE: this code is used only
+ * if SLAP_COMPARE_IN_FRONTEND
+ * is #define'd (it's not by default)
+ * or if op->o_bd->be_compare is NULL.
+ *
+ * FIXME: one potential issue is that
+ * if SLAP_COMPARE_IN_FRONTEND overlays
+ * are not executed for compare. */
+ BerVarray vals = NULL;
+ int rc = LDAP_OTHER;
+
+ rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
+ ava.aa_desc, &vals, ACL_COMPARE );
+ switch ( rs->sr_err ) {
+ default:
+#ifdef SLAP_ACL_HONOR_DISCLOSE
+ /* return error only if "disclose"
+ * is granted on the object */
+ if ( backend_access( op, NULL, &op->o_req_ndn,
+ slap_schema.si_ad_entry,
+ NULL, ACL_DISCLOSE, NULL )
+ == LDAP_INSUFFICIENT_ACCESS )
+ {
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ }
+#endif /* SLAP_ACL_HONOR_DISCLOSE */
+ break;
+
+ case LDAP_SUCCESS:
+ if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
+ SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
+ SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
+ vals, &ava.aa_value, op->o_tmpmemctx ) == 0 )
+ {
+ rs->sr_err = LDAP_COMPARE_TRUE;
+ break;
+
+ } else {
+ rs->sr_err = LDAP_COMPARE_FALSE;
+ }
+ rc = LDAP_SUCCESS;
+ break;
+ }
+
+ send_ldap_result( op, rs );
+
+ if ( rc == 0 ) {
+ rs->sr_err = LDAP_SUCCESS;
+ }
+
+ if ( vals ) {
+ ber_bvarray_free_x( vals, op->o_tmpmemctx );
+ }
}
#if defined( LDAP_SLAPI )
#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE
{ LDAP_CONTROL_X_DOMAIN_SCOPE,
(int)offsetof(struct slap_control_ids, sc_domainScope),
- SLAP_CTRL_FRONTEND|SLAP_CTRL_SEARCH, NULL,
+ SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH, NULL,
parseDomainScope, LDAP_SLIST_ENTRY_INITIALIZER(next) },
#endif
#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY
#ifdef LDAP_CONTORL_X_SEARCH_OPTIONS
{ LDAP_CONTORL_X_SEARCH_OPTIONS,
(int)offsetof(struct slap_control_ids, sc_searchOptions),
- SLAP_CTRL_FRONTEND|SLAP_CTRL_SEARCH, NULL,
+ SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH, NULL,
parseSearchOptions, LDAP_SLIST_ENTRY_INITIALIZER(next) },
#endif
#ifdef LDAP_CONTROL_SUBENTRIES
parseManageDSAit, LDAP_SLIST_ENTRY_INITIALIZER(next) },
{ LDAP_CONTROL_PROXY_AUTHZ,
(int)offsetof(struct slap_control_ids, sc_proxyAuthz),
- SLAP_CTRL_FRONTEND|SLAP_CTRL_ACCESS, proxy_authz_extops,
+ SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS, proxy_authz_extops,
parseProxyAuthz, LDAP_SLIST_ENTRY_INITIALIZER(next) },
{ NULL, 0, 0, NULL, 0, LDAP_SLIST_ENTRY_INITIALIZER(next) }
};
return LDAP_CONTROL_NOT_FOUND;
}
+int
+slap_global_control( Operation *op, const char *oid )
+{
+ struct slap_control *ctrl = find_ctrl( oid );
+
+ if ( ctrl == NULL ) {
+ /* should not be reachable */
+ Debug( LDAP_DEBUG_ANY,
+ "slap_global_control: unrecognized control: %s\n",
+ oid, 0, 0 );
+ assert( 0 );
+ return 0;
+ }
+
+ if ( ctrl->sc_mask & SLAP_CTRL_GLOBAL ) return 1;
+
+ if (( op->o_tag & LDAP_REQ_SEARCH ) &&
+ ( ctrl->sc_mask & SLAP_CTRL_GLOBAL_SEARCH ))
+ {
+ return 1;
+ }
+
+ Debug( LDAP_DEBUG_ANY,
+ "slap_global_control: unavailable control: %s\n",
+ oid, 0, 0 );
+ return 0;
+}
+
void slap_free_ctrls(
Operation *op,
LDAPControl **ctrls )
goto return_results;
}
- if ( sc->sc_mask & SLAP_CTRL_FRONTEND ) {
- /* kludge to disable backend_control() check */
- c->ldctl_iscritical = 0;
-
- } else if ( tagmask == SLAP_CTRL_SEARCH &&
- sc->sc_mask & SLAP_CTRL_FRONTEND_SEARCH )
- {
- /* kludge to disable backend_control() check */
- c->ldctl_iscritical = 0;
- }
-
} else if( c->ldctl_iscritical ) {
/* unavailable CRITICAL control */
rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
* one attribute, and SEARCH permissions can be checked
* directly.
*/
- if( !access_allowed( op, e,
+ if ( !access_allowed( op, e,
mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
return LDAP_COMPARE_FALSE;
}
- for(a = attrs_find( e->e_attrs, mra->ma_desc );
+ for ( a = attrs_find( e->e_attrs, mra->ma_desc );
a != NULL;
a = attrs_find( a->a_next, mra->ma_desc ) )
{
- struct berval *bv;
+ struct berval *bv;
+ int normalize_attribute = 0;
+
#ifdef LDAP_COMP_MATCH
/* Component Matching */
- if( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
+ if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
num_attr_vals = 0;
if ( !a->a_comp_data ) {
for ( ;
- a->a_vals[num_attr_vals].bv_val != NULL;
+ !BER_BVISNULL( &a->a_vals[num_attr_vals] );
num_attr_vals++ )
{
/* empty */;
/* If ma_rule is not the same as the attribute's
* normal rule, then we can't use the a_nvals.
*/
- if (mra->ma_rule == a->a_desc->ad_type->sat_equality) {
+ if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
bv = a->a_nvals;
+
} else {
bv = a->a_vals;
+ normalize_attribute = 1;
}
#ifdef LDAP_COMP_MATCH
i = 0;
#endif
- for ( ; bv->bv_val != NULL; bv++ ) {
+ for ( ; !BER_BVISNULL( bv ); bv++ ) {
int ret;
int rc;
const char *text;
#ifdef LDAP_COMP_MATCH
- if( mra->ma_cf &&
- mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
+ if ( mra->ma_cf &&
+ mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
+ {
/* Check if decoded component trees are already linked */
if ( num_attr_vals ) {
a->a_comp_data->cd_tree[i] = attr_converter(
} else
#endif
{
+ struct berval nbv = BER_BVNULL;
+
+ if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
+ /*
+
+ Document: draft-ietf-ldapbis-protocol
+
+ 4.5.1. Search Request
+ ...
+ If the type field is present and the matchingRule is present,
+ the matchValue is compared against entry attributes of the
+ specified type. In this case, the matchingRule MUST be one
+ suitable for use with the specified type (see [Syntaxes]),
+ otherwise the filter item is Undefined.
+
+
+ In this case, since the matchingRule requires the assertion
+ value to be normalized, we normalize the attribute value
+ according to the syntax of the matchingRule.
+
+ This should likely be done inside value_match(), by passing
+ the appropriate flags, but this is not done at present.
+ See ITS#3406.
+ */
+ if ( mra->ma_rule->smr_normalize(
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ mra->ma_rule->smr_syntax,
+ mra->ma_rule,
+ bv, &nbv, memctx ) != LDAP_SUCCESS )
+ {
+ /* FIXME: stop processing? */
+ continue;
+ }
+
+ } else {
+ nbv = *bv;
+ }
+
rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
- bv, &mra->ma_value, &text );
+ &nbv, &mra->ma_value, &text );
+
+ if ( nbv.bv_val != bv->bv_val ) {
+ memfree( nbv.bv_val, memctx );
+ }
}
- if( rc != LDAP_SUCCESS ) return rc;
+ if ( rc != LDAP_SUCCESS ) return rc;
if ( ret == 0 ) return LDAP_COMPARE_TRUE;
}
}
struct berval *bv, value;
const char *text = NULL;
int rc;
+ int normalize_attribute = 0;
/* check if matching is appropriate */
- if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type )) {
+ if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) {
continue;
}
/* check search access */
if ( !access_allowed( op, e,
- a->a_desc, &value, ACL_SEARCH, NULL ) ) {
+ a->a_desc, &value, ACL_SEARCH, NULL ) )
+ {
memfree( value.bv_val, memctx );
continue;
}
#ifdef LDAP_COMP_MATCH
/* Component Matching */
- if( mra->ma_cf &&
- mra->ma_rule->smr_usage & SLAP_MR_COMPONENT)
+ if ( mra->ma_cf &&
+ mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
{
int ret;
rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
(struct berval*)a, (void*)mra, &text );
- if( rc != LDAP_SUCCESS ) break;
+ if ( rc != LDAP_SUCCESS ) break;
if ( ret == 0 ) {
rc = LDAP_COMPARE_TRUE;
#endif
/* check match */
- if (mra->ma_rule == a->a_desc->ad_type->sat_equality) {
+ if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
bv = a->a_nvals;
+
} else {
bv = a->a_vals;
+ normalize_attribute = 1;
}
- for ( ; bv->bv_val != NULL; bv++ ) {
- int ret;
-
+ for ( ; !BER_BVISNULL( bv ); bv++ ) {
+ int ret;
+ struct berval nbv = BER_BVNULL;
+
+ if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
+ /* see comment above */
+ if ( mra->ma_rule->smr_normalize(
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ mra->ma_rule->smr_syntax,
+ mra->ma_rule,
+ bv, &nbv, memctx ) != LDAP_SUCCESS )
+ {
+ /* FIXME: stop processing? */
+ continue;
+ }
+
+ } else {
+ nbv = *bv;
+ }
+
rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
- bv, &value, &text );
+ &nbv, &value, &text );
+
+ if ( nbv.bv_val != bv->bv_val ) {
+ memfree( nbv.bv_val, memctx );
+ }
- if( rc != LDAP_SUCCESS ) break;
+ if ( rc != LDAP_SUCCESS ) break;
if ( ret == 0 ) {
rc = LDAP_COMPARE_TRUE;
const char *text = NULL;
/* check if matching is appropriate */
- if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type )) {
+ if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type ) ) {
continue;
}
if ( rc == LDAP_SUCCESS && ret == 0 ) rc = LDAP_COMPARE_TRUE;
- if( rc != LDAP_SUCCESS ) {
+ if ( rc != LDAP_SUCCESS ) {
ldap_dnfree_x( dn, memctx );
return rc;
}
continue;
}
- for ( bv = a->a_nvals; bv->bv_val != NULL; bv++ ) {
+ for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
int ret, match;
const char *text;
continue;
}
- for ( bv = a->a_nvals; bv->bv_val != NULL; bv++ ) {
+ for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
int ret, match;
const char *text;
#include "slapi/slapi.h"
#endif
-BackendInfo slap_frontendInfo;
-BackendDB slap_frontendDB;
+static BackendInfo slap_frontendInfo;
+static BackendDB slap_frontendDB;
BackendDB *frontendDB;
int
/* known controls */
frontendDB->bd_info->bi_controls = slap_known_controls;
+ frontendDB->be_controls = ldap_charray_dup( slap_known_controls );
/* calls */
frontendDB->bd_info->bi_op_abandon = fe_op_abandon;
char *serverName;
int serverMode = SLAP_SERVER_MODE;
- struct berval cookie = BER_BVNULL;
struct sync_cookie *scp = NULL;
struct sync_cookie *scp_entry = NULL;
case 'c': /* provide sync cookie, override if exist in replica */
scp = (struct sync_cookie *) ch_calloc( 1,
sizeof( struct sync_cookie ));
- ber_str2bv( optarg, strlen( optarg ), 1, &cookie );
- ber_bvarray_add( &scp->octet_str, &cookie );
+ ber_str2bv( optarg, 0, 1, &scp->octet_str );
slap_parse_sync_cookie( scp );
LDAP_STAILQ_FOREACH( scp_entry, &slap_sync_cookie, sc_next ) {
if( mr == NULL ) continue;
bv = a->a_nvals;
- for ( j=0; bv->bv_val != NULL; bv++, j++ ) {
+ for ( j=0; !BER_BVISNULL( bv ); bv++, j++ ) {
int rc, match;
const char *text;
if ( !is_ad_subtype( a->a_desc, desc ) ) continue;
- for ( bv = a->a_vals, j=0; bv->bv_val != NULL; bv++, j++ );
+ for ( bv = a->a_vals, j = 0; !BER_BVISNULL( bv ); bv++, j++ );
memset( (*e_flags)[i], 1, j);
}
if( mr == NULL ) continue;
bv = a->a_nvals;
- for ( j = 0; bv->bv_val != NULL; bv++, j++ ) {
+ for ( j = 0; !BER_BVISNULL( bv ); bv++, j++ ) {
int rc, match;
const char *text;
MatchingRuleAssertion *mra,
char ***e_flags )
{
- int i, j;
+ int i, j;
- for ( i=0; a != NULL; a = a->a_next, i++ ) {
- struct berval *bv, assertedValue;
+ for ( i = 0; a != NULL; a = a->a_next, i++ ) {
+ struct berval *bv, assertedValue;
+ int normalize_attribute = 0;
if ( mra->ma_desc ) {
if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
&mra->ma_value, &assertedValue, &text, op->o_tmpmemctx );
- if( rc != LDAP_SUCCESS ) continue;
+ if ( rc != LDAP_SUCCESS ) continue;
}
/* check match */
- if (mra->ma_rule == a->a_desc->ad_type->sat_equality) {
+ if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
bv = a->a_nvals;
+
} else {
bv = a->a_vals;
+ normalize_attribute = 1;
}
- for ( j = 0; bv->bv_val != NULL; bv++, j++ ) {
- int rc, match;
- const char *text;
+ for ( j = 0; !BER_BVISNULL( bv ); bv++, j++ ) {
+ int rc, match;
+ const char *text;
+ struct berval nbv = BER_BVNULL;
+
+ if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
+ /* see comment in filterentry.c */
+ if ( mra->ma_rule->smr_normalize(
+ SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+ mra->ma_rule->smr_syntax,
+ mra->ma_rule,
+ bv, &nbv, op->o_tmpmemctx ) != LDAP_SUCCESS )
+ {
+ /* FIXME: stop processing? */
+ continue;
+ }
+
+ } else {
+ nbv = *bv;
+ }
rc = value_match( &match, a->a_desc, mra->ma_rule, 0,
- bv, &assertedValue, &text );
- if( rc != LDAP_SUCCESS ) return rc;
+ &nbv, &assertedValue, &text );
+
+ if ( nbv.bv_val != bv->bv_val ) {
+ op->o_tmpfree( nbv.bv_val, op->o_tmpmemctx );
+ }
+
+ if ( rc != LDAP_SUCCESS ) return rc;
if ( match == 0 ) {
(*e_flags)[i][j] = 1;
int code;
const char *err;
- if( def->mrd_usage == SLAP_MR_NONE &&
- def->mrd_compat_syntaxes == NULL )
- {
+ if( def->mrd_usage == SLAP_MR_NONE && def->mrd_compat_syntaxes == NULL ) {
Debug( LDAP_DEBUG_ANY, "register_matching_rule: not usable %s\n",
def->mrd_desc, 0, 0 );
if( def->mrd_associated != NULL ) {
amr = mr_find( def->mrd_associated );
-
if( amr == NULL ) {
- Debug( LDAP_DEBUG_ANY, "register_matching_rule: could not locate "
- "associated matching rule %s for %s\n",
+ Debug( LDAP_DEBUG_ANY, "register_matching_rule: "
+ "could not locate associated matching rule %s for %s\n",
def->mrd_associated, def->mrd_desc, 0 );
return -1;
if (( def->mrd_usage & SLAP_MR_EQUALITY ) &&
(( def->mrd_usage & SLAP_MR_SUBTYPE_MASK ) != SLAP_MR_NONE ))
{
- Debug( LDAP_DEBUG_ANY,
- "register_matching_rule: inappropriate (approx) association "
- "%s for %s\n",
+ Debug( LDAP_DEBUG_ANY, "register_matching_rule: "
+ "inappropriate (approx) association %s for %s\n",
def->mrd_associated, def->mrd_desc, 0 );
return -1;
}
} else if (!( amr->smr_usage & SLAP_MR_EQUALITY )) {
- Debug( LDAP_DEBUG_ANY,
- "register_matching_rule: inappropriate (equalilty) association "
- "%s for %s\n",
+ Debug( LDAP_DEBUG_ANY, "register_matching_rule: "
+ "inappropriate (equalilty) association %s for %s\n",
def->mrd_associated, def->mrd_desc, 0 );
return -1;
}
return 0;
}
+static int
+ppolicy_db_open(
+ BackendDB *be
+)
+{
+ return overlay_register_control( be, LDAP_CONTROL_PASSWORDPOLICYREQUEST );
+}
+
static int
ppolicy_close(
BackendDB *be
}
code = register_supported_control( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
- SLAP_CTRL_ADD|SLAP_CTRL_BIND|SLAP_CTRL_MODIFY, extops,
+ SLAP_CTRL_ADD|SLAP_CTRL_BIND|SLAP_CTRL_MODIFY|SLAP_CTRL_HIDE, extops,
ppolicy_parseCtrl, &ppolicy_cid );
if ( code != LDAP_SUCCESS ) {
fprintf( stderr, "Failed to register control %d\n", code );
ppolicy.on_bi.bi_type = "ppolicy";
ppolicy.on_bi.bi_db_init = ppolicy_db_init;
+ ppolicy.on_bi.bi_db_open = ppolicy_db_open;
ppolicy.on_bi.bi_db_config = ppolicy_config;
ppolicy.on_bi.bi_db_close = ppolicy_close;
Attribute *a;
int rc;
+ rc = overlay_register_control( be, LDAP_CONTROL_SYNC );
+ if ( rc ) {
+ return rc;
+ }
+
connection_fake_init( &conn, op, thrctx );
op->o_bd = be;
op->o_dn = be->be_rootdn;
slap_access_t access
));
+LDAP_SLAPD_F (int) backend_access LDAP_P((
+ Operation *op,
+ Entry *target,
+ struct berval *edn,
+ AttributeDescription *entry_at,
+ struct berval *nval,
+ slap_access_t access,
+ slap_mask_t *mask ));
+
LDAP_SLAPD_F (int) backend_operational LDAP_P((
Operation *op,
SlapReply *rs
LDAP_SLAPD_F (slap_overinst *) overlay_find LDAP_P(( const char *name ));
LDAP_SLAPD_F (int) overlay_is_over LDAP_P(( BackendDB *be ));
LDAP_SLAPD_F (int) overlay_is_inst LDAP_P(( BackendDB *be, const char *name ));
+LDAP_SLAPD_F (int) overlay_register_control LDAP_P((
+ BackendDB *be,
+ const char *oid ));
/*
* ch_malloc.c
LDAP_SLAPD_F (int) slap_controls_init LDAP_P ((void));
LDAP_SLAPD_F (void) controls_destroy LDAP_P ((void));
LDAP_SLAPD_F (int) controls_root_dse_info LDAP_P ((Entry *e));
-LDAP_SLAPD_F (int) get_supported_controls LDAP_P (( char ***ctrloidsp, slap_mask_t **ctrlmasks ));
-LDAP_SLAPD_F (int) slap_find_control_id LDAP_P (( const char *oid, int *cid ));
+LDAP_SLAPD_F (int) get_supported_controls LDAP_P ((
+ char ***ctrloidsp, slap_mask_t **ctrlmasks ));
+LDAP_SLAPD_F (int) slap_find_control_id LDAP_P ((
+ const char *oid, int *cid ));
+LDAP_SLAPD_F (int) slap_global_control LDAP_P ((
+ Operation *op, const char *oid ));
/*
* config.c
LDAP_SLAPD_F (int) read_config LDAP_P(( const char *fname, int depth ));
LDAP_SLAPD_F (void) config_destroy LDAP_P ((void));
LDAP_SLAPD_F (char **) slap_str2clist LDAP_P((
- char ***,
- char *,
- const char * ));
+ char ***, char *, const char * ));
#ifdef LDAP_SLAPI
LDAP_SLAPD_V (int) slapi_plugins_used;
#endif
*/
#define be_has_subordinates bd_info->bi_has_subordinates
-#define be_controls bd_info->bi_controls
+ /* supported controls */
+ /* NOTE: this stores a duplicate of the control OIDs as listed
+ * in bd_info->bi_controls at database startup; later on,
+ * controls may be added run-time, e.g. by overlays */
+ char **be_controls;
#define be_connection_init bd_info->bi_connection_init
#define be_connection_destroy bd_info->bi_connection_destroy
#define SLAP_DBFLAG_GLUE_INSTANCE 0x0010U /* a glue backend */
#define SLAP_DBFLAG_GLUE_SUBORDINATE 0x0020U /* child of a glue hierarchy */
#define SLAP_DBFLAG_GLUE_LINKED 0x0040U /* child is connected to parent */
-#define SLAP_DBFLAG_OVERLAY 0x0080U /* this db struct is an overlay */
+#define SLAP_DBFLAG_OVERLAY 0x0080U /* this db struct is an overlay */
+#define SLAP_DBFLAG_GLOBAL_OVERLAY 0x0100U /* this db struct is a global overlay */
#define SLAP_DBFLAG_SHADOW 0x8000U /* a shadow */
#define SLAP_DBFLAG_SYNC_SHADOW 0x1000U /* a sync shadow */
#define SLAP_DBFLAG_SLURP_SHADOW 0x2000U /* a slurp shadow */
#define SLAP_CTRL_HIDE 0x80000000U
#endif
-#define SLAP_CTRL_FRONTEND 0x00800000U
-#define SLAP_CTRL_FRONTEND_SEARCH 0x00010000U /* for NOOP */
+#define SLAP_CTRL_GLOBAL 0x00800000U
+#define SLAP_CTRL_GLOBAL_SEARCH 0x00010000U /* for NOOP */
#define SLAP_CTRL_OPFLAGS 0x0000FFFFU
#define SLAP_CTRL_ABANDON 0x00000001U
case SLAPADD:
options = "\n\t[-n databasenumber | -b suffix]\n"
- "\t[-l ldiffile] [-u] [-w]\n";
+ "\t[-l ldiffile] [-q] [-u] [-w]\n";
break;
case SLAPAUTH:
break;
case SLAPINDEX:
- options = "\n\t[-n databasenumber | -b suffix]\n";
+ options = "\n\t[-n databasenumber | -b suffix] [-q]\n";
break;
case SLAPTEST:
break;
case SLAPINDEX:
- options = "b:cd:f:n:v";
+ options = "b:cd:f:n:qv";
mode |= SLAP_TOOL_READMAIN;
break;