Full_Name: Christian Forster Version: 1.1.1 OS: Linux/i386 URL: Submission from: (NULL) (131.188.2.7) Hi! I tried to control write access to the directory by using ACL GROUPS. Unfortunately when I modify the group that is providing the access rights for my DN, slapd freezes. (I needed "kill -9 <pid>" to remove the process!) An example should make things clear. Here is the test database I used: dn: o=Your Organization Name, c=US objectclass: organization o: Your Organization Name dn: cn=rootUser, o=Your Organization Name, c=US objectclass: person cn: rootUser sn: rootUser userpassword: abc dn: cn=normalUser, o=Your Organization Name, c=US objectclass: person cn: normalUser sn: normalUser userpassword: 123 dn: cn=roots, o=Your Organization Name, c=US objectclass: groupOfNames cn: roots member: cn=rootUser,o=Your Organization Name,c=US slapd.conf contains the following ACL: access to * by group="cn=roots, o=Your Organization Name, c=US" write by * read "cn=rootUser,..." has no other privileges. Especially the "rootdn=..." statement in slapd.conf points to an other DN. Now I tried the following LDAP modification: ./ldapmodify -D "cn=rootUser, o=Your Organization Name, c=US" -w abc cn=roots, o=Your Organization Name, c=US description=New description At this point slapd freezes... Here are "the last words" form the debug output (slapd -d 65535): do_modify: dn (cn=roots,o=Your Organization Name,c=US) modifications: add: description conn=0 op=1 MOD dn="cn=roots,o=Your Organization Name,c=US" ldbm_back_modify: dn2entry_w: dn: cn=roots, o=Your Organization Name, c=US => dn2id( "cn=roots, o=Your Organization Name, c=US" ) => ldbm_cache_open( "/var/ldap/test/dn2id.dbb", 66, 600 ) <= ldbm_cache_open (cache 0) <= dn2id 4 => id2entry_w( 4 ) => ldbm_cache_open( "/var/ldap/test/id2entry.dbb", 66, 600 ) <= ldbm_cache_open (cache 1) => str2entry <= str2entry 0x8076008 entry_rdwr_wlock: ID: 4 <= id2entry_w( 4 ) (disk) => acl_get: entry (cn=roots, o=Your Organization Name, c=US) attr (description) => acl_get: edn CN=ROOTS,O=YOUR ORGANIZATION NAME,C=US => dnpat: [1] .* nsub: 0 => acl_get: [1] global ACL match => acl_get: [1] check attr <= acl_get: [1] global acl cn=roots, o=Your Organization Name, c=US attr: description => acl_access_allowed: write access to entry "cn=roots, o=Your Organization Name, c=US" => acl_access_allowed: write access to value "New description" by "cn=rootUser,o=Your Organization Name,c=US" => string_expand: pattern: CN=ROOTS, O=YOUR ORGANIZATION NAME, C=US => string_expand: expanded: CN=ROOTS, O=YOUR ORGANIZATION NAME, C=US => ldbm_back_group: bdn: CN=ROOTS, O=YOUR ORGANIZATION NAME, C=US => ldbm_back_group: edn: CN=ROOTUSER,O=YOUR ORGANIZATION NAME,C=US => ldbm_back_group: objectClass: groupOfNames attrName: member dn2entry_r: dn: CN=ROOTS, O=YOUR ORGANIZATION NAME, C=US => dn2id( "CN=ROOTS, O=YOUR ORGANIZATION NAME, C=US" ) => ldbm_cache_open( "/var/ldap/test/dn2id.dbb", 66, 600 ) <= ldbm_cache_open (cache 0) <= dn2id 4 => id2entry_r( 4 ) ====> cache_find_entry_dn2id: found id: 4 rw: 0 entry_rdwr_rlock: ID: 4 I used the following statements to build openldap: configure --prefix=/opt/openldap-1.1.1 --libexecdir=/opt/openldap-1.1.1/sbin --enable-debug --enable-dns --with-wrappers --enable-shared --disable-static Happy hacking, Christian Forster
changed notes moved from Incoming to Software
Christian, I am testing the following patch (against -devel) to resolve ITS#24 (and ITS#26). Please let me know if it resolves your problems. Kurt Index: servers/slapd/acl.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/acl.c,v retrieving revision 1.12 diff -u -r1.12 acl.c --- acl.c 1998/12/20 23:21:58 1.12 +++ acl.c 1998/12/29 21:23:49 @@ -360,7 +360,9 @@ /* 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 ); Index: servers/slapd/backend.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/backend.c,v retrieving revision 1.13 diff -u -r1.13 backend.c --- backend.c 1998/12/29 20:45:08 1.13 +++ backend.c 1998/12/29 21:23:50 @@ -261,6 +261,7 @@ int be_group( Backend *be, + Entry *e, char *bdn, char *edn, char *objectclassValue, @@ -268,7 +269,8 @@ ) { 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); } Index: servers/slapd/proto-slap.h =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/proto-slap.h,v retrieving revision 1.12 diff -u -r1.12 proto-slap.h --- proto-slap.h 1998/12/29 20:45:08 1.12 +++ proto-slap.h 1998/12/29 21:23:51 @@ -256,7 +256,8 @@ 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)); @@ -295,7 +296,8 @@ 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 Index: servers/slapd/slap.h =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/slap.h,v retrieving revision 1.15 diff -u -r1.15 slap.h --- slap.h 1998/12/22 00:34:03 1.15 +++ slap.h 1998/12/29 21:23:53 @@ -249,7 +249,9 @@ 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 }; Index: servers/slapd/back-ldbm/add.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-ldbm/add.c,v retrieving revision 1.6 diff -u -r1.6 add.c --- add.c 1998/11/27 19:21:55 1.6 +++ add.c 1998/12/29 21:23:54 @@ -28,22 +28,22 @@ 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, "", @@ -52,28 +52,6 @@ } /* - * 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 * add the entry. @@ -85,6 +63,7 @@ /* 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,33 +73,63 @@ 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 */ @@ -191,6 +200,9 @@ if (p != NULL) { 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 ); } Index: servers/slapd/back-ldbm/back-ldbm.h =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-ldbm/back-ldbm.h,v retrieving revision 1.6 diff -u -r1.6 back-ldbm.h --- back-ldbm.h 1998/12/27 23:44:15 1.6 +++ back-ldbm.h 1998/12/29 21:23:54 @@ -106,6 +106,7 @@ struct ldbminfo { ID li_nextid; + pthread_mutex_t li_add_mutex; pthread_mutex_t li_nextid_mutex; int li_mode; char *li_directory; Index: servers/slapd/back-ldbm/group.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-ldbm/group.c,v retrieving revision 1.9 diff -u -r1.9 group.c --- group.c 1998/11/23 19:08:25 1.9 +++ group.c 1998/12/29 21:23:55 @@ -20,6 +20,7 @@ int ldbm_back_group( Backend *be, + Entry *target, char *bdn, char *edn, char *objectclassValue, @@ -28,6 +29,7 @@ { struct ldbminfo *li = (struct ldbminfo *) be->be_private; Entry *e; + char *tdn; char *matched; Attribute *objectClass; Attribute *member; @@ -38,15 +40,30 @@ 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 ) ); + if (strcmp(tdn, bdn) == 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); + return( 1 ); + } + Debug( LDAP_DEBUG_ARGS, + "=> ldbm_back_group: found bdn: %s\n", + bdn, 0, 0 ); } + free(tdn); - Debug( LDAP_DEBUG_ARGS, "=> ldbm_back_group: found bdn: %s\n", bdn, 0, 0 ); /* check for deleted */ @@ -90,8 +107,10 @@ } } - /* 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); } Index: servers/slapd/back-ldbm/init.c =================================================================== RCS file: /repo/OpenLDAP/pkg/ldap/servers/slapd/back-ldbm/init.c,v retrieving revision 1.7 diff -u -r1.7 init.c --- init.c 1998/12/29 20:45:08 1.7 +++ init.c 1998/12/29 21:23:55 @@ -63,6 +63,7 @@ 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 );
changed notes changed state Open to Feedback
changed notes changed state Feedback to Test
changed notes changed state Test to Release
changed notes
changed notes changed state Release to Closed
moved from Software to Software Bugs
Released with 1.1.2