]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
Apply fixes for ITS24 & ITS26 from devel.
authorKurt Zeilenga <kurt@openldap.org>
Wed, 30 Dec 1998 21:00:56 +0000 (21:00 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Wed, 30 Dec 1998 21:00:56 +0000 (21:00 +0000)
 * slapd aclgroup deadlock bug fix
 * slapd non-authorized add bug fix

servers/slapd/acl.c
servers/slapd/back-ldbm/add.c
servers/slapd/back-ldbm/back-ldbm.h
servers/slapd/back-ldbm/group.c
servers/slapd/back-ldbm/init.c
servers/slapd/backend.c
servers/slapd/proto-slap.h
servers/slapd/slap.h

index 6e630ab14e7aaec19f9b686d32ed323eeaf3b887..f8e567efebe6df2ee1f19d7e075efa30ff99448f 100644 (file)
@@ -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 );
index 3b3dcee66258665c51ebc5bb00ae96d46d072e2f..801359e27bf4d78ed57595a62649f618c557ba43 100644 (file)
@@ -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 );
 }
index c85df113672c2ebec3e6afb71e66c4dff854d61d..7bf2861002a64c4806204c6f88e56a23f11a6ab8 100644 (file)
@@ -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;
index a889041c25254e242e4c88d328e074dd87604c44..623aa2c95bcafa21f1c903151cfb8560ccbaa684 100644 (file)
@@ -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);
 }
index 36ebbc963c6cdfcc5d3e9b41523c5c36ba221f9b..1f322e67bc64010fa45b26c6d8eca958ebdd3c88 100644 (file)
@@ -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 );
index 35f8b22a6473b0ff144019ccc68364d8610aec7a..ffae45af4ffa945b4301abb92f04afb3ce309154 100644 (file)
@@ -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);
 }
index 8d47589abc79dbc84ae5af0c3c7fc5f534f917b9..61c9f45aae4ec3e62a466fd28510c2ea3ec35bf2 100644 (file)
@@ -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
index 053feea4495bfca86d83d800ebdea7c3294bf45d..4a311bac64452da45bcd4dd3ecac620e29c11474 100644 (file)
@@ -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
 };