From: Kurt Zeilenga Date: Wed, 30 Dec 1998 21:00:56 +0000 (+0000) Subject: Apply fixes for ITS24 & ITS26 from devel. X-Git-Tag: OPENLDAP_REL_ENG_1_1_2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ceb1c5ce1c22a1e062cf724d222b126751e2906a;p=thirdparty%2Fopenldap.git Apply fixes for ITS24 & ITS26 from devel. * slapd aclgroup deadlock bug fix * slapd non-authorized add bug fix --- diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 6e630ab14e..f8e567efeb 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -360,7 +360,9 @@ acl_access_allowed( /* see if asker is listed in dnattr */ string_expand(buf, sizeof(buf), b->a_group, edn, matches); - if (be_group(be, buf, odn, b->a_objectclassvalue, b->a_groupattrname) == 0) { + if (be_group(be, e, buf, odn, + b->a_objectclassvalue, b->a_groupattrname) == 0) + { Debug( LDAP_DEBUG_ACL, "<= acl_access_allowed: matched by clause #%d (group) access granted\n", i, 0, 0 ); diff --git a/servers/slapd/back-ldbm/add.c b/servers/slapd/back-ldbm/add.c index 3b3dcee662..801359e27b 100644 --- a/servers/slapd/back-ldbm/add.c +++ b/servers/slapd/back-ldbm/add.c @@ -28,22 +28,22 @@ ldbm_back_add( Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", dn, 0, 0); + pthread_mutex_lock(&li->li_add_mutex); + if ( ( dn2id( be, dn ) ) != NOID ) { + pthread_mutex_unlock(&li->li_add_mutex); entry_free( e ); free( dn ); send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" ); return( -1 ); } - /* XXX race condition here til we cache_add_entry_lock below XXX */ - if ( global_schemacheck && oc_schema_check( e ) != 0 ) { + pthread_mutex_unlock(&li->li_add_mutex); + Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n", 0, 0, 0 ); - /* XXX this should be ok, no other thread should have access - * because e hasn't been added to the cache yet - */ entry_free( e ); free( dn ); send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "", @@ -51,28 +51,6 @@ ldbm_back_add( return( -1 ); } - /* - * Try to add the entry to the cache, assign it a new dnid - * and mark it locked. This should only fail if the entry - * already exists. - */ - - e->e_id = next_id( be ); - if ( cache_add_entry_lock( &li->li_cache, e, ENTRY_STATE_CREATING ) - != 0 ) { - Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0, - 0 ); - next_id_return( be, e->e_id ); - - /* XXX this should be ok, no other thread should have access - * because e hasn't been added to the cache yet - */ - entry_free( e ); - free( dn ); - send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" ); - return( -1 ); - } - /* * Get the parent dn and see if the corresponding entry exists. * If the parent does not exist, only allow the "root" user to @@ -85,6 +63,7 @@ ldbm_back_add( /* get entry with reader lock */ if ( (p = dn2entry_r( be, pdn, &matched )) == NULL ) { + pthread_mutex_unlock(&li->li_add_mutex); Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, @@ -94,32 +73,62 @@ ldbm_back_add( free( matched ); } - rc = -1; - goto return_results; + entry_free( e ); + free( dn ); + return -1; } if ( ! access_allowed( be, conn, op, p, "children", NULL, - op->o_dn, ACL_WRITE ) ) { + op->o_dn, ACL_WRITE ) ) + { + pthread_mutex_unlock(&li->li_add_mutex); Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" ); - rc = -1; - goto return_results; + entry_free( e ); + free( dn ); + return -1; } + } else { if ( ! be_isroot( be, op->o_dn ) ) { + pthread_mutex_unlock(&li->li_add_mutex); Debug( LDAP_DEBUG_TRACE, "no parent & not root\n", 0, 0, 0 ); send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" ); - rc = -1; - goto return_results; + entry_free( e ); + free( dn ); + return -1; } } + /* + * Try to add the entry to the cache, assign it a new dnid + * and mark it locked. This should only fail if the entry + * already exists. + */ + + e->e_id = next_id( be ); + if ( cache_add_entry_lock( &li->li_cache, e, ENTRY_STATE_CREATING ) != 0 ) { + pthread_mutex_unlock(&li->li_add_mutex); + + Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0, + 0 ); + next_id_return( be, e->e_id ); + + /* XXX this should be ok, no other thread should have access + * because e hasn't been added to the cache yet + */ + entry_free( e ); + free( dn ); + send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" ); + return( -1 ); + } + /* * add it to the id2children index for the parent */ @@ -192,5 +201,8 @@ return_results:; cache_return_entry_r( &li->li_cache, p ); } + /* it might actually be okay to release this lock sooner */ + pthread_mutex_unlock(&li->li_add_mutex); + return( rc ); } diff --git a/servers/slapd/back-ldbm/back-ldbm.h b/servers/slapd/back-ldbm/back-ldbm.h index c85df11367..7bf2861002 100644 --- a/servers/slapd/back-ldbm/back-ldbm.h +++ b/servers/slapd/back-ldbm/back-ldbm.h @@ -106,6 +106,7 @@ struct attrinfo { struct ldbminfo { ID li_nextid; + pthread_mutex_t li_add_mutex; pthread_mutex_t li_nextid_mutex; int li_mode; char *li_directory; diff --git a/servers/slapd/back-ldbm/group.c b/servers/slapd/back-ldbm/group.c index a889041c25..623aa2c95b 100644 --- a/servers/slapd/back-ldbm/group.c +++ b/servers/slapd/back-ldbm/group.c @@ -20,6 +20,7 @@ int ldbm_back_group( Backend *be, + Entry *target, char *bdn, char *edn, char *objectclassValue, @@ -28,6 +29,7 @@ ldbm_back_group( { struct ldbminfo *li = (struct ldbminfo *) be->be_private; Entry *e; + char *tdn, *xdn; char *matched; Attribute *objectClass; Attribute *member; @@ -38,15 +40,34 @@ ldbm_back_group( Debug( LDAP_DEBUG_TRACE, "=> ldbm_back_group: objectClass: %s attrName: %s\n", objectclassValue, groupattrName, 0 ); - /* can we find bdn entry with reader lock */ - if ((e = dn2entry_r(be, bdn, &matched )) == NULL) { - Debug( LDAP_DEBUG_TRACE, "=> ldbm_back_group: cannot find bdn: %s matched: %s\n", bdn, (matched ? matched : ""), 0 ); - if (matched != NULL) - free(matched); - return( 1 ); + tdn = dn_normalize_case( ch_strdup( target->e_dn ) ); + xdn = dn_normalize_case( ch_strdup( bdn ) ); + Debug( LDAP_DEBUG_TRACE, "=> ldbm_back_group: tdn: %s\n", tdn, 0, 0 ); + if (strcmp(tdn, xdn) == 0) { + /* we already have a LOCKED copy of the entry */ + e = target; + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_group: target is bdn: %s\n", + bdn, 0, 0 ); + } else { + /* can we find bdn entry with reader lock */ + if ((e = dn2entry_r(be, bdn, &matched )) == NULL) { + Debug( LDAP_DEBUG_TRACE, + "=> ldbm_back_group: cannot find bdn: %s matched: %s\n", + bdn, (matched ? matched : ""), 0 ); + if (matched != NULL) + free(matched); + free(tdn); + free(xdn); + return( 1 ); + } + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_group: found bdn: %s\n", + bdn, 0, 0 ); } + free(tdn); + free(xdn); - Debug( LDAP_DEBUG_ARGS, "=> ldbm_back_group: found bdn: %s\n", bdn, 0, 0 ); /* check for deleted */ @@ -90,8 +111,10 @@ ldbm_back_group( } } - /* free entry and reader lock */ - cache_return_entry_r( &li->li_cache, e ); + if( target != e ) { + /* free entry and reader lock */ + cache_return_entry_r( &li->li_cache, e ); + } Debug( LDAP_DEBUG_ARGS, "ldbm_back_group: rc: %d\n", rc, 0, 0 ); return(rc); } diff --git a/servers/slapd/back-ldbm/init.c b/servers/slapd/back-ldbm/init.c index 36ebbc963c..1f322e67bc 100644 --- a/servers/slapd/back-ldbm/init.c +++ b/servers/slapd/back-ldbm/init.c @@ -63,6 +63,7 @@ ldbm_back_init( free( argv[ 1 ] ); /* initialize various mutex locks & condition variables */ + pthread_mutex_init( &li->li_add_mutex, pthread_mutexattr_default ); pthread_mutex_init( &li->li_cache.c_mutex, pthread_mutexattr_default ); pthread_mutex_init( &li->li_nextid_mutex, pthread_mutexattr_default ); pthread_mutex_init( &li->li_dbcache_mutex, pthread_mutexattr_default ); diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 35f8b22a64..ffae45af4f 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -260,6 +260,7 @@ be_unbind( int be_group( Backend *be, + Entry *e, char *bdn, char *edn, char *objectclassValue, @@ -267,7 +268,8 @@ be_group( ) { if (be->be_group) - return(be->be_group(be, bdn, edn, objectclassValue, groupattrName)); + return(be->be_group(be, e, bdn, edn, + objectclassValue, groupattrName)); else return(1); } diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 8d47589abc..61c9f45aae 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -254,7 +254,8 @@ extern struct acl *global_acl; extern struct objclass *global_oc; extern time_t currenttime; -extern int be_group LDAP_P((Backend *be, char *bdn, char *edn, char *objectclassValue, char *groupattrName)); +extern int be_group LDAP_P((Backend *be, Entry *e, + char *bdn, char *edn, char *objectclassValue, char *groupattrName)); extern void init LDAP_P((void)); extern void be_unbind LDAP_P((Connection *conn, Operation *op)); extern void config_info LDAP_P((Connection *conn, Operation *op)); @@ -293,7 +294,8 @@ extern void ldbm_back_abandon LDAP_P((Backend *be, Connection *c, Operation *o, extern void ldbm_back_config LDAP_P((Backend *be, char *fname, int lineno, int argc, char **argv )); extern void ldbm_back_init LDAP_P((Backend *be)); extern void ldbm_back_close LDAP_P((Backend *be)); -extern int ldbm_back_group LDAP_P((Backend *be, char *bdn, char *edn, char *objectclassValue, char *groupattrName )); +extern int ldbm_back_group LDAP_P((Backend *be, Entry *target, + char *bdn, char *edn, char *objectclassValue, char *groupattrName )); #endif #ifdef SLAPD_PASSWD diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 053feea449..4a311bac64 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -227,7 +227,9 @@ struct backend { void (*be_close) LDAP_P((Backend *be)); #ifdef SLAPD_ACLGROUPS - int (*be_group) LDAP_P((Backend *be, char *bdn, char *edn, char *objectclassValue, char *groupattrName )); + int (*be_group) LDAP_P((Backend *be, Entry *e, + char *bdn, char *edn, + char *objectclassValue, char *groupattrName )); #endif };