lib/system.c (Finally) fixed all insure errors in password caching code. We can't
authorJeremy Allison <jra@samba.org>
Sat, 17 Mar 2001 03:36:38 +0000 (03:36 +0000)
committerJeremy Allison <jra@samba.org>
Sat, 17 Mar 2001 03:36:38 +0000 (03:36 +0000)
stop libc routines from calling getpwXXX functions, so caching a pointer to them
is impossible. This new code now makes two copies of the returned struct passwd
struct - one used as a cache, one returned to allow the caller to modify. When
doing a lookup we compare against the cached copy. Code is now easier to understand
also.
smbd/posix_acls.c: If we move the head of the linked list, remember to pass a
reference to that pointer.....
Jeremy.
(This used to be commit af364b93d92f70aa52195c46d3cc516830752609)

source3/lib/system.c
source3/smbd/posix_acls.c

index 5557aa8735d8c0da6b60d54541c824b14d498add..526113dcf7a4d775b0522a702cbd990e2044da36 100644 (file)
@@ -580,49 +580,61 @@ int sys_setgroups(int setlen, gid_t *gidset)
  Helper function for getpwnam/getpwuid wrappers.
 ****************************************************************************/
 
+struct saved_pw {
+       fstring         pw_name;
+       fstring         pw_passwd;
+       struct passwd pass;
+};
+
+static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
+static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
+
+static int num_lookups; /* Counter so we don't always use cache. */
+#ifndef PW_RET_CACHE_MAX_LOOKUPS
+#define PW_RET_CACHE_MAX_LOOKUPS 100
+#endif
+
 static struct passwd *setup_pwret(struct passwd *pass)
 {
-       static fstring  pw_name;
-       static fstring  pw_passwd;
-       static struct passwd pw_ret;
-       
-       if (pass == NULL)
+       if (pass == NULL) {
+               /* Clear the caches. */
+               memset(&pw_cache, '\0', sizeof(struct saved_pw));
+               memset(&pw_mod, '\0', sizeof(struct saved_pw));
+               num_lookups = 0;
                return NULL;
+       }
 
        /* this gets the uid, gid and null pointers */
-       memcpy((char *)&pw_ret, pass, sizeof(struct passwd));
 
-       if (pass->pw_name)
-       {
-               pw_ret.pw_name = pw_name;
-               fstrcpy(pw_ret.pw_name, pass->pw_name);
-       }
+       memcpy((char *)&pw_mod.pass, pass, sizeof(struct passwd));
+       fstrcpy(pw_mod.pw_name, pass->pw_name);
+       pw_mod.pass.pw_name = pw_mod.pw_name;
+       fstrcpy(pw_mod.pw_passwd, pass->pw_passwd);
+       pw_mod.pass.pw_passwd = pw_mod.pw_passwd;
 
-       if (pass->pw_passwd)
-       {
-               pw_ret.pw_passwd = pw_passwd;
-               fstrcpy(pw_ret.pw_passwd, pass->pw_passwd);
-       }
 
-       return &pw_ret;
-}
+       if (pass != &pw_cache.pass) {
 
-/* static pointer to be used for caching the last 
-   getpw[nam|uid]() call.  Patch by "Richard Bollinger" 
-   <rabollinger@home.com> */
+               /* If it's a cache miss we must also refill the cache. */
 
-/*
- * This next static pointer is used to cache the results
- * from the real getpwXX calls. It is never returned to 
- * the caller, only the output from calling setup_pwret with
- * this is returned. JRA.
- */
+               memcpy((char *)&pw_cache.pass, pass, sizeof(struct passwd));
+               fstrcpy(pw_cache.pw_name, pass->pw_name);
+               pw_cache.pass.pw_name = pw_cache.pw_name;
+               fstrcpy(pw_cache.pw_passwd, pass->pw_passwd);
+               pw_cache.pass.pw_passwd = pw_cache.pw_passwd;
 
-static struct passwd *sv_pw_ret; /* implicitly initialized to NULL */
-static int num_lookups; /* Counter so we don't always use cache. */
-#ifndef PW_RET_CACHE_MAX_LOOKUPS
-#define PW_RET_CACHE_MAX_LOOKUPS 100
-#endif
+               num_lookups = 1;
+
+       } else {
+
+               /* Cache hit. */
+
+               num_lookups++;
+               num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
+       }
+
+       return &pw_mod.pass;
+}
 
 /**************************************************************************
  Wrappers for setpwent(), getpwent() and endpwent()
@@ -630,19 +642,18 @@ static int num_lookups; /* Counter so we don't always use cache. */
 
 void sys_setpwent(void)
 {
-       sv_pw_ret = NULL;
+       setup_pwret(NULL); /* Clear cache. */
        setpwent();
 }
 
 struct passwd *sys_getpwent(void)
 {
-       sv_pw_ret = getpwent();
-       return setup_pwret(sv_pw_ret);
+       return setup_pwret(getpwent());
 }
 
 void sys_endpwent(void)
 {
-       sv_pw_ret = NULL;
+       setup_pwret(NULL); /* Clear cache. */
        endpwent();
 }
 
