cache unix groups so that two-level getgrent calls don't occur.
authorLuke Leighton <lkcl@samba.org>
Wed, 3 Feb 1999 00:49:24 +0000 (00:49 +0000)
committerLuke Leighton <lkcl@samba.org>
Wed, 3 Feb 1999 00:49:24 +0000 (00:49 +0000)
source/groupdb/aliasunix.c
source/groupdb/builtinunix.c
source/groupdb/groupunix.c
source/include/proto.h
source/lib/replace.c
source/lib/util.c
source/rpc_parse/parse_reg.c
source/rpc_parse/parse_samr.c
source/rpc_server/srv_reg.c

index f9537ddeb4c6a98a1a7851ee1eb04c5410d10d67..39d7255ac5bec4c0fe3141eab8666a9de54b76e0 100644 (file)
@@ -27,6 +27,13 @@ extern int DEBUGLEVEL;
 extern DOM_SID global_sam_sid;
 extern fstring global_sam_name;
 
+struct unix_entries
+{
+       struct group *grps;
+       int num_grps;
+       int grp_idx;
+};
+
 /***************************************************************
  Start to enumerate the alspasswd list. Returns a void pointer
  to ensure no modification outside this module.
@@ -34,8 +41,23 @@ extern fstring global_sam_name;
 
 static void *startalsunixpwent(BOOL update)
 {
-       setgrent();
-       return (void*)(-1);
+       struct unix_entries *grps;
+       grps = (struct unix_entries*)malloc(sizeof(struct unix_entries));
+
+       if (grps == NULL)
+       {
+               return NULL;
+       }
+
+       if (!get_unix_grps(&grps->num_grps, &grps->grps))
+       {
+               free(grps);
+               return NULL;
+       }
+
+       grps->grp_idx = 0;
+
+       return (void*)grps;
 }
 
 /***************************************************************
@@ -44,7 +66,13 @@ static void *startalsunixpwent(BOOL update)
 
 static void endalsunixpwent(void *vp)
 {
-       endgrent();
+       struct unix_entries *grps = (struct unix_entries *)vp;
+
+       if (grps != NULL)
+       {
+               free_unix_grps(grps->num_grps, grps->grps);
+               free(vp);
+       }
 }
 
 /*************************************************************************
@@ -142,7 +170,8 @@ static LOCAL_GRP *getalsunixpwent(void *vp, LOCAL_GRP_MEMBER **mem, int *num_mem
 {
        /* Static buffers we will return. */
        static LOCAL_GRP gp_buf;
