nwrap: Implement nwrap_files_initgroups_dyn()
authorPavel Filipenský <pfilipensky@samba.org>
Tue, 17 Jan 2023 08:51:08 +0000 (09:51 +0100)
committerAndreas Schneider <asn@samba.org>
Tue, 24 Jan 2023 08:56:35 +0000 (09:56 +0100)
This implements the initgroups_dyn() for the files part correctly. We need to
reimplement initgroups() later.

Signed-off-by: Pavel Filipenský <pfilipensky@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
src/nss_wrapper.c

index ffa36580d7ed87823cef8b5e9d43acff9e6ff60a..b2e9f2af1d061dd9666b3683da78cea5f62ccd33 100644 (file)
@@ -609,8 +609,6 @@ struct nwrap_ops {
                                         struct passwd *pwdst, char *buf,
                                         size_t buflen, struct passwd **pwdstp);
        void            (*nw_endpwent)(struct nwrap_backend *b);
-       int             (*nw_initgroups)(struct nwrap_backend *b,
-                                        const char *user, gid_t group);
        int             (*nw_initgroups_dyn)(struct nwrap_backend *b,
                                             const char *user,
                                             gid_t group,
@@ -674,8 +672,14 @@ static int nwrap_files_getpwent_r(struct nwrap_backend *b,
                                  struct passwd *pwdst, char *buf,
                                  size_t buflen, struct passwd **pwdstp);
 static void nwrap_files_endpwent(struct nwrap_backend *b);
-static int nwrap_files_initgroups(struct nwrap_backend *b,
-                                 const char *user, gid_t group);
+static int nwrap_files_initgroups_dyn(struct nwrap_backend *b,
+                                     const char *user,
+                                     gid_t group,
+                                     long int *start,
+                                     long int *size,
+                                     gid_t **groups,
+                                     long int limit,
+                                     int *errnop);
 static struct group *nwrap_files_getgrnam(struct nwrap_backend *b,
                                          const char *name);
 static int nwrap_files_getgrnam_r(struct nwrap_backend *b,
@@ -771,7 +775,7 @@ struct nwrap_ops nwrap_files_ops = {
        .nw_getpwent    = nwrap_files_getpwent,
        .nw_getpwent_r  = nwrap_files_getpwent_r,
        .nw_endpwent    = nwrap_files_endpwent,
-       .nw_initgroups  = nwrap_files_initgroups,
+       .nw_initgroups_dyn      = nwrap_files_initgroups_dyn,
        .nw_getgrnam    = nwrap_files_getgrnam,
        .nw_getgrnam_r  = nwrap_files_getgrnam_r,
        .nw_getgrgid    = nwrap_files_getgrgid,
@@ -3708,27 +3712,21 @@ static struct spwd *nwrap_files_getspnam(const char *name)
 #endif /* defined(HAVE_SHADOW_H) && defined(HAVE_GETSPNAM) */
 
 /* misc functions */
-static int nwrap_files_initgroups(struct nwrap_backend *b,
-                                 const char *user,
-                                 gid_t group)
+static int nwrap_files_initgroups_dyn(struct nwrap_backend *b,
+                                     const char *user,
+                                     gid_t group,
+                                     long int *start,
+                                     long int *size,
+                                     gid_t **groups,
+                                     long int limit,
+                                     int *errnop)
 {
        struct group *grp;
-       gid_t *groups;
-       int size = 1;
-       int rc;
-
-       groups = (gid_t *)malloc(size * sizeof(gid_t));
-       if (groups == NULL) {
-               NWRAP_LOG(NWRAP_LOG_ERROR, "Out of memory");
-               errno = ENOMEM;
-               return -1;
-       }
-       groups[0] = group;
+       int i = 0;
 
+       (void)errnop; /* unused */
        nwrap_files_setgrent(b);
        while ((grp = nwrap_files_getgrent(b)) != NULL) {
-               int i = 0;
-
                NWRAP_LOG(NWRAP_LOG_DEBUG,
                          "Inspecting %s for group membership",
                          grp->gr_name);
@@ -3741,33 +3739,31 @@ static int nwrap_files_initgroups(struct nwrap_backend *b,
                                          user,
                                          grp->gr_name);
 
-                               groups = (gid_t *)realloc(groups,
-                                                         (size + 1) * sizeof(gid_t));
-                               if (groups == NULL) {
-                                       NWRAP_LOG(NWRAP_LOG_ERROR,
-                                                 "Out of memory");
-                                       errno = ENOMEM;
-                                       return -1;
+                               if (*start == *size) {
+                                       long int newsize;
+                                       gid_t *newgroups;
+
+                                       newsize = 2 * (*size);
+                                       if (limit > 0 && newsize > limit) {
+                                               newsize = MAX(limit, *size);
+                                       }
+                                       newgroups = (gid_t *) realloc((*groups),
+                                                       newsize * sizeof(**groups));
+                                       if (!newgroups) {
+                                               errno = ENOMEM;
+                                               return -1;
+                                       }
+                                       *groups = newgroups;
+                                       *size = newsize;
                                }
-
-                               groups[size] = grp->gr_gid;
-                               size++;
+                               (*groups)[*start] = grp->gr_gid;
+                               (*start)++;
                        }
                }
        }
 
        nwrap_files_endgrent(b);
-
-       NWRAP_LOG(NWRAP_LOG_DEBUG,
-                 "%s is member of %d groups",
-                 user, size);
-
-       /* This really only works if uid_wrapper is loaded */
-       rc = setgroups(size, groups);
-
-       free(groups);
-
-       return rc;
+       return *start;
 }
 
 /* group functions */