X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fbackend.c;h=349b7a621cc2cfed2cc86edf907581df80fa310f;hb=98dc97bcb922a4bcfe02b27b4f1282660be6059b;hp=6c7fd50a0c2330856fd26b83b244cfea6e519ce5;hpb=b89c894effbcfb4f8e78bbd2d9d80e8246982e5f;p=openldap diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 6c7fd50a0c..349b7a621c 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -41,7 +41,12 @@ #ifdef LDAP_SLAPI #include "slapi/slapi.h" -#endif + +static void init_group_pblock( Operation *op, Entry *target, + Entry *e, struct berval *op_ndn, AttributeDescription *group_at ); +static int call_group_preop_plugins( Operation *op ); +static void call_group_postop_plugins( Operation *op ); +#endif /* LDAP_SLAPI */ /* * If a module is configured as dynamic, its header should not @@ -51,97 +56,97 @@ * imported into slapd without appropriate __declspec(dllimport) directives. */ -#if defined(SLAPD_BDB) && !defined(SLAPD_BDB_DYNAMIC) +#if SLAPD_BDB == SLAPD_MOD_STATIC #include "back-bdb/external.h" #endif -#if defined(SLAPD_DNSSRV) && !defined(SLAPD_DNSSRV_DYNAMIC) +#if SLAPD_DNSSRV == SLAPD_MOD_STATIC #include "back-dnssrv/external.h" #endif -#if defined(SLAPD_HDB) && !defined(SLAPD_HDB_DYNAMIC) +#if SLAPD_HDB == SLAPD_MOD_STATIC #include "back-hdb/external.h" #endif -#if defined(SLAPD_LDAP) && !defined(SLAPD_LDAP_DYNAMIC) +#if SLAPD_LDAP == SLAPD_MOD_STATIC #include "back-ldap/external.h" #endif -#if defined(SLAPD_LDBM) && !defined(SLAPD_LDBM_DYNAMIC) +#if SLAPD_LDBM == SLAPD_MOD_STATIC #include "back-ldbm/external.h" #endif -#if defined(SLAPD_META) && !defined(SLAPD_META_DYNAMIC) +#if SLAPD_META == SLAPD_MOD_STATIC #include "back-meta/external.h" #endif -#if defined(SLAPD_MONITOR) && !defined(SLAPD_MONITOR_DYNAMIC) +#if SLAPD_MONITOR == SLAPD_MOD_STATIC #include "back-monitor/external.h" #endif -#if defined(SLAPD_NULL) && !defined(SLAPD_NULL_DYNAMIC) +#if SLAPD_NULL == SLAPD_MOD_STATIC #include "back-null/external.h" #endif -#if defined(SLAPD_PASSWD) && !defined(SLAPD_PASSWD_DYNAMIC) +#if SLAPD_PASSWD == SLAPD_MOD_STATIC #include "back-passwd/external.h" #endif -#if defined(SLAPD_PERL) && !defined(SLAPD_PERL_DYNAMIC) +#if SLAPD_PERL == SLAPD_MOD_STATIC #include "back-perl/external.h" #endif -#if defined(SLAPD_RELAY) && !defined(SLAPD_RELAY_DYNAMIC) +#if SLAPD_RELAY == SLAPD_MOD_STATIC #include "back-relay/external.h" #endif -#if defined(SLAPD_SHELL) && !defined(SLAPD_SHELL_DYNAMIC) +#if SLAPD_SHELL == SLAPD_MOD_STATIC #include "back-shell/external.h" #endif -#if defined(SLAPD_TCL) && !defined(SLAPD_TCL_DYNAMIC) +#if SLAPD_TCL == SLAPD_MOD_STATIC #include "back-tcl/external.h" #endif -#if defined(SLAPD_SQL) && !defined(SLAPD_SQL_DYNAMIC) +#if SLAPD_SQL == SLAPD_MOD_STATIC #include "back-sql/external.h" #endif -#if defined(SLAPD_PRIVATE) && !defined(SLAPD_PRIVATE_DYNAMIC) +#if SLAPD_PRIVATE == SLAPD_MOD_STATIC #include "private/external.h" #endif static BackendInfo binfo[] = { -#if defined(SLAPD_BDB) && !defined(SLAPD_BDB_DYNAMIC) +#if SLAPD_BDB == SLAPD_MOD_STATIC {"bdb", bdb_initialize}, #endif -#if defined(SLAPD_DNSSRV) && !defined(SLAPD_DNSSRV_DYNAMIC) +#if SLAPD_DNSSRV == SLAPD_MOD_STATIC {"dnssrv", dnssrv_back_initialize}, #endif -#if defined(SLAPD_HDB) && !defined(SLAPD_HDB_DYNAMIC) +#if SLAPD_HDB == SLAPD_MOD_STATIC {"hdb", hdb_initialize}, #endif -#if defined(SLAPD_LDAP) && !defined(SLAPD_LDAP_DYNAMIC) +#if SLAPD_LDAP == SLAPD_MOD_STATIC {"ldap", ldap_back_initialize}, #endif -#if defined(SLAPD_LDBM) && !defined(SLAPD_LDBM_DYNAMIC) +#if SLAPD_LDBM == SLAPD_MOD_STATIC {"ldbm", ldbm_back_initialize}, #endif -#if defined(SLAPD_META) && !defined(SLAPD_META_DYNAMIC) +#if SLAPD_META == SLAPD_MOD_STATIC {"meta", meta_back_initialize}, #endif -#if defined(SLAPD_MONITOR) && !defined(SLAPD_MONITOR_DYNAMIC) +#if SLAPD_MONITOR == SLAPD_MOD_STATIC {"monitor", monitor_back_initialize}, #endif -#if defined(SLAPD_NULL) && !defined(SLAPD_NULL_DYNAMIC) +#if SLAPD_NULL == SLAPD_MOD_STATIC {"null", null_back_initialize}, #endif -#if defined(SLAPD_PASSWD) && !defined(SLAPD_PASSWD_DYNAMIC) +#if SLAPD_PASSWD == SLAPD_MOD_STATIC {"passwd", passwd_back_initialize}, #endif -#if defined(SLAPD_PERL) && !defined(SLAPD_PERL_DYNAMIC) +#if SLAPD_PERL == SLAPD_MOD_STATIC {"perl", perl_back_initialize}, #endif -#if defined(SLAPD_RELAY) && !defined(SLAPD_RELAY_DYNAMIC) +#if SLAPD_RELAY == SLAPD_MOD_STATIC {"relay", relay_back_initialize}, #endif -#if defined(SLAPD_SHELL) && !defined(SLAPD_SHELL_DYNAMIC) +#if SLAPD_SHELL == SLAPD_MOD_STATIC {"shell", shell_back_initialize}, #endif -#if defined(SLAPD_TCL) && !defined(SLAPD_TCL_DYNAMIC) +#if SLAPD_TCL == SLAPD_MOD_STATIC {"tcl", tcl_back_initialize}, #endif -#if defined(SLAPD_SQL) && !defined(SLAPD_SQL_DYNAMIC) - {"sql", sql_back_initialize}, +#if SLAPD_SQL == SLAPD_MOD_STATIC + {"sql", backsql_initialize}, #endif /* for any private backend */ -#if defined(SLAPD_PRIVATE) && !defined(SLAPD_PRIVATE_DYNAMIC) +#if SLAPD_PRIVATE == SLAPD_MOD_STATIC {"private", private_back_initialize}, #endif {NULL} @@ -164,13 +169,8 @@ int backend_init(void) if((nBackendInfo != 0) || (backendInfo != NULL)) { /* already initialized */ -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, ERR, - "backend_init: backend already initialized\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "backend_init: already initialized.\n", 0, 0, 0 ); -#endif return -1; } @@ -183,15 +183,9 @@ int backend_init(void) rc = binfo[nBackendInfo].bi_init( &binfo[nBackendInfo] ); if(rc != 0) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, INFO, - "backend_init: initialized for type \"%s\"\n", - binfo[nBackendInfo].bi_type, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "backend_init: initialized for type \"%s\"\n", binfo[nBackendInfo].bi_type, 0, 0 ); -#endif /* destroy those we've already inited */ for( nBackendInfo--; nBackendInfo >= 0 ; @@ -215,13 +209,9 @@ int backend_init(void) return 0; #else -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, ERR, "backend_init: failed\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "backend_init: failed\n", 0, 0, 0 ); -#endif return rc; #endif /* SLAPD_MODULES */ @@ -229,56 +219,71 @@ int backend_init(void) int backend_add(BackendInfo *aBackendInfo) { - int rc = 0; - - if ( aBackendInfo->bi_init == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, ERR, - "backend_add: backend type \"%s\" does not have the " - "(mandatory)init function\n", - aBackendInfo->bi_type, 0, 0 ); -#else - Debug( LDAP_DEBUG_ANY, - "backend_add: backend type \"%s\" does not have the " - "(mandatory)init function\n", - aBackendInfo->bi_type, 0, 0 ); -#endif - return -1; - } + int rc = 0; + + if ( aBackendInfo->bi_init == NULL ) { + Debug( LDAP_DEBUG_ANY, "backend_add: " + "backend type \"%s\" does not have the (mandatory)init function\n", + aBackendInfo->bi_type, 0, 0 ); + return -1; + } if ((rc = aBackendInfo->bi_init(aBackendInfo)) != 0) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, ERR, - "backend_add: initialization for type \"%s\" failed\n", - aBackendInfo->bi_type, 0, 0 ); -#else - Debug( LDAP_DEBUG_ANY, - "backend_add: initialization for type \"%s\" failed\n", - aBackendInfo->bi_type, 0, 0 ); -#endif - return rc; + Debug( LDAP_DEBUG_ANY, + "backend_add: initialization for type \"%s\" failed\n", + aBackendInfo->bi_type, 0, 0 ); + return rc; } - /* now add the backend type to the Backend Info List */ - { - BackendInfo *newBackendInfo = 0; - - /* if backendInfo == binfo no deallocation of old backendInfo */ - if (backendInfo == binfo) { - newBackendInfo = ch_calloc(nBackendInfo + 1, sizeof(BackendInfo)); - AC_MEMCPY(newBackendInfo, backendInfo, sizeof(BackendInfo) * - nBackendInfo); - } else { - newBackendInfo = ch_realloc(backendInfo, sizeof(BackendInfo) * - (nBackendInfo + 1)); - } - AC_MEMCPY(&newBackendInfo[nBackendInfo], aBackendInfo, - sizeof(BackendInfo)); - backendInfo = newBackendInfo; - nBackendInfo++; - - return 0; - } + /* now add the backend type to the Backend Info List */ + { + BackendInfo *newBackendInfo = 0; + + /* if backendInfo == binfo no deallocation of old backendInfo */ + if (backendInfo == binfo) { + newBackendInfo = ch_calloc(nBackendInfo + 1, sizeof(BackendInfo)); + AC_MEMCPY(newBackendInfo, backendInfo, + sizeof(BackendInfo) * nBackendInfo); + } else { + newBackendInfo = ch_realloc(backendInfo, + sizeof(BackendInfo) * (nBackendInfo + 1)); + } + + AC_MEMCPY(&newBackendInfo[nBackendInfo], aBackendInfo, + sizeof(BackendInfo)); + backendInfo = newBackendInfo; + nBackendInfo++; + return 0; + } +} + +/* startup a specific backend database */ +int backend_startup_one(Backend *be) +{ + int rc = 0; + + assert(be); + + be->be_pending_csn_list = (struct be_pcl *) + ch_calloc( 1, sizeof( struct be_pcl )); + build_new_dn( &be->be_context_csn, be->be_nsuffix, + (struct berval *)&slap_ldapsync_cn_bv, NULL ); + + LDAP_TAILQ_INIT( be->be_pending_csn_list ); + + Debug( LDAP_DEBUG_TRACE, + "backend_startup: 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 ); + } + } + return rc; } int backend_startup(Backend *be) @@ -288,64 +293,36 @@ int backend_startup(Backend *be) if( ! ( nBackendDB > 0 ) ) { /* no databases */ -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, INFO, - "backend_startup: %d databases to startup. \n", nBackendDB, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "backend_startup: %d databases to startup.\n", nBackendDB, 0, 0 ); -#endif return 1; } if(be != NULL) { - /* startup a specific backend database */ - - LDAP_TAILQ_INIT( &be->be_pending_csn_list ); - -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, DETAIL1, "backend_startup: starting \"%s\"\n", - be->be_suffix ? be->be_suffix[0].bv_val : "(unknown)", - 0, 0 ); -#else - Debug( LDAP_DEBUG_TRACE, - "backend_startup: starting \"%s\"\n", - be->be_suffix ? be->be_suffix[0].bv_val : "(unknown)", - 0, 0 ); -#endif - if ( be->bd_info->bi_open ) { rc = be->bd_info->bi_open( be->bd_info ); if ( rc != 0 ) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, CRIT, "backend_startup: bi_open failed!\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "backend_startup: bi_open failed!\n", 0, 0, 0 ); -#endif return rc; } } - if ( be->bd_info->bi_db_open ) { - rc = be->bd_info->bi_db_open( be ); - if ( rc != 0 ) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, CRIT, - "backend_startup: bi_db_open failed! (%d)\n", rc, 0, 0 ); -#else - Debug( LDAP_DEBUG_ANY, - "backend_startup: bi_db_open failed! (%d)\n", - rc, 0, 0 ); -#endif - return rc; - } - } + return backend_startup_one( be ); + } - return rc; + /* open frontend, if required */ + if ( frontendDB->bd_info->bi_db_open ) { + rc = frontendDB->bd_info->bi_db_open( frontendDB ); + if ( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, + "backend_startup: bi_db_open(frontend) failed! (%d)\n", + rc, 0, 0 ); + return rc; + } } /* open each backend type */ @@ -359,14 +336,9 @@ int backend_startup(Backend *be) rc = backendInfo[i].bi_open( &backendInfo[i] ); if ( rc != 0 ) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, CRIT, - "backend_startup: bi_open %d failed!\n", i, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "backend_startup: bi_open %d failed!\n", i, 0, 0 ); -#endif return rc; } } @@ -378,55 +350,28 @@ int backend_startup(Backend *be) /* open each backend database */ for( i = 0; i < nBackendDB; i++ ) { - /* append global access controls */ - acl_append( &backendDB[i].be_acl, global_acl ); - - LDAP_TAILQ_INIT( &backendDB[i].be_pending_csn_list ); - if ( backendDB[i].be_suffix == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, CRIT, - "backend_startup: warning, database %d (%s) " - "has no suffix\n", - i, backendDB[i].bd_info->bi_type, 0 ); -#else Debug( LDAP_DEBUG_ANY, "backend_startup: warning, database %d (%s) " "has no suffix\n", i, backendDB[i].bd_info->bi_type, 0 ); -#endif } + /* append global access controls */ + acl_append( &backendDB[i].be_acl, frontendDB->be_acl ); + + rc = backend_startup_one( &backendDB[i] ); + + if ( rc ) return rc; - if ( backendDB[i].bd_info->bi_db_open ) { - rc = backendDB[i].bd_info->bi_db_open( - &backendDB[i] ); - if ( rc != 0 ) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, CRIT, - "backend_startup: bi_db_open(%d) failed! (%d)\n", i, rc, 0 ); -#else - Debug( LDAP_DEBUG_ANY, - "backend_startup: bi_db_open(%d) failed! (%d)\n", - i, rc, 0 ); -#endif - return rc; - } - } if ( !LDAP_STAILQ_EMPTY( &backendDB[i].be_syncinfo )) { syncinfo_t *si; if ( !( backendDB[i].be_search && backendDB[i].be_add && backendDB[i].be_modify && backendDB[i].be_delete )) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, CRIT, - "backend_startup: database(%d) does not support " - "operations required for syncrepl", i, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "backend_startup: database(%d) does not support " "operations required for syncrepl", i, 0, 0 ); -#endif continue; } @@ -488,15 +433,9 @@ int backend_shutdown( Backend *be ) } if(rc != 0) { -#ifdef NEW_LOGGING - LDAP_LOG( BACKEND, NOTICE, - "backend_shutdown: bi_close %s failed!\n", - backendDB[i].be_type, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, - "backend_close: bi_close %s failed!\n", + "backend_close: bi_db_close %s failed!\n", backendDB[i].be_type, 0, 0 ); -#endif } } @@ -513,6 +452,16 @@ int backend_shutdown( Backend *be ) } } + /* close frontend, if required */ + if ( frontendDB->bd_info->bi_db_close ) { + rc = frontendDB->bd_info->bi_db_close ( frontendDB ); + if ( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, + "backend_startup: bi_db_close(frontend) failed! (%d)\n", + rc, 0, 0 ); + } + } + return 0; } @@ -520,11 +469,19 @@ int backend_destroy(void) { int i; BackendDB *bd; + syncinfo_t *si_entry; ldap_pvt_thread_pool_destroy( &syncrepl_pool, 1 ); /* destroy each backend database */ for( i = 0, bd = backendDB; i < nBackendDB; i++, bd++ ) { + + while ( !LDAP_STAILQ_EMPTY( &bd->be_syncinfo )) { + si_entry = LDAP_STAILQ_FIRST( &bd->be_syncinfo ); + LDAP_STAILQ_REMOVE_HEAD( &bd->be_syncinfo, si_next ); + syncinfo_free( si_entry ); + } + if ( bd->bd_info->bi_db_destroy ) { bd->bd_info->bi_db_destroy( bd ); } @@ -533,7 +490,8 @@ int backend_destroy(void) if ( bd->be_rootdn.bv_val ) free( bd->be_rootdn.bv_val ); if ( bd->be_rootndn.bv_val ) free( bd->be_rootndn.bv_val ); if ( bd->be_rootpw.bv_val ) free( bd->be_rootpw.bv_val ); - acl_destroy( bd->be_acl, global_acl ); + if ( bd->be_context_csn.bv_val ) free( bd->be_context_csn.bv_val ); + acl_destroy( bd->be_acl, frontendDB->be_acl ); } free( backendDB ); @@ -554,6 +512,18 @@ int backend_destroy(void) nBackendInfo = 0; backendInfo = NULL; + /* destroy frontend database */ + bd = frontendDB; + if ( bd->bd_info->bi_db_destroy ) { + bd->bd_info->bi_db_destroy( bd ); + } + ber_bvarray_free( bd->be_suffix ); + ber_bvarray_free( bd->be_nsuffix ); + if ( bd->be_rootdn.bv_val ) free( bd->be_rootdn.bv_val ); + if ( bd->be_rootndn.bv_val ) free( bd->be_rootndn.bv_val ); + if ( bd->be_rootpw.bv_val ) free( bd->be_rootpw.bv_val ); + acl_destroy( bd->be_acl, frontendDB->be_acl ); + return 0; } @@ -574,8 +544,7 @@ BackendInfo* backend_info(const char *type) BackendDB * backend_db_init( - const char *type -) + const char *type ) { Backend *be; BackendInfo *bi = backend_info(type); @@ -586,26 +555,36 @@ backend_db_init( return NULL; } + be = backendDB; + backendDB = (BackendDB *) ch_realloc( (char *) backendDB, (nBackendDB + 1) * sizeof(Backend) ); memset( &backendDB[nbackends], '\0', sizeof(Backend) ); + /* did realloc move our table? if so, fix up dependent pointers */ + if ( be != backendDB ) { + int i; + for ( i=0, be=backendDB; ibe_pcl_mutexp = &be->be_pcl_mutex; + } + } + be = &backends[nbackends++]; be->bd_info = bi; - be->be_def_limit = deflimit; - be->be_dfltaccess = global_default_access; + be->be_def_limit = frontendDB->be_def_limit; + be->be_dfltaccess = frontendDB->be_dfltaccess; - be->be_restrictops = global_restrictops; - be->be_requires = global_requires; - be->be_ssf_set = global_ssf_set; + be->be_restrictops = frontendDB->be_restrictops; + be->be_requires = frontendDB->be_requires; + be->be_ssf_set = frontendDB->be_ssf_set; be->be_context_csn.bv_len = 0; be->be_context_csn.bv_val = NULL; - ldap_pvt_thread_mutex_init( &be->be_pcl_mutex ); - ldap_pvt_thread_mutex_init( &be->be_context_csn_mutex ); + be->be_pcl_mutexp = &be->be_pcl_mutex; + ldap_pvt_thread_mutex_init( be->be_pcl_mutexp ); LDAP_STAILQ_INIT( &be->be_syncinfo ); @@ -636,6 +615,10 @@ be_db_close( void ) (*backends[i].bd_info->bi_db_close)( &backends[i] ); } } + + if ( frontendDB->bd_info->bi_db_close ) { + (*frontendDB->bd_info->bi_db_close)( frontendDB ); + } } Backend * @@ -698,13 +681,15 @@ select_backend( int be_issuffix( - Backend *be, - struct berval *bvsuffix -) + Backend *be, + struct berval *bvsuffix ) { int i; - for ( i = 0; be->be_nsuffix != NULL && be->be_nsuffix[i].bv_val != NULL; i++ ) { + for ( i = 0; + be->be_nsuffix != NULL && be->be_nsuffix[i].bv_val != NULL; + i++ ) + { if ( bvmatch( &be->be_nsuffix[i], bvsuffix ) ) { return( 1 ); } @@ -714,7 +699,7 @@ be_issuffix( } int -be_isroot( Backend *be, struct berval *ndn ) +be_isroot_dn( Backend *be, struct berval *ndn ) { if ( !ndn->bv_len ) { return( 0 ); @@ -728,15 +713,31 @@ be_isroot( Backend *be, struct berval *ndn ) } int -be_isupdate( Backend *be, struct berval *ndn ) +be_sync_update( Operation *op ) { - if ( !ndn->bv_len ) { - return( 0 ); - } + return ( SLAP_SYNC_SHADOW( op->o_bd ) && syncrepl_isupdate( op ) ); +} - if ( !be->be_update_ndn.bv_len ) { - return( 0 ); - } +int +be_slurp_update( Operation *op ) +{ + return ( SLAP_SLURP_SHADOW( op->o_bd ) && + be_isupdate_dn( op->o_bd, &op->o_ndn )); +} + +int +be_shadow_update( Operation *op ) +{ + return ( SLAP_SHADOW( op->o_bd ) && + ( syncrepl_isupdate( op ) || be_isupdate_dn( op->o_bd, &op->o_ndn ))); +} + +int +be_isupdate_dn( Backend *be, struct berval *ndn ) +{ + if ( !ndn->bv_len ) return( 0 ); + + if ( !be->be_update_ndn.bv_len ) return( 0 ); return dn_match( &be->be_update_ndn, ndn ); } @@ -748,18 +749,17 @@ be_root_dn( Backend *be ) } int -be_isroot_dn( Operation *op ) +be_isroot( Operation *op ) { - return be_isroot( op->o_bd, &op->o_ndn ); + return be_isroot_dn( op->o_bd, &op->o_ndn ); } int be_isroot_pw( Operation *op ) { int result; - char *errmsg; - if ( ! be_isroot_dn( op ) ) { + if ( ! be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) { return 0; } @@ -813,20 +813,16 @@ backend_unbind( Operation *op, SlapReply *rs ) int rc; if ( i == 0 ) slapi_int_pblock_set_operation( op->o_pb, op ); slapi_pblock_set( op->o_pb, SLAPI_BACKEND, (void *)&backends[i] ); - rc = slapi_int_call_plugins( &backends[i], SLAPI_PLUGIN_PRE_UNBIND_FN, - (Slapi_PBlock *)op->o_pb ); + rc = slapi_int_call_plugins( &backends[i], + SLAPI_PLUGIN_PRE_UNBIND_FN, (Slapi_PBlock *)op->o_pb ); if ( rc < 0 ) { /* * A preoperation plugin failure will abort the * entire operation. */ -#ifdef NEW_LOGGING - LDAP_LOG( OPERATION, INFO, "do_bind: Unbind preoperation plugin " - "failed\n", 0, 0, 0); -#else - Debug(LDAP_DEBUG_TRACE, "do_bind: Unbind preoperation plugin " - "failed.\n", 0, 0, 0); -#endif + Debug(LDAP_DEBUG_TRACE, + "do_bind: Unbind preoperation plugin failed\n", + 0, 0, 0); return 0; } } @@ -838,15 +834,12 @@ backend_unbind( Operation *op, SlapReply *rs ) } #if defined( LDAP_SLAPI ) - if ( op->o_pb != NULL && slapi_int_call_plugins( &backends[i], SLAPI_PLUGIN_POST_UNBIND_FN, - (Slapi_PBlock *)op->o_pb ) < 0 ) { -#ifdef NEW_LOGGING - LDAP_LOG( OPERATION, INFO, "do_unbind: Unbind postoperation plugins " - "failed\n", 0, 0, 0); -#else - Debug(LDAP_DEBUG_TRACE, "do_unbind: Unbind postoperation plugins " - "failed.\n", 0, 0, 0); -#endif + if ( op->o_pb != NULL && slapi_int_call_plugins( &backends[i], + SLAPI_PLUGIN_POST_UNBIND_FN, (Slapi_PBlock *)op->o_pb ) < 0 ) + { + Debug(LDAP_DEBUG_TRACE, + "do_unbind: Unbind postoperation plugins failed\n", + 0, 0, 0); } #endif /* defined( LDAP_SLAPI ) */ } @@ -856,8 +849,7 @@ backend_unbind( Operation *op, SlapReply *rs ) int backend_connection_init( - Connection *conn -) + Connection *conn ) { int i; @@ -872,8 +864,7 @@ backend_connection_init( int backend_connection_destroy( - Connection *conn -) + Connection *conn ) { int i; @@ -899,6 +890,20 @@ backend_check_controls( if( (*ctrls)->ldctl_iscritical && !ldap_charray_inlist( op->o_bd->be_controls, (*ctrls)->ldctl_oid ) ) { + /* FIXME: standards compliance issue + * + * 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. + */ rs->sr_text = "control unavailable in context"; rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; break; @@ -918,6 +923,7 @@ backend_check_restrictions( slap_mask_t restrictops; slap_mask_t requires; slap_mask_t opflag; + slap_mask_t exopflag = 0; slap_ssf_set_t *ssf; int updateop = 0; int starttls = 0; @@ -933,9 +939,9 @@ backend_check_restrictions( ssf = &op->o_bd->be_ssf_set; } else { - restrictops = global_restrictops; - requires = global_requires; - ssf = &global_ssf_set; + restrictops = frontendDB->be_restrictops; + requires = frontendDB->be_requires; + ssf = &frontendDB->be_ssf_set; } switch( op->o_tag ) { @@ -967,14 +973,23 @@ backend_check_restrictions( if( bvmatch( opdata, &slap_EXOP_START_TLS ) ) { session++; starttls++; + exopflag = SLAP_RESTRICT_EXOP_START_TLS; break; } if( bvmatch( opdata, &slap_EXOP_WHOAMI ) ) { + exopflag = SLAP_RESTRICT_EXOP_WHOAMI; break; } if ( bvmatch( opdata, &slap_EXOP_CANCEL ) ) { + exopflag = SLAP_RESTRICT_EXOP_CANCEL; + break; + } + + if ( bvmatch( opdata, &slap_EXOP_MODIFY_PASSWD ) ) { + exopflag = SLAP_RESTRICT_EXOP_MODIFY_PASSWD; + updateop++; break; } @@ -1009,12 +1024,16 @@ backend_check_restrictions( rs->sr_err = LDAP_CONFIDENTIALITY_REQUIRED; if( op->o_transport_ssf < ssf->sss_transport ) { - rs->sr_text = "transport confidentiality required"; + rs->sr_text = op->o_transport_ssf + ? "stronger transport confidentiality required" + : "transport confidentiality required"; return rs->sr_err; } if( op->o_tls_ssf < ssf->sss_tls ) { - rs->sr_text = "TLS confidentiality required"; + rs->sr_text = op->o_tls_ssf + ? "stronger TLS confidentiality required" + : "TLS confidentiality required"; return rs->sr_err; } @@ -1022,7 +1041,9 @@ backend_check_restrictions( if( op->o_tag == LDAP_REQ_BIND && opdata == NULL ) { /* simple bind specific check */ if( op->o_ssf < ssf->sss_simple_bind ) { - rs->sr_text = "confidentiality required"; + rs->sr_text = op->o_ssf + ? "stronger confidentiality required" + : "confidentiality required"; return rs->sr_err; } } @@ -1031,34 +1052,46 @@ backend_check_restrictions( /* these checks don't apply to SASL bind */ if( op->o_sasl_ssf < ssf->sss_sasl ) { - rs->sr_text = "SASL confidentiality required"; + rs->sr_text = op->o_sasl_ssf + ? "stronger SASL confidentiality required" + : "SASL confidentiality required"; return rs->sr_err; } if( op->o_ssf < ssf->sss_ssf ) { - rs->sr_text = "confidentiality required"; + rs->sr_text = op->o_ssf + ? "stronger confidentiality required" + : "confidentiality required"; return rs->sr_err; } } if( updateop ) { if( op->o_transport_ssf < ssf->sss_update_transport ) { - rs->sr_text = "transport update confidentiality required"; + rs->sr_text = op->o_transport_ssf + ? "stronger transport confidentiality required for update" + : "transport confidentiality required for update"; return rs->sr_err; } if( op->o_tls_ssf < ssf->sss_update_tls ) { - rs->sr_text = "TLS update confidentiality required"; + rs->sr_text = op->o_tls_ssf + ? "stronger TLS confidentiality required for update" + : "TLS confidentiality required for update"; return rs->sr_err; } if( op->o_sasl_ssf < ssf->sss_update_sasl ) { - rs->sr_text = "SASL update confidentiality required"; + rs->sr_text = op->o_sasl_ssf + ? "stronger SASL confidentiality required for update" + : "SASL confidentiality required for update"; return rs->sr_err; } if( op->o_ssf < ssf->sss_update_ssf ) { - rs->sr_text = "update confidentiality required"; + rs->sr_text = op->o_ssf + ? "stronger confidentiality required for update" + : "confidentiality required for update"; return rs->sr_err; } @@ -1137,7 +1170,9 @@ backend_check_restrictions( #ifdef SLAP_X_LISTENER_MOD if ( !starttls && op->o_dn.bv_len == 0 ) { - if ( op->o_conn->c_listener && ! ( op->o_conn->c_listener->sl_perms & S_IXOTH ) ) { + if ( op->o_conn->c_listener && + !( op->o_conn->c_listener->sl_perms & S_IXOTH )) + { /* no "x" mode means bind required */ rs->sr_text = "bind required on this listener"; rs->sr_err = LDAP_STRONG_AUTH_REQUIRED; @@ -1146,7 +1181,10 @@ backend_check_restrictions( } if ( !starttls && !updateop ) { - if ( op->o_conn->c_listener && ! ( op->o_conn->c_listener->sl_perms & ( op->o_dn.bv_len > 0 ? S_IRUSR : S_IROTH ) ) ) { + if ( op->o_conn->c_listener && + !( op->o_conn->c_listener->sl_perms & + ( op->o_dn.bv_len > 0 ? S_IRUSR : S_IROTH ))) + { /* no "r" mode means no read */ rs->sr_text = "read not allowed on this listener"; rs->sr_err = LDAP_UNWILLING_TO_PERFORM; @@ -1157,9 +1195,12 @@ backend_check_restrictions( } - if( restrictops & opflag ) { - if( restrictops == SLAP_RESTRICT_OP_READS ) { + if( ( restrictops & opflag ) + || ( exopflag && ( restrictops & exopflag ) ) ) { + if( ( restrictops & SLAP_RESTRICT_OP_MASK) == SLAP_RESTRICT_OP_READS ) { rs->sr_text = "read operations restricted"; + } else if ( restrictops & exopflag ) { + rs->sr_text = "extended operation restricted"; } else { rs->sr_text = "operation restricted"; } @@ -1217,8 +1258,7 @@ backend_group( struct berval *gr_ndn, struct berval *op_ndn, ObjectClass *group_oc, - AttributeDescription *group_at -) + AttributeDescription *group_at ) { Entry *e; Attribute *a; @@ -1250,12 +1290,25 @@ backend_group( rc = be_entry_get_rw(op, gr_ndn, group_oc, group_at, 0, &e ); } if ( e ) { +#ifdef LDAP_SLAPI + if ( op->o_pb != NULL ) { + init_group_pblock( op, target, e, op_ndn, group_at ); + + rc = call_group_preop_plugins( op ); + if ( rc == LDAP_SUCCESS ) { + goto done; + } + } +#endif /* LDAP_SLAPI */ + a = attr_find( e->e_attrs, group_at ); if ( a ) { /* If the attribute is a subtype of labeledURI, treat this as * a dynamic group ala groupOfURLs */ - if (is_at_subtype( group_at->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) { + if (is_at_subtype( group_at->ad_type, + slap_schema.si_ad_labeledURI->ad_type ) ) + { int i; LDAPURLDesc *ludp; struct berval bv, nbase; @@ -1273,17 +1326,25 @@ backend_group( if ( rc == 0 ) { rc = 1; for (i=0; a->a_vals[i].bv_val; i++) { - if ( ldap_url_parse( a->a_vals[i].bv_val, &ludp ) != LDAP_SUCCESS ) + if ( ldap_url_parse( a->a_vals[i].bv_val, &ludp ) != + LDAP_SUCCESS ) + { continue; + } nbase.bv_val = NULL; /* host part must be empty */ /* attrs and extensions parts must be empty */ - if (( ludp->lud_host && *ludp->lud_host ) - || ludp->lud_attrs || ludp->lud_exts ) + if (( ludp->lud_host && *ludp->lud_host ) || + ludp->lud_attrs || ludp->lud_exts ) + { goto loopit; + } ber_str2bv( ludp->lud_dn, 0, 0, &bv ); - if ( dnNormalize( 0, NULL, NULL, &bv, &nbase, op->o_tmpmemctx ) != LDAP_SUCCESS ) + if ( dnNormalize( 0, NULL, NULL, &bv, &nbase, + op->o_tmpmemctx ) != LDAP_SUCCESS ) + { goto loopit; + } switch(ludp->lud_scope) { case LDAP_SCOPE_BASE: if ( !dn_match( &nbase, op_ndn )) goto loopit; @@ -1306,13 +1367,14 @@ backend_group( } filter = str2filter_x( op, ludp->lud_filter ); if ( filter ) { - if ( test_filter( NULL, user, filter ) == LDAP_COMPARE_TRUE ) + if ( test_filter( NULL, user, filter ) == + LDAP_COMPARE_TRUE ) { rc = 0; } filter_free_x( op, filter ); } - loopit: +loopit: ldap_free_urldesc( ludp ); if ( nbase.bv_val ) { op->o_tmpfree( nbase.bv_val, op->o_tmpmemctx ); @@ -1340,8 +1402,13 @@ backend_group( rc = LDAP_NO_SUCH_OBJECT; } +#ifdef LDAP_SLAPI + if ( op->o_pb ) call_group_postop_plugins( op ); +#endif /* LDAP_SLAPI */ + if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache ) { - g = op->o_tmpalloc(sizeof(GroupAssertion) + gr_ndn->bv_len, op->o_tmpmemctx); + g = op->o_tmpalloc(sizeof(GroupAssertion) + gr_ndn->bv_len, + op->o_tmpmemctx); g->ga_be = op->o_bd; g->ga_oc = group_oc; g->ga_at = group_at; @@ -1356,14 +1423,65 @@ done: return rc; } +#ifdef LDAP_SLAPI +static int backend_compute_output_attr(computed_attr_context *c, Slapi_Attr *a, Slapi_Entry *e) +{ + BerVarray v; + int rc; + BerVarray *vals = (BerVarray *)c->cac_private; + Operation *op = NULL; + int i, j; + + slapi_pblock_get( c->cac_pb, SLAPI_OPERATION, &op ); + if ( op == NULL ) { + return 1; + } + + if ( op->o_conn && access_allowed( op, + e, a->a_desc, NULL, ACL_AUTH, + &c->cac_acl_state ) == 0 ) { + return 1; + } + + for ( i=0; a->a_vals[i].bv_val; i++ ) ; + + v = op->o_tmpalloc( sizeof(struct berval) * (i+1), + op->o_tmpmemctx ); + for ( i=0,j=0; a->a_vals[i].bv_val; i++ ) { + if ( op->o_conn && access_allowed( op, + e, a->a_desc, + &a->a_nvals[i], + ACL_AUTH, &c->cac_acl_state ) == 0 ) { + continue; + } + ber_dupbv_x( &v[j], + &a->a_nvals[i], op->o_tmpmemctx ); + if (v[j].bv_val ) j++; + } + + if (j == 0) { + op->o_tmpfree( v, op->o_tmpmemctx ); + *vals = NULL; + rc = 1; + } else { + v[j].bv_val = NULL; + v[j].bv_len = 0; + *vals = v; + rc = 0; + } + + return rc; +} +#endif /* LDAP_SLAPI */ + int backend_attribute( Operation *op, Entry *target, struct berval *edn, AttributeDescription *entry_at, - BerVarray *vals -) + BerVarray *vals, + slap_access_t access ) { Entry *e; Attribute *a; @@ -1384,8 +1502,8 @@ backend_attribute( if ( a ) { BerVarray v; - if ( op->o_conn && access_allowed( op, - e, entry_at, NULL, ACL_AUTH, + if ( op->o_conn && access > ACL_NONE && access_allowed( op, + e, entry_at, NULL, access, &acl_state ) == 0 ) { rc = LDAP_INSUFFICIENT_ACCESS; goto freeit; @@ -1393,12 +1511,13 @@ backend_attribute( for ( i=0; a->a_vals[i].bv_val; i++ ) ; - v = op->o_tmpalloc( sizeof(struct berval) * (i+1), op->o_tmpmemctx ); + v = op->o_tmpalloc( sizeof(struct berval) * (i+1), + op->o_tmpmemctx ); for ( i=0,j=0; a->a_vals[i].bv_val; i++ ) { - if ( op->o_conn && access_allowed( op, + if ( op->o_conn && access > ACL_NONE && access_allowed( op, e, entry_at, &a->a_nvals[i], - ACL_AUTH, &acl_state ) == 0 ) { + access, &acl_state ) == 0 ) { continue; } ber_dupbv_x( &v[j], @@ -1416,6 +1535,27 @@ backend_attribute( rc = LDAP_SUCCESS; } } +#ifdef LDAP_SLAPI + else if ( op->o_pb ) { + /* try any computed attributes */ + computed_attr_context ctx; + AttributeName aname; + + 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_acl_state = acl_state; + ctx.cac_private = (void *)vals; + + if ( compute_evaluator( &ctx, entry_at->ad_cname.bv_val, e, backend_compute_output_attr ) == 1) + rc = LDAP_INSUFFICIENT_ACCESS; + else + rc = LDAP_SUCCESS; + } +#endif /* LDAP_SLAPI */ freeit: if (e != target ) { be_entry_release_r( op, e ); } @@ -1425,28 +1565,93 @@ freeit: if (e != target ) { return rc; } -Attribute *backend_operational( +int backend_operational( Operation *op, - SlapReply *rs, - int opattrs ) + SlapReply *rs ) { - Attribute *a = NULL, **ap = &a; + Attribute **ap; + int rc = 0; + + for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) + /* just count them */ ; /* * If operational attributes (allegedly) are required, * and the backend supports specific operational attributes, * add them to the attribute list */ - if ( opattrs || ( op->ors_attrs && - ad_inlist( slap_schema.si_ad_subschemaSubentry, op->ors_attrs )) ) { + if ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( op->ors_attrs && + ad_inlist( slap_schema.si_ad_entryDN, op->ors_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 ))) + { *ap = slap_operational_subschemaSubentry( op->o_bd ); ap = &(*ap)->a_next; } - if ( ( opattrs || op->ors_attrs ) && op->o_bd && op->o_bd->be_operational != NULL ) { - ( void )op->o_bd->be_operational( op, rs, opattrs, ap ); + if (( SLAP_OPATTRS( rs->sr_attr_flags ) || op->ors_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 */ ; } - return a; + return rc; +} + +#ifdef LDAP_SLAPI +static void init_group_pblock( Operation *op, Entry *target, + Entry *e, struct berval *op_ndn, AttributeDescription *group_at ) +{ + slapi_int_pblock_set_operation( op->o_pb, op ); + + slapi_pblock_set( op->o_pb, + SLAPI_X_GROUP_ENTRY, (void *)e ); + slapi_pblock_set( op->o_pb, + SLAPI_X_GROUP_OPERATION_DN, (void *)op_ndn->bv_val ); + slapi_pblock_set( op->o_pb, + SLAPI_X_GROUP_ATTRIBUTE, (void *)group_at->ad_cname.bv_val ); + slapi_pblock_set( op->o_pb, + SLAPI_X_GROUP_TARGET_ENTRY, (void *)target ); +} + +static int call_group_preop_plugins( Operation *op ) +{ + int rc; + + rc = slapi_int_call_plugins( op->o_bd, + SLAPI_X_PLUGIN_PRE_GROUP_FN, op->o_pb ); + if ( rc < 0 ) { + if (( slapi_pblock_get( op->o_pb, SLAPI_RESULT_CODE, + (void *)&rc ) != 0 ) || rc == LDAP_SUCCESS ) + { + rc = LDAP_NO_SUCH_ATTRIBUTE; + } + } else { + rc = LDAP_SUCCESS; + } + + return rc; +} + +static void call_group_postop_plugins( Operation *op ) +{ + (void) slapi_int_call_plugins( op->o_bd, SLAPI_X_PLUGIN_POST_GROUP_FN, op->o_pb ); } +#endif /* LDAP_SLAPI */