-       struct group *unix_grp;
+       struct group *unix_grp = NULL;
+       struct unix_entries *grps = (struct unix_entries *)vp;
 
        if (lp_server_role() == ROLE_DOMAIN_NONE)
        {
@@ -156,11 +185,18 @@ static LOCAL_GRP *getalsunixpwent(void *vp, LOCAL_GRP_MEMBER **mem, int *num_mem
 
        aldb_init_als(&gp_buf);
 
+       /* get array of unix names + gids.  this function does NOT
+          get a copy of the unix group members
+        */
+
        /* cycle through unix groups */
-       while ((unix_grp = getgrent()) != NULL)
+       for (; grps->grp_idx < grps->num_grps; grps->grp_idx++)
        {
                DOM_NAME_MAP gmep;
                fstring sid_str;
+
+               unix_grp = &grps->grps[grps->grp_idx];
+
                DEBUG(10,("getgrpunixpwent: enum unix group entry %s\n",
                           unix_grp->gr_name));
                        
@@ -185,10 +221,11 @@ static LOCAL_GRP *getalsunixpwent(void *vp, LOCAL_GRP_MEMBER **mem, int *num_mem
                }
 
                fstrcpy(gp_buf.name, gmep.nt_name);
+               grps->grp_idx++;
                break;
        }
 
-       if (unix_grp == NULL)
+       if (unix_grp == NULL || grps->grp_idx >= grps->num_grps)
        {
                return NULL;
        }
@@ -200,6 +237,7 @@ static LOCAL_GRP *getalsunixpwent(void *vp, LOCAL_GRP_MEMBER **mem, int *num_mem
                (*mem) = NULL;
                (*num_mem) = 0;
 
+               unix_grp = getgrgid(unix_grp->gr_gid);
                get_unixalias_members(unix_grp, num_mem, mem);
        }
 
index c8ea767a77450c3515c5dffec3fe56559586c53d..bb45f2983fd916bf6b70d77c594fba95121db138 100644 (file)
 
 extern int DEBUGLEVEL;
 
+struct unix_entries
+{
+       struct group *grps;
+       int num_grps;
+       int grp_idx;
+};
 
 extern DOM_SID global_sid_S_1_5_20;
 extern DOM_SID global_sam_sid;
@@ -35,8 +41,23 @@ extern fstring global_sam_name;
 
 static void *startbltunixpwent(BOOL update)
 {
-       setgrent();
-       return (void*)(-1);
+       struct unix_entries *grps;
+       grps = (struct unix_entries*)malloc(sizeof(struct unix_entries));
+
+       if (grps == NULL)
+       {
+               return NULL;
+       }
+
+       if (!get_unix_grps(&grps->num_grps, &grps->grps))
+       {
+               free(grps);
+               return NULL;
+       }
+
+       grps->grp_idx = 0;
+
+       return (void*)grps;
 }
 
 /***************************************************************
@@ -45,7 +66,13 @@ static void *startbltunixpwent(BOOL update)
 
 static void endbltunixpwent(void *vp)
 {
-       endgrent();
+       struct unix_entries *grps = (struct unix_entries *)vp;
+
+       if (grps != NULL)
+       {
+               free_unix_grps(grps->num_grps, grps->grps);
+               free(vp);
+       }
 }
 
 /*************************************************************************
@@ -143,12 +170,18 @@ static LOCAL_GRP *getbltunixpwent(void *vp, LOCAL_GRP_MEMBER **mem, int *num_mem
 {
        /* Static buffers we will return. */
        static LOCAL_GRP gp_buf;
-       struct group *unix_grp;
+       struct group *unix_grp = NULL;
+       struct unix_entries *grps = (struct unix_entries *)vp;
+
+       if (grps == NULL)
+       {
+               return NULL;
+       }
 
        if (lp_server_role() == ROLE_DOMAIN_NONE)
        {
                /*
-                * no domain role, no domain builtin aliases (or domain groups,
+                * no domain role, no domain aliases (or domain groups,
                 * but that's dealt with by groupdb...).
                 */
 
@@ -157,12 +190,19 @@ static LOCAL_GRP *getbltunixpwent(void *vp, LOCAL_GRP_MEMBER **mem, int *num_mem
 
        bidb_init_blt(&gp_buf);
 
+       /* get array of unix names + gids.  this function does NOT
+          get a copy of the unix group members
+        */
+
        /* cycle through unix groups */
-       while ((unix_grp = getgrent()) != NULL)
+       for (; grps->grp_idx < grps->num_grps; grps->grp_idx++)
        {
                DOM_NAME_MAP gmep;
                fstring sid_str;
-               DEBUG(10,("getbltunixpwent: enum unix group entry %s\n",
+
+               unix_grp = &grps->grps[grps->grp_idx];
+
+               DEBUG(10,("getgrpunixpwent: enum unix group entry %s\n",
                           unix_grp->gr_name));
                        
                if (!lookupsmbgrpgid(unix_grp->gr_gid, &gmep))
@@ -180,33 +220,35 @@ static LOCAL_GRP *getbltunixpwent(void *vp, LOCAL_GRP_MEMBER **mem, int *num_mem
                }
 
                sid_split_rid(&gmep.sid, &gp_buf.rid);
-               if (!sid_equal(&global_sid_S_1_5_20, &gmep.sid))
+               if (!sid_equal(&global_sam_sid, &gmep.sid))
                {
                        continue;
                }
 
                fstrcpy(gp_buf.name, gmep.nt_name);
+               grps->grp_idx++;
                break;
        }
 
-       if (unix_grp == NULL)
+       if (unix_grp == NULL || grps->grp_idx >= grps->num_grps)
        {
                return NULL;
        }
 
-       /* get the user's domain builtin aliases.  there are a maximum of 32 */
+       /* get the user's domain aliases.  there are a maximum of 32 */
 
        if (mem != NULL && num_mem != NULL)
        {
                (*mem) = NULL;
                (*num_mem) = 0;
 
+               unix_grp = getgrgid(unix_grp->gr_gid);
                get_unixbuiltin_members(unix_grp, num_mem, mem);
        }
 
        {
                pstring linebuf;
-               make_builtin_line(linebuf, sizeof(linebuf), &gp_buf, mem, num_mem);
+               make_alias_line(linebuf, sizeof(linebuf), &gp_buf, mem, num_mem);
                DEBUG(10,("line: '%s'\n", linebuf));
        }
 
index 35f386cbf8bf4e6e8b31c7ac6431c4cfd34ca1a1..a8f40a313a1629d1eccc77b31657c8638c89e3c8 100644 (file)
@@ -31,10 +31,32 @@ extern DOM_SID global_sam_sid;
  to ensure no modification outside this module.
 ****************************************************************/
 
+struct unix_entries
+{
+       struct group *grps;
+       int num_grps;
+       int grp_idx;
+};
+
 static void *startgrpunixpwent(BOOL update)
 {
-       setgrent();
-       return (void*)(-1);
+       struct unix_entries *grps;
+       grps = (struct unix_entries*)malloc(sizeof(struct unix_entries));
+
+       if (grps == NULL)
+       {
+               return NULL;
+       }
+
+       if (!get_unix_grps(&grps->num_grps, &grps->grps))
+       {
+               free(grps);
+               return NULL;
+       }
+
+       grps->grp_idx = 0;
+
+       return (void*)grps;
 }
 
 /***************************************************************
@@ -43,7 +65,13 @@ static void *startgrpunixpwent(BOOL update)
 
 static void endgrpunixpwent(void *vp)
 {
-       endgrent();
+       struct unix_entries *grps = (struct unix_entries *)vp;
+
+       if (grps != NULL)
+       {
+               free_unix_grps(grps->num_grps, grps->grps);
+               free(vp);
+       }
 }
 
 /*************************************************************************
@@ -142,7 +170,13 @@ static DOMAIN_GRP *getgrpunixpwent(void *vp, DOMAIN_GRP_MEMBER **mem, int *num_m
 {
        /* Static buffers we will return. */
        static DOMAIN_GRP gp_buf;
-       struct group *unix_grp;
+       struct group *unix_grp = NULL;
+       struct unix_entries *grps = (struct unix_entries *)vp;
+
+       if (grps == NULL)
+       {
+               return NULL;
+       }
 
        if (lp_server_role() == ROLE_DOMAIN_NONE || 
            lp_server_role() == ROLE_DOMAIN_MEMBER)
@@ -161,10 +195,17 @@ static DOMAIN_GRP *getgrpunixpwent(void *vp, DOMAIN_GRP_MEMBER **mem, int *num_m
        fstrcpy(gp_buf.comment, "");
        gp_buf.attr    = 0x07;
 
+       /* get array of unix names + gids.  this function does NOT
+          get a copy of the unix group members
+        */
+
        /* cycle through unix groups */
-       while ((unix_grp = getgrent()) != NULL)
+       for (; grps->grp_idx < grps->num_grps; grps->grp_idx++)
        {
                DOM_NAME_MAP gmep;
+
+               unix_grp = &grps->grps[grps->grp_idx];
+
                DEBUG(10,("getgrpunixpwent: enum unix group entry %s\n",
                           unix_grp->gr_name));
                        
@@ -186,10 +227,11 @@ static DOMAIN_GRP *getgrpunixpwent(void *vp, DOMAIN_GRP_MEMBER **mem, int *num_m
                }
 
                fstrcpy(gp_buf.name, gmep.nt_name);
+               grps->grp_idx++;
                break;
        }
 
-       if (unix_grp == NULL)
+       if (unix_grp == NULL || grps->grp_idx >= grps->num_grps)
        {
                return NULL;
        }
@@ -201,6 +243,7 @@ static DOMAIN_GRP *getgrpunixpwent(void *vp, DOMAIN_GRP_MEMBER **mem, int *num_m
                (*mem) = NULL;
                (*num_mem) = 0;
 
+               unix_grp = getgrgid(unix_grp->gr_gid);
                get_unixgroup_members(unix_grp, num_mem, mem);
        }
 
index c3843814f8e23839fb866f570007e0ff90fd3296..bf5f8076fe4c63ce23c114075202732a17c474b9 100644 (file)
@@ -432,6 +432,8 @@ BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask);
 struct hostent *Get_Hostbyname(const char *name);
 BOOL process_exists(int pid);
 int get_unixgroups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_groups);
+BOOL get_unix_grps(int *p_ngroups, struct group **p_groups);
+void free_unix_grps(int ngroups, struct group *p_groups);
 char *uidtoname(uid_t uid);
 char *gidtoname(gid_t gid);
 BOOL nametogid(const char *name, gid_t *gid);
@@ -2068,7 +2070,6 @@ void make_reg_q_info(REG_Q_INFO *q_i, POLICY_HND *pol, char *product_type,
 void reg_io_q_info(char *desc,  REG_Q_INFO *r_q, prs_struct *ps, int depth);
 void make_reg_r_info(REG_R_INFO *r_r,
                                uint32 level, char *os_type,
-                               uint32 unknown_0, uint32 unknown_1,
                                uint32 status);
 void reg_io_r_info(char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth);
 void make_reg_q_enum_val(REG_Q_ENUM_VALUE *q_i, POLICY_HND *pol,
@@ -2186,7 +2187,7 @@ void make_samr_q_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_e, POLICY_HND *pol,
                                uint16 acb_mask, uint16 unk_1, uint32 size);
 void samr_io_q_enum_dom_users(char *desc,  SAMR_Q_ENUM_DOM_USERS *q_e, prs_struct *ps, int depth);
 void make_samr_r_enum_dom_users(SAMR_R_ENUM_DOM_USERS *r_u,
-               uint32 unk_0,
+               uint32 next_idx,
                uint32 num_sam_entries, SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES], uint32 status);
 void samr_io_r_enum_dom_users(char *desc,  SAMR_R_ENUM_DOM_USERS *r_u, prs_struct *ps, int depth);
 void make_samr_q_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_e, POLICY_HND *pol,
index a768e9ce47a6a05d923d132a91e4c4a278af0c91..c6a4259417714133e9a8babf1e4bcf3ac76eb5ad 100644 (file)
@@ -168,6 +168,7 @@ Corrections by richard.kettlewell@kewill.com
        struct group *g;
        char   *gr;
        
+       setgrent();
        grouplst[0] = id;
        i = 1;
        while (i < NGROUPS_MAX && 
index 066984962b88d0b811f1413f1e4eecce1f70cd12..127f69dc7d65c64b774371671d1b715a095a8837 100644 (file)
@@ -2384,6 +2384,77 @@ int get_unixgroups(char *user, uid_t uid, gid_t gid, int *p_ngroups, gid_t **p_g
        return 0;
 }
 
+/****************************************************************************
+get all unix groups.  copying group members is hideous on memory, so it's
+NOT done here.  however, names of unix groups _are_ string-allocated so
+free_unix_grps() must be called.
+****************************************************************************/
+BOOL get_unix_grps(int *p_ngroups, struct group **p_groups)
+{
+       struct group *grp;
+
+       DEBUG(10,("get_unix_grps\n"));
+
+       if (p_ngroups == NULL || *p_groups == NULL)
+       {
+               return False;
+       }
+
+       (*p_ngroups) = 0;
+       (*p_groups) = NULL;
+
+       setgrent();
+
+       while ((grp = getgrent()) != NULL)
+       {
+               struct group *copy_grp;
+               
+               (*p_groups) = (struct group*)Realloc((*p_groups), (size_t)((*p_ngroups)+1) * sizeof(struct group));
+               if ((*p_groups) == NULL)
+               {
+                       (*p_ngroups) = 0;
+                       endgrent();
+                       
+                       return False;
+               }
+
+               copy_grp = &(*p_groups)[*p_ngroups];
+               memcpy(copy_grp, grp, sizeof(*grp));
+               copy_grp->gr_name = strdup(copy_grp->gr_name);
+               copy_grp->gr_mem  = NULL;
+
+               (*p_ngroups)++;
+       }
+
+       endgrent();
+
+       DEBUG(10,("get_unix_grps: %d groups\n", (*p_ngroups)));
+       return True;
+}
+
+/****************************************************************************
+free memory associated with unix groups.
+****************************************************************************/
+void free_unix_grps(int ngroups, struct group *p_groups)
+{
+       int i;
+
+       if (p_groups == NULL)
+       {
+               return;
+       }
+
+       for (i = 0; i < ngroups; i++)
+       {
+               if (p_groups[i].gr_name != NULL)
+               {
+                       free(p_groups[i].gr_name);
+               }
+       }
+
+       free(p_groups);
+}
+
 /*******************************************************************
 turn a uid into a user name
 ********************************************************************/
index 3365a68b3dc531193854a2cea856adc9e8c43a20..b0086f402a45cb5f45f5df6ebb457b3bc3d9725c 100644 (file)
@@ -766,7 +766,6 @@ creates a structure.
 ********************************************************************/
 void make_reg_r_info(REG_R_INFO *r_r,
                                uint32 level, char *os_type,
-                               uint32 unknown_0, uint32 unknown_1,
                                uint32 status)
 {
        uint8 buf[512];
@@ -779,10 +778,10 @@ void make_reg_r_info(REG_R_INFO *r_r,
        make_buffer2(&(r_r->uni_type), buf, len*2);
 
        r_r->ptr2 = 1;
-       r_r->unknown_0 = unknown_0;
+       r_r->unknown_0 = len*2;
 
        r_r->ptr3 = 1;
-       r_r->unknown_1 = unknown_1;
+       r_r->unknown_1 = len*2;
 
        r_r->status = status;
 }
index 1fcb57c4359791840d80b5a2ac67bed40c72535d..cadeffdfd0e447d473b902ef53c26746e0e22f9d 100644 (file)
@@ -1232,7 +1232,7 @@ void make_samr_r_query_dispinfo(SAMR_R_QUERY_DISPINFO *r_u,
 {
        if (r_u == NULL) return;
 
-       DEBUG(5,("make_samr_r_query_dispinfo\n"));
+       DEBUG(5,("make_samr_r_query_dispinfo: level %d\n", switch_level));
 
        if (status == 0x0)
        {
@@ -1910,7 +1910,7 @@ void make_samr_r_query_groupmem(SAMR_R_QUERY_GROUPMEM *r_u,
 
        if (status == 0x0)
        {
-               r_u->ptr         = (num_entries != 0) ? 1 : 0;
+               r_u->ptr         = 1;
                r_u->num_entries = num_entries;
 
                r_u->ptr_attrs = attr != NULL ? 1 : 0;
index 33ccae3f934d4d23edc3f0a33a04c5203ea3919c..b90912488f1b5ed70984250206cb8a0565d9f9c8 100644 (file)
@@ -194,7 +194,7 @@ static void reg_reply_info(REG_Q_INFO *q_u,
        {
        }
 
-       make_reg_r_info(&r_u, 1, "LanmanNT", 0x12, 0x12, status);
+       make_reg_r_info(&r_u, 1, "LanmanNT", status);
 
        /* store the response in the SMB stream */
        reg_io_r_info("", &r_u, rdata, 0);