int nBackendDB = 0;
BackendDB *backendDB = NULL;
-ldap_pvt_thread_pool_t syncrepl_pool;
-int syncrepl_pool_max = SLAP_MAX_SYNCREPL_THREADS;
+static int
+backend_init_controls( BackendInfo *bi )
+{
+ if ( bi->bi_controls ) {
+ int i;
+
+ for ( i = 0; bi->bi_controls[ i ]; i++ ) {
+ int cid;
+
+ if ( slap_find_control_id( bi->bi_controls[ i ], &cid )
+ == LDAP_CONTROL_NOT_FOUND )
+ {
+ if ( !( slapMode & SLAP_TOOL_MODE ) ) {
+ assert( 0 );
+ }
+
+ return -1;
+ }
+
+ bi->bi_ctrls[ cid ] = 1;
+ }
+ }
+
+ return 0;
+}
int backend_init(void)
{
int rc = -1;
- ldap_pvt_thread_pool_init( &syncrepl_pool, syncrepl_pool_max, 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;
}
return -1;
}
- if ((rc = aBackendInfo->bi_init(aBackendInfo)) != 0) {
+ rc = aBackendInfo->bi_init(aBackendInfo);
+ if ( rc != 0) {
Debug( LDAP_DEBUG_ANY,
"backend_add: initialization for type \"%s\" failed\n",
aBackendInfo->bi_type, 0, 0 );
return rc;
- }
+ }
+
+ (void)backend_init_controls( aBackendInfo );
/* now add the backend type to the Backend Info List */
{
}
}
+static int
+backend_set_controls( BackendDB *be )
+{
+ BackendInfo *bi = be->bd_info;
+
+ /* back-relay takes care of itself; so may do other */
+ if ( overlay_is_over( be ) ) {
+ bi = ((slap_overinfo *)be->bd_info->bi_private)->oi_orig;
+ }
+
+ if ( bi->bi_controls ) {
+ if ( be->be_ctrls[ SLAP_MAX_CIDS ] == 0 ) {
+ AC_MEMCPY( be->be_ctrls, bi->bi_ctrls,
+ sizeof( be->be_ctrls ) );
+ be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
+
+ } else {
+ int i;
+
+ for ( i = 0; i < SLAP_MAX_CIDS; i++ ) {
+ if ( bi->bi_ctrls[ i ] ) {
+ be->be_ctrls[ i ] = bi->bi_ctrls[ i ];
+ }
+ }
+ }
+
+ }
+
+ return 0;
+}
+
/* startup a specific backend database */
int backend_startup_one(Backend *be)
{
int rc = 0;
- BackendInfo *bi = be->bd_info;
- assert(be);
+ assert( be );
be->be_pending_csn_list = (struct be_pcl *)
ch_calloc( 1, sizeof( struct be_pcl ));
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",
+ "backend_startup_one: starting \"%s\"\n",
be->be_suffix ? be->be_suffix[0].bv_val : "(unknown)",
0, 0 );
- if ( be->bd_info->bi_db_open ) {
- rc = be->bd_info->bi_db_open( be );
- if ( rc != 0 ) {
- Debug( LDAP_DEBUG_ANY,
- "backend_startup: bi_db_open failed! (%d)\n",
- 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;
- }
+ /* set database controls */
+ (void)backend_set_controls( be );
- if ( bi->bi_controls ) {
- if ( be->be_controls == NULL ) {
- be->be_controls = ldap_charray_dup( bi->bi_controls );
+ if ( be->bd_info->bi_db_open ) {
+ rc = be->bd_info->bi_db_open( be );
+ if ( rc == 0 ) {
+ (void)backend_set_controls( be );
} 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;
- }
- }
- }
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup_one: bi_db_open failed! (%d)\n",
+ rc, 0, 0 );
}
}
}
if( backendInfo[i].bi_open ) {
- rc = backendInfo[i].bi_open(
- &backendInfo[i] );
+ rc = backendInfo[i].bi_open( &backendInfo[i] );
if ( rc != 0 ) {
Debug( LDAP_DEBUG_ANY,
"backend_startup: bi_open %d failed!\n",
return rc;
}
}
+
+ (void)backend_init_controls( &backendInfo[i] );
}
ldap_pvt_thread_mutex_init( &slapd_rq.rq_mutex );
BackendDB *bd;
struct slap_csn_entry *csne;
- ldap_pvt_thread_pool_destroy( &syncrepl_pool, 1 );
-
/* destroy each backend database */
for( i = 0, bd = backendDB; i < nBackendDB; i++, bd++ ) {
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 );
/* 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 *
return 0;
}
-static int
+int
backend_check_controls(
Operation *op,
SlapReply *rs )
if( ctrls ) {
for( ; *ctrls != NULL ; ctrls++ ) {
- /* KLUDGE: ldctl_iscritical munged by controls.c:get_ctrls()
- * to ensure this check is enabled/disabled appropriately.
- */
- if( (*ctrls)->ldctl_iscritical && !ldap_charray_inlist(
- op->o_bd->be_controls, (*ctrls)->ldctl_oid ) )
- {
- /* 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.
- *
- * 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_UNWILLING_TO_PERFORM;
+ int cid;
+
+ switch ( slap_global_control( op, (*ctrls)->ldctl_oid, &cid ) ) {
+ case 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 );
+ }
+ break;
+
+ case LDAP_COMPARE_FALSE:
+ if ( !op->o_bd->be_ctrls[ cid ] )
+ {
+ /* 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.
+ *
+ * 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_UNWILLING_TO_PERFORM;
+ goto done;
+ }
break;
+
+ case LDAP_COMPARE_TRUE:
+ break;
+
+ default:
+ /* unreachable */
+ rs->sr_text = "unable to check control";
+ rs->sr_err = LDAP_OTHER;
+ goto done;
}
}
}
+done:;
return rs->sr_err;
}
int starttls = 0;
int session = 0;
- if( op->o_bd ) {
- if ( backend_check_controls( op, rs ) != LDAP_SUCCESS ) {
+ if ( op->o_bd ) {
+ int rc = SLAP_CB_CONTINUE;
+
+ if ( op->o_bd->be_chk_controls ) {
+ rc = ( *op->o_bd->be_chk_controls )( op, rs );
+ }
+
+ if ( rc == SLAP_CB_CONTINUE ) {
+ rc = backend_check_controls( op, rs );
+ }
+
+ if ( rc != LDAP_SUCCESS ) {
return rs->sr_err;
}
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;
-
- a = rs->sr_operational_attrs;
- rs->sr_operational_attrs = NULL;
rc = op->o_bd->be_operational( op, rs );
- *ap = rs->sr_operational_attrs;
- if ( a != NULL ) {
- rs->sr_operational_attrs = a;
- }
-
- for ( ; *ap; ap = &(*ap)->a_next )
- /* just count them */ ;
}
op->o_bd = be_orig;