int bdb_dn2id_matched( BackendDB *be, DB_TXN *txn, struct berval *in, ID *id, ID *id2, int flags ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; struct berval rdn; char *p1, *p2; idNode *n, *p; int rc = 0; if (!bdb->bi_troot) return DB_NOTFOUND; p = bdb->bi_troot; if (be_issuffix(be, in)) { *id = p->i_id; return 0; } p1 = in->bv_val + in->bv_len - be->be_nsuffix[0].bv_len - 1; n = p; ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); for (;;) { for (p2 = p1-1; (p2 >= in->bv_val) && !DN_SEPARATOR(*p2); p2--); rdn.bv_val = p2+1; rdn.bv_len = p1-rdn.bv_val; p1 = p2; ldap_pvt_thread_rdwr_rlock(&p->i_kids_rdwr); n = bdb_find_rdn_node(&rdn, p->i_kids); ldap_pvt_thread_rdwr_runlock(&p->i_kids_rdwr); if (!n || p2 < in->bv_val) break; p = n; } ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); if (n) { *id = n->i_id; } else if (id2) { *id2 = p->i_id; } else { rc = DB_NOTFOUND; } return rc; }
int bdb_dn2id_children( BackendDB *be, DB_TXN *txn, struct berval *dn, int flags ) { int rc; struct bdb_info *bdb = (struct bdb_info *) be->be_private; ID id; idNode *n; rc = bdb_dn2id(be, txn, dn, &id, flags); if (rc != 0) return rc; ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); n = bdb_find_id_node(id, bdb->bi_tree); ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); if (!n->i_kids) return DB_NOTFOUND; else return 0; }
/* Find a db/key pair in the IDL cache. If ids is non-NULL, * copy the cached IDL into it, otherwise just return the status. */ int bdb_idl_cache_get( struct bdb_info *bdb, DB *db, DBT *key, ID *ids ) { 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; ldap_pvt_thread_rdwr_rlock( &bdb->bi_idl_tree_rwlock ); matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, bdb_idl_entry_cmp ); if ( matched_idl_entry != NULL ) { if ( matched_idl_entry->idl && ids ) BDB_IDL_CPY( ids, matched_idl_entry->idl ); matched_idl_entry->idl_flags |= CACHE_ENTRY_REFERENCED; if ( matched_idl_entry->idl ) rc = LDAP_SUCCESS; else rc = DB_NOTFOUND; } ldap_pvt_thread_rdwr_runlock( &bdb->bi_idl_tree_rwlock ); return rc; }
/* * Fetches a session */ struct rewrite_session * rewrite_session_find( struct rewrite_info *info, const void *cookie ) { struct rewrite_session *session, tmp; assert( info != NULL ); assert( cookie != NULL ); tmp.ls_cookie = ( void * )cookie; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_rlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ session = ( struct rewrite_session * )avl_find( info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp ); #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( session ) { ldap_pvt_thread_mutex_lock( &session->ls_mutex ); } ldap_pvt_thread_rdwr_runlock( &info->li_cookies_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return session; }
static int ndb_oc_check( BackendDB *be, Ndb *ndb, struct berval *ocsin, NdbOcs *out ) { struct ndb_info *ni = (struct ndb_info *) be->be_private; const NdbDictionary::Dictionary *myDict = ndb->getDictionary(); int i, rc = 0; out->no_ninfo = 0; out->no_ntext = 0; out->no_nitext = 0; /* Find all objectclasses and their superiors. List * the superiors first. */ ldap_pvt_thread_rdwr_rlock( &ni->ni_oc_rwlock ); for ( i=0; !BER_BVISNULL( &ocsin[i] ); i++ ) { rc = ndb_oc_list( ni, myDict, &ocsin[i], 0, out ); if ( rc ) break; } ldap_pvt_thread_rdwr_runlock( &ni->ni_oc_rwlock ); return rc; }
/* * Gets a var with global scope */ int rewrite_param_get( struct rewrite_info *info, const char *name, struct berval *value ) { struct rewrite_var *var; assert( info != NULL ); assert( name != NULL ); assert( value != NULL ); value->bv_val = NULL; value->bv_len = 0; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_rlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ var = rewrite_var_find( info->li_params, name ); if ( var == NULL ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_runlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return REWRITE_ERR; } else { value->bv_val = strdup( var->lv_value.bv_val ); value->bv_len = var->lv_value.bv_len; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_runlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ return REWRITE_SUCCESS; }
/* * Gets a var with session scope */ int rewrite_session_var_get( struct rewrite_info *info, const void *cookie, const char *name, struct berval *value ) { struct rewrite_session *session; struct rewrite_var *var; int rc = REWRITE_SUCCESS; assert( info != NULL ); assert( cookie != NULL ); assert( name != NULL ); assert( value != NULL ); value->bv_val = NULL; value->bv_len = 0; if ( cookie == NULL ) { return REWRITE_ERR; } session = rewrite_session_find( info, cookie ); if ( session == NULL ) { return REWRITE_ERR; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_rlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ var = rewrite_var_find( session->ls_vars, name ); if ( var != NULL ) { value->bv_val = strdup( var->lv_value.bv_val ); value->bv_len = var->lv_value.bv_len; } if ( var == NULL || value->bv_val == NULL ) { rc = REWRITE_ERR; } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ rewrite_session_return( info, session ); return rc; }
int bdb_dn2idl( BackendDB *be, struct berval *dn, int prefix, ID *ids ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; int rc; ID id; idNode *n; if (prefix == DN_SUBTREE_PREFIX && be_issuffix(be, dn)) { BDB_IDL_ALL(bdb, ids); return 0; } rc = bdb_dn2id(be, NULL, dn, &id, 0); if (rc) return rc; ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); n = bdb_find_id_node(id, bdb->bi_tree); ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); ids[0] = 0; ldap_pvt_thread_rdwr_rlock(&n->i_kids_rdwr); if (prefix == DN_ONE_PREFIX) { rc = avl_apply(n->i_kids, insert_one, ids, -1, AVL_INORDER); } else { ids[0] = 1; ids[1] = id; if (n->i_kids) rc = avl_apply(n->i_kids, insert_sub, ids, -1, AVL_INORDER); } ldap_pvt_thread_rdwr_runlock(&n->i_kids_rdwr); return rc; }
EntryInfo * bdb_cache_find_info( struct bdb_info *bdb, ID id ) { EntryInfo ei = { 0 }, *ei2; ei.bei_id = id; ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock ); ei2 = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree, (caddr_t) &ei, bdb_id_cmp ); ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock ); return ei2; }
static int bdb_cache_entry_rdwr_unlock(Entry *e, int rw) { #ifdef NEW_LOGGING LDAP_LOG( CACHE, ENTRY, "bdb_cache_entry_rdwr_unlock: remove %s lock on ID %ld.\n", rw ? "w" : "r", e->e_id, 0 ); #else Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%sunlock: ID: %ld\n", rw ? "w" : "r", e->e_id, 0); #endif if (rw) return ldap_pvt_thread_rdwr_wunlock(&BEI(e)->bei_rdwr); else return ldap_pvt_thread_rdwr_runlock(&BEI(e)->bei_rdwr); }
static int insert_sub( void *v_n, void *v_ids ) { idNode *n = v_n; ID *ids = v_ids; int rc; rc = bdb_idl_insert(ids, n->i_id); if (rc == 0) { ldap_pvt_thread_rdwr_rlock(&n->i_kids_rdwr); rc = avl_apply(n->i_kids, insert_sub, ids, -1, AVL_INORDER); ldap_pvt_thread_rdwr_runlock(&n->i_kids_rdwr); } return rc; }
/* This function constructs a full DN for a given id. We really should * be passing idNodes directly, to save some effort... */ int bdb_fix_dn( BackendDB *be, ID id, Entry *e ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; idNode *n, *o; int rlen, nrlen; char *ptr, *nptr; ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); o = bdb_find_id_node(id, bdb->bi_tree); rlen = be->be_suffix[0].bv_len + 1; nrlen = be->be_nsuffix[0].bv_len + 1; for (n = o; n && n->i_parent; n=n->i_parent) { rlen += n->i_rdn->rdn.bv_len + 1; nrlen += n->i_rdn->nrdn.bv_len + 1; } e->e_name.bv_len = rlen - 1; e->e_nname.bv_len = nrlen - 1; e->e_name.bv_val = ch_malloc(rlen + nrlen); e->e_nname.bv_val = e->e_name.bv_val + rlen; ptr = e->e_name.bv_val; nptr = e->e_nname.bv_val; for (n = o; n && n->i_parent; n=n->i_parent) { ptr = lutil_strcopy(ptr, n->i_rdn->rdn.bv_val); *ptr++ = ','; nptr = lutil_strcopy(nptr, n->i_rdn->nrdn.bv_val); *nptr++ = ','; } ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); strcpy(ptr, be->be_suffix[0].bv_val); strcpy(nptr, be->be_nsuffix[0].bv_val); return 0; }
static int ndb_oc_list( struct ndb_info *ni, const NdbDictionary::Dictionary *myDict, struct berval *oname, int implied, NdbOcs *out ) { const NdbDictionary::Table *myTable; NdbOcInfo *oci, octmp; ObjectClass *oc; int i, rc; /* shortcut top */ if ( ber_bvstrcasecmp( oname, &slap_schema.si_oc_top->soc_cname )) { octmp.no_name = *oname; oci = (NdbOcInfo *)avl_find( ni->ni_oc_tree, &octmp, ndb_name_cmp ); if ( oci ) { oc = oci->no_oc; } else { oc = oc_bvfind( oname ); if ( !oc ) { /* undefined - shouldn't happen */ return LDAP_INVALID_SYNTAX; } } if ( oc->soc_sups ) { int i; for ( i=0; oc->soc_sups[i]; i++ ) { rc = ndb_oc_list( ni, myDict, &oc->soc_sups[i]->soc_cname, 1, out ); if ( rc ) return rc; } } } else { oc = slap_schema.si_oc_top; } /* Only insert once */ for ( i=0; i<out->no_ntext; i++ ) if ( out->no_text[i].bv_val == oc->soc_cname.bv_val ) break; if ( i == out->no_ntext ) { for ( i=0; i<out->no_nitext; i++ ) if ( out->no_itext[i].bv_val == oc->soc_cname.bv_val ) break; if ( i == out->no_nitext ) { if ( implied ) out->no_itext[out->no_nitext++] = oc->soc_cname; else out->no_text[out->no_ntext++] = oc->soc_cname; } } /* ignore top, etc... */ if ( oc->soc_kind == LDAP_SCHEMA_ABSTRACT ) return 0; if ( !oci ) { ldap_pvt_thread_rdwr_runlock( &ni->ni_oc_rwlock ); oci = (NdbOcInfo *)ch_malloc( sizeof( NdbOcInfo )+oc->soc_cname.bv_len+1 ); oci->no_table.bv_val = (char *)(oci+1); strcpy( oci->no_table.bv_val, oc->soc_cname.bv_val ); oci->no_table.bv_len = oc->soc_cname.bv_len; oci->no_name = oci->no_table; oci->no_oc = oc; oci->no_flag = 0; oci->no_nsets = 0; oci->no_nattrs = 0; ldap_pvt_thread_rdwr_wlock( &ni->ni_oc_rwlock ); if ( avl_insert( &ni->ni_oc_tree, oci, ndb_name_cmp, ndb_oc_dup_err )) { octmp.no_oc = oci->no_oc; ch_free( oci ); oci = (NdbOcInfo *)octmp.no_oc; } /* see if the oc table already exists in the DB */ myTable = myDict->getTable( oci->no_table.bv_val ); rc = ndb_oc_create( ni, oci, myTable == NULL ); ldap_pvt_thread_rdwr_wunlock( &ni->ni_oc_rwlock ); ldap_pvt_thread_rdwr_rlock( &ni->ni_oc_rwlock ); if ( rc ) return rc; } /* Only insert once */ for ( i=0; i<out->no_ninfo; i++ ) if ( out->no_info[i] == oci ) break; if ( i == out->no_ninfo ) out->no_info[out->no_ninfo++] = oci; return 0; }
int bdb_cache_find_id( Operation *op, DB_TXN *tid, ID id, EntryInfo **eip, int flag, DB_LOCK *lock ) { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; Entry *ep = NULL; int rc = 0, load = 0; EntryInfo ei = { 0 }; ei.bei_id = id; #ifdef SLAP_ZONE_ALLOC slap_zh_rlock(bdb->bi_cache.c_zctx); #endif /* If we weren't given any info, see if we have it already cached */ if ( !*eip ) { again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock ); *eip = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree, (caddr_t) &ei, bdb_id_cmp ); if ( *eip ) { /* If the lock attempt fails, the info is in use */ if ( bdb_cache_entryinfo_trylock( *eip )) { int del = (*eip)->bei_state & CACHE_ENTRY_DELETED; ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock ); /* If this node is being deleted, treat * as if the delete has already finished */ if ( del ) { return DB_NOTFOUND; } /* otherwise, wait for the info to free up */ ldap_pvt_thread_yield(); goto again; } /* If this info isn't hooked up to its parent yet, * unlock and wait for it to be fully initialized */ if ( (*eip)->bei_state & CACHE_ENTRY_NOT_LINKED ) { bdb_cache_entryinfo_unlock( *eip ); ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock ); ldap_pvt_thread_yield(); goto again; } flag |= ID_LOCKED; } ldap_pvt_thread_rdwr_runlock( &bdb->bi_cache.c_rwlock ); } /* See if the ID exists in the database; add it to the cache if so */ if ( !*eip ) { #ifndef BDB_HIER rc = bdb_id2entry( op->o_bd, tid, id, &ep ); if ( rc == 0 ) { rc = bdb_cache_find_ndn( op, tid, &ep->e_nname, eip ); if ( *eip ) flag |= ID_LOCKED; if ( rc ) { ep->e_private = NULL; #ifdef SLAP_ZONE_ALLOC bdb_entry_return( bdb, ep, (*eip)->bei_zseq ); #else bdb_entry_return( ep ); #endif ep = NULL; } } #else rc = hdb_cache_find_parent(op, tid, id, eip ); if ( rc == 0 ) flag |= ID_LOCKED; #endif } /* Ok, we found the info, do we have the entry? */ if ( rc == 0 ) { if ( !( flag & ID_LOCKED )) { bdb_cache_entryinfo_lock( *eip ); flag |= ID_LOCKED; } if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) { rc = DB_NOTFOUND; } else { (*eip)->bei_finders++; (*eip)->bei_state |= CACHE_ENTRY_REFERENCED; if ( flag & ID_NOENTRY ) { bdb_cache_entryinfo_unlock( *eip ); return 0; } /* Make sure only one thread tries to load the entry */ load1: #ifdef SLAP_ZONE_ALLOC if ((*eip)->bei_e && !slap_zn_validate( bdb->bi_cache.c_zctx, (*eip)->bei_e, (*eip)->bei_zseq)) { (*eip)->bei_e = NULL; (*eip)->bei_zseq = 0; } #endif if ( !(*eip)->bei_e && !((*eip)->bei_state & CACHE_ENTRY_LOADING)) { load = 1; (*eip)->bei_state |= CACHE_ENTRY_LOADING; flag |= ID_CHKPURGE; } if ( !load ) { /* Clear the uncached state if we are not * loading it, i.e it is already cached or * another thread is currently loading it. */ if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) { (*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED; flag |= ID_CHKPURGE; } } if ( flag & ID_LOCKED ) { bdb_cache_entryinfo_unlock( *eip ); flag ^= ID_LOCKED; } rc = bdb_cache_entry_db_lock( bdb, tid, *eip, load, 0, lock ); if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) { rc = DB_NOTFOUND; bdb_cache_entry_db_unlock( bdb, lock ); bdb_cache_entryinfo_lock( *eip ); (*eip)->bei_finders--; bdb_cache_entryinfo_unlock( *eip ); } else if ( rc == 0 ) { if ( load ) { if ( !ep) { rc = bdb_id2entry( op->o_bd, tid, id, &ep ); } if ( rc == 0 ) { ep->e_private = *eip; #ifdef BDB_HIER while ( (*eip)->bei_state & CACHE_ENTRY_NOT_LINKED ) ldap_pvt_thread_yield(); bdb_fix_dn( ep, 0 ); #endif bdb_cache_entryinfo_lock( *eip ); (*eip)->bei_e = ep; #ifdef SLAP_ZONE_ALLOC (*eip)->bei_zseq = *((ber_len_t *)ep - 2); #endif ep = NULL; if ( flag & ID_NOCACHE ) { /* Set the cached state only if no other thread * found the info while we were loading the entry. */ if ( (*eip)->bei_finders == 1 ) { (*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED; flag ^= ID_CHKPURGE; } } bdb_cache_entryinfo_unlock( *eip ); bdb_cache_lru_link( bdb, *eip ); } if ( rc == 0 ) { /* If we succeeded, downgrade back to a readlock. */ rc = bdb_cache_entry_db_relock( bdb, tid, *eip, 0, 0, lock ); } else { /* Otherwise, release the lock. */ bdb_cache_entry_db_unlock( bdb, lock ); } } else if ( !(*eip)->bei_e ) { /* Some other thread is trying to load the entry, * wait for it to finish. */ bdb_cache_entry_db_unlock( bdb, lock ); bdb_cache_entryinfo_lock( *eip ); flag |= ID_LOCKED; goto load1; #ifdef BDB_HIER } else { /* Check for subtree renames */ rc = bdb_fix_dn( (*eip)->bei_e, 1 ); if ( rc ) { bdb_cache_entry_db_relock( bdb, tid, *eip, 1, 0, lock ); /* check again in case other modifier did it already */ if ( bdb_fix_dn( (*eip)->bei_e, 1 ) ) rc = bdb_fix_dn( (*eip)->bei_e, 2 ); bdb_cache_entry_db_relock( bdb, tid, *eip, 0, 0, lock ); } #endif } bdb_cache_entryinfo_lock( *eip ); (*eip)->bei_finders--; if ( load ) (*eip)->bei_state ^= CACHE_ENTRY_LOADING; bdb_cache_entryinfo_unlock( *eip ); } } } if ( flag & ID_LOCKED ) { bdb_cache_entryinfo_unlock( *eip ); } if ( ep ) { ep->e_private = NULL; #ifdef SLAP_ZONE_ALLOC bdb_entry_return( bdb, ep, (*eip)->bei_zseq ); #else bdb_entry_return( ep ); #endif } if ( rc == 0 ) { int purge = 0; if (( flag & ID_CHKPURGE ) || bdb->bi_cache.c_eimax ) { ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex ); if ( flag & ID_CHKPURGE ) { bdb->bi_cache.c_cursize++; if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) { purge = 1; bdb->bi_cache.c_purging = 1; } } else if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) { purge = 1; bdb->bi_cache.c_purging = 1; } ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex ); } if ( purge ) bdb_cache_lru_purge( bdb ); } #ifdef SLAP_ZONE_ALLOC if (rc == 0 && (*eip)->bei_e) { slap_zn_rlock(bdb->bi_cache.c_zctx, (*eip)->bei_e); } slap_zh_runlock(bdb->bi_cache.c_zctx); #endif return rc; }
int ldbm_back_bind( Backend *be, Connection *conn, Operation *op, struct berval *dn, struct berval *ndn, int method, struct berval *cred, struct berval *edn ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; Entry *e; Attribute *a; int rc; Entry *matched; #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND char krbname[MAX_K_NAME_SZ + 1]; AttributeDescription *krbattr = slap_schema.si_ad_krbName; AUTH_DAT ad; #endif AttributeDescription *password = slap_schema.si_ad_userPassword; #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_back_bind: dn: %s.\n", dn->bv_val, 0, 0 ); #else Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_bind: dn: %s\n", dn->bv_val, 0, 0); #endif dn = ndn; /* grab giant lock for reading */ ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock); /* get entry with reader lock */ if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) { char *matched_dn = NULL; BerVarray refs = NULL; if( matched != NULL ) { matched_dn = ch_strdup( matched->e_dn ); refs = is_entry_referral( matched ) ? get_entry_referrals( be, conn, op, matched ) : NULL; cache_return_entry_r( &li->li_cache, matched ); } else { refs = referral_rewrite( default_referral, NULL, dn, LDAP_SCOPE_DEFAULT ); } ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); /* allow noauth binds */ rc = 1; if ( method == LDAP_AUTH_SIMPLE ) { if ( be_isroot_pw( be, conn, dn, cred ) ) { ber_dupbv( edn, be_root_dn( be ) ); rc = 0; /* front end will send result */ } else if ( refs != NULL ) { send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); } else { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); } } else if ( refs != NULL ) { send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); } else { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); } if ( refs ) ber_bvarray_free( refs ); if ( matched_dn ) free( matched_dn ); return( rc ); } ber_dupbv( edn, &e->e_name ); /* check for deleted */ if ( is_entry_alias( e ) ) { /* entry is an alias, don't allow bind */ #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, INFO, "ldbm_back_bind: entry (%s) is an alias.\n", e->e_dn, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0, 0, 0 ); #endif send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, NULL, "entry is alias", NULL, NULL ); rc = 1; goto return_results; } if ( is_entry_referral( e ) ) { /* entry is a referral, don't allow bind */ BerVarray refs = get_entry_referrals( be, conn, op, e ); #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, INFO, "ldbm_back_bind: entry(%s) is a referral.\n", e->e_dn, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); #endif if( refs != NULL ) { send_ldap_result( conn, op, LDAP_REFERRAL, e->e_dn, NULL, refs, NULL ); } else { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); } ber_bvarray_free( refs ); rc = 1; goto return_results; } switch ( method ) { case LDAP_AUTH_SIMPLE: /* check for root dn/passwd */ if ( be_isroot_pw( be, conn, dn, cred ) ) { /* front end will send result */ if(edn->bv_val != NULL) free( edn->bv_val ); ber_dupbv( edn, be_root_dn( be ) ); rc = 0; goto return_results; } if ( ! access_allowed( be, conn, op, e, password, NULL, ACL_AUTH, NULL ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } if ( (a = attr_find( e->e_attrs, password )) == NULL ) { send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, NULL, NULL ); /* stop front end from sending result */ rc = 1; goto return_results; } if ( slap_passwd_check( conn, a, cred ) != 0 ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); /* stop front end from sending result */ rc = 1; goto return_results; } rc = 0; break; #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND case LDAP_AUTH_KRBV41: if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } if ( ! access_allowed( be, conn, op, e, krbattr, NULL, ACL_AUTH, NULL ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "." : "", ad.pinst, ad.prealm ); if ( (a = attr_find( e->e_attrs, krbattr )) == NULL ) { /* * no krbname values present: check against DN */ if ( strcasecmp( dn->bv_val, krbname ) == 0 ) { rc = 0; break; } send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } else { /* look for krbname match */ struct berval krbval; krbval.bv_val = krbname; krbval.bv_len = strlen( krbname ); if ( value_find( a->a_desc, a->a_vals, &krbval ) != 0 ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } } rc = 0; break; case LDAP_AUTH_KRBV42: send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL, "Kerberos bind step 2 not supported", NULL, NULL ); /* stop front end from sending result */ rc = LDAP_UNWILLING_TO_PERFORM; goto return_results; #endif default: send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED, NULL, "authentication method not supported", NULL, NULL ); rc = 1; goto return_results; } return_results:; /* free entry and reader lock */ cache_return_entry_r( &li->li_cache, e ); ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); /* front end will send result on success (rc==0) */ return( rc ); }
int bdb_dn2id_add( BackendDB *be, DB_TXN *txn, struct berval *pdn, Entry *e ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; int rc, rlen, nrlen; DBT key, data; DB *db = bdb->bi_id2parent->bdi_db; diskNode *d; idNode *n; nrlen = dn_rdnlen( be, &e->e_nname ); if (nrlen) { rlen = dn_rdnlen( be, &e->e_name ); } else { rlen = 0; } d = ch_malloc(sizeof(diskNode) + rlen + nrlen + 2); d->rdn.bv_len = rlen; d->nrdn.bv_len = nrlen; d->rdn.bv_val = (char *)(d+1); d->nrdn.bv_val = d->rdn.bv_val + rlen + 1; strncpy(d->rdn.bv_val, e->e_dn, rlen); d->rdn.bv_val[rlen] = '\0'; strncpy(d->nrdn.bv_val, e->e_ndn, nrlen); d->nrdn.bv_val[nrlen] = '\0'; d->rdn.bv_val -= (long)d; d->nrdn.bv_val -= (long)d; if (pdn->bv_len) { bdb_dn2id(be, txn, pdn, &d->parent, 0); } else { d->parent = 0; } DBTzero(&key); DBTzero(&data); key.data = &e->e_id; key.size = sizeof(ID); key.flags = DB_DBT_USERMEM; data.data = d; data.size = sizeof(diskNode) + rlen + nrlen + 2; data.flags = DB_DBT_USERMEM; rc = db->put( db, txn, &key, &data, DB_NOOVERWRITE ); if (rc == 0) { ldap_pvt_thread_rdwr_wlock(&bdb->bi_tree_rdwr); n = bdb_add_node( e->e_id, data.data, bdb); ldap_pvt_thread_rdwr_wunlock(&bdb->bi_tree_rdwr); if (d->parent) { ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr); bdb_insert_kid(n, bdb->bi_tree); ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr); } } else { free(d); } return rc; }
Entry * bdb_cache_find_entry_id( DB_ENV *env, Cache *cache, ID id, int rw, u_int32_t locker, DB_LOCK *lock ) { Entry e; Entry *ep; int count = 0; int rc; e.e_id = id; try_again: /* set cache read lock */ ldap_pvt_thread_rdwr_rlock( &cache->c_rwlock ); if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e, entry_id_cmp )) != NULL ) { int state; ID ep_id; count++; assert( ep->e_private ); ep_id = ep->e_id; state = BEI(ep)->bei_state; /* * entry is deleted or not fully created yet */ if ( state != CACHE_ENTRY_READY && state != CACHE_ENTRY_COMMITTED ) { assert(state != CACHE_ENTRY_UNDEFINED); /* free cache read lock */ ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); #ifdef NEW_LOGGING LDAP_LOG( CACHE, INFO, "bdb_cache_find_entry_id: (%ld)->%ld not ready (%d).\n", id, ep_id, state ); #else Debug(LDAP_DEBUG_TRACE, "====> bdb_cache_find_entry_id( %ld ): %ld (not ready) %d\n", id, ep_id, state); #endif ldap_pvt_thread_yield(); goto try_again; } /* acquire reader lock */ rc = bdb_cache_entry_db_lock ( env, locker, ep, rw, 0, lock ); #if 0 if ( bdb_cache_entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) { #endif if ( rc ) { /* will be changed to retry beyond threshold */ /* could not acquire entry lock... * owner cannot free as we have the cache locked. * so, unlock the cache, yield, and try again. */ /* free cache read lock */ ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); #ifdef NEW_LOGGING LDAP_LOG( CACHE, INFO, "bdb_cache_find_entry_id: %ld -> %ld (busy) %d.\n", id, ep_id, state ); #else Debug(LDAP_DEBUG_TRACE, "====> bdb_cache_find_entry_id( %ld ): %ld (busy) %d\n", id, ep_id, state); Debug(LDAP_DEBUG_TRACE, "locker = %d\n", locker, 0, 0); #endif ldap_pvt_thread_yield(); goto try_again; } /* Mark entry in-use */ BEI(ep)->bei_refcnt++; /* free cache read lock */ ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); /* set lru mutex */ ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); /* lru */ LRU_DELETE( cache, ep ); LRU_ADD( cache, ep ); /* free lru mutex */ ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); #ifdef NEW_LOGGING LDAP_LOG( CACHE, DETAIL1, "bdb_cache_find_entry_id: %ld -> %s found %d tries.\n", ep_id, ep->e_dn, count ); #else Debug(LDAP_DEBUG_TRACE, "====> bdb_cache_find_entry_id( %ld ) \"%s\" (found) (%d tries)\n", ep_id, ep->e_dn, count); #endif return( ep ); } /* free cache read lock */ ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); return( NULL ); } /* * cache_delete_entry - delete the entry e from the cache. the caller * should have obtained e (increasing its ref count) via a call to one * of the cache_find_* routines. the caller should *not* call the * cache_return_entry() routine prior to calling cache_delete_entry(). * it performs this function. * * returns: 0 e was deleted ok * 1 e was not in the cache * -1 something bad happened */ int bdb_cache_delete_entry( Cache *cache, Entry *e ) { int rc; /* set cache write lock */ ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock ); assert( e->e_private ); #ifdef NEW_LOGGING LDAP_LOG( CACHE, ENTRY, "bdb_cache_delete_entry: delete %ld.\n", e->e_id, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_delete_entry( %ld )\n", e->e_id, 0, 0 ); #endif /* set lru mutex */ ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); rc = bdb_cache_delete_entry_internal( cache, e ); /* free lru mutex */ ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); /* free cache write lock */ ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); return( rc ); }
int ndb_modify_internal( Operation *op, NdbArgs *NA, const char **text, char *textbuf, size_t textlen ) { struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; Modification *mod; Modifications *ml; Modifications *modlist = op->orm_modlist; NdbAttrInfo **modai, *atmp; const NdbDictionary::Dictionary *myDict; const NdbDictionary::Table *myTable; int got_oc = 0, nmods = 0, nai = 0, i, j; int rc, indexed = 0; Attribute *old = NULL; Debug( LDAP_DEBUG_TRACE, "ndb_modify_internal: 0x%08lx: %s\n", NA->e->e_id, NA->e->e_dn, 0); if ( !acl_check_modlist( op, NA->e, modlist )) { return LDAP_INSUFFICIENT_ACCESS; } old = attrs_dup( NA->e->e_attrs ); for ( ml = modlist; ml != NULL; ml = ml->sml_next ) { mod = &ml->sml_mod; nmods++; switch ( mod->sm_op ) { case LDAP_MOD_ADD: Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: add %s\n", mod->sm_desc->ad_cname.bv_val, 0, 0); rc = modify_add_values( NA->e, mod, get_permissiveModify(op), text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n", rc, *text, 0); } break; case LDAP_MOD_DELETE: Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: delete %s\n", mod->sm_desc->ad_cname.bv_val, 0, 0); rc = ndb_modify_delete( NA->e, mod, get_permissiveModify(op), text, textbuf, textlen, NULL ); assert( rc != LDAP_TYPE_OR_VALUE_EXISTS ); if( rc != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n", rc, *text, 0); } break; case LDAP_MOD_REPLACE: Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: replace %s\n", mod->sm_desc->ad_cname.bv_val, 0, 0); rc = modify_replace_values( NA->e, mod, get_permissiveModify(op), text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n", rc, *text, 0); } break; case LDAP_MOD_INCREMENT: Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: increment %s\n", mod->sm_desc->ad_cname.bv_val, 0, 0); rc = modify_increment_values( NA->e, mod, get_permissiveModify(op), text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n", rc, *text, 0); } break; case SLAP_MOD_SOFTADD: Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: softadd %s\n", mod->sm_desc->ad_cname.bv_val, 0, 0); mod->sm_op = LDAP_MOD_ADD; rc = modify_add_values( NA->e, mod, get_permissiveModify(op), text, textbuf, textlen ); mod->sm_op = SLAP_MOD_SOFTADD; if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { rc = LDAP_SUCCESS; } if( rc != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n", rc, *text, 0); } break; case SLAP_MOD_SOFTDEL: Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: softdel %s\n", mod->sm_desc->ad_cname.bv_val, 0, 0); mod->sm_op = LDAP_MOD_DELETE; rc = modify_delete_values( NA->e, mod, get_permissiveModify(op), text, textbuf, textlen ); mod->sm_op = SLAP_MOD_SOFTDEL; if ( rc == LDAP_NO_SUCH_ATTRIBUTE) { rc = LDAP_SUCCESS; } if( rc != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n", rc, *text, 0); } break; case SLAP_MOD_ADD_IF_NOT_PRESENT: Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: add_if_not_present %s\n", mod->sm_desc->ad_cname.bv_val, 0, 0); if ( attr_find( NA->e->e_attrs, mod->sm_desc ) ) { rc = LDAP_SUCCESS; break; } mod->sm_op = LDAP_MOD_ADD; rc = modify_add_values( NA->e, mod, get_permissiveModify(op), text, textbuf, textlen ); mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT; if( rc != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n", rc, *text, 0); } break; default: Debug(LDAP_DEBUG_ANY, "ndb_modify_internal: invalid op %d\n", mod->sm_op, 0, 0); *text = "Invalid modify operation"; rc = LDAP_OTHER; Debug(LDAP_DEBUG_ARGS, "ndb_modify_internal: %d %s\n", rc, *text, 0); } if ( rc != LDAP_SUCCESS ) { attrs_free( old ); return rc; } /* If objectClass was modified, reset the flags */ if ( mod->sm_desc == slap_schema.si_ad_objectClass ) { NA->e->e_ocflags = 0; got_oc = 1; } } /* check that the entry still obeys the schema */ rc = entry_schema_check( op, NA->e, NULL, get_relax(op), 0, NULL, text, textbuf, textlen ); if ( rc != LDAP_SUCCESS || op->o_noop ) { if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "entry failed schema check: %s\n", *text, 0, 0 ); } attrs_free( old ); return rc; } if ( got_oc ) { rc = ndb_entry_put_info( op->o_bd, NA, 1 ); if ( rc ) { attrs_free( old ); return rc; } } /* apply modifications to DB */ modai = (NdbAttrInfo **)op->o_tmpalloc( nmods * sizeof(NdbAttrInfo*), op->o_tmpmemctx ); /* Get the unique list of modified attributes */ ldap_pvt_thread_rdwr_rlock( &ni->ni_ai_rwlock ); for ( ml = modlist; ml != NULL; ml = ml->sml_next ) { /* Already took care of objectclass */ if ( ml->sml_desc == slap_schema.si_ad_objectClass ) continue; for ( i=0; i<nai; i++ ) { if ( ml->sml_desc->ad_type == modai[i]->na_attr ) break; } /* This attr was already updated */ if ( i < nai ) continue; modai[nai] = ndb_ai_find( ni, ml->sml_desc->ad_type ); if ( modai[nai]->na_flag & NDB_INFO_INDEX ) indexed++; nai++; } ldap_pvt_thread_rdwr_runlock( &ni->ni_ai_rwlock ); /* If got_oc, this was already done above */ if ( indexed && !got_oc) { rc = ndb_entry_put_info( op->o_bd, NA, 1 ); if ( rc ) { attrs_free( old ); return rc; } } myDict = NA->ndb->getDictionary(); /* sort modai so that OcInfo's are contiguous */ { int j, k; for ( i=0; i<nai; i++ ) { for ( j=i+1; j<nai; j++ ) { if ( modai[i]->na_oi == modai[j]->na_oi ) continue; for ( k=j+1; k<nai; k++ ) { if ( modai[i]->na_oi == modai[k]->na_oi ) { atmp = modai[j]; modai[j] = modai[k]; modai[k] = atmp; break; } } /* there are no more na_oi's that match modai[i] */ if ( k == nai ) { i = j; } } } } /* One call per table... */ for ( i=0; i<nai; i += j ) { atmp = modai[i]; for ( j=i+1; j<nai; j++ ) if ( atmp->na_oi != modai[j]->na_oi ) break; j -= i; myTable = myDict->getTable( atmp->na_oi->no_table.bv_val ); if ( !myTable ) continue; rc = ndb_oc_attrs( NA->txn, myTable, NA->e, atmp->na_oi, &modai[i], j, old ); if ( rc ) break; } attrs_free( old ); return rc; }
int ldbm_back_compare( Backend *be, Connection *conn, Operation *op, struct berval *dn, struct berval *ndn, AttributeAssertion *ava ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; Entry *matched; Entry *e; Attribute *a; int rc; int manageDSAit = get_manageDSAit( op ); /* grab giant lock for reading */ ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock); /* get entry with reader lock */ if ( (e = dn2entry_r( be, ndn, &matched )) == NULL ) { char *matched_dn = NULL; BerVarray refs = NULL; if ( matched != NULL ) { matched_dn = ch_strdup( matched->e_dn ); refs = is_entry_referral( matched ) ? get_entry_referrals( be, conn, op, matched ) : NULL; cache_return_entry_r( &li->li_cache, matched ); } else { refs = referral_rewrite( default_referral, NULL, dn, LDAP_SCOPE_DEFAULT ); } ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); send_ldap_result( conn, op, LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); if ( refs ) ber_bvarray_free( refs ); free( matched_dn ); return( 1 ); } if (!manageDSAit && is_entry_referral( e ) ) { /* entry is a referral, don't allow add */ BerVarray refs = get_entry_referrals( be, conn, op, e ); #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, INFO, "ldbm_back_compare: entry (%s) is a referral.\n", e->e_dn, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); #endif send_ldap_result( conn, op, LDAP_REFERRAL, e->e_dn, NULL, refs, NULL ); if (refs ) ber_bvarray_free( refs ); rc = 1; goto return_results; } if ( ! access_allowed( be, conn, op, e, ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) ) { send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, NULL, NULL ); rc = 1; goto return_results; } rc = LDAP_NO_SUCH_ATTRIBUTE; for(a = attrs_find( e->e_attrs, ava->aa_desc ); a != NULL; a = attrs_find( a->a_next, ava->aa_desc )) { rc = LDAP_COMPARE_FALSE; if ( value_find( ava->aa_desc, a->a_vals, &ava->aa_value ) == 0 ) { rc = LDAP_COMPARE_TRUE; break; } } send_ldap_result( conn, op, rc, NULL, NULL, NULL, NULL ); if( rc != LDAP_NO_SUCH_ATTRIBUTE ) { rc = 0; } return_results: ; cache_return_entry_r( &li->li_cache, e ); ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); return( rc ); }
int ldbm_back_referrals( Backend *be, Connection *conn, Operation *op, struct berval *dn, struct berval *ndn, const char **text ) { struct ldbminfo *li = (struct ldbminfo *) be->be_private; int rc = LDAP_SUCCESS; Entry *e, *matched; if( op->o_tag == LDAP_REQ_SEARCH ) { /* let search take care of itself */ return rc; } if( get_manageDSAit( op ) ) { /* let op take care of DSA management */ return rc; } /* grab giant lock for reading */ ldap_pvt_thread_rdwr_rlock(&li->li_giant_rwlock); /* get entry with reader lock */ e = dn2entry_r( be, ndn, &matched ); if ( e == NULL ) { char *matched_dn = NULL; BerVarray refs = NULL; if ( matched != NULL ) { matched_dn = ch_strdup( matched->e_dn ); #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, DETAIL1, "ldbm_back_referrals: op=%ld target=\"%s\" matched=\"%s\"\n", op->o_tag, dn->bv_val, matched_dn ); #else Debug( LDAP_DEBUG_TRACE, "ldbm_referrals: op=%ld target=\"%s\" matched=\"%s\"\n", op->o_tag, dn->bv_val, matched_dn ); #endif if( is_entry_referral( matched ) ) { rc = LDAP_OTHER; refs = get_entry_referrals( be, conn, op, matched ); } cache_return_entry_r( &li->li_cache, matched ); } else if ( default_referral != NULL ) { rc = LDAP_OTHER; refs = referral_rewrite( default_referral, NULL, dn, LDAP_SCOPE_DEFAULT ); } ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); if( refs != NULL ) { /* send referrals */ send_ldap_result( conn, op, rc = LDAP_REFERRAL, matched_dn, NULL, refs, NULL ); ber_bvarray_free( refs ); } else if ( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, matched_dn, matched_dn ? "bad referral object" : "bad default referral", NULL, NULL ); } if ( matched_dn ) free( matched_dn ); return rc; } if ( is_entry_referral( e ) ) { /* entry is a referral */ BerVarray refs = get_entry_referrals( be, conn, op, e ); BerVarray rrefs = referral_rewrite( refs, &e->e_name, dn, LDAP_SCOPE_DEFAULT ); #ifdef NEW_LOGGING LDAP_LOG( BACK_LDBM, DETAIL1, "ldbm_referrals: op=%ld target=\"%s\" matched=\"%s\"\n", op->o_tag, dn->bv_val, e->e_dn ); #else Debug( LDAP_DEBUG_TRACE, "ldbm_referrals: op=%ld target=\"%s\" matched=\"%s\"\n", op->o_tag, dn->bv_val, e->e_dn ); #endif if( rrefs != NULL ) { send_ldap_result( conn, op, rc = LDAP_REFERRAL, e->e_dn, NULL, rrefs, NULL ); ber_bvarray_free( rrefs ); } else { send_ldap_result( conn, op, rc = LDAP_OTHER, e->e_dn, "bad referral object", NULL, NULL ); } if( refs != NULL ) ber_bvarray_free( refs ); } cache_return_entry_r( &li->li_cache, e ); ldap_pvt_thread_rdwr_runlock(&li->li_giant_rwlock); return rc; }
ID bdb_cache_find_entry_ndn2id( Backend *be, Cache *cache, struct berval *ndn ) { Entry e, *ep; ID id; int count = 0; /* this function is always called with normalized DN */ e.e_nname = *ndn; try_again: /* set cache read lock */ ldap_pvt_thread_rdwr_rlock( &cache->c_rwlock ); if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e, entry_dn_cmp )) != NULL ) { int state; count++; /* * ep now points to an unlocked entry * we do not need to lock the entry if we only * check the state, refcnt, LRU, and id. */ assert( ep->e_private ); /* save id */ id = ep->e_id; state = BEI(ep)->bei_state; /* * entry is deleted or not fully created yet */ if ( state != CACHE_ENTRY_READY && state != CACHE_ENTRY_COMMITTED ) { assert(state != CACHE_ENTRY_UNDEFINED); /* free cache read lock */ ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); #ifdef NEW_LOGGING LDAP_LOG( CACHE, INFO, "bdb_cache_find_entry_dn2id: (%s) %ld not ready: %d\n", ndn->bv_val, id, state ); #else Debug(LDAP_DEBUG_TRACE, "====> bdb_cache_find_entry_dn2id(\"%s\"): %ld (not ready) %d\n", ndn->bv_val, id, state); #endif ldap_pvt_thread_yield(); goto try_again; } /* free cache read lock */ ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); /* set lru mutex */ ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); /* lru */ LRU_DELETE( cache, ep ); LRU_ADD( cache, ep ); /* free lru mutex */ ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); #ifdef NEW_LOGGING LDAP_LOG( CACHE, DETAIL1, "bdb_cache_find_entry_dn2id: (%s): %ld %d tries\n", ndn->bv_val, id, count ); #else Debug(LDAP_DEBUG_TRACE, "====> bdb_cache_find_entry_dn2id(\"%s\"): %ld (%d tries)\n", ndn->bv_val, id, count); #endif } else { /* free cache read lock */ ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); id = NOID; } return( id ); }