diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/password.c | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/source3/smbd/password.c b/source3/smbd/password.c index ca588c6681..e7f7f2c039 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -618,24 +618,61 @@ static char *validate_group(char *group,char *password,int pwlen,int snum) #ifdef HAVE_GETGRENT { struct group *gptr; - char **member; setgrent(); while ((gptr = (struct group *)getgrent())) { - if (!strequal(gptr->gr_name,group)) - continue; - member = gptr->gr_mem; - while (member && *member) { + if (strequal(gptr->gr_name,group)) + break; + } + + /* + * As user_ok can recurse doing a getgrent(), we must + * copy the member list into a pstring on the stack before + * use. Bug pointed out by leon@eatworms.swmed.edu. + */ + + if (gptr) { + pstring member_list; + char *member; + size_t copied_len = 0; + int i; + + *member_list = '\0'; + member = member_list; + + for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) { + size_t member_len = strlen(gptr->gr_mem[i]) + 1; + if( copied_len + member_len < sizeof(pstring)) { + + DEBUG(10,("validate_group: = gr_mem = %s\n", gptr->gr_mem[i])); + + safe_strcpy(member, gptr->gr_mem[i], sizeof(pstring) - copied_len - 1); + copied_len += member_len; + member += copied_len; + } else { + *member = '\0'; + } + } + + endgrent(); + + member = member_list; + while (*member) { static fstring name; - fstrcpy(name,*member); + fstrcpy(name,member); if (user_ok(name,snum) && password_ok(name,password,pwlen,NULL)) { endgrent(); return(&name[0]); } - member++; + + DEBUG(10,("validate_group = member = %s\n", member)); + + member += strlen(member) + 1; } + } else { + endgrent(); + return NULL; } - endgrent(); } #endif return(NULL); |