diff options
author | Jeremy Allison <jra@samba.org> | 2005-10-18 03:24:00 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:05:02 -0500 |
commit | 8d7c88667190fe286971ac4fffb64ee5bd9eeeb0 (patch) | |
tree | d5b2f0850d63a07e051c03a7abe1f10884598161 /source3/lib/system_smbd.c | |
parent | afca439d19e3d9e67b127d7060df630e2218bcb2 (diff) | |
download | samba-8d7c88667190fe286971ac4fffb64ee5bd9eeeb0.tar.gz samba-8d7c88667190fe286971ac4fffb64ee5bd9eeeb0.tar.bz2 samba-8d7c88667190fe286971ac4fffb64ee5bd9eeeb0.zip |
r11137: Compile with only 2 warnings (I'm still working on that code) on a gcc4
x86_64 box.
Jeremy.
(This used to be commit d720867a788c735e56d53d63265255830ec21208)
Diffstat (limited to 'source3/lib/system_smbd.c')
-rw-r--r-- | source3/lib/system_smbd.c | 105 |
1 files changed, 78 insertions, 27 deletions
diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c index f124983006..1afd44b709 100644 --- a/source3/lib/system_smbd.c +++ b/source3/lib/system_smbd.c @@ -27,15 +27,58 @@ #include "includes.h" #ifndef HAVE_GETGROUPLIST + +static int int_compare( int *a, int *b ) +{ + if ( *a == *b ) + return 0; + else if ( *a < *b ) + return -1; + else + return 1; +} + +void remove_duplicate_gids( int *num_groups, gid_t *groups ) +{ + int i; + int count = *num_groups; + + if ( *num_groups <= 0 || !groups ) + return; + + DEBUG(8,("remove_duplicate_gids: Enter %d gids\n", *num_groups)); + + qsort( groups, *num_groups, sizeof(gid_t), QSORT_CAST int_compare ); + + for ( i=1; i<count; ) { + if ( groups[i-1] == groups[i] ) { + memmove( &groups[i-1], &groups[i], (count - i + 1)*sizeof(gid_t) ); + + /* decrement the total number of groups and do not increment + the loop counter */ + count--; + continue; + } + i++; + } + + *num_groups = count; + + DEBUG(8,("remove_duplicate_gids: Exit %d gids\n", *num_groups)); + + return; +} + /* This is a *much* faster way of getting the list of groups for a user - without changing the current supplemenrary group list. The old + without changing the current supplementary group list. The old method used getgrent() which could take 20 minutes on a really big network with hundeds of thousands of groups and users. The new method takes a couple of seconds. NOTE!! this function only works if it is called as root! */ + static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, int *grpcnt) { gid_t *gids_saved; @@ -52,7 +95,7 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in /* this shouldn't happen */ return -1; } - + gids_saved = SMB_MALLOC_ARRAY(gid_t, ngrp_saved+1); if (!gids_saved) { errno = ENOMEM; @@ -79,18 +122,26 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in setgid(gid); num_gids = getgroups(0, NULL); + if (num_gids == -1) { + SAFE_FREE(gids_saved); + /* very strange! */ + return -1; + } + if (num_gids + 1 > *grpcnt) { *grpcnt = num_gids + 1; ret = -1; } else { ret = getgroups(*grpcnt - 1, &groups[1]); - if (ret >= 0) { - groups[0] = gid; - *grpcnt = ret + 1; + if (ret < 0) { + SAFE_FREE(gids_saved); + /* very strange! */ + return -1; } - - /* remove any duplicates gids in the list */ + groups[0] = gid; + *grpcnt = ret + 1; + /* remove any duplicates gids in the list */ remove_duplicate_gids( grpcnt, groups ); } @@ -103,7 +154,7 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in free(gids_saved); return -1; } - + free(gids_saved); return ret; } @@ -140,9 +191,10 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp } BOOL getgroups_user(const char *user, gid_t primary_gid, - gid_t **ret_groups, int *ngroups) + gid_t **ret_groups, size_t *p_ngroups) { - int ngrp, max_grp; + size_t ngrp; + int max_grp; gid_t *temp_groups; gid_t *groups; int i; @@ -154,9 +206,8 @@ BOOL getgroups_user(const char *user, gid_t primary_gid, } if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) { - gid_t *groups_tmp; - + groups_tmp = SMB_REALLOC_ARRAY(temp_groups, gid_t, max_grp); if (!groups_tmp) { @@ -183,7 +234,7 @@ BOOL getgroups_user(const char *user, gid_t primary_gid, for (i=0; i<max_grp; i++) add_gid_to_array_unique(NULL, temp_groups[i], &groups, &ngrp); - *ngroups = ngrp; + *p_ngroups = ngrp; *ret_groups = groups; SAFE_FREE(temp_groups); return True; @@ -192,34 +243,34 @@ BOOL getgroups_user(const char *user, gid_t primary_gid, NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods, const char *username, gid_t primary_gid, - DOM_SID **sids, - gid_t **gids, - int *num_groups) + DOM_SID **pp_sids, + gid_t **pp_gids, + size_t *p_num_groups) { - int i; + size_t i; - if (!getgroups_user(username, primary_gid, gids, num_groups)) { + if (!getgroups_user(username, primary_gid, pp_gids, p_num_groups)) { return NT_STATUS_NO_SUCH_USER; } - if (*num_groups == 0) { + if (*p_num_groups == 0) { smb_panic("primary group missing"); } - *sids = SMB_MALLOC_ARRAY(DOM_SID, *num_groups); + *pp_sids = SMB_MALLOC_ARRAY(DOM_SID, *p_num_groups); - if (*sids == NULL) { - SAFE_FREE(gids); + if (*pp_sids == NULL) { + SAFE_FREE(pp_gids); return NT_STATUS_NO_MEMORY; } - for (i=0; i<*num_groups; i++) { - if (!NT_STATUS_IS_OK(gid_to_sid(&(*sids)[i], (*gids)[i]))) { + for (i=0; i<*p_num_groups; i++) { + if (!NT_STATUS_IS_OK(gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]))) { DEBUG(1, ("get_user_groups: failed to convert " "gid %ld to a sid!\n", - (long int)(*gids)[i+1])); - SAFE_FREE(*sids); - SAFE_FREE(*gids); + (long int)(*pp_gids)[i+1])); + SAFE_FREE(*pp_sids); + SAFE_FREE(*pp_gids); return NT_STATUS_NO_SUCH_USER; } } |