Imported Upstream version 1.8.3
[debian/sudo] / plugins / sudoers / pwutil.c
index b511472c3fdc2e79be62d0c38a85f591b90ebc63..aac32325ac42b7ad0d59e0dd0c3a68ac565be115 100644 (file)
@@ -312,10 +312,10 @@ done:
 }
 
 /*
- * Take a uid in string form "#123" and return a faked up passwd struct.
+ * Take a user, uid and gid and return a faked up passwd struct.
  */
 struct passwd *
-sudo_fakepwnam(const char *user, gid_t gid)
+sudo_fakepwnamid(const char *user, uid_t uid, gid_t gid)
 {
     struct cache_item *item;
     struct passwd *pw;
@@ -332,7 +332,7 @@ sudo_fakepwnam(const char *user, gid_t gid)
        item = emalloc(len);
        zero_bytes(item, sizeof(*item) + sizeof(*pw));
        pw = (struct passwd *) ((char *)item + sizeof(*item));
-       pw->pw_uid = (uid_t) atoi(user + 1);
+       pw->pw_uid = uid;
        pw->pw_gid = gid;
        pw->pw_name = (char *)pw + sizeof(struct passwd);
        memcpy(pw->pw_name, user, namelen + 1);
@@ -367,6 +367,18 @@ sudo_fakepwnam(const char *user, gid_t gid)
     return pw;
 }
 
+/*
+ * Take a uid in string form "#123" and return a faked up passwd struct.
+ */
+struct passwd *
+sudo_fakepwnam(const char *user, gid_t gid)
+{
+    uid_t uid;
+
+    uid = (uid_t) atoi(user + 1);
+    return sudo_fakepwnamid(user, uid, gid);
+}
+
 void
 sudo_setpwent(void)
 {
@@ -474,12 +486,12 @@ make_gritem(const struct group *gr, const char *name)
 }
 
 #ifdef HAVE_UTMPX_H
-# define GROUPNAME_LEN (sizeof((struct utmpx *)0)->ut_user)
+# define GROUPNAME_LEN (sizeof((struct utmpx *)0)->ut_user + 1)
 #else
 # ifdef HAVE_STRUCT_UTMP_UT_USER
-#  define GROUPNAME_LEN        (sizeof((struct utmp *)0)->ut_user)
+#  define GROUPNAME_LEN        (sizeof((struct utmp *)0)->ut_user + 1)
 # else
-#  define GROUPNAME_LEN        (sizeof((struct utmp *)0)->ut_name)
+#  define GROUPNAME_LEN        (sizeof((struct utmp *)0)->ut_name + 1)
 # endif
 #endif /* HAVE_UTMPX_H */
 
@@ -491,11 +503,15 @@ static struct cache_item *
 make_grlist_item(const char *user, GETGROUPS_T *gids, int ngids)
 {
     char *cp;
-    size_t i, nsize, ngroups = 0, total, len;
+    size_t i, nsize, ngroups, total, len;
     struct cache_item *item;
     struct group_list *grlist;
     struct group *grp;
 
+#ifdef HAVE_SETAUTHDB
+    aix_setauthdb((char *) user);
+#endif
+
     /* Allocate in one big chunk for easy freeing. */
     nsize = strlen(user) + 1;
     total = sizeof(struct cache_item) + sizeof(struct group_list) + nsize;
@@ -503,21 +519,22 @@ make_grlist_item(const char *user, GETGROUPS_T *gids, int ngids)
     total += sizeof(gid_t *) * ngids;
     total += GROUPNAME_LEN * ngids;
 
+again:
     item = emalloc(total);
     cp = (char *) item + sizeof(struct cache_item);
 
     /*
      * Copy in group list and make pointers relative to space
-     * at the end of the buffer.  Note that the gids array must come
+     * at the end of the buffer.  Note that the groups array must come
      * immediately after struct group to guarantee proper alignment.
      */
     grlist = (struct group_list *)cp;
     zero_bytes(grlist, sizeof(struct group_list));
     cp += sizeof(struct group_list);
-    grlist->gids = (gid_t *)cp;
-    cp += sizeof(gid_t) * ngids;
     grlist->groups = (char **)cp;
     cp += sizeof(char *) * ngids;
+    grlist->gids = (gid_t *)cp;
+    cp += sizeof(gid_t) * ngids;
 
     /* Set key and datum. */
     memcpy(cp, user, nsize);
@@ -533,20 +550,18 @@ make_grlist_item(const char *user, GETGROUPS_T *gids, int ngids)
        grlist->gids[i] = gids[i];
     grlist->ngids = ngids;
 
-#ifdef HAVE_SETAUTHDB
-    aix_setauthdb((char *) user);
-#endif
     /*
-     * Resolve group names by ID and store at the end.
+     * Resolve and store group names by ID.
      */
+    ngroups = 0;
     for (i = 0; i < ngids; i++) {
        if ((grp = sudo_getgrgid(gids[i])) != NULL) {
            len = strlen(grp->gr_name) + 1;
-           if (cp - (char *)grlist + len > total) {
-               void *ptr = erealloc(grlist, total + len + GROUPNAME_LEN);
+           if (cp - (char *)item + len > total) {
                total += len + GROUPNAME_LEN;
-               cp = (char *)ptr + (cp - (char *)grlist);
-               grlist = ptr;
+               efree(item);
+               gr_delref(grp);
+               goto again;
            }
            memcpy(cp, grp->gr_name, len);
            grlist->groups[ngroups++] = cp;