From 1153f00f889e5bb310e895d319eed75bc93deef4 Mon Sep 17 00:00:00 2001 From: Luke Leighton Date: Wed, 3 Feb 1999 00:49:24 +0000 Subject: cache unix groups so that two-level getgrent calls don't occur. (This used to be commit f7dfa55a2e191ae780d399026bce48f68cda4bf0) --- source3/groupdb/aliasunix.c | 50 +++++++++++++++++++++++++---- source3/groupdb/builtinunix.c | 64 ++++++++++++++++++++++++++++++------- source3/groupdb/groupunix.c | 55 ++++++++++++++++++++++++++++---- source3/include/proto.h | 5 +-- source3/lib/replace.c | 1 + source3/lib/util.c | 71 ++++++++++++++++++++++++++++++++++++++++++ source3/rpc_parse/parse_reg.c | 5 ++- source3/rpc_parse/parse_samr.c | 4 +-- source3/rpc_server/srv_reg.c | 2 +- 9 files changed, 226 insertions(+), 31 deletions(-) diff --git a/source3/groupdb/aliasunix.c b/source3/groupdb/aliasunix.c index f9537ddeb4..39d7255ac5 100644 --- a/source3/groupdb/aliasunix.c +++ b/source3/groupdb/aliasunix.c @@ -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); } diff --git a/source3/groupdb/builtinunix.c b/source3/groupdb/builtinunix.c index c8ea767a77..bb45f2983f 100644 --- a/source3/groupdb/builtinunix.c +++ b/source3/groupdb/builtinunix.c @@ -23,6 +23,12 @@ 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)); } diff --git a/source3/groupdb/groupunix.c b/source3/groupdb/groupunix.c index 35f386cbf8..a8f40a313a 100644 --- a/source3/groupdb/groupunix.c +++ b/source3/groupdb/groupunix.c @@ -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); } diff --git a/source3/include/proto.h b/source3/include/proto.h index c3843814f8..bf5f8076fe 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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, diff --git a/source3/lib/replace.c b/source3/lib/replace.c index a768e9ce47..c6a4259417 100644 --- a/source3/lib/replace.c +++ b/source3/lib/replace.c @@ -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 && diff --git a/source3/lib/util.c b/source3/lib/util.c index 066984962b..127f69dc7d 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -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 ********************************************************************/ diff --git a/source3/rpc_parse/parse_reg.c b/source3/rpc_parse/parse_reg.c index 3365a68b3d..b0086f402a 100644 --- a/source3/rpc_parse/parse_reg.c +++ b/source3/rpc_parse/parse_reg.c @@ -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; } diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index 1fcb57c435..cadeffdfd0 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -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; diff --git a/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c index 33ccae3f93..b90912488f 100644 --- a/source3/rpc_server/srv_reg.c +++ b/source3/rpc_server/srv_reg.c @@ -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); -- cgit