X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-ldap%2Fchain.c;h=8f37efb236c30ac0f6a80f2ba4f0756f5855fef0;hb=473e2c997f6b1f226d35da186db8033c922001f3;hp=102374a40cfc2bdd99eee9bdeeb59c23bee17173;hpb=5ae46c195ed5dd2b5117d2301645e8b7a00d9a0a;p=openldap diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c index 102374a40c..8f37efb236 100644 --- a/servers/slapd/back-ldap/chain.c +++ b/servers/slapd/back-ldap/chain.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2003-2007 The OpenLDAP Foundation. + * Copyright 2003-2011 The OpenLDAP Foundation. * Portions Copyright 2003 Howard Chu. * All rights reserved. * @@ -63,6 +63,7 @@ typedef enum { LDAP_CH_RES, LDAP_CH_ERR } ldap_chain_status_t; + static BackendInfo *lback; typedef struct ldap_chain_t { @@ -224,7 +225,6 @@ ldap_chain_uri_cmp( const void *c1, const void *c2 ) assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) ); assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) ); - /* If local DNs don't match, it is definitely not a match */ return ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] ); } @@ -242,11 +242,10 @@ ldap_chain_uri_dup( void *c1, void *c2 ) assert( !BER_BVISNULL( &li2->li_bvuri[ 0 ] ) ); assert( BER_BVISNULL( &li2->li_bvuri[ 1 ] ) ); - /* Cannot have more than one shared session with same DN */ if ( ber_bvcmp( &li1->li_bvuri[ 0 ], &li2->li_bvuri[ 0 ] ) == 0 ) { return -1; } - + return 0; } @@ -398,6 +397,8 @@ ldap_chain_op( slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; ldap_chain_cb_t *lb = (ldap_chain_cb_t *)op->o_callback->sc_private; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; + struct berval odn = op->o_req_dn, + ondn = op->o_req_ndn; ldapinfo_t li = { 0 }, *lip = NULL; struct berval bvuri[ 2 ] = { { 0 } }; @@ -416,12 +417,14 @@ ldap_chain_op( for ( ; !BER_BVISNULL( ref ); ref++ ) { SlapReply rs2 = { 0 }; LDAPURLDesc *srv = NULL; - struct berval save_req_dn = op->o_req_dn, - save_req_ndn = op->o_req_ndn, - dn = BER_BVNULL, - pdn = BER_BVNULL, - ndn = BER_BVNULL; + req_search_s save_oq_search = op->oq_search, + tmp_oq_search = { 0 }; + struct berval dn = BER_BVNULL, + pdn = odn, + ndn = ondn; + char *filter = NULL; int temporary = 0; + int free_dn = 0; /* We're setting the URI of the first referral; * what if there are more? @@ -443,15 +446,37 @@ Document: RFC 4511 * proto://[host][:port]/ only */ rc = ldap_url_parse_ext( ref->bv_val, &srv, LDAP_PVT_URL_PARSE_NONE ); if ( rc != LDAP_URL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_op: unable to parse ref=\"%s\"\n", + op->o_log_prefix, ref->bv_val, 0 ); + /* try next */ rc = LDAP_OTHER; continue; } - /* normalize DN */ + if ( op->o_tag == LDAP_REQ_SEARCH ) { + if ( srv->lud_scope != LDAP_SCOPE_DEFAULT ) { + /* RFC 4511: if scope is present, use it */ + tmp_oq_search.rs_scope = srv->lud_scope; + + } else { + /* RFC 4511: if scope is absent, use original */ + tmp_oq_search.rs_scope = op->ors_scope; + } + } + rc = LDAP_SUCCESS; srv->lud_scope = LDAP_SCOPE_DEFAULT; - if ( srv->lud_dn != NULL ) { + dn.bv_val = srv->lud_dn; + filter = srv->lud_filter; + + /* normalize DN */ + if ( srv->lud_dn == NULL || srv->lud_dn[0] == '\0' ) { + if ( srv->lud_dn == NULL ) { + srv->lud_dn = ""; + } + + } else { ber_str2bv( srv->lud_dn, 0, 0, &dn ); rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx ); if ( rc == LDAP_SUCCESS ) { @@ -459,14 +484,38 @@ Document: RFC 4511 * ldap_initialize() will parse the URL * as a comma-separated URL list */ srv->lud_dn = ""; + free_dn = 1; } + } - } else { - srv->lud_dn = ""; + /* prepare filter */ + if ( rc == LDAP_SUCCESS && op->o_tag == LDAP_REQ_SEARCH ) { + /* filter */ + if ( srv->lud_filter != NULL + && srv->lud_filter[0] != '\0' + && strcasecmp( srv->lud_filter, "(objectClass=*)" ) != 0 ) + { + /* RFC 4511: if filter is present, use it; + * otherwise, use original */ + tmp_oq_search.rs_filter = str2filter_x( op, srv->lud_filter ); + if ( tmp_oq_search.rs_filter != NULL ) { + filter2bv_x( op, tmp_oq_search.rs_filter, &tmp_oq_search.rs_filterstr ); + + } else { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_op: ref=\"%s\": unable to parse filter=\"%s\"\n", + op->o_log_prefix, ref->bv_val, srv->lud_filter ); + rc = LDAP_OTHER; + } + } + } + srv->lud_filter = NULL; + + if ( rc == LDAP_SUCCESS ) { + li.li_uri = ldap_url_desc2str( srv ); } - li.li_uri = ldap_url_desc2str( srv ); srv->lud_dn = dn.bv_val; + srv->lud_filter = filter; ldap_free_urldesc( srv ); if ( rc != LDAP_SUCCESS ) { @@ -476,14 +525,28 @@ Document: RFC 4511 } if ( li.li_uri == NULL ) { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_op: ref=\"%s\" unable to reconstruct URI\n", + op->o_log_prefix, ref->bv_val, 0 ); + /* try next */ rc = LDAP_OTHER; goto further_cleanup; } + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_op: ref=\"%s\" -> \"%s\"\n", + op->o_log_prefix, ref->bv_val, li.li_uri ); + op->o_req_dn = pdn; op->o_req_ndn = ndn; + if ( op->o_tag == LDAP_REQ_SEARCH ) { + op->ors_scope = tmp_oq_search.rs_scope; + if ( tmp_oq_search.rs_filter != NULL ) { + op->ors_filter = tmp_oq_search.rs_filter; + op->ors_filterstr = tmp_oq_search.rs_filterstr; + } + } + ber_str2bv( li.li_uri, 0, 0, &li.li_bvuri[ 0 ] ); /* Searches for a ldapinfo in the avl tree */ @@ -495,9 +558,14 @@ Document: RFC 4511 if ( lip != NULL ) { op->o_bd->be_private = (void *)lip; + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_op: ref=\"%s\": URI=\"%s\" found in cache\n", + op->o_log_prefix, ref->bv_val, li.li_uri ); + } else { rc = ldap_chain_db_init_one( op->o_bd ); if ( rc != 0 ) { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_op: ref=\"%s\" unable to init back-ldap for URI=\"%s\"\n", + op->o_log_prefix, ref->bv_val, li.li_uri ); goto cleanup; } lip = (ldapinfo_t *)op->o_bd->be_private; @@ -505,6 +573,8 @@ Document: RFC 4511 lip->li_bvuri = bvuri; rc = ldap_chain_db_open_one( op->o_bd ); if ( rc != 0 ) { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_op: ref=\"%s\" unable to open back-ldap for URI=\"%s\"\n", + op->o_log_prefix, ref->bv_val, li.li_uri ); lip->li_uri = NULL; lip->li_bvuri = NULL; (void)ldap_chain_db_destroy_one( op->o_bd, NULL); @@ -526,6 +596,9 @@ Document: RFC 4511 } else { temporary = 1; } + + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_op: ref=\"%s\" %s\n", + op->o_log_prefix, ref->bv_val, temporary ? "temporary" : "caching" ); } lb->lb_op_f = op_f; @@ -550,16 +623,23 @@ cleanup:; } further_cleanup:; - if ( !BER_BVISNULL( &pdn ) ) { + if ( free_dn ) { op->o_tmpfree( pdn.bv_val, op->o_tmpmemctx ); + op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); } - op->o_req_dn = save_req_dn; + + if ( op->o_tag == LDAP_REQ_SEARCH ) { + if ( tmp_oq_search.rs_filter != NULL ) { + filter_free_x( op, tmp_oq_search.rs_filter, 1 ); + } - if ( !BER_BVISNULL( &ndn ) ) { - op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); + if ( !BER_BVISNULL( &tmp_oq_search.rs_filterstr ) ) { + slap_sl_free( tmp_oq_search.rs_filterstr.bv_val, op->o_tmpmemctx ); + } + + op->oq_search = save_oq_search; } - op->o_req_ndn = save_req_ndn; - + if ( rc == LDAP_SUCCESS && rs2.sr_err == LDAP_SUCCESS ) { *rs = rs2; break; @@ -568,6 +648,9 @@ further_cleanup:; rc = rs2.sr_err; } + op->o_req_dn = odn; + op->o_req_ndn = ondn; + #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR (void)chaining_control_remove( op, &ctrls ); #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ @@ -595,7 +678,8 @@ ldap_chain_search( struct berval odn = op->o_req_dn, ondn = op->o_req_ndn; - slap_response *save_response = op->o_callback->sc_response; + Entry *save_entry = rs->sr_entry; + slap_mask_t save_flags = rs->sr_flags; int rc = LDAP_OTHER, first_rc = -1; @@ -606,9 +690,9 @@ ldap_chain_search( (void)chaining_control_add( lc, op, &ctrls ); #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ - rs->sr_type = REP_SEARCH; + assert( rs->sr_type == REP_SEARCHREF ); - op->o_callback->sc_response = ldap_chain_cb_search_response; + rs->sr_type = REP_SEARCH; /* if we parse the URI then by no means * we can cache stuff or reuse connections, @@ -617,27 +701,61 @@ ldap_chain_search( * to be set once for all (correct?) */ li.li_bvuri = bvuri; for ( ; !BER_BVISNULL( &ref[0] ); ref++ ) { - SlapReply rs2 = { 0 }; + SlapReply rs2 = { REP_RESULT }; LDAPURLDesc *srv; - struct berval save_req_dn = op->o_req_dn, - save_req_ndn = op->o_req_ndn, - dn, - pdn = BER_BVNULL, - ndn = BER_BVNULL; + req_search_s save_oq_search = op->oq_search, + tmp_oq_search = { 0 }; + struct berval dn, + pdn = op->o_req_dn, + ndn = op->o_req_ndn; + char *filter = NULL; int temporary = 0; + int free_dn = 0; /* parse reference and use * proto://[host][:port]/ only */ rc = ldap_url_parse_ext( ref[0].bv_val, &srv, LDAP_PVT_URL_PARSE_NONE ); if ( rc != LDAP_URL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_search: unable to parse ref=\"%s\"\n", + op->o_log_prefix, ref->bv_val, 0 ); + /* try next */ rs->sr_err = LDAP_OTHER; continue; } + if ( srv->lud_scope != LDAP_SCOPE_DEFAULT ) { + /* RFC 4511: if scope is present, use it */ + tmp_oq_search.rs_scope = srv->lud_scope; + + } else { + /* RFC 4511: if scope is absent, use original */ + /* Section 4.5.3: if scope is onelevel, use base */ + if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) + tmp_oq_search.rs_scope = LDAP_SCOPE_BASE; + else + tmp_oq_search.rs_scope = op->ors_scope; + } + + rc = LDAP_SUCCESS; + srv->lud_scope = LDAP_SCOPE_DEFAULT; + dn.bv_val = srv->lud_dn; + filter = srv->lud_filter; + /* normalize DN */ - rc = LDAP_INVALID_SYNTAX; - if ( srv->lud_dn != NULL ) { + if ( srv->lud_dn == NULL || srv->lud_dn[0] == '\0' ) { + if ( srv->lud_dn == NULL ) { + srv->lud_dn = ""; + } + + if ( save_entry != NULL ) { + /* use the "right" DN, if available */ + pdn = save_entry->e_name; + ndn = save_entry->e_nname; + } /* else leave the original req DN in place, if any RFC 4511 */ + + } else { + /* RFC 4511: if DN is present, use it */ ber_str2bv( srv->lud_dn, 0, 0, &dn ); rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx ); if ( rc == LDAP_SUCCESS ) { @@ -645,27 +763,59 @@ ldap_chain_search( * ldap_initialize() will parse the URL * as a comma-separated URL list */ srv->lud_dn = ""; - srv->lud_scope = LDAP_SCOPE_DEFAULT; - li.li_uri = ldap_url_desc2str( srv ); - srv->lud_dn = dn.bv_val; + free_dn = 1; } } - ldap_free_urldesc( srv ); - if ( rc != LDAP_SUCCESS ) { - /* try next */ - rc = LDAP_OTHER; - continue; + /* prepare filter */ + if ( rc == LDAP_SUCCESS ) { + /* filter */ + if ( srv->lud_filter != NULL + && srv->lud_filter[0] != '\0' + && strcasecmp( srv->lud_filter, "(objectClass=*)" ) != 0 ) + { + /* RFC 4511: if filter is present, use it; + * otherwise, use original */ + tmp_oq_search.rs_filter = str2filter_x( op, srv->lud_filter ); + if ( tmp_oq_search.rs_filter != NULL ) { + filter2bv_x( op, tmp_oq_search.rs_filter, &tmp_oq_search.rs_filterstr ); + + } else { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_search: ref=\"%s\": unable to parse filter=\"%s\"\n", + op->o_log_prefix, ref->bv_val, srv->lud_filter ); + rc = LDAP_OTHER; + } + } } + srv->lud_filter = NULL; + + if ( rc == LDAP_SUCCESS ) { + li.li_uri = ldap_url_desc2str( srv ); + } + + srv->lud_dn = dn.bv_val; + srv->lud_filter = filter; + ldap_free_urldesc( srv ); + + if ( rc != LDAP_SUCCESS || li.li_uri == NULL ) { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_search: ref=\"%s\" unable to reconstruct URI\n", + op->o_log_prefix, ref->bv_val, 0 ); - if ( li.li_uri == NULL ) { /* try next */ rc = LDAP_OTHER; goto further_cleanup; } + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_search: ref=\"%s\" -> \"%s\"\n", + op->o_log_prefix, ref->bv_val, li.li_uri ); + op->o_req_dn = pdn; op->o_req_ndn = ndn; + op->ors_scope = tmp_oq_search.rs_scope; + if ( tmp_oq_search.rs_filter != NULL ) { + op->ors_filter = tmp_oq_search.rs_filter; + op->ors_filterstr = tmp_oq_search.rs_filterstr; + } ber_str2bv( li.li_uri, 0, 0, &li.li_bvuri[ 0 ] ); @@ -678,10 +828,15 @@ ldap_chain_search( if ( lip != NULL ) { op->o_bd->be_private = (void *)lip; + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_search: ref=\"%s\": URI=\"%s\" found in cache\n", + op->o_log_prefix, ref->bv_val, li.li_uri ); + } else { /* if none is found, create a temporary... */ rc = ldap_chain_db_init_one( op->o_bd ); if ( rc != 0 ) { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_search: ref=\"%s\" unable to init back-ldap for URI=\"%s\"\n", + op->o_log_prefix, ref->bv_val, li.li_uri ); goto cleanup; } lip = (ldapinfo_t *)op->o_bd->be_private; @@ -689,6 +844,8 @@ ldap_chain_search( lip->li_bvuri = bvuri; rc = ldap_chain_db_open_one( op->o_bd ); if ( rc != 0 ) { + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_search: ref=\"%s\" unable to open back-ldap for URI=\"%s\"\n", + op->o_log_prefix, ref->bv_val, li.li_uri ); lip->li_uri = NULL; lip->li_bvuri = NULL; (void)ldap_chain_db_destroy_one( op->o_bd, NULL ); @@ -710,6 +867,9 @@ ldap_chain_search( } else { temporary = 1; } + + Debug( LDAP_DEBUG_TRACE, "%s ldap_chain_search: ref=\"%s\" %s\n", + op->o_log_prefix, ref->bv_val, temporary ? "temporary" : "caching" ); } lb->lb_op_f = lback->bi_op_search; @@ -726,9 +886,6 @@ cleanup:; ldap_memfree( li.li_uri ); li.li_uri = NULL; - op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); - op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); - if ( temporary ) { lip->li_uri = NULL; lip->li_bvuri = NULL; @@ -737,15 +894,23 @@ cleanup:; } further_cleanup:; - if ( !BER_BVISNULL( &pdn ) ) { + if ( free_dn ) { op->o_tmpfree( pdn.bv_val, op->o_tmpmemctx ); + op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); } - op->o_req_dn = save_req_dn; - if ( !BER_BVISNULL( &ndn ) ) { - op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); + op->o_req_dn = odn; + op->o_req_ndn = ondn; + + if ( tmp_oq_search.rs_filter != NULL ) { + filter_free_x( op, tmp_oq_search.rs_filter, 1 ); } - op->o_req_ndn = save_req_ndn; + + if ( !BER_BVISNULL( &tmp_oq_search.rs_filterstr ) ) { + slap_sl_free( tmp_oq_search.rs_filterstr.bv_val, op->o_tmpmemctx ); + } + + op->oq_search = save_oq_search; if ( rc == LDAP_SUCCESS && rs2.sr_err == LDAP_SUCCESS ) { *rs = rs2; @@ -761,9 +926,9 @@ further_cleanup:; op->o_req_dn = odn; op->o_req_ndn = ondn; - op->o_callback->sc_response = save_response; rs->sr_type = REP_SEARCHREF; - rs->sr_entry = NULL; + rs->sr_entry = save_entry; + rs->sr_flags = save_flags; if ( rc != LDAP_SUCCESS ) { /* couldn't chase any of the referrals */ @@ -853,6 +1018,7 @@ ldap_chain_response( Operation *op, SlapReply *rs ) /* we need this to know if back-ldap returned any result */ lb.lb_lc = lc; + sc2.sc_next = sc->sc_next; sc2.sc_private = &lb; sc2.sc_response = ldap_chain_cb_response; op->o_callback = &sc2; @@ -905,6 +1071,7 @@ ldap_chain_response( Operation *op, SlapReply *rs ) case LDAP_REQ_SEARCH: if ( rs->sr_type == REP_SEARCHREF ) { + sc2.sc_response = ldap_chain_cb_search_response; rc = ldap_chain_search( op, rs, ref, 0 ); } else { @@ -946,6 +1113,7 @@ ldap_chain_response( Operation *op, SlapReply *rs ) case LDAP_SUCCESS: case LDAP_REFERRAL: + sr_err = rs->sr_err; /* slapd-ldap sent response */ if ( !op->o_abandon && lb.lb_status != LDAP_CH_RES ) { /* FIXME: should we send response? */ @@ -973,7 +1141,7 @@ cannot_chain:; default: #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ if ( LDAP_CHAIN_RETURN_ERR( lc ) ) { - rs->sr_err = rc; + sr_err = rs->sr_err = rc; rs->sr_type = sr_type; } else { @@ -991,7 +1159,8 @@ cannot_chain:; } if ( lb.lb_status == LDAP_CH_NONE && rc != SLAPD_ABANDON ) { - op->o_callback = NULL; + /* give the remaining callbacks a chance */ + op->o_callback = sc->sc_next; rc = rs->sr_err = slap_map_api2result( rs ); send_ldap_result( op, rs ); } @@ -1052,6 +1221,9 @@ enum { static ConfigDriver chain_cf_gen; static ConfigCfAdd chain_cfadd; static ConfigLDAPadd chain_ldadd; +#ifdef SLAP_CONFIG_DELETE +static ConfigLDAPdel chain_lddel; +#endif static ConfigTable chaincfg[] = { #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR @@ -1099,7 +1271,11 @@ static ConfigOCs chainocs[] = { "NAME 'olcChainDatabase' " "DESC 'Chain remote server configuration' " "AUXILIARY )", - Cft_Misc, chaincfg, chain_ldadd }, + Cft_Misc, olcDatabaseDummy, chain_ldadd +#ifdef SLAP_CONFIG_DELETE + , NULL, chain_lddel +#endif + }, { NULL, 0, NULL } }; @@ -1136,6 +1312,7 @@ chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) assert( rc == LDAP_SUCCESS ); at = attr_find( e->e_attrs, ad ); +#if 0 if ( lc->lc_common_li == NULL && at != NULL ) { /* FIXME: we should generate an empty default entry * if none is supplied */ @@ -1146,7 +1323,9 @@ chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) rc = LDAP_CONSTRAINT_VIOLATION; goto done; - } else if ( lc->lc_common_li != NULL && at == NULL ) { + } else +#endif + if ( lc->lc_common_li != NULL && at == NULL ) { /* FIXME: we should generate an empty default entry * if none is supplied */ Debug( LDAP_DEBUG_ANY, "slapd-chain: " @@ -1190,6 +1369,8 @@ chain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) } } + ca->ca_private = on; + done:; if ( rc != LDAP_SUCCESS ) { (void)ldap_chain_db_destroy_one( ca->be, NULL ); @@ -1217,9 +1398,9 @@ ldap_chain_cfadd_apply( void *datum, void *arg ) struct berval bv; /* FIXME: should not hardcode "olcDatabase" here */ - bv.bv_len = snprintf( lca->ca->msg, sizeof( lca->ca->msg ), + bv.bv_len = snprintf( lca->ca->cr_msg, sizeof( lca->ca->cr_msg ), "olcDatabase={%d}%s", lca->count, lback->bi_type ); - bv.bv_val = lca->ca->msg; + bv.bv_val = lca->ca->cr_msg; lca->ca->be->be_private = (void *)li; config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca, @@ -1258,6 +1439,45 @@ chain_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca ) return 0; } +#ifdef SLAP_CONFIG_DELETE +static int +chain_lddel( CfEntryInfo *ce, Operation *op ) +{ + CfEntryInfo *pe = ce->ce_parent; + slap_overinst *on = (slap_overinst *)pe->ce_bi; + ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; + ldapinfo_t *li = (ldapinfo_t *) ce->ce_be->be_private; + + if ( li != lc->lc_common_li ) { + if (! avl_delete( &lc->lc_lai.lai_tree, li, ldap_chain_uri_cmp ) ) { + Debug( LDAP_DEBUG_ANY, "slapd-chain: avl_delete failed. " + "\"%s\" not found.\n", li->li_uri, 0, 0 ); + return -1; + } + } else if ( lc->lc_lai.lai_tree ) { + Debug( LDAP_DEBUG_ANY, "slapd-chain: cannot delete first underlying " + "LDAP database when other databases are still present.\n", 0, 0, 0 ); + return -1; + } else { + lc->lc_common_li = NULL; + } + + ce->ce_be->bd_info = lback; + + if ( ce->ce_be->bd_info->bi_db_close ) { + ce->ce_be->bd_info->bi_db_close( ce->ce_be, NULL ); + } + if ( ce->ce_be->bd_info->bi_db_destroy ) { + ce->ce_be->bd_info->bi_db_destroy( ce->ce_be, NULL ); + } + + ch_free(ce->ce_be); + ce->ce_be = NULL; + + return LDAP_SUCCESS; +} +#endif /* SLAP_CONFIG_DELETE */ + #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR static slap_verbmasks chaining_mode[] = { { BER_BVC("referralsRequired"), LDAP_REFERRALS_REQUIRED }, @@ -1479,11 +1699,11 @@ chain_cf_gen( ConfigArgs *c ) case CH_MAX_DEPTH: if ( c->value_int < 0 ) { - snprintf( c->msg, sizeof( c->msg ), + snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid max referral depth %d", c->argv[0], c->value_int ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", - c->log, c->msg, 0 ); + c->log, c->cr_msg, 0 ); rc = 1; break; } @@ -1507,23 +1727,17 @@ chain_cf_gen( ConfigArgs *c ) static int ldap_chain_db_init( BackendDB *be, - ConfigArgs *ca ) + ConfigReply *cr ) { slap_overinst *on = (slap_overinst *)be->bd_info; ldap_chain_t *lc = NULL; if ( lback == NULL ) { - static BackendInfo lback2; - lback = backend_info( "ldap" ); if ( lback == NULL ) { return 1; } - - lback2 = *lback; - lback2.bi_type = ldapchain.on_bi.bi_type; - lback = &lback2; } lc = ch_malloc( sizeof( ldap_chain_t ) ); @@ -1551,20 +1765,17 @@ ldap_chain_db_config( ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; int rc = SLAP_CONF_UNKNOWN; - + if ( lc->lc_common_li == NULL ) { - void *be_private = be->be_private; - ldap_chain_db_init_common( be ); - lc->lc_common_li = lc->lc_cfg_li = (ldapinfo_t *)be->be_private; - be->be_private = be_private; + BackendDB db = *be; + ldap_chain_db_init_common( &db ); + lc->lc_common_li = lc->lc_cfg_li = (ldapinfo_t *)db.be_private; } /* Something for the chain database? */ if ( strncasecmp( argv[ 0 ], "chain-", STRLENOF( "chain-" ) ) == 0 ) { char *save_argv0 = argv[ 0 ]; - BackendInfo *bd_info = be->bd_info; - void *be_private = be->be_private; - ConfigOCs *be_cf_ocs = be->be_cf_ocs; + BackendDB db = *be; static char *allowed_argv[] = { /* special: put URI here, so in the meanwhile * it detects whether a new URI is being provided */ @@ -1603,14 +1814,14 @@ ldap_chain_db_config( } if ( which_argv == 0 ) { - rc = ldap_chain_db_init_one( be ); + rc = ldap_chain_db_init_one( &db ); if ( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "underlying slapd-ldap initialization failed.\n.", fname, lineno, 0 ); return 1; } - lc->lc_cfg_li = be->be_private; + lc->lc_cfg_li = db.be_private; } /* TODO: add checks on what other slapd-ldap(5) args @@ -1620,27 +1831,21 @@ ldap_chain_db_config( * be warned. */ - be->bd_info = lback; - be->be_private = (void *)lc->lc_cfg_li; - be->be_cf_ocs = lback->bi_cf_ocs; + db.bd_info = lback; + db.be_private = (void *)lc->lc_cfg_li; + db.be_cf_ocs = lback->bi_cf_ocs; - rc = config_generic_wrapper( be, fname, lineno, argc, argv ); + rc = config_generic_wrapper( &db, fname, lineno, argc, argv ); argv[ 0 ] = save_argv0; - be->be_cf_ocs = be_cf_ocs; - be->be_private = be_private; - be->bd_info = bd_info; if ( which_argv == 0 ) { private_destroy:; if ( rc != 0 ) { - BackendDB db = *be; - db.bd_info = lback; db.be_private = (void *)lc->lc_cfg_li; ldap_chain_db_destroy_one( &db, NULL ); lc->lc_cfg_li = NULL; - } else { if ( lc->lc_cfg_li->li_bvuri == NULL || BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 0 ] ) @@ -1666,7 +1871,7 @@ private_destroy:; } } } - + return rc; } @@ -1739,7 +1944,7 @@ ldap_chain_db_func( static int ldap_chain_db_open( BackendDB *be, - ConfigArgs *ca ) + ConfigReply *cr ) { slap_overinst *on = (slap_overinst *) be->bd_info; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; @@ -1772,15 +1977,20 @@ ldap_chain_db_open( static int ldap_chain_db_close( BackendDB *be, - ConfigArgs *ca ) + ConfigReply *cr ) { +#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR +#ifdef SLAP_CONFIG_DELETE + overlay_unregister_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR ); +#endif /* SLAP_CONFIG_DELETE */ +#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ return ldap_chain_db_func( be, db_close ); } static int ldap_chain_db_destroy( BackendDB *be, - ConfigArgs *ca ) + ConfigReply *cr ) { slap_overinst *on = (slap_overinst *) be->bd_info; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; @@ -2065,7 +2275,7 @@ ldap_chain_parse_ctrl( int chain_initialize( void ) { - int rc; + int rc; /* Make sure we don't exceed the bits reserved for userland */ config_check_userland( CH_LAST );