From: Pierangelo Masarati Date: Tue, 29 Mar 2005 18:57:42 +0000 (+0000) Subject: add manageDSAit & referral support (to be tested); cleanup some error conditions X-Git-Tag: OPENLDAP_AC_BP~1042 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=908aaa51074c27cb3a5089ff8eb18b3431912cf0;p=openldap add manageDSAit & referral support (to be tested); cleanup some error conditions --- diff --git a/servers/slapd/back-ldif/ldif.c b/servers/slapd/back-ldif/ldif.c index 4cca3cd1ab..e26affdae3 100644 --- a/servers/slapd/back-ldif/ldif.c +++ b/servers/slapd/back-ldif/ldif.c @@ -304,29 +304,31 @@ typedef struct enumCookie { int scope; } enumCookie; -static void r_enum_tree(enumCookie *ck, struct berval *path, - struct berval *pdn, struct berval *pndn) { +static int r_enum_tree(enumCookie *ck, struct berval *path, + struct berval *pdn, struct berval *pndn) +{ Entry *e; - int fd; - - if(ck->entries == NULL) { - ck->entries = (Entry **) SLAP_MALLOC(sizeof(Entry *) * ENTRY_BUFF_INCREMENT); - ck->elen = ENTRY_BUFF_INCREMENT; - } + int fd, rc = LDAP_SUCCESS; fd = open( path->bv_val, O_RDONLY ); if ( fd < 0 ) { Debug( LDAP_DEBUG_TRACE, "=> ldif_enum_tree: failed to open %s\n", path->bv_val, 0, 0 ); - return; + return LDAP_NO_SUCH_OBJECT; + } + + if(ck->entries == NULL) { + ck->entries = (Entry **) SLAP_MALLOC(sizeof(Entry *) * ENTRY_BUFF_INCREMENT); + ck->elen = ENTRY_BUFF_INCREMENT; } + e = get_entry_for_fd(fd, pdn, pndn); if ( !e ) { Debug( LDAP_DEBUG_ANY, "=> ldif_enum_tree: failed to read entry for %s\n", path->bv_val, 0, 0 ); - return; + return LDAP_BUSY; } if ( ck->scope == LDAP_SCOPE_BASE || ck->scope == LDAP_SCOPE_SUBTREE ) { @@ -350,10 +352,14 @@ static void r_enum_tree(enumCookie *ck, struct berval *path, path->bv_val[path->bv_len] = '\0'; dir_of_path = opendir(path->bv_val); - if(dir_of_path == NULL) {/* can't open directory */ + if(dir_of_path == NULL) { /* can't open directory */ Debug( LDAP_DEBUG_TRACE, "=> ldif_enum_tree: failed to opendir %s\n", path->bv_val, 0, 0 ); +#if 0 + /* so, what? */ + rc = LDAP_BUSY; +#endif goto leave; } @@ -407,7 +413,7 @@ static void r_enum_tree(enumCookie *ck, struct berval *path, else if ( ck->scope == LDAP_SCOPE_SUBORDINATE) ck->scope = LDAP_SCOPE_SUBTREE; - while ( ptr=list ) { + while ( ( ptr = list ) ) { struct berval fpath; list = ptr->next; @@ -426,29 +432,35 @@ static void r_enum_tree(enumCookie *ck, struct berval *path, } leave: if ( fd ) entry_free( e ); - return; + return rc; } -static Entry ** enum_tree( +static int +enum_tree( BackendDB *be, struct berval *dn, struct berval *ndn, int * length, + Entry ***e, int scope ) { struct ldif_info *ni = (struct ldif_info *) be->be_private; struct berval path; - int index = 0; + int index = 0, rc; enumCookie ck = {0}; struct berval pdn, pndn; + assert( e != NULL ); + *e = NULL; + ck.scope = scope; dnParent( dn, &pdn ); dnParent( ndn, &pndn ); dn2path(ndn, &be->be_nsuffix[0], &ni->li_base_path, &path); - r_enum_tree(&ck, &path, &pdn, &pndn); + rc = r_enum_tree(&ck, &path, &pdn, &pndn); *length = ck.eind; - return ck.entries; + *e = ck.entries; + return rc; } /* Get the parent path plus the LDIF suffix */ @@ -542,6 +554,134 @@ static int apply_modify_to_entry(Entry * entry, return rc; } +int +ldif_back_referrals( Operation *op, SlapReply *rs ) +{ + struct ldif_info *ni = NULL; + Entry *entry; + int rc = LDAP_SUCCESS; + +#if 0 + if ( op->o_tag == LDAP_REQ_SEARCH ) { + /* let search take care of itself */ + return rc; + } +#endif + + if ( get_manageDSAit( op ) ) { + /* let op take care of DSA management */ + return rc; + } + + ni = (struct ldif_info *)op->o_bd->be_private; + ldap_pvt_thread_mutex_lock( &ni->li_mutex ); + entry = (Entry *)get_entry( op, &ni->li_base_path ); + + /* no object is found for them */ + if ( entry == NULL ) { + struct berval odn = op->o_req_dn; + struct berval ondn = op->o_req_ndn; + + struct berval pndn = op->o_req_ndn; + + for ( ; entry == NULL; ) { + struct berval opndn = pndn; + dnParent( &opndn, &pndn ); + + if ( !dnIsSuffix( &pndn, &op->o_bd->be_nsuffix[0] ) ) { + break; + } + + op->o_req_dn = pndn; + op->o_req_ndn = pndn; + + entry = (Entry *)get_entry( op, &ni->li_base_path ); + } + + op->o_req_dn = odn; + op->o_req_ndn = ondn; + + rc = LDAP_SUCCESS; + rs->sr_matched = NULL; + if ( entry != NULL ) { + Debug( LDAP_DEBUG_TRACE, + "ldif_back_referrals: op=%ld target=\"%s\" matched=\"%s\"\n", + (long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val ); + + if ( is_entry_referral( entry ) ) { + rc = LDAP_OTHER; + rs->sr_ref = get_entry_referrals( op, entry ); + if ( rs->sr_ref ) { + rs->sr_matched = ber_strdup_x( + entry->e_name.bv_val, op->o_tmpmemctx ); + } + } + + entry_free(entry); + + } else if ( default_referral != NULL ) { + rc = LDAP_OTHER; + rs->sr_ref = referral_rewrite( default_referral, + NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); + } + + if ( rs->sr_ref != NULL ) { + /* send referrals */ + rc = rs->sr_err = LDAP_REFERRAL; + send_ldap_result( op, rs ); + ber_bvarray_free( rs->sr_ref ); + rs->sr_ref = NULL; + + } else if ( rc != LDAP_SUCCESS ) { + rs->sr_err = rc; + rs->sr_text = rs->sr_matched ? "bad referral object" : NULL; + send_ldap_result( op, rs ); + } + + if ( rs->sr_matched ) { + op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx ); + rs->sr_matched = NULL; + } + + ldap_pvt_thread_mutex_unlock( &ni->li_mutex ); + + return rc; + + } + + if ( is_entry_referral( entry ) ) { + /* entry is a referral */ + BerVarray refs = get_entry_referrals( op, entry ); + rs->sr_ref = referral_rewrite( + refs, &entry->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); + + Debug( LDAP_DEBUG_TRACE, + "ldif_back_referrals: op=%ld target=\"%s\" matched=\"%s\"\n", + (long) op->o_tag, op->o_req_dn.bv_val, entry->e_name.bv_val ); + + rs->sr_matched = entry->e_name.bv_val; + if ( rs->sr_ref != NULL ) { + rc = rs->sr_err = LDAP_REFERRAL; + send_ldap_result( op, rs ); + ber_bvarray_free( rs->sr_ref ); + rs->sr_ref = NULL; + + } else { + send_ldap_error( op, rs, LDAP_OTHER, "bad referral object" ); + rc = rs->sr_err; + } + + rs->sr_matched = NULL; + ber_bvarray_free( refs ); + + entry_free( entry ); + } + + ldap_pvt_thread_mutex_unlock( &ni->li_mutex ); + + return rc; +} + static int ldif_back_bind( Operation *op, SlapReply *rs ) { @@ -558,19 +698,11 @@ ldif_back_bind( Operation *op, SlapReply *rs ) /* no object is found for them */ if(entry == NULL) { if(be_isroot_pw(op)) { - return_val = LDAP_SUCCESS; - goto return_result; - } - else if(be_root_dn(op->o_bd)) { - return_val = LDAP_INVALID_CREDENTIALS; - rs->sr_err = LDAP_INVALID_CREDENTIALS; - goto return_result; - } - else { - rs->sr_err = LDAP_NO_SUCH_OBJECT; - return_val = 1; - goto return_result; + rs->sr_err = return_val = LDAP_SUCCESS; + } else { + rs->sr_err = return_val = LDAP_INVALID_CREDENTIALS; } + goto return_result; } /* they don't have userpassword */ @@ -609,11 +741,34 @@ static int ldif_back_search(Operation *op, SlapReply *rs) Entry ** entries = NULL; ldap_pvt_thread_mutex_lock(&ni->li_mutex); - entries = (Entry **) enum_tree(op->o_bd, &op->o_req_dn, &op->o_req_ndn, &numentries, op->ors_scope); - - if(entries != NULL) { - for(i=0;iors_filter) == LDAP_COMPARE_TRUE) { + rs->sr_err = enum_tree(op->o_bd, &op->o_req_dn, &op->o_req_ndn, &numentries, &entries, op->ors_scope); + if ( rs->sr_err == LDAP_SUCCESS ) { + for ( i = 0; i < numentries; i++ ) { + + + /* + * if it's a referral, add it to the list of referrals. only do + * this for non-base searches, and don't check the filter + * explicitly here since it's only a candidate anyway. + */ + if ( !get_manageDSAit( op ) + && op->oq_search.rs_scope != LDAP_SCOPE_BASE + && is_entry_referral( entries[i] ) ) + { + BerVarray erefs = get_entry_referrals( op, entries[i] ); + rs->sr_ref = referral_rewrite( erefs, + &entries[i]->e_name, NULL, + op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL + ? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE ); + + send_search_reference( op, rs ); + + ber_bvarray_free( rs->sr_ref ); + ber_bvarray_free( erefs ); + rs->sr_ref = NULL; + + } else if ( test_filter( op, entries[i], op->ors_filter ) == LDAP_COMPARE_TRUE ) + { rs->sr_entry = entries[i]; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; @@ -621,18 +776,12 @@ static int ldif_back_search(Operation *op, SlapReply *rs) } entry_free(entries[i]); } - SLAP_FREE(entries); - rs->sr_err = LDAP_SUCCESS; - ldap_pvt_thread_mutex_unlock(&ni->li_mutex); - send_ldap_result(op, rs); - } - else { - rs->sr_err = LDAP_BUSY; - ldap_pvt_thread_mutex_unlock(&ni->li_mutex); - send_ldap_result(op, rs); } + SLAP_FREE(entries); + ldap_pvt_thread_mutex_unlock(&ni->li_mutex); + send_ldap_result(op, rs); - return 0; + return rs->sr_err; } static int ldif_back_add(Operation *op, SlapReply *rs) { @@ -939,25 +1088,30 @@ static int ldif_tool_entry_close(BackendDB * be) { return 0; } -static ID ldif_tool_entry_first(BackendDB *be) { +static ID +ldif_tool_entry_first(BackendDB *be) +{ struct ldif_info *ni = (struct ldif_info *) be->be_private; ID id = 1; /* first entry in the array of entries shifted by one */ ni->tool_current = 1; if(ni->tool_entries == NULL || ni->tool_put_entry_flag) { - ni->tool_entries = (Entry **) enum_tree(be, be->be_suffix, - be->be_nsuffix, &ni->tool_numentries, LDAP_SCOPE_SUBTREE); + (void)enum_tree(be, be->be_suffix, be->be_nsuffix, + &ni->tool_numentries, &ni->tool_entries, + LDAP_SCOPE_SUBTREE); ni->tool_put_entry_flag = 0; } return id; } -static ID ldif_tool_entry_next(BackendDB *be) { +static ID ldif_tool_entry_next(BackendDB *be) +{ struct ldif_info *ni = (struct ldif_info *) be->be_private; ni->tool_current += 1; if(ni->tool_put_entry_flag) { - ni->tool_entries = (Entry **) enum_tree(be, be->be_suffix, - be->be_nsuffix, &ni->tool_numentries, LDAP_SCOPE_SUBTREE); + (void)enum_tree(be, be->be_suffix, be->be_nsuffix, + &ni->tool_numentries, &ni->tool_entries, + LDAP_SCOPE_SUBTREE); ni->tool_put_entry_flag = 0; } if(ni->tool_current > ni->tool_numentries) @@ -1075,8 +1229,17 @@ ldif_back_initialize( BackendInfo *bi ) { + static char *controls[] = { + LDAP_CONTROL_MANAGEDSAIT, + NULL + }; int rc; + bi->bi_flags |= + SLAP_BFLAG_REFERRALS; + + bi->bi_controls = controls; + bi->bi_cf_table = ldifcfg; bi->bi_open = 0; @@ -1102,7 +1265,7 @@ ldif_back_initialize( bi->bi_extended = 0; - bi->bi_chk_referrals = 0; + bi->bi_chk_referrals = ldif_back_referrals; bi->bi_connection_init = 0; bi->bi_connection_destroy = 0;