include/dlinklist.h: Added '{' '}' around DLIST_PROMOTE so it can be used as a single
authorJeremy Allison <jra@samba.org>
Tue, 28 Nov 2000 22:17:44 +0000 (22:17 +0000)
committerJeremy Allison <jra@samba.org>
Tue, 28 Nov 2000 22:17:44 +0000 (22:17 +0000)
statement after an 'if'. Tracking this down took 4 hours from my life and ANDREW I WANT
THEM BACK !!!!! :-).
include/smb.h smbd/password.c: Fixed the bug veritas reported with realloc of the validated_users
array growing without bounds. This is now a linked list as god (Andrew) intended :-).
Jeremy.
(This used to be commit 346f2f9206b9b4ed123e2a61c0a48de630397b8a)

source3/include/dlinklist.h
source3/include/smb.h
source3/smbd/password.c

index 851bf01d380a0999335997d1b65e034c132f1f60..447948b5211183a936fab6223e68910dec1be73e 100644 (file)
@@ -52,5 +52,7 @@
 
 /* promote an element to the top of the list */
 #define DLIST_PROMOTE(list, p) \
+{ \
           DLIST_REMOVE(list, p) \
-          DLIST_ADD(list, p)
+          DLIST_ADD(list, p) \
+}
index 756737af1d5c4cd852b94bfda9948f9e1eef225b..300fd9872adef8b84c21793126db48472e92c4d9 100644 (file)
@@ -1608,8 +1608,10 @@ struct ncacn_np
 #include "rpc_secdes.h"
 #include "nt_printing.h"
 
-typedef struct
+typedef struct user_struct
 {
+       struct user_struct *next, *prev;
+       uint16 vuid; /* Tag for this entry. */
        uid_t uid; /* uid of a validated user */
        gid_t gid; /* gid of a validated user */
 
index a1df5bf7f0fadcef0971e4136f91bb4cce55874e..48e4172ace8a60a0b7a3919553e0df8236838d9d 100644 (file)
@@ -93,8 +93,9 @@ static BOOL last_challenge(unsigned char *challenge)
 }
 
 /* this holds info on user ids that are already validated for this VC */
-static user_struct *validated_users = NULL;
-static int num_validated_users = 0;
+static user_struct *validated_users;
+static int next_vuid = VUID_OFFSET;
+static int num_validated_vuids;
 
 /****************************************************************************
 check if a uid has been validated, and return an pointer to the user_struct
@@ -103,13 +104,21 @@ tell random client vuid's (normally zero) from valid vuids.
 ****************************************************************************/
 user_struct *get_valid_user_struct(uint16 vuid)
 {
-  if (vuid == UID_FIELD_INVALID)
-    return NULL;
-  vuid -= VUID_OFFSET;
-  if ((vuid >= (uint16)num_validated_users) || 
-     (validated_users[vuid].uid == (uid_t)-1) || (validated_users[vuid].gid == (gid_t)-1))
-    return NULL;
-  return &validated_users[vuid];
+       user_struct *usp;
+       int count=0;
+
+       if (vuid == UID_FIELD_INVALID)
+               return NULL;
+
+       for (usp=validated_users;usp;usp=usp->next,count++) {
+               if (vuid == usp->vuid) {
+                       if (count > 10)
+                DLIST_PROMOTE(validated_users, usp);
+                       return usp;
+               }
+       }
+
+       return NULL;
 }
 
 /****************************************************************************
@@ -122,18 +131,12 @@ void invalidate_vuid(uint16 vuid)
        if (vuser == NULL)
                return;
 
-       vuser->uid = (uid_t)-1;
-       vuser->gid = (gid_t)-1;
-
-       /* same number of igroups as groups */
-       vuser->n_groups = 0;
-
-       if (vuser->groups)
-               free((char *)vuser->groups);
-
-       vuser->groups  = NULL;
+       DLIST_REMOVE(validated_users, vuser);
 
+       safe_free(vuser->groups);
        delete_nt_token(&vuser->nt_user_token);
+       safe_free(vuser);
+       num_validated_vuids--;
 }
 
 /****************************************************************************
@@ -206,58 +209,76 @@ tell random client vuid's (normally zero) from valid vuids.
 uint16 register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name, 
                     char *domain,BOOL guest)
 {
-  user_struct *vuser;
-  struct passwd *pwfile; /* for getting real name from passwd file */
+       user_struct *vuser = NULL;
+       user_struct *vsp;
+       struct passwd *pwfile; /* for getting real name from passwd file */
 
