From 7d101bcd9801fcfcc67fb0b20a3dd4127a3a4cdc Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Wed, 2 Feb 2005 18:32:43 +0000 Subject: [PATCH] Sync with HEAD ready for 1alpha release --- build/version.var | 8 +- doc/man/man5/slapd-ldap.5 | 29 +++- doc/man/man5/slapo-glue.5 | 8 +- libraries/libldap/os-ip.c | 11 +- servers/slapd/back-bdb/idl.c | 8 +- servers/slapd/back-bdb/init.c | 1 - servers/slapd/back-dnssrv/init.c | 18 ++- servers/slapd/back-dnssrv/referral.c | 10 +- servers/slapd/back-dnssrv/search.c | 79 +++++------ servers/slapd/back-ldap/back-ldap.h | 1 + servers/slapd/back-ldap/bind.c | 15 +- servers/slapd/back-ldap/chain.c | 25 +++- servers/slapd/back-ldap/config.c | 24 +++- servers/slapd/back-ldap/init.c | 3 + servers/slapd/back-ldap/search.c | 4 +- servers/slapd/back-ldbm/init.c | 1 - servers/slapd/back-monitor/init.c | 1 - servers/slapd/back-relay/init.c | 9 +- servers/slapd/back-sql/init.c | 3 - servers/slapd/backend.c | 199 ++++++++++++++++----------- servers/slapd/backover.c | 82 +++++++++-- servers/slapd/compare.c | 6 +- servers/slapd/config.h | 46 +++---- servers/slapd/controls.c | 21 +-- servers/slapd/frontend.c | 21 ++- servers/slapd/init.c | 4 +- servers/slapd/overlays/glue.c | 84 ++++++++++- servers/slapd/overlays/refint.c | 1 + servers/slapd/overlays/rwm.c | 24 ++-- servers/slapd/overlays/unique.c | 1 + servers/slapd/proto-slap.h | 5 +- servers/slapd/result.c | 6 +- servers/slapd/root_dse.c | 2 +- servers/slapd/schema_init.c | 4 +- servers/slapd/slap.h | 33 +++-- servers/slapd/slapadd.c | 1 + tests/scripts/defines.sh | 8 +- tests/scripts/test032-chain | 25 +++- 38 files changed, 571 insertions(+), 260 deletions(-) diff --git a/build/version.var b/build/version.var index 598c9009bd..3c6fb5bc5c 100644 --- a/build/version.var +++ b/build/version.var @@ -15,9 +15,9 @@ ol_package=OpenLDAP ol_major=2 ol_minor=3 -ol_patch=X -ol_api_inc=20300 +ol_patch=1alpha +ol_api_inc=20301 ol_api_current=0 -ol_api_revision=0 +ol_api_revision=1 ol_api_age=0 -ol_release_date="2004/12/31" +ol_release_date="2005/02/02" diff --git a/doc/man/man5/slapd-ldap.5 b/doc/man/man5/slapd-ldap.5 index 893861c504..c9253f9d1f 100644 --- a/doc/man/man5/slapd-ldap.5 +++ b/doc/man/man5/slapd-ldap.5 @@ -47,7 +47,7 @@ Other database options are described in the .BR slapd.conf (5) manual page. .LP -Note: It is strongly recommended to set +Note: In early versions of back-ldap it was recommended to always set .LP .RS .nf @@ -63,6 +63,8 @@ database. This is because operational attributes related to entry creation and modification should not be used, as they could be passed to the target servers, generating an error. +The current implementation automatically sets ldapmod to off, so its use +is redundant and can be safely omitted. .TP .B uri LDAP server to use. Multiple URIs can be set in in a single @@ -234,7 +236,30 @@ in conjunction with Proxy Authorization. .TP .B rebind-as-user If this option is given, the client's bind credentials are remembered -for rebinds when chasing referrals. +for rebinds when chasing referrals. Useful in conjunction with +\fBchase-referrals\fP, useless if \fBdont-chase-referrals\fP is set. +.LP +.B chase-referrals +.br +.B dont-chase-referrals +.RS +enable/disable automatic referral chasing, which is delegated to the +underlying libldap, with rebinding eventually performed if the +\fBrebind-as-user\fP directive is used. The default is to chase referrals. +.RE + +.LP +.B start-tls +.br +.B try-start-tls +.RS +execute the start TLS extended operation when the connection is initialized. +\fBtry-start-tls\fP continues operations if start TLS fails. +.RE + + + + .TP .\".B suffixmassage .\"DNs ending with in a request are changed to end with [async] +.B glue-sub [async] [advertise] Specify the suffix of a database to attach as a subordinate to the root database. The specified database must have already been configured. If the -optional "async" keyword is supplied, searches against this database may -be spawned in a separate thread to run concurrently with other operations. +optional \fBasync\fP keyword is supplied, searches against this database may +be spawned in a separate thread to run concurrently with other operations +(currently not implemented). If the optional \fBadvertise\fI flag +is supplied, the naming context is advertised in the rootDSE. .SH FILES .TP ETCDIR/slapd.conf diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index dad33ed000..ae5225ca00 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -291,15 +291,16 @@ ldap_pvt_connect(LDAP *ld, ber_socket_t s, return rc; } #endif - FD_ZERO(&wfds); - FD_SET(s, &wfds ); + + do { + FD_ZERO(&wfds); + FD_SET(s, &wfds ); #ifdef HAVE_WINSOCK - FD_ZERO(&efds); - FD_SET(s, &efds ); + FD_ZERO(&efds); + FD_SET(s, &efds ); #endif - do { rc = select(ldap_int_tblsize, z, &wfds, #ifdef HAVE_WINSOCK &efds, diff --git a/servers/slapd/back-bdb/idl.c b/servers/slapd/back-bdb/idl.c index 29a337218d..038de21ef2 100644 --- a/servers/slapd/back-bdb/idl.c +++ b/servers/slapd/back-bdb/idl.c @@ -292,6 +292,7 @@ bdb_idl_cache_get( { bdb_idl_cache_entry_t idl_tmp; bdb_idl_cache_entry_t *matched_idl_entry; + int rc = LDAP_NO_SUCH_OBJECT; DBT2bv( key, &idl_tmp.kstr ); idl_tmp.db = db; @@ -301,19 +302,18 @@ bdb_idl_cache_get( if ( matched_idl_entry != NULL ) { if ( matched_idl_entry->idl && ids ) BDB_IDL_CPY( ids, matched_idl_entry->idl ); - ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock ); ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); IDL_LRU_DELETE( bdb, matched_idl_entry ); IDL_LRU_ADD( bdb, matched_idl_entry ); ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); if ( matched_idl_entry->idl ) - return LDAP_SUCCESS; + rc = LDAP_SUCCESS; else - return DB_NOTFOUND; + rc = DB_NOTFOUND; } ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock ); - return LDAP_NO_SUCH_OBJECT; + return rc; } void diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 32892d6014..39e9239092 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -472,7 +472,6 @@ bdb_back_initialize( #ifdef LDAP_CONTROL_SUBENTRIES LDAP_CONTROL_SUBENTRIES, #endif - LDAP_CONTROL_VALUESRETURNFILTER, #ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY LDAP_CONTROL_X_PERMISSIVE_MODIFY, #endif diff --git a/servers/slapd/back-dnssrv/init.c b/servers/slapd/back-dnssrv/init.c index e3f26d4aa0..980d231200 100644 --- a/servers/slapd/back-dnssrv/init.c +++ b/servers/slapd/back-dnssrv/init.c @@ -34,13 +34,12 @@ dnssrv_back_initialize( { static char *controls[] = { LDAP_CONTROL_MANAGEDSAIT, - LDAP_CONTROL_VALUESRETURNFILTER, NULL }; bi->bi_controls = controls; - bi->bi_open = 0; + bi->bi_open = dnssrv_back_open; bi->bi_config = 0; bi->bi_close = 0; bi->bi_destroy = 0; @@ -71,6 +70,21 @@ dnssrv_back_initialize( return 0; } +AttributeDescription *ad_dc; +AttributeDescription *ad_associatedDomain; + +int +dnssrv_back_open( + BackendInfo *bi ) +{ + const char *text; + + (void)slap_str2ad( "dc", &ad_dc, &text ); + (void)slap_str2ad( "associatedDomain", &ad_associatedDomain, &text ); + + return 0; +} + int dnssrv_back_db_init( Backend *be ) diff --git a/servers/slapd/back-dnssrv/referral.c b/servers/slapd/back-dnssrv/referral.c index 76b3372227..77cd3fcc3f 100644 --- a/servers/slapd/back-dnssrv/referral.c +++ b/servers/slapd/back-dnssrv/referral.c @@ -41,7 +41,15 @@ dnssrv_back_referrals( char **hosts = NULL; BerVarray urls = NULL; - if( op->o_req_dn.bv_len == 0 ) { + if ( BER_BVISEMPTY( &op->o_req_dn ) ) { +#ifdef LDAP_DEVEL + /* FIXME: need some means to determine whether the database + * is a glue instance */ + if ( SLAP_GLUE_INSTANCE( op->o_bd ) ) { + return LDAP_SUCCESS; + } +#endif /* LDAP_DEVEL */ + rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed"; return LDAP_UNWILLING_TO_PERFORM; } diff --git a/servers/slapd/back-dnssrv/search.c b/servers/slapd/back-dnssrv/search.c index b191fca7fa..26fc1a32cd 100644 --- a/servers/slapd/back-dnssrv/search.c +++ b/servers/slapd/back-dnssrv/search.c @@ -47,11 +47,27 @@ dnssrv_back_search( rs->sr_ref = NULL; + if ( BER_BVISEMPTY( &op->o_req_ndn ) ) { +#ifdef LDAP_DEVEL + /* FIXME: need some means to determine whether the database + * is a glue instance; if we got here with empty DN, then + * we passed this same test in dnssrv_back_referrals() */ + if ( !SLAP_GLUE_INSTANCE( op->o_bd ) ) { + rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed"; + + } else { + rs->sr_err = LDAP_SUCCESS; + } + goto done; +#endif /* LDAP_DEVEL */ + } + manageDSAit = get_manageDSAit( op ); /* * FIXME: we may return a referral if manageDSAit is not set */ - if ( ! manageDSAit ) { + if ( !manageDSAit ) { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "manageDSAit must be set" ); goto done; @@ -151,7 +167,6 @@ dnssrv_back_search( send_ldap_error( op, rs, LDAP_SUCCESS, NULL ); } else { - struct berval vals[2]; Entry *e = ch_calloc( 1, sizeof(Entry) ); AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; @@ -164,54 +179,36 @@ dnssrv_back_search( e->e_attrs = NULL; e->e_private = NULL; - vals[1].bv_val = NULL; - - vals[0].bv_val = "top"; - vals[0].bv_len = sizeof("top")-1; - attr_mergeit( e, ad_objectClass, vals ); - - vals[0].bv_val = "referral"; - vals[0].bv_len = sizeof("referral")-1; - attr_mergeit( e, ad_objectClass, vals ); + attr_mergeit_one( e, ad_objectClass, &slap_schema.si_oc_top->soc_cname ); + attr_mergeit_one( e, ad_objectClass, &slap_schema.si_oc_referral->soc_cname ); + attr_mergeit_one( e, ad_objectClass, &slap_schema.si_oc_extensibleObject->soc_cname ); - vals[0].bv_val = "extensibleObject"; - vals[0].bv_len = sizeof("extensibleObject")-1; - attr_mergeit( e, ad_objectClass, vals ); + if ( ad_dc ) { + char *p; + struct berval bv; - { - AttributeDescription *ad = NULL; - const char *text; + bv.bv_val = domain; - rc = slap_str2ad( "dc", &ad, &text ); + p = strchr( bv.bv_val, '.' ); + + if ( p == bv.bv_val ) { + bv.bv_len = 1; - if( rc == LDAP_SUCCESS ) { - char *p; - vals[0].bv_val = ch_strdup( domain ); + } else if ( p != NULL ) { + bv.bv_len = p - bv.bv_val; - p = strchr( vals[0].bv_val, '.' ); - - if( p == vals[0].bv_val ) { - vals[0].bv_val[1] = '\0'; - } else if ( p != NULL ) { - *p = '\0'; - } - - vals[0].bv_len = strlen(vals[0].bv_val); - attr_mergeit( e, ad, vals ); + } else { + bv.bv_len = strlen( bv.bv_val ); } - } - { - AttributeDescription *ad = NULL; - const char *text; + attr_mergeit_one( e, ad_dc, &bv ); + } - rc = slap_str2ad( "associatedDomain", &ad, &text ); + if ( ad_associatedDomain ) { + struct berval bv; - if( rc == LDAP_SUCCESS ) { - vals[0].bv_val = domain; - vals[0].bv_len = strlen(domain); - attr_mergeit( e, ad, vals ); - } + ber_str2bv( domain, 0, 0, &bv ); + attr_mergeit_one( e, ad_associatedDomain, &bv ); } attr_mergeit( e, ad_ref, urls ); diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index 174a7039c5..f881c38749 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -95,6 +95,7 @@ struct ldapinfo { #define LDAP_BACK_F_SAVECRED 0x01U #define LDAP_BACK_F_USE_TLS 0x02U #define LDAP_BACK_F_TLS_CRITICAL ( 0x04U | LDAP_BACK_F_USE_TLS ) +#define LDAP_BACK_F_CHASE_REFERRALS 0x8U Avlnode *conntree; int rwm_started; diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index bdf8078e2f..817235ee3a 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -68,7 +68,7 @@ ldap_back_bind( Operation *op, SlapReply *rs ) rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val, LDAP_SASL_SIMPLE, &op->orb_cred, op->o_ctrls, NULL, &msgid ); - rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDRESULT ); + rc = ldap_back_op_result( lc, op, rs, msgid, LDAP_BACK_SENDERR ); if ( rc == LDAP_SUCCESS ) { /* If defined, proxyAuthz will be used also when @@ -241,15 +241,12 @@ ldap_back_prepare_conn( struct ldapconn **lcp, Operation *op, SlapReply *rs, lda */ ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&vers ); - /* Set LDAP version. This will always succeed: If the client - * bound with a particular version, then so can we. - */ - ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, - (const void *)&vers ); - - /* FIXME: configurable? */ - ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON ); + /* automatically chase referrals ("chase-referrals"/"dont-chase-referrals" statement) */ + if ( li->flags & LDAP_BACK_F_CHASE_REFERRALS ) { + ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON ); + } + /* start TLS ("start-tls"/"try-start-tls" statements) */ if ( ( li->flags & LDAP_BACK_F_USE_TLS ) && !ldap_is_ldaps_url( li->url ) && ( rs->sr_err = ldap_start_tls_s( ld, NULL, NULL ) ) != LDAP_SUCCESS ) diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c index d481abb7a4..7dcb95f29f 100644 --- a/servers/slapd/back-ldap/chain.c +++ b/servers/slapd/back-ldap/chain.c @@ -614,6 +614,23 @@ ldap_chain_db_destroy( return rc; } +static int +ldap_chain_connection_destroy( + BackendDB *be, + Connection *conn +) +{ + slap_overinst *on = (slap_overinst *) be->bd_info; + void *private = be->be_private; + int rc; + + be->be_private = on->on_bi.bi_private; + rc = lback->bi_connection_destroy( be, conn ); + on->on_bi.bi_private = be->be_private; + be->be_private = private; + return rc; +} + #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR static int ldap_chain_parse_ctrl( @@ -766,18 +783,20 @@ chain_init( void ) #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; - + /* ... otherwise the underlying backend's function would be called, * likely passing an invalid entry; on the contrary, the requested * operational attributes should have been returned while chasing * the referrals. This all in all is a bit messy, because part - * of the operational attributes are generated by they backend; + * of the operational attributes are generated by the backend; * part by the frontend; back-ldap should receive all the available - * ones from the remote server, but then, on it own, it strips those + * ones from the remote server, but then, on its own, it strips those * it assumes will be (re)generated by the frontend (e.g. * subschemaSubentry.) */ ldapchain.on_bi.bi_operational = ldap_chain_operational; + ldapchain.on_bi.bi_connection_destroy = ldap_chain_connection_destroy; + ldapchain.on_response = ldap_chain_response; return overlay_register( &ldapchain ); diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index 470becaa3c..afd8f71204 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -289,12 +289,32 @@ ldap_back_db_config( } else if ( strcasecmp( argv[0], "rebind-as-user" ) == 0 ) { if ( argc != 1 ) { fprintf( stderr, - "%s: line %d: rebind-as-user takes no arguments\n", + "%s: line %d: \"rebind-as-user\" takes no arguments\n", fname, lineno ); return( 1 ); } li->flags |= LDAP_BACK_F_SAVECRED; - + + } else if ( strcasecmp( argv[0], "chase-referrals" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: \"chase-referrals\" takes no arguments\n", + fname, lineno ); + return( 1 ); + } + + li->flags |= LDAP_BACK_F_CHASE_REFERRALS; + + } else if ( strcasecmp( argv[0], "dont-chase-referrals" ) == 0 ) { + if ( argc != 1 ) { + fprintf( stderr, + "%s: line %d: \"dont-chase-referrals\" takes no arguments\n", + fname, lineno ); + return( 1 ); + } + + li->flags &= ~LDAP_BACK_F_CHASE_REFERRALS; + /* intercept exop_who_am_i? */ } else if ( strcasecmp( argv[0], "proxy-whoami" ) == 0 ) { if ( argc != 1 ) { diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index 84f47becbd..08767a4811 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -109,6 +109,9 @@ ldap_back_db_init( Backend *be ) /* by default, use proxyAuthz control on each operation */ li->idassert_flags = LDAP_BACK_AUTH_NONE; + /* initialize flags */ + li->flags = LDAP_BACK_F_CHASE_REFERRALS; + ldap_pvt_thread_mutex_init( &li->conn_mutex ); be->be_private = li; diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index cd84f8dcda..8c610a5798 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -573,8 +573,8 @@ ldap_back_entry_get( retry: rc = ldap_search_ext_s( lc->lc_ld, ndn->bv_val, LDAP_SCOPE_BASE, filter, - at ? gattr : NULL, 0, ctrls, NULL, LDAP_NO_LIMIT, - LDAP_NO_LIMIT, &result ); + at ? gattr : NULL, 0, ctrls, NULL, + LDAP_NO_LIMIT, LDAP_NO_LIMIT, &result ); if ( rc != LDAP_SUCCESS ) { if ( rc == LDAP_SERVER_DOWN && do_retry ) { do_retry = 0; diff --git a/servers/slapd/back-ldbm/init.c b/servers/slapd/back-ldbm/init.c index 424e621b16..85802bff9d 100644 --- a/servers/slapd/back-ldbm/init.c +++ b/servers/slapd/back-ldbm/init.c @@ -31,7 +31,6 @@ ldbm_back_initialize( { static char *controls[] = { LDAP_CONTROL_MANAGEDSAIT, - LDAP_CONTROL_VALUESRETURNFILTER, #ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY LDAP_CONTROL_X_PERMISSIVE_MODIFY, #endif diff --git a/servers/slapd/back-monitor/init.c b/servers/slapd/back-monitor/init.c index 437815779c..6fed315d2f 100644 --- a/servers/slapd/back-monitor/init.c +++ b/servers/slapd/back-monitor/init.c @@ -671,7 +671,6 @@ monitor_back_initialize( monitor_subsys_t *ms; static char *controls[] = { LDAP_CONTROL_MANAGEDSAIT, - LDAP_CONTROL_VALUESRETURNFILTER, NULL }; diff --git a/servers/slapd/back-relay/init.c b/servers/slapd/back-relay/init.c index d5a3d9ac15..d3b19e6d49 100644 --- a/servers/slapd/back-relay/init.c +++ b/servers/slapd/back-relay/init.c @@ -21,6 +21,7 @@ #include "portable.h" #include +#include #include "slap.h" #include "back-relay.h" @@ -102,15 +103,11 @@ relay_back_db_open( Backend *be ) assert( ri->ri_bd ); /* inherit controls */ - if ( ri->ri_bd->be_controls ) { - be->be_controls = ldap_charray_dup( ri->ri_bd->be_controls ); - } + AC_MEMCPY( be->be_ctrls, ri->ri_bd->be_ctrls, sizeof( be->be_ctrls ) ); } else { /* inherit all? */ - if ( frontendDB->be_controls ) { - be->be_controls = ldap_charray_dup( frontendDB->be_controls ); - } + AC_MEMCPY( be->be_ctrls, frontendDB->be_ctrls, sizeof( be->be_ctrls ) ); } return 0; diff --git a/servers/slapd/back-sql/init.c b/servers/slapd/back-sql/init.c index 69c72e85c7..4a236a1718 100644 --- a/servers/slapd/back-sql/init.c +++ b/servers/slapd/back-sql/init.c @@ -42,9 +42,6 @@ sql_back_initialize( #ifdef LDAP_CONTROL_X_TREE_DELETE LDAP_CONTROL_X_TREE_DELETE, #endif /* LDAP_CONTROL_X_TREE_DELETE */ -#ifdef LDAP_CONTROL_VALUESRETURNFILTER - LDAP_CONTROL_VALUESRETURNFILTER, -#endif /* LDAP_CONTROL_VALUESRETURNFILTER */ NULL }; diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 084a825688..daaf245439 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -65,6 +65,32 @@ 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; @@ -132,12 +158,15 @@ int backend_add(BackendInfo *aBackendInfo) 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 */ { @@ -161,65 +190,66 @@ int backend_add(BackendInfo *aBackendInfo) } } +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 ); } } @@ -273,8 +303,7 @@ int backend_startup(Backend *be) } 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", @@ -282,6 +311,8 @@ int backend_startup(Backend *be) return rc; } } + + (void)backend_init_controls( &backendInfo[i] ); } ldap_pvt_thread_mutex_init( &slapd_rq.rq_mutex ); @@ -448,9 +479,6 @@ int backend_destroy(void) 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 ); @@ -836,7 +864,7 @@ backend_connection_destroy( return 0; } -static int +int backend_check_controls( Operation *op, SlapReply *rs ) @@ -847,9 +875,9 @@ backend_check_controls( if( ctrls ) { for( ; *ctrls != NULL ; ctrls++ ) { int cid; - if( slap_find_control_id( (*ctrls)->ldctl_oid, &cid ) == - LDAP_CONTROL_NOT_FOUND ) - { + + switch ( slap_global_control( op, (*ctrls)->ldctl_oid, &cid ) ) { + case LDAP_CONTROL_NOT_FOUND: /* unrecognized control */ if ( (*ctrls)->ldctl_iscritical ) { /* should not be reachable */ @@ -858,27 +886,39 @@ backend_check_controls( (*ctrls)->ldctl_oid, 0, 0 ); assert( 0 ); } + break; - } else if ( !slap_global_control( op, (*ctrls)->ldctl_oid ) && - !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; + 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; } @@ -897,8 +937,18 @@ backend_check_restrictions( 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; } @@ -1759,18 +1809,7 @@ int backend_operational( 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; diff --git a/servers/slapd/backover.c b/servers/slapd/backover.c index 4f0082b0d6..f7e572071c 100644 --- a/servers/slapd/backover.c +++ b/servers/slapd/backover.c @@ -223,6 +223,7 @@ enum op_which { op_extended, op_aux_operational, op_aux_chk_referrals, + op_aux_chk_controls, op_last }; @@ -234,7 +235,7 @@ static int op_rc[] = { LDAP_UNWILLING_TO_PERFORM, /* bind */ LDAP_UNWILLING_TO_PERFORM, /* unbind */ LDAP_UNWILLING_TO_PERFORM, /* search */ - LDAP_UNWILLING_TO_PERFORM, /* compare */ + SLAP_CB_CONTINUE, /* compare; pass to frontend */ LDAP_UNWILLING_TO_PERFORM, /* modify */ LDAP_UNWILLING_TO_PERFORM, /* modrdn */ LDAP_UNWILLING_TO_PERFORM, /* add */ @@ -243,7 +244,8 @@ static int op_rc[] = { LDAP_UNWILLING_TO_PERFORM, /* cancel */ LDAP_UNWILLING_TO_PERFORM, /* extended */ LDAP_SUCCESS, /* aux_operational */ - LDAP_SUCCESS /* aux_chk_referrals */ + LDAP_SUCCESS, /* aux_chk_referrals */ + SLAP_CB_CONTINUE /* aux_chk_controls; pass to frontend */ }; static int @@ -377,6 +379,56 @@ over_aux_chk_referrals( Operation *op, SlapReply *rs ) return over_op_func( op, rs, op_aux_chk_referrals ); } +static int +over_aux_chk_controls( Operation *op, SlapReply *rs ) +{ + return over_op_func( op, rs, op_aux_chk_controls ); +} + +static int +over_connection_destroy( + BackendDB *bd, + Connection *conn +) +{ + slap_overinfo *oi; + slap_overinst *on; + BackendDB db; + int rc = SLAP_CB_CONTINUE; + + /* FIXME: used to happen for instance during abandon + * when global overlays are used... */ + assert( bd != NULL ); + + oi = bd->bd_info->bi_private; + on = oi->oi_list; + + if ( !SLAP_ISOVERLAY( bd )) { + db = *bd; + db.be_flags |= SLAP_DBFLAG_OVERLAY; + bd = &db; + } + + for (; on; on=on->on_next ) { + if ( on->on_bi.bi_connection_destroy ) { + bd->bd_info = (BackendInfo *)on; + rc = on->on_bi.bi_connection_destroy( bd, conn ); + if ( rc != SLAP_CB_CONTINUE ) break; + } + } + + if ( oi->oi_orig->bi_connection_destroy && rc == SLAP_CB_CONTINUE ) { + bd->bd_info = oi->oi_orig; + rc = oi->oi_orig->bi_connection_destroy( bd, conn ); + } + /* should not fall thru this far without anything happening... */ + if ( rc == SLAP_CB_CONTINUE ) { + rc = LDAP_UNWILLING_TO_PERFORM; + } + + return rc; +} + int overlay_register( slap_overinst *on @@ -472,6 +524,11 @@ overlay_register_control( BackendDB *be, const char *oid ) { int rc = 0; int gotit = 0; + int cid; + + if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) { + return -1; + } if ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_GLOBAL_OVERLAY ) { int i; @@ -484,23 +541,15 @@ overlay_register_control( BackendDB *be, const char *oid ) 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; - } - } + bd->be_ctrls[ cid ] = 1; + bd->be_ctrls[ SLAP_MAX_CIDS ] = 1; } } - if ( rc == 0 && !gotit && !ldap_charray_inlist( be->be_controls, oid ) ) { - rc = ldap_charray_add( &be->be_controls, oid ); - if ( rc ) { - return rc; - } + if ( rc == 0 && !gotit ) { + be->be_ctrls[ cid ] = 1; + be->be_ctrls[ SLAP_MAX_CIDS ] = 1; } return rc; @@ -569,6 +618,9 @@ overlay_config( BackendDB *be, const char *ov ) */ bi->bi_operational = over_aux_operational; bi->bi_chk_referrals = over_aux_chk_referrals; + bi->bi_chk_controls = over_aux_chk_controls; + + bi->bi_connection_destroy = over_connection_destroy; be->bd_info = bi; diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index 9c41d57d41..3541118d03 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -326,10 +326,14 @@ fe_op_compare( Operation *op, SlapReply *rs ) } } else if ( op->o_bd->be_compare ) { - op->o_bd->be_compare( op, rs ); + rs->sr_err = op->o_bd->be_compare( op, rs ); #endif /* ! SLAP_COMPARE_IN_FRONTEND */ } else { + rs->sr_err = SLAP_CB_CONTINUE; + } + + if ( rs->sr_err == SLAP_CB_CONTINUE ) { /* do our best to compare that AVA * * NOTE: this code is used only diff --git a/servers/slapd/config.h b/servers/slapd/config.h index 0abd270013..acc04f7a93 100644 --- a/servers/slapd/config.h +++ b/servers/slapd/config.h @@ -28,31 +28,31 @@ typedef struct config_table_s { void *notify; } ConfigTable; -#define ARGS_USERLAND 0x0000ffffL -#define ARGS_TYPES 0x00ff0000L -#define ARGS_POINTER 0x001f0000L -#define ARGS_NUMERIC 0x000f0000L -#define ARG_INT 0x00010000L -#define ARG_LONG 0x00020000L -#define ARG_BER_LEN_T 0x00040000L -#define ARG_ON_OFF 0x00080000L -#define ARG_STRING 0x00100000L -#define ARG_BERVAL 0x00200000L /* XXX not yet */ -#define ARG_EXISTS 0x00400000L /* XXX not yet */ -#define ARG_IGNORED 0x00800000L +#define ARGS_USERLAND 0x0000ffff +#define ARGS_TYPES 0x00ff0000 +#define ARGS_POINTER 0x001f0000 +#define ARGS_NUMERIC 0x000f0000 +#define ARG_INT 0x00010000 +#define ARG_LONG 0x00020000 +#define ARG_BER_LEN_T 0x00040000 +#define ARG_ON_OFF 0x00080000 +#define ARG_STRING 0x00100000 +#define ARG_BERVAL 0x00200000 /* XXX not yet */ +#define ARG_EXISTS 0x00400000 /* XXX not yet */ +#define ARG_IGNORED 0x00800000 -#define ARGS_SYNTAX 0xff000000L -#define ARG_DB 0x01000000L -#define ARG_PRE_DB 0x02000000L -#define ARG_PAREN 0x04000000L -#define ARG_NONZERO 0x08000000L -#define ARG_UNIQUE 0x10000000L /* XXX not yet */ -#define ARG_SPECIAL 0x20000000L /* one special case */ -#define ARG_OFFSET 0x40000000L -#define ARG_MAGIC 0x80000000L +#define ARGS_SYNTAX 0xff000000 +#define ARG_DB 0x01000000 +#define ARG_PRE_DB 0x02000000 +#define ARG_PAREN 0x04000000 +#define ARG_NONZERO 0x08000000 +#define ARG_UNIQUE 0x10000000 /* XXX not yet */ +#define ARG_SPECIAL 0x20000000 /* one special case */ +#define ARG_OFFSET 0x40000000 +#define ARG_MAGIC 0x80000000 -#define ARG_BAD_CONF 0xdead0000L /* overload return values */ -#define ARG_UNKNOWN 0xc0de0000L +#define ARG_BAD_CONF 0xdead0000 /* overload return values */ +#define ARG_UNKNOWN 0xc0de0000 typedef struct config_args_s { int argc; diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index c201273eb5..f67c7e8f81 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -106,7 +106,7 @@ static struct slap_control control_defs[] = { parsePostRead, LDAP_SLIST_ENTRY_INITIALIZER(next) }, { LDAP_CONTROL_VALUESRETURNFILTER, (int)offsetof(struct slap_control_ids, sc_valuesReturnFilter), - SLAP_CTRL_SEARCH, NULL, + SLAP_CTRL_GLOBAL|SLAP_CTRL_SEARCH, NULL, parseValuesReturnFilter, LDAP_SLIST_ENTRY_INITIALIZER(next) }, { LDAP_CONTROL_PAGEDRESULTS, (int)offsetof(struct slap_control_ids, sc_pagedResults), @@ -381,7 +381,7 @@ slap_find_control_id( } int -slap_global_control( Operation *op, const char *oid ) +slap_global_control( Operation *op, const char *oid, int *cid ) { struct slap_control *ctrl = find_ctrl( oid ); @@ -390,22 +390,23 @@ slap_global_control( Operation *op, const char *oid ) Debug( LDAP_DEBUG_ANY, "slap_global_control: unrecognized control: %s\n", oid, 0, 0 ); - assert( 0 ); - return 0; + return LDAP_CONTROL_NOT_FOUND; } - if ( ctrl->sc_mask & SLAP_CTRL_GLOBAL ) return 1; + if ( cid ) *cid = ctrl->sc_cid; - if (( op->o_tag & LDAP_REQ_SEARCH ) && - ( ctrl->sc_mask & SLAP_CTRL_GLOBAL_SEARCH )) + if ( ( ctrl->sc_mask & SLAP_CTRL_GLOBAL ) || + ( ( op->o_tag & LDAP_REQ_SEARCH ) && + ( ctrl->sc_mask & SLAP_CTRL_GLOBAL_SEARCH ) ) ) { - return 1; + return LDAP_COMPARE_TRUE; } - Debug( LDAP_DEBUG_ANY, + Debug( LDAP_DEBUG_TRACE, "slap_global_control: unavailable control: %s\n", oid, 0, 0 ); - return 0; + + return LDAP_COMPARE_FALSE; } void slap_free_ctrls( diff --git a/servers/slapd/frontend.c b/servers/slapd/frontend.c index bf9635b875..f9cfe6f466 100644 --- a/servers/slapd/frontend.c +++ b/servers/slapd/frontend.c @@ -86,8 +86,25 @@ frontend_init( void ) frontendDB->bd_info->bi_type = "frontend"; /* known controls */ - frontendDB->bd_info->bi_controls = slap_known_controls; - frontendDB->be_controls = ldap_charray_dup( slap_known_controls ); + if ( slap_known_controls ) { + int i; + + frontendDB->bd_info->bi_controls = slap_known_controls; + + for ( i = 0; slap_known_controls[ i ]; i++ ) { + int cid; + + if ( slap_find_control_id( slap_known_controls[ i ], &cid ) + == LDAP_CONTROL_NOT_FOUND ) + { + assert( 0 ); + return -1; + } + + frontendDB->bd_info->bi_ctrls[ cid ] = 1; + frontendDB->be_ctrls[ cid ] = 1; + } + } /* calls */ frontendDB->bd_info->bi_op_abandon = fe_op_abandon; diff --git a/servers/slapd/init.c b/servers/slapd/init.c index 1c34f10d3e..e606e3da9e 100644 --- a/servers/slapd/init.c +++ b/servers/slapd/init.c @@ -126,8 +126,8 @@ slap_init( int mode, const char *name ) ldap_pvt_mp_init( slap_counters.sc_entries ); ldap_pvt_mp_init( slap_counters.sc_refs ); - ldap_pvt_mp_init( slap_counters.sc_ops_completed ); ldap_pvt_mp_init( slap_counters.sc_ops_initiated ); + ldap_pvt_mp_init( slap_counters.sc_ops_completed ); #ifdef SLAPD_MONITOR for ( i = 0; i < SLAP_OP_LAST; i++ ) { @@ -239,8 +239,8 @@ int slap_destroy(void) ldap_pvt_mp_clear( slap_counters.sc_pdu ); ldap_pvt_mp_clear( slap_counters.sc_entries ); ldap_pvt_mp_clear( slap_counters.sc_refs ); - ldap_pvt_mp_clear( slap_counters.sc_ops_completed ); ldap_pvt_mp_clear( slap_counters.sc_ops_initiated ); + ldap_pvt_mp_clear( slap_counters.sc_ops_completed ); #ifdef SLAPD_MONITOR for ( i = 0; i < SLAP_OP_LAST; i++ ) { diff --git a/servers/slapd/overlays/glue.c b/servers/slapd/overlays/glue.c index c5852e8914..a09176e5c7 100644 --- a/servers/slapd/overlays/glue.c +++ b/servers/slapd/overlays/glue.c @@ -193,6 +193,58 @@ glue_op_func ( Operation *op, SlapReply *rs ) return rc; } +static int +glue_chk_referrals ( Operation *op, SlapReply *rs ) +{ + slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + glueinfo *gi = (glueinfo *)on->on_bi.bi_private; + BackendDB *b0 = op->o_bd; + BackendInfo *bi0 = op->o_bd->bd_info; + int rc; + + op->o_bd = glue_back_select (b0, &op->o_req_ndn); + b0->bd_info = on->on_info->oi_orig; + + if ( op->o_bd->bd_info->bi_chk_referrals ) + rc = ( *op->o_bd->bd_info->bi_chk_referrals )( op, rs ); + else + rc = SLAP_CB_CONTINUE; + + op->o_bd = b0; + op->o_bd->bd_info = bi0; + return rc; +} + +static int +glue_chk_controls ( Operation *op, SlapReply *rs ) +{ + slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; + glueinfo *gi = (glueinfo *)on->on_bi.bi_private; + BackendDB *b0 = op->o_bd; + BackendInfo *bi0 = op->o_bd->bd_info; + int rc = SLAP_CB_CONTINUE; + + op->o_bd = glue_back_select (b0, &op->o_req_ndn); + b0->bd_info = on->on_info->oi_orig; + + /* if the subordinate database has overlays, the bi_chk_controls() + * hook is actually over_aux_chk_controls(); in case it actually + * wraps a missing hok, we need to mimic the behavior + * of the frontend applied to that database */ + if ( op->o_bd->bd_info->bi_chk_controls ) { + rc = ( *op->o_bd->bd_info->bi_chk_controls )( op, rs ); + } + + + if ( rc == SLAP_CB_CONTINUE ) { + rc = backend_check_controls( op, rs ); + } + + op->o_bd = b0; + op->o_bd->bd_info = bi0; + return rc; +} + static int glue_op_search ( Operation *op, SlapReply *rs ) { @@ -326,6 +378,9 @@ glue_op_search ( Operation *op, SlapReply *rs ) case LDAP_TIMELIMIT_EXCEEDED: case LDAP_ADMINLIMIT_EXCEEDED: case LDAP_NO_SUCH_OBJECT: +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR + case LDAP_CANNOT_CHAIN: +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ goto end_of_loop; default: @@ -679,6 +734,8 @@ glue_db_open ( int i; for ( i=0; igi_nodes; i++ ) { + int j; + gi->gi_n[i].gn_be = backendDB + gi->gi_n[i].gn_bx; } return 0; @@ -707,23 +764,30 @@ glue_db_config( slap_overinst *on = (slap_overinst *)be->bd_info; glueinfo *gi = (glueinfo *)on->on_bi.bi_private; + /* redundant; could be applied just once */ + SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLUE_INSTANCE; + if ( strcasecmp( argv[0], "glue-sub" ) == 0 ) { - int async = 0; + int i, async = 0, advertise = 0; BackendDB *b2; struct berval bv, dn; gluenode *gn; if ( argc < 2 ) { fprintf( stderr, "%s: line %d: too few arguments in " - "\"glue-sub [async]\"\n", fname, lineno ); + "\"glue-sub [async] [advertise]\"\n", fname, lineno ); return -1; } - if ( argc == 3 ) { - if ( strcasecmp( argv[2], "async" )) { - fprintf( stderr, "%s: line %d: unrecognized option " - "\"%s\" ignored.\n", fname, lineno, argv[2] ); - } else { + for ( i = 2; i < argc; i++ ) { + if ( strcasecmp( argv[i], "async" ) == 0 ) { async = 1; + + } else if ( strcasecmp( argv[i], "advertise" ) == 0 ) { + advertise = 1; + + } else { + fprintf( stderr, "%s: line %d: unrecognized option " + "\"%s\" ignored.\n", fname, lineno, argv[i] ); } } ber_str2bv( argv[1], 0, 0, &bv ); @@ -738,6 +802,9 @@ glue_db_config( return -1; } SLAP_DBFLAGS(b2) |= SLAP_DBFLAG_GLUE_SUBORDINATE; + if ( advertise ) { + SLAP_DBFLAGS(b2) |= SLAP_DBFLAG_GLUE_ADVERTISE; + } gi = (glueinfo *)ch_realloc( gi, sizeof(glueinfo) + gi->gi_nodes * sizeof(gluenode)); gi->gi_n[gi->gi_nodes].gn_bx = b2 - backendDB; @@ -767,6 +834,9 @@ glue_init() glue.on_bi.bi_op_add = glue_op_func; glue.on_bi.bi_op_delete = glue_op_func; + glue.on_bi.bi_chk_referrals = glue_chk_referrals; + glue.on_bi.bi_chk_controls = glue_chk_controls; + return overlay_register( &glue ); } diff --git a/servers/slapd/overlays/refint.c b/servers/slapd/overlays/refint.c index 4f522d789c..ff6cb83350 100644 --- a/servers/slapd/overlays/refint.c +++ b/servers/slapd/overlays/refint.c @@ -551,6 +551,7 @@ refint_response( nop.o_tag = LDAP_REQ_SEARCH; nop.ors_scope = LDAP_SCOPE_SUBTREE; nop.ors_deref = LDAP_DEREF_NEVER; + nop.ors_limit = NULL; nop.ors_slimit = SLAP_NO_LIMIT; nop.ors_tlimit = SLAP_NO_LIMIT; diff --git a/servers/slapd/overlays/rwm.c b/servers/slapd/overlays/rwm.c index d9ca042554..00227172c6 100644 --- a/servers/slapd/overlays/rwm.c +++ b/servers/slapd/overlays/rwm.c @@ -785,7 +785,7 @@ rwm_matched( Operation *op, SlapReply *rs ) } static int -rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first ) +rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; struct ldaprwmap *rwmap = @@ -852,11 +852,13 @@ rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first ) } if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) { - /* will be generated by frontend */ - goto cleanup_attr; - } - - if ( !isupdate && (*ap)->a_desc->ad_type->sat_no_user_mod + if ( stripEntryDN ) { + /* will be generated by frontend */ + goto cleanup_attr; + } + + } else if ( !isupdate + && (*ap)->a_desc->ad_type->sat_no_user_mod && (*ap)->a_desc->ad_type != slap_schema.si_at_undefined ) { goto next_attr; @@ -1029,7 +1031,13 @@ rwm_send_entry( Operation *op, SlapReply *rs ) /* FIXME: the entries are in the remote mapping form; * so we need to select those attributes we are willing * to return, and remap them accordingly */ - (void)rwm_attrs( op, rs, &e->e_attrs ); + (void)rwm_attrs( op, rs, &e->e_attrs, 1 ); + +#if 0 + if ( rs->sr_operational_attrs ) { + (void)rwm_attrs( op, rs, &rs->sr_operational_attrs, 0 ); + } +#endif rs->sr_entry = e; rs->sr_flags = flags; @@ -1059,7 +1067,7 @@ rwm_operational( Operation *op, SlapReply *rs ) * so we need to select those attributes we are willing * to return, and remap them accordingly */ if ( rs->sr_operational_attrs ) { - rwm_attrs( op, rs, &rs->sr_operational_attrs ); + rwm_attrs( op, rs, &rs->sr_operational_attrs, 1 ); } return SLAP_CB_CONTINUE; diff --git a/servers/slapd/overlays/unique.c b/servers/slapd/overlays/unique.c index e9f60fb8e1..d44e205fdf 100644 --- a/servers/slapd/overlays/unique.c +++ b/servers/slapd/overlays/unique.c @@ -328,6 +328,7 @@ static int unique_search( nop->o_tag = LDAP_REQ_SEARCH; nop->ors_scope = LDAP_SCOPE_SUBTREE; nop->ors_deref = LDAP_DEREF_NEVER; + nop->ors_limit = NULL; nop->ors_slimit = SLAP_NO_LIMIT; nop->ors_tlimit = SLAP_NO_LIMIT; nop->ors_attrs = slap_anlist_no_attrs; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 133ecb8d00..bfb41fb18f 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -264,6 +264,9 @@ LDAP_SLAPD_F (int) backend_unbind LDAP_P((Operation *op, SlapReply *rs)); LDAP_SLAPD_F (int) backend_connection_init LDAP_P((Connection *conn)); LDAP_SLAPD_F (int) backend_connection_destroy LDAP_P((Connection *conn)); +LDAP_SLAPD_F( int ) backend_check_controls LDAP_P(( + Operation *op, + SlapReply *rs )); LDAP_SLAPD_F( int ) backend_check_restrictions LDAP_P(( Operation *op, SlapReply *rs, @@ -430,7 +433,7 @@ LDAP_SLAPD_F (int) get_supported_controls LDAP_P (( 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 )); + Operation *op, const char *oid, int *cid )); /* * config.c diff --git a/servers/slapd/result.c b/servers/slapd/result.c index 9c9d2ea587..c2efc492fd 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -453,7 +453,7 @@ send_ldap_response( ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex ); ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 ); - ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, bytes ); + ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes ); ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex ); cleanup:; @@ -1180,7 +1180,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) rs->sr_nentries++; ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex ); - ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, bytes ); + ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes ); ldap_pvt_mp_add_ulong( slap_counters.sc_entries, 1 ); ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 ); ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex ); @@ -1369,7 +1369,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) ber_free_buf( ber ); ldap_pvt_thread_mutex_lock( &slap_counters.sc_sent_mutex ); - ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, bytes ); + ldap_pvt_mp_add_ulong( slap_counters.sc_bytes, (unsigned long)bytes ); ldap_pvt_mp_add_ulong( slap_counters.sc_refs, 1 ); ldap_pvt_mp_add_ulong( slap_counters.sc_pdu, 1 ); ldap_pvt_thread_mutex_unlock( &slap_counters.sc_sent_mutex ); diff --git a/servers/slapd/root_dse.c b/servers/slapd/root_dse.c index 46e77968ce..8d18760abe 100644 --- a/servers/slapd/root_dse.c +++ b/servers/slapd/root_dse.c @@ -128,7 +128,7 @@ root_dse_info( } continue; } - if ( SLAP_GLUE_SUBORDINATE( &backends[i] ) ) { + if ( SLAP_GLUE_SUBORDINATE( &backends[i] ) && !SLAP_GLUE_ADVERTISE( &backends[i] ) ) { continue; } for ( j = 0; backends[i].be_suffix[j].bv_val != NULL; j++ ) { diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index a9df65cf96..5d37337439 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -537,7 +537,7 @@ octetStringSubstringsFilter ( if ( sa->sa_initial.bv_len > index_substr_if_maxlen && ( flags & SLAP_INDEX_SUBSTR_ANY )) { - nkeys += (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step; + nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step; } } @@ -560,7 +560,7 @@ octetStringSubstringsFilter ( if ( sa->sa_final.bv_len > index_substr_if_maxlen && ( flags & SLAP_INDEX_SUBSTR_ANY )) { - nkeys += (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step; + nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step; } } diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 08566e4730..ee65e32dc8 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1527,6 +1527,10 @@ typedef struct syncinfo_s { LDAP_TAILQ_HEAD( be_pcl, slap_csn_entry ); +#ifndef SLAP_MAX_CIDS +#define SLAP_MAX_CIDS 32 /* Maximum number of supported controls */ +#endif + struct slap_backend_db { BackendInfo *bd_info; /* pointer to shared backend info */ @@ -1551,6 +1555,7 @@ struct slap_backend_db { #define be_extended bd_info->bi_extended #define be_chk_referrals bd_info->bi_chk_referrals +#define be_chk_controls bd_info->bi_chk_controls #define be_fetch bd_info->bi_entry_get_rw #define be_release bd_info->bi_entry_release_rw #define be_group bd_info->bi_acl_group @@ -1564,12 +1569,6 @@ struct slap_backend_db { */ #define be_has_subordinates bd_info->bi_has_subordinates - /* 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 @@ -1587,14 +1586,20 @@ struct slap_backend_db { #define be_entry_modify bd_info->bi_tool_entry_modify #endif + /* supported controls */ + /* note: set to 0 if the database does not support the control; + * be_ctrls[SLAP_MAX_CIDS] is set to 1 if initialized */ + char be_ctrls[SLAP_MAX_CIDS + 1]; + /* Database flags */ #define SLAP_DBFLAG_NOLASTMOD 0x0001U #define SLAP_DBFLAG_NO_SCHEMA_CHECK 0x0002U #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_GLOBAL_OVERLAY 0x0100U /* this db struct is a global overlay */ +#define SLAP_DBFLAG_GLUE_ADVERTISE 0x0080U /* advertise in rootDSE */ +#define SLAP_DBFLAG_OVERLAY 0x0100U /* this db struct is an overlay */ +#define SLAP_DBFLAG_GLOBAL_OVERLAY 0x0200U /* 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 */ @@ -1611,6 +1616,8 @@ struct slap_backend_db { (SLAP_DBFLAGS(be) & SLAP_DBFLAG_GLUE_SUBORDINATE) #define SLAP_GLUE_LINKED(be) \ (SLAP_DBFLAGS(be) & SLAP_DBFLAG_GLUE_LINKED) +#define SLAP_GLUE_ADVERTISE(be) \ + (SLAP_DBFLAGS(be) & SLAP_DBFLAG_GLUE_ADVERTISE) #define SLAP_SHADOW(be) (SLAP_DBFLAGS(be) & SLAP_DBFLAG_SHADOW) #define SLAP_SYNC_SHADOW(be) (SLAP_DBFLAGS(be) & SLAP_DBFLAG_SYNC_SHADOW) #define SLAP_SLURP_SHADOW(be) (SLAP_DBFLAGS(be) & SLAP_DBFLAG_SLURP_SHADOW) @@ -1873,6 +1880,8 @@ typedef int (BI_op_extended) LDAP_P(( struct slap_op *op, struct slap_rep *rs )); typedef int (BI_chk_referrals) LDAP_P(( struct slap_op *op, struct slap_rep *rs )); +typedef int (BI_chk_controls) LDAP_P(( + struct slap_op *op, struct slap_rep *rs )); typedef int (BI_entry_release_rw) LDAP_P(( struct slap_op *op, Entry *e, int rw )); typedef int (BI_entry_get_rw) LDAP_P(( struct slap_op *op, struct berval *ndn, @@ -1974,6 +1983,7 @@ struct slap_backend_info { /* Auxilary Functions */ BI_operational *bi_operational; BI_chk_referrals *bi_chk_referrals; + BI_chk_controls *bi_chk_controls; BI_entry_get_rw *bi_entry_get_rw; BI_entry_release_rw *bi_entry_release_rw; @@ -2017,7 +2027,8 @@ struct slap_backend_info { #define SLAP_NOLASTMODCMD(be) (SLAP_BFLAGS(be) & SLAP_BFLAG_NOLASTMODCMD) #define SLAP_LASTMODCMD(be) (!SLAP_NOLASTMODCMD(be)) - char **bi_controls; /* supported controls */ + char **bi_controls; /* supported controls */ + char bi_ctrls[SLAP_MAX_CIDS + 1]; unsigned int bi_nDB; /* number of databases of this type */ void *bi_private; /* anything the backend type needs */ @@ -2103,10 +2114,6 @@ typedef struct slap_gacl { char ga_ndn[1]; } GroupAssertion; -#ifndef SLAP_MAX_CIDS -#define SLAP_MAX_CIDS 32 /* Maximum number of supported controls */ -#endif - struct slap_control_ids { int sc_assert; int sc_preRead; diff --git a/servers/slapd/slapadd.c b/servers/slapd/slapadd.c index 1d45cd8a73..09734c6a2d 100644 --- a/servers/slapd/slapadd.c +++ b/servers/slapd/slapadd.c @@ -99,6 +99,7 @@ static void *do_put(void *ptr) } while (1); ldap_pvt_thread_mutex_unlock( &put_mutex1 ); + return NULL; } int diff --git a/tests/scripts/defines.sh b/tests/scripts/defines.sh index bb6d4011d4..1bf43a34d1 100755 --- a/tests/scripts/defines.sh +++ b/tests/scripts/defines.sh @@ -39,7 +39,10 @@ DBDIR1A=$TESTDIR/db.1.a DBDIR1B=$TESTDIR/db.1.b DBDIR1C=$TESTDIR/db.1.c DBDIR1=$DBDIR1A -DBDIR2=$TESTDIR/db.2.a +DBDIR2A=$TESTDIR/db.2.a +DBDIR2B=$TESTDIR/db.2.b +DBDIR2C=$TESTDIR/db.2.c +DBDIR2=$DBDIR2A DBDIR3=$TESTDIR/db.3.a DBDIR4=$TESTDIR/db.4.a DBDIR5=$TESTDIR/db.5.a @@ -79,6 +82,8 @@ LDAPGLUECONF3=$DATADIR/slapd-ldapgluegroups.conf RWMCONF=$DATADIR/slapd-relay.conf CHAINCONF1=$DATADIR/slapd-chain1.conf CHAINCONF2=$DATADIR/slapd-chain2.conf +GLUESYNCCONF1=$DATADIR/slapd-glue-syncrepl1.conf +GLUESYNCCONF2=$DATADIR/slapd-glue-syncrepl2.conf SQLCONF=$DATADIR/slapd-sql.conf CONF1=$TESTDIR/slapd.1.conf @@ -237,6 +242,7 @@ RELAYOUT=$DATADIR/relay.out CHAINOUT=$DATADIR/chain.out CHAINREFOUT=$DATADIR/chainref.out CHAINMODOUT=$DATADIR/chainmod.out +GLUESYNCOUT=$DATADIR/gluesync.out SQLREAD=$DATADIR/sql-read.out SQLWRITE=$DATADIR/sql-write.out diff --git a/tests/scripts/test032-chain b/tests/scripts/test032-chain index 7bf073a3fd..0d930ceef8 100755 --- a/tests/scripts/test032-chain +++ b/tests/scripts/test032-chain @@ -133,8 +133,31 @@ for P in $PORT1 $PORT2 ; do echo "comparison failed - chained search didn't succeed" test $KILLSERVERS != no && kill -HUP $KILLPIDS exit 1 -fi + fi + DN="cn=Mark Elliot,ou=Alumni Association,ou=People,$BASEDN" + echo "Comparing \"$DN\" on port $P..." + $LDAPCOMPARE -h $LOCALHOST -p $P "$DN" "cn:Mark Elliot" + > $TESTOUT 2>&1 + + RC=$? + if test $RC != 0 ; then + echo "ldapcompare failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC + fi + + DN="ou=Other,$BASEDN" + echo "Comparing \"$DN\" on port $P with manageDSAit control..." + $LDAPCOMPARE -h $LOCALHOST -p $P -M "$DN" "ou:Other" + > $TESTOUT 2>&1 + + RC=$? + if test $RC != 0 ; then + echo "ldapcompare failed ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC + fi done # -- 2.39.2