@@ -656,22 +667,15 @@ struct passwd *sys_getpwnam(const char *name)
                return NULL;
 
        /* check for a cache hit first */
-       if (num_lookups && sv_pw_ret && !strcmp(name, sv_pw_ret->pw_name))
-       {
+       if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
                DEBUG(2,("getpwnam(%s) avoided - using cached results\n",name));
-               num_lookups++;
-               num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
-               return setup_pwret(sv_pw_ret);
+               return setup_pwret(&pw_cache.pass);
        }
 
        /* no cache hit--use old lookup instead */
        DEBUG(2,("getpwnam(%s) called\n",name));
 
-       num_lookups = 1;
-
-       sv_pw_ret = getpwnam(name);
-
-       return setup_pwret(sv_pw_ret);
+       return setup_pwret(getpwnam(name));
 }
 
 /**************************************************************************
@@ -680,21 +684,14 @@ struct passwd *sys_getpwnam(const char *name)
 
 struct passwd *sys_getpwuid(uid_t uid)
 {
-       if (num_lookups && sv_pw_ret && (uid == sv_pw_ret->pw_uid))
-       {
+       if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
                DEBUG(2,("getpwuid(%d) avoided - using cached results\n",uid));
-               num_lookups++;
-               num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
-               return setup_pwret(sv_pw_ret);
+               return setup_pwret(&pw_cache.pass);
        }
        
        DEBUG(2,("getpwuid(%d) called\n",uid));
 
-       num_lookups = 1;
-
-       sv_pw_ret = getpwuid(uid);
-
-       return setup_pwret(sv_pw_ret);
+       return setup_pwret(getpwuid(uid));
 }
 
 /**************************************************************************
index f73f122f431789721f4f14963af8599a24a2cff5..e358e0238ceb784a2242cb7a81d6fceef63c244d 100644 (file)
@@ -930,9 +930,10 @@ static void free_canon_ace_list( canon_ace *list_head )
  entries, last entry = other.
 ********************************************************************************/
 
-static void arrange_posix_perms( char *filename, canon_ace *list_head)
+static void arrange_posix_perms( char *filename, canon_ace **pp_list_head)
 {
        extern DOM_SID global_sid_World;
+       canon_ace *list_head = *pp_list_head;
        canon_ace *owner_ace = NULL;
        canon_ace *other_ace = NULL;
        canon_ace *ace = NULL;
@@ -1011,6 +1012,10 @@ static void arrange_posix_perms( char *filename, canon_ace *list_head)
                owner_ace->attr = DENY_ACE;
                owner_ace->perms = 0;
        }
+
+       /* We have probably changed the head of the list. */
+
+       *pp_list_head = list_head;
 }
                
 /******************************************************************************
@@ -1080,7 +1085,7 @@ static canon_ace *unix_canonicalise_acl(files_struct *fsp, SMB_STRUCT_STAT *psbu
        DLIST_ADD(list_head, group_ace);
        DLIST_ADD(list_head, owner_ace);
 
-       arrange_posix_perms(fsp->fsp_name,list_head );
+       arrange_posix_perms(fsp->fsp_name,&list_head );
 
        return list_head;
 
@@ -1219,6 +1224,8 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_
         * acl_mask.
         */
 
+       DEBUG(10,("canonicalize_acl: ace entries before arrange :\n"));
+
        for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) {
                next_ace = ace->next;
 
@@ -1229,9 +1236,13 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_
                if (ace->perms == 0) {
                        DLIST_PROMOTE(list_head, ace);
                }
+
+               if( DEBUGLVL( 10 ) ) {
+                       print_canon_ace(ace, ace_count);
+               }
        }
 
-       arrange_posix_perms(fsp->fsp_name,list_head );
+       arrange_posix_perms(fsp->fsp_name,&list_head );
 
        if( DEBUGLVL( 10 ) ) {
                char *acl_text = sys_acl_to_text( posix_acl, NULL);
@@ -1239,6 +1250,12 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_
                dbgtext("canonicalize_acl: processed acl %s\n", acl_text == NULL ? "NULL" : acl_text );
                if (acl_text)
                        sys_acl_free_text(acl_text);
+
+               dbgtext("canonicalize_acl: ace entries after arrange :\n");
+
+               for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) {
+                       print_canon_ace(ace, ace_count);
+               }
        }
 
        return list_head;