-  /* Ensure no vuid gets registered in share level security. */
-  if(lp_security() == SEC_SHARE)
-    return UID_FIELD_INVALID;
+       /* Ensure no vuid gets registered in share level security. */
+       if(lp_security() == SEC_SHARE)
+               return UID_FIELD_INVALID;
 
-  validated_users = (user_struct *)Realloc(validated_users,
-                          sizeof(user_struct)*
-                          (num_validated_users+1));
-  
-  if (!validated_users) {
-      DEBUG(0,("Failed to realloc users struct!\n"));
-      num_validated_users = 0;
-      return UID_FIELD_INVALID;
-  }
+       /* Limit allowed vuids to 16bits - VUID_OFFSET. */
+       if (num_validated_vuids >= 0xFFFF-VUID_OFFSET)
+               return UID_FIELD_INVALID;
 
-  vuser = &validated_users[num_validated_users];
-  num_validated_users++;
+       if((vuser = (user_struct *)malloc( sizeof(user_struct) )) == NULL) {
+               DEBUG(0,("Failed to malloc users struct!\n"));
+               return UID_FIELD_INVALID;
+       }
 
-  vuser->uid = uid;
-  vuser->gid = gid;
-  vuser->guest = guest;
-  fstrcpy(vuser->user.unix_name,unix_name);
-  fstrcpy(vuser->user.smb_name,requested_name);
-  fstrcpy(vuser->user.domain,domain);
+       ZERO_STRUCTP(vuser);
 
-  vuser->n_groups = 0;
-  vuser->groups  = NULL;
+       DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)uid, (unsigned int)gid,
+                               unix_name, requested_name, domain, guest ));
 
-  /* Find all the groups this uid is in and store them. 
-     Used by become_user() */
-  initialise_groups(unix_name, uid, gid);
-  get_current_groups( &vuser->n_groups, &vuser->groups);
+       /* Allocate a free vuid. Yes this is a linear search... :-) */
+       while( (vsp = get_valid_user_struct(next_vuid)) != NULL ) {
+               next_vuid++;
+               /* Check for vuid wrap. */
+               if (next_vuid == UID_FIELD_INVALID)
+                       next_vuid = VUID_OFFSET;
+       }
 
-  /* Create an NT_USER_TOKEN struct for this user. */
-  vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups);
+       DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid ));
 
-  DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name));
+       vuser->vuid = next_vuid;
+       vuser->uid = uid;
+       vuser->gid = gid;
+       vuser->guest = guest;
+       fstrcpy(vuser->user.unix_name,unix_name);
+       fstrcpy(vuser->user.smb_name,requested_name);
+       fstrcpy(vuser->user.domain,domain);
 
-  DEBUG(3, ("Clearing default real name\n"));
-  fstrcpy(vuser->user.full_name, "<Full Name>");
-  if (lp_unix_realname()) {
-    if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) {
-      DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos));
-      fstrcpy(vuser->user.full_name, pwfile->pw_gecos);
-    }
-  }
+       vuser->n_groups = 0;
+       vuser->groups  = NULL;
+
+       /* Find all the groups this uid is in and store them. 
+               Used by become_user() */
+       initialise_groups(unix_name, uid, gid);
+       get_current_groups( &vuser->n_groups, &vuser->groups);
+
+       /* Create an NT_USER_TOKEN struct for this user. */
+       vuser->nt_user_token = create_nt_token(uid,gid, vuser->n_groups, vuser->groups);
+
+       next_vuid++;
+       num_validated_vuids++;
+
+       DLIST_ADD(validated_users, vuser);
+
+       DEBUG(3,("uid %d registered to name %s\n",(int)uid,unix_name));
+
+       DEBUG(3, ("Clearing default real name\n"));
+       fstrcpy(vuser->user.full_name, "<Full Name>");
+       if (lp_unix_realname()) {
+               if ((pwfile=sys_getpwnam(vuser->user.unix_name))!= NULL) {
+                       DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,pwfile->pw_gecos));
+                       fstrcpy(vuser->user.full_name, pwfile->pw_gecos);
+               }
+       }
 
-  memset(&vuser->dc, '\0', sizeof(vuser->dc));
+       memset(&vuser->dc, '\0', sizeof(vuser->dc));
 
-  return (uint16)((num_validated_users - 1) + VUID_OFFSET);
+       return vuser->vuid;
 }