From 99950e4fe4187550e6d5b4c5621fbb9a598f6821 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Wed, 26 Mar 2003 11:50:03 +0000 Subject: [PATCH] Deleted BackendInfo->bi_acl_attribute, bi_acl_group. Replaced with bi_entry_get_rw. Implemented for back-bdb, back-ldbm, back-ldap. --- servers/slapd/back-bdb/id2entry.c | 166 ++++++++++++++++++++ servers/slapd/back-bdb/init.c | 13 +- servers/slapd/back-bdb/proto-bdb.h | 13 +- servers/slapd/back-dnssrv/init.c | 2 - servers/slapd/back-ldap/back-ldap.h | 3 + servers/slapd/back-ldap/external.h | 4 +- servers/slapd/back-ldap/init.c | 3 +- servers/slapd/back-ldap/search.c | 175 +++++++++++++++++----- servers/slapd/back-ldbm/entry.c | 115 ++++++++++++++ servers/slapd/back-ldbm/external.h | 4 - servers/slapd/back-ldbm/init.c | 3 +- servers/slapd/back-ldbm/proto-back-ldbm.h | 2 + servers/slapd/back-meta/external.h | 3 - servers/slapd/back-meta/init.c | 2 - servers/slapd/back-monitor/init.c | 2 - servers/slapd/back-passwd/init.c | 2 - servers/slapd/back-perl/init.c | 2 - servers/slapd/back-shell/init.c | 2 - servers/slapd/back-sql/init.c | 2 - servers/slapd/backend.c | 166 +++++++++++++++----- servers/slapd/proto-slap.h | 4 + servers/slapd/slap.h | 27 ++-- 22 files changed, 565 insertions(+), 150 deletions(-) diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c index 6065491faa..598ee76ce8 100644 --- a/servers/slapd/back-bdb/id2entry.c +++ b/servers/slapd/back-bdb/id2entry.c @@ -267,3 +267,169 @@ int bdb_entry_release( return 0; } + +/* return LDAP_SUCCESS IFF we can retrieve the specified entry. + */ +int bdb_entry_get( + BackendDB *be, + Connection *c, + Operation *op, + struct berval *ndn, + ObjectClass *oc, + AttributeDescription *at, + int rw, + Entry **ent ) +{ + struct bdb_info *bdb = (struct bdb_info *) be->be_private; + struct bdb_op_info *boi = NULL; + DB_TXN *txn = NULL; + Entry *e; + int rc; + const char *at_name = at->ad_cname.bv_val; + + u_int32_t locker = 0; + DB_LOCK lock; + int free_lock_id = 0; + +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, ARGS, + "bdb_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 ); + LDAP_LOG( BACK_BDB, ARGS, + "bdb_entry_get: oc: \"%s\", at: \"%s\"\n", + oc ? oc->soc_cname.bv_val : "(null)", at_name, 0); +#else + Debug( LDAP_DEBUG_ARGS, + "=> bdb_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 ); + Debug( LDAP_DEBUG_ARGS, + "=> bdb_entry_get: oc: \"%s\", at: \"%s\"\n", + oc ? oc->soc_cname.bv_val : "(null)", at_name, 0); +#endif + + if( op ) boi = (struct bdb_op_info *) op->o_private; + if( boi != NULL && be == boi->boi_bdb ) { + txn = boi->boi_txn; + locker = boi->boi_locker; + } + + if ( txn != NULL ) { + locker = TXN_ID ( txn ); + } else if ( !locker ) { + rc = LOCK_ID ( bdb->bi_dbenv, &locker ); + free_lock_id = 1; + switch(rc) { + case 0: + break; + default: + return LDAP_OTHER; + } + } + +dn2entry_retry: + /* can we find entry */ + rc = bdb_dn2entry_rw( be, txn, ndn, &e, NULL, 0, rw, locker, &lock ); + switch( rc ) { + case DB_NOTFOUND: + case 0: + break; + case DB_LOCK_DEADLOCK: + case DB_LOCK_NOTGRANTED: + /* the txn must abort and retry */ + if ( txn ) { + boi->boi_err = rc; + return LDAP_BUSY; + } + ldap_pvt_thread_yield(); + goto dn2entry_retry; + default: + boi->boi_err = rc; + if ( free_lock_id ) { + LOCK_ID_FREE( bdb->bi_dbenv, locker ); + } + return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY; + } + if (e == NULL) { +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, INFO, + "bdb_entry_get: cannot find entry (%s)\n", + ndn->bv_val, 0, 0 ); +#else + Debug( LDAP_DEBUG_ACL, + "=> bdb_entry_get: cannot find entry: \"%s\"\n", + ndn->bv_val, 0, 0 ); +#endif + if ( free_lock_id ) { + LOCK_ID_FREE( bdb->bi_dbenv, locker ); + } + return LDAP_NO_SUCH_OBJECT; + } + +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, DETAIL1, "bdb_entry_get: found entry (%s)\n", + ndn->bv_val, 0, 0 ); +#else + Debug( LDAP_DEBUG_ACL, + "=> bdb_entry_get: found entry: \"%s\"\n", + ndn->bv_val, 0, 0 ); +#endif + +#ifdef BDB_ALIASES + /* find attribute values */ + if( is_entry_alias( e ) ) { +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, INFO, + "bdb_entry_get: entry (%s) is an alias\n", e->e_name.bv_val, 0, 0 ); +#else + Debug( LDAP_DEBUG_ACL, + "<= bdb_entry_get: entry is an alias\n", 0, 0, 0 ); +#endif + rc = LDAP_ALIAS_PROBLEM; + goto return_results; + } +#endif + + if( is_entry_referral( e ) ) { +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, INFO, + "bdb_entry_get: entry (%s) is a referral.\n", e->e_name.bv_val, 0, 0); +#else + Debug( LDAP_DEBUG_ACL, + "<= bdb_entry_get: entry is a referral\n", 0, 0, 0 ); +#endif + rc = LDAP_REFERRAL; + goto return_results; + } + + if ( oc && !is_entry_objectclass( e, oc, 0 )) { +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, INFO, + "bdb_entry_get: failed to find objectClass.\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ACL, + "<= bdb_entry_get: failed to find objectClass\n", + 0, 0, 0 ); +#endif + rc = LDAP_NO_SUCH_ATTRIBUTE; + goto return_results; + } + +return_results: + if( rc != LDAP_SUCCESS ) { + /* free entry */ + bdb_cache_return_entry_rw(bdb->bi_dbenv, &bdb->bi_cache, e, rw, &lock); + } else { + *ent = e; + } + + if ( free_lock_id ) { + LOCK_ID_FREE( bdb->bi_dbenv, locker ); + } + +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, ENTRY, "bdb_entry_get: rc=%d\n", rc, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_entry_get: rc=%d\n", + rc, 0, 0 ); +#endif + return(rc); +} diff --git a/servers/slapd/back-bdb/init.c b/servers/slapd/back-bdb/init.c index 039934c474..c99c70a7bb 100644 --- a/servers/slapd/back-bdb/init.c +++ b/servers/slapd/back-bdb/init.c @@ -665,22 +665,11 @@ bdb_initialize( bi->bi_extended = bdb_extended; -#if 1 - /* - * these routines (and their callers) are not yet designed - * to work with transaction. Using them may cause deadlock. - */ - bi->bi_acl_group = bdb_group; - bi->bi_acl_attribute = bdb_attribute; -#else - bi->bi_acl_group = 0; - bi->bi_acl_attribute = 0; -#endif - bi->bi_chk_referrals = bdb_referrals; bi->bi_operational = bdb_operational; bi->bi_has_subordinates = bdb_hasSubordinates; bi->bi_entry_release_rw = bdb_entry_release; + bi->bi_entry_get_rw = bdb_entry_get; /* * hooks for slap tools diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index 8cb1ed5808..87e6d414b8 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -39,12 +39,6 @@ int bdb_attr_index_config LDAP_P(( struct bdb_info *bdb, void bdb_attr_index_destroy LDAP_P(( Avlnode *tree )); -/* - * attribute.c - */ - -BI_acl_attribute bdb_attribute; - /* * dbcache.c */ @@ -114,6 +108,7 @@ bdb_dn2idl( */ int bdb_entry_return( Entry *e ); BI_entry_release_rw bdb_entry_release; +BI_entry_get_rw bdb_entry_get; /* * error.c @@ -130,12 +125,6 @@ int bdb_filter_candidates( ID *tmp, ID *stack ); -/* - * group.c - */ - -BI_acl_group bdb_group; - /* * id2entry.c */ diff --git a/servers/slapd/back-dnssrv/init.c b/servers/slapd/back-dnssrv/init.c index 52bcd6658d..adb99fc282 100644 --- a/servers/slapd/back-dnssrv/init.c +++ b/servers/slapd/back-dnssrv/init.c @@ -66,8 +66,6 @@ dnssrv_back_initialize( bi->bi_op_unbind = 0; bi->bi_extended = 0; - bi->bi_acl_group = 0; - bi->bi_acl_attribute = 0; bi->bi_connection_init = 0; bi->bi_connection_destroy = 0; diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index ffe616e24b..68c4e2eeec 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -159,6 +159,9 @@ extern int suffix_massage_config( struct rewrite_info *info, extern int ldap_dnattr_rewrite( struct rewrite_info *rwinfo, BerVarray a_vals, void *cookie ); #endif /* ENABLE_REWRITE */ +int ldap_build_entry( Backend *be, Connection *c, LDAPMessage *e, Entry *ent, + struct berval *bdn, int private ); + LDAP_END_DECL #endif /* SLAPD_LDAP_H */ diff --git a/servers/slapd/back-ldap/external.h b/servers/slapd/back-ldap/external.h index e12b6b5ecb..dd88337658 100644 --- a/servers/slapd/back-ldap/external.h +++ b/servers/slapd/back-ldap/external.h @@ -39,9 +39,7 @@ extern BI_op_abandon ldap_back_abandon; extern BI_op_extended ldap_back_extended; -extern BI_acl_group ldap_back_group; - -extern BI_acl_attribute ldap_back_attribute; +extern BI_entry_get_rw ldap_back_entry_get; LDAP_END_DECL diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index 5cffa2f67f..765660806e 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -89,9 +89,8 @@ ldap_back_initialize( bi->bi_extended = ldap_back_extended; - bi->bi_acl_group = ldap_back_group; - bi->bi_acl_attribute = ldap_back_attribute; bi->bi_chk_referrals = 0; + bi->bi_entry_get_rw = ldap_back_entry_get; bi->bi_connection_init = 0; bi->bi_connection_destroy = ldap_back_conn_destroy; diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index 60232de30a..c68cb2469c 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -48,8 +48,9 @@ #undef ldap_debug /* silence a warning in ldap-int.h */ #include "../../../libraries/libldap/ldap-int.h" -static int ldap_send_entry( Backend *be, Operation *op, Connection *conn, - LDAPMessage *e, AttributeName *attrs, int attrsonly ); +#include "lutil.h" + +static struct berval dummy = { 0, NULL }; int ldap_back_search( @@ -244,10 +245,26 @@ fail:; ldap_pvt_thread_yield(); } else if (rc == LDAP_RES_SEARCH_ENTRY) { + Entry ent; + struct berval bdn; e = ldap_first_entry(lc->ld,res); - if ( ldap_send_entry(be, op, conn, e, attrs, attrsonly) - == LDAP_SUCCESS ) { + if ( ldap_build_entry(be, conn, e, &ent, &bdn, 1) == LDAP_SUCCESS ) { + Attribute *a; count++; + send_search_entry( be, conn, op, &ent, attrs, + attrsonly, NULL ); + while (ent.e_attrs) { + a = ent.e_attrs; + ent.e_attrs = a->a_next; + if (a->a_vals != &dummy) + ber_bvarray_free(a->a_vals); + ch_free(a); + } + + if ( ent.e_dn && ( ent.e_dn != bdn.bv_val ) ) + free( ent.e_dn ); + if ( ent.e_ndn ) + free( ent.e_ndn ); } ldap_msgfree(res); @@ -381,26 +398,24 @@ finish:; return rc; } -static int -ldap_send_entry( +int +ldap_build_entry( Backend *be, - Operation *op, Connection *conn, LDAPMessage *e, - AttributeName *attrs, - int attrsonly + Entry *ent, + struct berval *bdn, + int private ) { struct ldapinfo *li = (struct ldapinfo *) be->be_private; struct berval a, mapped; - Entry ent; BerElement ber = *e->lm_ber; Attribute *attr, **attrp; - struct berval dummy = { 0, NULL }; - struct berval *bv, bdn; + struct berval *bv; const char *text; - if ( ber_scanf( &ber, "{m{", &bdn ) == LBER_ERROR ) { + if ( ber_scanf( &ber, "{m{", bdn ) == LBER_ERROR ) { return LDAP_DECODING_ERROR; } #ifdef ENABLE_REWRITE @@ -409,20 +424,20 @@ ldap_send_entry( * Rewrite the dn of the result, if needed */ switch ( rewrite_session( li->rwinfo, "searchResult", - bdn.bv_val, conn, &ent.e_name.bv_val ) ) { + bdn->bv_val, conn, &ent->e_name.bv_val ) ) { case REWRITE_REGEXEC_OK: - if ( ent.e_name.bv_val == NULL ) { - ent.e_name = bdn; + if ( ent->e_name.bv_val == NULL ) { + ent->e_name = *bdn; } else { #ifdef NEW_LOGGING LDAP_LOG( BACK_LDAP, DETAIL1, "[rw] searchResult: \"%s\"" " -> \"%s\"\n", - bdn.bv_val, ent.e_dn, 0 ); + bdn->bv_val, ent->e_dn, 0 ); #else /* !NEW_LOGGING */ Debug( LDAP_DEBUG_ARGS, "rw> searchResult: \"%s\"" - " -> \"%s\"\n%s", bdn.bv_val, ent.e_dn, "" ); + " -> \"%s\"\n%s", bdn->bv_val, ent->e_dn, "" ); #endif /* !NEW_LOGGING */ - ent.e_name.bv_len = strlen( ent.e_name.bv_val ); + ent->e_name.bv_len = strlen( ent->e_name.bv_val ); } break; @@ -431,7 +446,7 @@ ldap_send_entry( return LDAP_OTHER; } #else /* !ENABLE_REWRITE */ - ldap_back_dn_massage( li, &bdn, &ent.e_name, 0, 0 ); + ldap_back_dn_massage( li, bdn, &ent->e_name, 0, 0 ); #endif /* !ENABLE_REWRITE */ /* @@ -441,14 +456,14 @@ ldap_send_entry( * * FIXME: should we log anything, or delegate to dnNormalize2? */ - if ( dnNormalize2( NULL, &ent.e_name, &ent.e_nname ) != LDAP_SUCCESS ) { + if ( dnNormalize2( NULL, &ent->e_name, &ent->e_nname ) != LDAP_SUCCESS ) { return LDAP_INVALID_DN_SYNTAX; } - ent.e_id = 0; - ent.e_attrs = 0; - ent.e_private = 0; - attrp = &ent.e_attrs; + ent->e_id = 0; + ent->e_attrs = 0; + ent->e_private = 0; + attrp = &ent->e_attrs; while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) { ldap_back_map(&li->at_map, &a, &mapped, BACKLDAP_REMAP); @@ -488,8 +503,13 @@ ldap_send_entry( * Note: attr->a_vals can be null when using * values result filter */ - attr->a_vals = &dummy; - + if (private) { + attr->a_vals = &dummy; + } else { + attr->a_vals = ch_malloc(sizeof(struct berval)); + attr->a_vals->bv_val = NULL; + attr->a_vals->bv_len = 0; + } } else if ( attr->a_desc == slap_schema.si_ad_objectClass || attr->a_desc == slap_schema.si_ad_structuralObjectClass ) { int last; @@ -602,19 +622,94 @@ next_attr:; *attrp = attr; attrp = &attr->a_next; } - send_search_entry( be, conn, op, &ent, attrs, attrsonly, NULL ); - while (ent.e_attrs) { - attr = ent.e_attrs; - ent.e_attrs = attr->a_next; - if (attr->a_vals != &dummy) - ber_bvarray_free(attr->a_vals); - ch_free(attr); + /* make sure it's free'able */ + if (!private && ent->e_name.bv_val == bdn->bv_val) + ber_dupbv( &ent->e_name, bdn ); + return LDAP_SUCCESS; +} + +/* return 0 IFF we can retrieve the entry with ndn + */ +int +ldap_back_entry_get( + Backend *be, + Connection *conn, + Operation *op, + struct berval *ndn, + ObjectClass *oc, + AttributeDescription *at, + int rw, + Entry **ent +) +{ + struct ldapinfo *li = (struct ldapinfo *) be->be_private; + struct ldapconn *lc; + int rc = 1, is_oc; + struct berval mapped = { 0, NULL }, bdn; + LDAPMessage *result = NULL, *e = NULL; + char *gattr[3]; + char *filter; + + ldap_back_map(&li->at_map, &at->ad_cname, &mapped, BACKLDAP_MAP); + if (mapped.bv_val == NULL || mapped.bv_val[0] == '\0') { + return 1; } - - if ( ent.e_dn && ( ent.e_dn != bdn.bv_val ) ) - free( ent.e_dn ); - if ( ent.e_ndn ) - free( ent.e_ndn ); - return LDAP_SUCCESS; + /* Tell getconn this is a privileged op */ + is_oc = op->o_do_not_cache; + op->o_do_not_cache = 1; + lc = ldap_back_getconn(li, conn, op); + if ( !lc || !ldap_back_dobind(li, lc, NULL, op) ) { + op->o_do_not_cache = is_oc; + return 1; + } + op->o_do_not_cache = is_oc; + + is_oc = (strcasecmp("objectclass", mapped.bv_val) == 0); + if (oc && !is_oc) { + gattr[0] = "objectclass"; + gattr[1] = mapped.bv_val; + gattr[2] = NULL; + } else { + gattr[0] = mapped.bv_val; + gattr[1] = NULL; + } + if (oc) { + char *ptr; + filter = ch_malloc(sizeof("(objectclass=)" + oc->soc_cname.bv_len)); + ptr = lutil_strcopy(filter, "(objectclass="); + ptr = lutil_strcopy(ptr, oc->soc_cname.bv_val); + *ptr++ = ')'; + *ptr++ = '\0'; + } else { + filter = "(objectclass=*)"; + } + + if (ldap_search_ext_s(lc->ld, ndn->bv_val, LDAP_SCOPE_BASE, filter, + gattr, 0, NULL, NULL, LDAP_NO_LIMIT, + LDAP_NO_LIMIT, &result) != LDAP_SUCCESS) + { + goto cleanup; + } + + if ((e = ldap_first_entry(lc->ld, result)) == NULL) { + goto cleanup; + } + + *ent = ch_malloc(sizeof(Entry)); + + rc = ldap_build_entry(be, conn, e, *ent, &bdn, 0); + + if (rc != LDAP_SUCCESS) { + ch_free(*ent); + *ent = NULL; + } + +cleanup: + if (result) { + ldap_msgfree(result); + } + + return(rc); } + diff --git a/servers/slapd/back-ldbm/entry.c b/servers/slapd/back-ldbm/entry.c index 4c87512b32..8ebf0ab2c5 100644 --- a/servers/slapd/back-ldbm/entry.c +++ b/servers/slapd/back-ldbm/entry.c @@ -43,3 +43,118 @@ ldbm_back_entry_release_rw( return 0; } + +/* return LDAP_SUCCESS IFF we can retrieve the specified entry. + */ +int ldbm_back_entry_get( + BackendDB *be, + Connection *c, + Operation *op, + struct berval *ndn, + ObjectClass *oc, + AttributeDescription *at, + int rw, + Entry **ent ) +{ + struct ldbminfo *li = (struct ldbminfo *) be->be_private; + Entry *e; + int rc; + const char *at_name = at->ad_cname.bv_val; + +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, ARGS, + "ldbm_back_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 ); + LDAP_LOG( BACK_BDB, ARGS, + "ldbm_back_entry_get: oc: \"%s\", at: \"%s\"\n", + oc ? oc->soc_cname.bv_val : "(null)", at_name, 0); +#else + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_entry_get: ndn: \"%s\"\n", ndn->bv_val, 0, 0 ); + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_entry_get: oc: \"%s\", at: \"%s\"\n", + oc ? oc->soc_cname.bv_val : "(null)", at_name, 0); +#endif + + /* can we find entry */ + e = dn2entry_rw( be, ndn, NULL, rw ); + if (e == NULL) { +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, INFO, + "ldbm_back_entry_get: cannot find entry (%s)\n", + ndn->bv_val, 0, 0 ); +#else + Debug( LDAP_DEBUG_ACL, + "=> ldbm_back_entry_get: cannot find entry: \"%s\"\n", + ndn->bv_val, 0, 0 ); +#endif + return LDAP_NO_SUCH_OBJECT; + } + +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, DETAIL1, "ldbm_back_entry_get: found entry (%s)\n", + ndn->bv_val, 0, 0 ); +#else + Debug( LDAP_DEBUG_ACL, + "=> ldbm_back_entry_get: found entry: \"%s\"\n", + ndn->bv_val, 0, 0 ); +#endif + +#ifdef BDB_ALIASES + /* find attribute values */ + if( is_entry_alias( e ) ) { +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, INFO, + "ldbm_back_entry_get: entry (%s) is an alias\n", e->e_name.bv_val, 0, 0 ); +#else + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_entry_get: entry is an alias\n", 0, 0, 0 ); +#endif + rc = LDAP_ALIAS_PROBLEM; + goto return_results; + } +#endif + + if( is_entry_referral( e ) ) { +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, INFO, + "ldbm_back_entry_get: entry (%s) is a referral.\n", e->e_name.bv_val, 0, 0); +#else + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_entry_get: entry is a referral\n", 0, 0, 0 ); +#endif + rc = LDAP_REFERRAL; + goto return_results; + } + + if ( oc && !is_entry_objectclass( e, oc, 0 )) { +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, INFO, + "ldbm_back_entry_get: failed to find objectClass.\n", 0, 0, 0 ); +#else + Debug( LDAP_DEBUG_ACL, + "<= ldbm_back_entry_get: failed to find objectClass\n", + 0, 0, 0 ); +#endif + rc = LDAP_NO_SUCH_ATTRIBUTE; + goto return_results; + } + + rc = LDAP_SUCCESS; + +return_results: + if( rc != LDAP_SUCCESS ) { + /* free entry */ + cache_return_entry_rw(&li->li_cache, e, rw); + } else { + *ent = e; + } + +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, ENTRY, "ldbm_back_entry_get: rc=%d\n", rc, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "ldbm_back_entry_get: rc=%d\n", + rc, 0, 0 ); +#endif + return(rc); +} diff --git a/servers/slapd/back-ldbm/external.h b/servers/slapd/back-ldbm/external.h index 0f3107d85b..d26999e4d0 100644 --- a/servers/slapd/back-ldbm/external.h +++ b/servers/slapd/back-ldbm/external.h @@ -37,10 +37,6 @@ extern BI_op_add ldbm_back_add; extern BI_op_delete ldbm_back_delete; -extern BI_acl_group ldbm_back_group; - -extern BI_acl_attribute ldbm_back_attribute; - extern BI_operational ldbm_back_operational; extern BI_has_subordinates ldbm_back_hasSubordinates; diff --git a/servers/slapd/back-ldbm/init.c b/servers/slapd/back-ldbm/init.c index cc023e8e18..26c411d171 100644 --- a/servers/slapd/back-ldbm/init.c +++ b/servers/slapd/back-ldbm/init.c @@ -67,8 +67,7 @@ ldbm_back_initialize( bi->bi_extended = ldbm_back_extended; bi->bi_entry_release_rw = ldbm_back_entry_release_rw; - bi->bi_acl_group = ldbm_back_group; - bi->bi_acl_attribute = ldbm_back_attribute; + bi->bi_entry_get_rw = ldbm_back_entry_get; bi->bi_chk_referrals = ldbm_back_referrals; bi->bi_operational = ldbm_back_operational; bi->bi_has_subordinates = ldbm_back_hasSubordinates; diff --git a/servers/slapd/back-ldbm/proto-back-ldbm.h b/servers/slapd/back-ldbm/proto-back-ldbm.h index dfd531629d..de1709ad36 100644 --- a/servers/slapd/back-ldbm/proto-back-ldbm.h +++ b/servers/slapd/back-ldbm/proto-back-ldbm.h @@ -97,6 +97,8 @@ int ldbm_back_entry_release_rw LDAP_P(( Backend *be, Connection *conn, Operation *op, Entry *e, int rw )); +BI_entry_get_rw ldbm_back_entry_get; + /* * filterindex.c */ diff --git a/servers/slapd/back-meta/external.h b/servers/slapd/back-meta/external.h index e37d552b8c..b9d3517ddb 100644 --- a/servers/slapd/back-meta/external.h +++ b/servers/slapd/back-meta/external.h @@ -88,9 +88,6 @@ extern BI_op_add meta_back_add; extern BI_op_delete meta_back_delete; extern BI_op_abandon meta_back_abandon; -extern BI_acl_group meta_back_group; -extern BI_acl_attribute meta_back_attribute; - LDAP_END_DECL #endif /* META_EXTERNAL_H */ diff --git a/servers/slapd/back-meta/init.c b/servers/slapd/back-meta/init.c index 1aa4054ed5..a0f7b4d943 100644 --- a/servers/slapd/back-meta/init.c +++ b/servers/slapd/back-meta/init.c @@ -120,8 +120,6 @@ meta_back_initialize( bi->bi_extended = 0; - bi->bi_acl_group = meta_back_group; - bi->bi_acl_attribute = meta_back_attribute; bi->bi_chk_referrals = 0; bi->bi_connection_init = 0; diff --git a/servers/slapd/back-monitor/init.c b/servers/slapd/back-monitor/init.c index 4c68e7491b..770f8e0bf8 100644 --- a/servers/slapd/back-monitor/init.c +++ b/servers/slapd/back-monitor/init.c @@ -211,8 +211,6 @@ monitor_back_initialize( bi->bi_extended = 0; bi->bi_entry_release_rw = 0; - bi->bi_acl_group = 0; - bi->bi_acl_attribute = 0; bi->bi_chk_referrals = 0; bi->bi_operational = monitor_back_operational; diff --git a/servers/slapd/back-passwd/init.c b/servers/slapd/back-passwd/init.c index 1bb6ad284d..d0405b4143 100644 --- a/servers/slapd/back-passwd/init.c +++ b/servers/slapd/back-passwd/init.c @@ -57,8 +57,6 @@ passwd_back_initialize( bi->bi_extended = 0; - bi->bi_acl_group = 0; - bi->bi_acl_attribute = 0; bi->bi_chk_referrals = 0; bi->bi_connection_init = 0; diff --git a/servers/slapd/back-perl/init.c b/servers/slapd/back-perl/init.c index 648ae715a9..e0f29ba3d4 100644 --- a/servers/slapd/back-perl/init.c +++ b/servers/slapd/back-perl/init.c @@ -97,8 +97,6 @@ perl_back_initialize( bi->bi_extended = 0; - bi->bi_acl_group = 0; - bi->bi_acl_attribute = 0; bi->bi_chk_referrals = 0; bi->bi_connection_init = 0; diff --git a/servers/slapd/back-shell/init.c b/servers/slapd/back-shell/init.c index cfbd8811c5..cfb5357dd0 100644 --- a/servers/slapd/back-shell/init.c +++ b/servers/slapd/back-shell/init.c @@ -57,8 +57,6 @@ shell_back_initialize( bi->bi_extended = 0; - bi->bi_acl_group = 0; - bi->bi_acl_attribute = 0; bi->bi_chk_referrals = 0; bi->bi_connection_init = 0; diff --git a/servers/slapd/back-sql/init.c b/servers/slapd/back-sql/init.c index 826e5dd92a..a5402355f2 100644 --- a/servers/slapd/back-sql/init.c +++ b/servers/slapd/back-sql/init.c @@ -83,8 +83,6 @@ sql_back_initialize( bi->bi_op_add = backsql_add; bi->bi_op_delete = backsql_delete; - bi->bi_acl_group = 0; - bi->bi_acl_attribute = 0; bi->bi_chk_referrals = 0; bi->bi_operational = backsql_operational; diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 637a1dfc31..c187574072 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -1080,6 +1080,31 @@ int backend_check_referrals( return rc; } +int +be_entry_get_rw( + Backend *be, + Connection *conn, + Operation *op, + struct berval *ndn, + ObjectClass *oc, + AttributeDescription *at, + int rw, + Entry **e ) +{ + be = select_backend( ndn, 0, 0 ); + + if (be == NULL) { + return LDAP_NO_SUCH_OBJECT; + } + + if ( be->be_fetch ) { + return be->be_fetch( be, conn, op, ndn, + oc, at, rw, e ); + } + + return LDAP_UNWILLING_TO_PERFORM; +} + int backend_group( Backend *be, @@ -1092,20 +1117,13 @@ backend_group( AttributeDescription *group_at ) { + Entry *e; + Attribute *a; + int i, j, rc; GroupAssertion *g; if ( op->o_abandon ) return SLAPD_ABANDON; - if ( !dn_match( &target->e_nname, gr_ndn ) ) { - /* we won't attempt to send it to a different backend */ - - be = select_backend( gr_ndn, 0, 0 ); - - if (be == NULL) { - return LDAP_NO_SUCH_OBJECT; - } - } - ldap_pvt_thread_mutex_lock( &conn->c_mutex ); for (g = conn->c_groups; g; g=g->ga_next) { @@ -1122,29 +1140,48 @@ backend_group( return g->ga_res; } - if( be->be_group ) { - int res = be->be_group( be, conn, op, - target, gr_ndn, op_ndn, - group_oc, group_at ); - - if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache ) { - g = ch_malloc(sizeof(GroupAssertion) + gr_ndn->bv_len); - g->ga_be = be; - g->ga_oc = group_oc; - g->ga_at = group_at; - g->ga_res = res; - g->ga_len = gr_ndn->bv_len; - strcpy(g->ga_ndn, gr_ndn->bv_val); - ldap_pvt_thread_mutex_lock( &conn->c_mutex ); - g->ga_next = conn->c_groups; - conn->c_groups = g; - ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); + if ( target && dn_match( &target->e_nname, gr_ndn ) ) { + e = target; + } else { + rc = be_entry_get_rw(be, conn, op, gr_ndn, group_oc, group_at, + 0, &e ); + } + if ( e ) { + a = attr_find( e->e_attrs, group_at ); + if ( a ) { +#ifdef SLAP_NVALUES + rc = value_find_ex( group_at, + SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | + SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, + a->a_nvals, op_ndn ); +#else + rc = value_find_ex( group_at, 0, a->a_vals, op_ndn ); +#endif + } else { + rc = LDAP_NO_SUCH_ATTRIBUTE; } + if (e != target ) { + be_entry_release_r( be, conn, op, e ); + } + } else { + rc = LDAP_NO_SUCH_OBJECT; + } - return res; + if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache ) { + g = ch_malloc(sizeof(GroupAssertion) + gr_ndn->bv_len); + g->ga_be = be; + g->ga_oc = group_oc; + g->ga_at = group_at; + g->ga_res = rc; + g->ga_len = gr_ndn->bv_len; + strcpy(g->ga_ndn, gr_ndn->bv_val); + ldap_pvt_thread_mutex_lock( &conn->c_mutex ); + g->ga_next = conn->c_groups; + conn->c_groups = g; + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); } - return LDAP_UNWILLING_TO_PERFORM; + return rc; } int @@ -1158,22 +1195,71 @@ backend_attribute( BerVarray *vals ) { - if ( target == NULL || !dn_match( &target->e_nname, edn ) ) { - /* we won't attempt to send it to a different backend */ - - be = select_backend( edn, 0, 0 ); + Entry *e; + Attribute *a; + int i, j, rc; + AccessControlState acl_state = ACL_STATE_INIT; - if (be == NULL) { - return LDAP_NO_SUCH_OBJECT; - } + if ( target && dn_match( &target->e_nname, edn ) ) { + e = target; + } else { + rc = be_entry_get_rw(be, conn, op, edn, NULL, entry_at, + 0, &e ); + if ( rc != LDAP_SUCCESS ) return rc; } - if( be->be_attribute ) { - return be->be_attribute( be, conn, op, target, edn, - entry_at, vals ); + if ( e ) { + a = attr_find( e->e_attrs, entry_at ); + if ( a ) { + BerVarray v; + + if ( conn && op && access_allowed( be, + conn, op, e, entry_at, NULL, ACL_AUTH, + &acl_state ) == 0 ) { + rc = LDAP_INSUFFICIENT_ACCESS; + goto freeit; + } + + for ( i=0; a->a_vals[i].bv_val; i++ ) ; + + v = ch_malloc( sizeof(struct berval) * (i+1) ); + for ( i=0,j=0; a->a_vals[i].bv_val; i++ ) { + if ( conn && op && access_allowed( be, + conn, op, e, entry_at, +#ifdef SLAP_NVALUES + &a->a_nvals[i], +#else + &a->a_vals[i], +#endif + ACL_AUTH, &acl_state ) == 0 ) { + continue; + } + ber_dupbv( &v[j], +#ifdef SLAP_NVALUES + &a->a_nvals[i] +#else + &a->a_vals[i] +#endif + ); + if (v[j].bv_val ) j++; + } + if (j == 0) { + ch_free( v ); + *vals = NULL; + rc = LDAP_INSUFFICIENT_ACCESS; + } else { + v[j].bv_val = NULL; + v[j].bv_len = 0; + *vals = v; + rc = LDAP_SUCCESS; + } + } +freeit: if (e != target ) { + be_entry_release_r( be, conn, op, e ); + } } - return LDAP_UNWILLING_TO_PERFORM; + return rc; } Attribute *backend_operational( diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index a3b75fd305..94e0606ce5 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -208,6 +208,10 @@ LDAP_SLAPD_F (int) be_isroot_pw LDAP_P(( Backend *be, Connection *conn, struct berval *ndn, struct berval *cred )); LDAP_SLAPD_F (int) be_isupdate LDAP_P(( Backend *be, struct berval *ndn )); LDAP_SLAPD_F (struct berval *) be_root_dn LDAP_P(( Backend *be )); +LDAP_SLAPD_F (int) be_entry_get_rw LDAP_P(( BackendDB *bd, + struct slap_conn *c, struct slap_op *o, + struct berval *ndn, ObjectClass *oc, + AttributeDescription *at, int rw, Entry **e )); LDAP_SLAPD_F (int) be_entry_release_rw LDAP_P(( BackendDB *be, Connection *c, Operation *o, Entry *e, int rw )); #define be_entry_release_r( be, c, o, e ) be_entry_release_rw( be, c, o, e, 0 ) diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 7aa3353bd4..76c3989071 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1301,6 +1301,7 @@ struct slap_backend_db { #define be_extended bd_info->bi_extended +#define be_fetch bd_info->bi_entry_get_rw #define be_release bd_info->bi_entry_release_rw #define be_chk_referrals bd_info->bi_chk_referrals #define be_group bd_info->bi_acl_group @@ -1542,6 +1543,12 @@ typedef int (BI_op_extended) LDAP_P(( const char ** text, BerVarray *refs )); +typedef int (BI_entry_get_rw) LDAP_P((BackendDB *bd, + struct slap_conn *c, struct slap_op *o, + struct berval *ndn, ObjectClass *oc, + AttributeDescription *at, int rw, + Entry **e )); + typedef int (BI_entry_release_rw) LDAP_P((BackendDB *bd, struct slap_conn *c, struct slap_op *o, Entry *e, int rw)); @@ -1550,21 +1557,7 @@ typedef int (BI_chk_referrals) LDAP_P((BackendDB *bd, struct slap_conn *c, struct slap_op *o, struct berval *dn, struct berval *ndn, const char **text )); - -typedef int (BI_acl_group) LDAP_P((Backend *bd, - struct slap_conn *c, struct slap_op *o, - Entry *e, - struct berval *bdn, - struct berval *edn, - ObjectClass *group_oc, - AttributeDescription *group_at )); - -typedef int (BI_acl_attribute) LDAP_P((Backend *bd, - struct slap_conn *c, struct slap_op *o, - Entry *e, struct berval *edn, - AttributeDescription *entry_at, - BerVarray *vals )); - + typedef int (BI_operational) LDAP_P((Backend *bd, struct slap_conn *c, struct slap_op *o, Entry *e, AttributeName *attrs, int opattrs, Attribute **a )); @@ -1660,12 +1653,10 @@ struct slap_backend_info { BI_op_extended *bi_extended; /* Auxilary Functions */ + BI_entry_get_rw *bi_entry_get_rw; BI_entry_release_rw *bi_entry_release_rw; BI_chk_referrals *bi_chk_referrals; - BI_acl_group *bi_acl_group; - BI_acl_attribute *bi_acl_attribute; - BI_operational *bi_operational; BI_has_subordinates *bi_has_subordinates; -- 2.39.5