lib/system_smbd.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    system call wrapper interface.
00004    Copyright (C) Andrew Tridgell 2002
00005    Copyright (C) Andrew Barteltt 2002
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011    
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016    
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 */
00021 
00022 /* 
00023    This file may assume linkage with smbd - for things like become_root()
00024    etc. 
00025 */
00026 
00027 #include "includes.h"
00028 
00029 #ifndef HAVE_GETGROUPLIST
00030 
00031 /*
00032   This is a *much* faster way of getting the list of groups for a user
00033   without changing the current supplementary group list. The old
00034   method used getgrent() which could take 20 minutes on a really big
00035   network with hundeds of thousands of groups and users. The new method
00036   takes a couple of seconds.
00037 
00038   NOTE!! this function only works if it is called as root!
00039   */
00040 
00041 static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups,
00042                                   int *grpcnt)
00043 {
00044         gid_t *gids_saved;
00045         int ret, ngrp_saved, num_gids;
00046 
00047         if (non_root_mode()) {
00048                 *grpcnt = 0;
00049                 return 0;
00050         }
00051 
00052         /* work out how many groups we need to save */
00053         ngrp_saved = getgroups(0, NULL);
00054         if (ngrp_saved == -1) {
00055                 /* this shouldn't happen */
00056                 return -1;
00057         }
00058 
00059         gids_saved = SMB_MALLOC_ARRAY(gid_t, ngrp_saved+1);
00060         if (!gids_saved) {
00061                 errno = ENOMEM;
00062                 return -1;
00063         }
00064 
00065         ngrp_saved = getgroups(ngrp_saved, gids_saved);
00066         if (ngrp_saved == -1) {
00067                 SAFE_FREE(gids_saved);
00068                 /* very strange! */
00069                 return -1;
00070         }
00071 
00072         if (initgroups(user, gid) != 0) {
00073                 DEBUG(0, ("getgrouplist_internals: initgroups() failed!\n"));
00074                 SAFE_FREE(gids_saved);
00075                 return -1;
00076         }
00077 
00078         /* this must be done to cope with systems that put the current egid in the
00079            return from getgroups() */
00080         save_re_gid();
00081         set_effective_gid(gid);
00082         setgid(gid);
00083 
00084         num_gids = getgroups(0, NULL);
00085         if (num_gids == -1) {
00086                 SAFE_FREE(gids_saved);
00087                 /* very strange! */
00088                 return -1;
00089         }
00090 
00091         if (num_gids + 1 > *grpcnt) {
00092                 *grpcnt = num_gids + 1;
00093                 ret = -1;
00094         } else {
00095                 ret = getgroups(*grpcnt - 1, &groups[1]);
00096                 if (ret < 0) {
00097                         SAFE_FREE(gids_saved);
00098                         /* very strange! */
00099                         return -1;
00100                 }
00101                 groups[0] = gid;
00102                 *grpcnt = ret + 1;
00103         }
00104 
00105         restore_re_gid();
00106 
00107         if (sys_setgroups(ngrp_saved, gids_saved) != 0) {
00108                 /* yikes! */
00109                 DEBUG(0,("ERROR: getgrouplist: failed to reset group list!\n"));
00110                 smb_panic("getgrouplist: failed to reset group list!\n");
00111                 free(gids_saved);
00112                 return -1;
00113         }
00114 
00115         free(gids_saved);
00116         return ret;
00117 }
00118 #endif
00119 
00120 static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
00121 {
00122         int retval;
00123         BOOL winbind_env;
00124 
00125         DEBUG(10,("sys_getgrouplist: user [%s]\n", user));
00126 
00127         /* This is only ever called for Unix users, remote memberships are
00128          * always determined by the info3 coming back from auth3 or the
00129          * PAC. */
00130         winbind_env = winbind_env_set();
00131         winbind_off();
00132 
00133 #ifdef HAVE_GETGROUPLIST
00134         retval = getgrouplist(user, gid, groups, grpcnt);
00135 #else
00136         become_root();
00137         retval = getgrouplist_internals(user, gid, groups, grpcnt);
00138         unbecome_root();
00139 #endif
00140 
00141         /* allow winbindd lookups, but only if they were not already disabled */
00142         if (!winbind_env) {
00143                 winbind_on();
00144         }
00145 
00146         return retval;
00147 }
00148 
00149 BOOL getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user,
00150                          gid_t primary_gid,
00151                          gid_t **ret_groups, size_t *p_ngroups)
00152 {
00153         size_t ngrp;
00154         int max_grp;
00155         gid_t *temp_groups;
00156         gid_t *groups;
00157         int i;
00158 
00159         max_grp = groups_max();
00160         temp_groups = SMB_MALLOC_ARRAY(gid_t, max_grp);
00161         if (! temp_groups) {
00162                 return False;
00163         }
00164 
00165         if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) {
00166                 temp_groups = SMB_REALLOC_ARRAY(temp_groups, gid_t, max_grp);
00167                 if (!temp_groups) {
00168                         return False;
00169                 }
00170                 
00171                 if (sys_getgrouplist(user, primary_gid,
00172                                      temp_groups, &max_grp) == -1) {
00173                         DEBUG(0, ("get_user_groups: failed to get the unix "
00174                                   "group list\n"));
00175                         SAFE_FREE(temp_groups);
00176                         return False;
00177                 }
00178         }
00179         
00180         ngrp = 0;
00181         groups = NULL;
00182 
00183         /* Add in primary group first */
00184         if (!add_gid_to_array_unique(mem_ctx, primary_gid, &groups, &ngrp)) {
00185                 SAFE_FREE(temp_groups);
00186                 return False;
00187         }
00188 
00189         for (i=0; i<max_grp; i++) {
00190                 if (!add_gid_to_array_unique(mem_ctx, temp_groups[i],
00191                                         &groups, &ngrp)) {
00192                         SAFE_FREE(temp_groups);
00193                         return False;
00194                 }
00195         }
00196 
00197         *p_ngroups = ngrp;
00198         *ret_groups = groups;
00199         SAFE_FREE(temp_groups);
00200         return True;
00201 }

Sambaに対してSat Aug 29 21:22:59 2009に生成されました。  doxygen 1.4.7