diff options
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/replace.c | 64 | ||||
-rw-r--r-- | source3/lib/system_smbd.c | 105 | ||||
-rw-r--r-- | source3/lib/util_getent.c | 35 | ||||
-rw-r--r-- | source3/lib/util_smbd.c | 65 |
4 files changed, 170 insertions, 99 deletions
diff --git a/source3/lib/replace.c b/source3/lib/replace.c index e2664accfa..fd7b2cf7f0 100644 --- a/source3/lib/replace.c +++ b/source3/lib/replace.c @@ -430,67 +430,3 @@ char *rep_inet_ntoa(struct in_addr ip) #endif /* HAVE_VSYSLOG */ -#ifndef HAVE_GETGROUPLIST -/* - This is a *much* faster way of getting the list of groups for a user - without changing the current supplemenrary 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! - */ - int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt) -{ - gid_t *gids_saved; - int ret, ngrp_saved; - - /* work out how many groups we need to save */ - ngrp_saved = getgroups(0, NULL); - if (ngrp_saved == -1) { - /* this shouldn't happen */ - return -1; - } - - gids_saved = (gid_t *)malloc(sizeof(gid_t) * (ngrp_saved+1)); - if (!gids_saved) { - errno = ENOMEM; - return -1; - } - - ngrp_saved = getgroups(ngrp_saved, gids_saved); - if (ngrp_saved == -1) { - free(gids_saved); - /* very strange! */ - return -1; - } - - if (initgroups(user, gid) != 0) { - free(gids_saved); - return -1; - } - - /* this must be done to cope with systems that put the current egid in the - return from getgroups() */ - save_re_gid(); - set_effective_gid(gid); - setgid(gid); - - ret = getgroups(*grpcnt, groups); - if (ret >= 0) { - *grpcnt = ret; - } - - restore_re_gid(); - - if (setgroups(ngrp_saved, gids_saved) != 0) { - /* yikes! */ - DEBUG(0,("ERROR: getgrouplist: failed to reset group list!\n")); - free(gids_saved); - return -1; - } - - free(gids_saved); - return ret; -} -#endif diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c new file mode 100644 index 0000000000..28ceaf3939 --- /dev/null +++ b/source3/lib/system_smbd.c @@ -0,0 +1,105 @@ +/* + Unix SMB/CIFS implementation. + system call wrapper interface. + Copyright (C) Andrew Tridgell 2002 + Copyright (C) Andrew Barteltt 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + This file may assume linkage with smbd - for things like become_root() + etc. +*/ + +#include "includes.h" + +#ifndef HAVE_GETGROUPLIST +/* + This is a *much* faster way of getting the list of groups for a user + without changing the current supplemenrary 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; + int ret, ngrp_saved; + + /* work out how many groups we need to save */ + ngrp_saved = getgroups(0, NULL); + if (ngrp_saved == -1) { + /* this shouldn't happen */ + return -1; + } + + gids_saved = (gid_t *)malloc(sizeof(gid_t) * (ngrp_saved+1)); + if (!gids_saved) { + errno = ENOMEM; + return -1; + } + + ngrp_saved = getgroups(ngrp_saved, gids_saved); + if (ngrp_saved == -1) { + free(gids_saved); + /* very strange! */ + return -1; + } + + if (initgroups(user, gid) != 0) { + free(gids_saved); + return -1; + } + + /* this must be done to cope with systems that put the current egid in the + return from getgroups() */ + save_re_gid(); + set_effective_gid(gid); + setgid(gid); + + ret = getgroups(*grpcnt, groups); + if (ret >= 0) { + *grpcnt = ret; + } + + restore_re_gid(); + + if (setgroups(ngrp_saved, gids_saved) != 0) { + /* yikes! */ + DEBUG(0,("ERROR: getgrouplist: failed to reset group list!\n")); + smb_panic("getgrouplist: failed to reset group list!\n"); + free(gids_saved); + return -1; + } + + free(gids_saved); + return ret; +} +#endif + +int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt) +{ +#ifdef HAVE_GETGROUPLIST + return getgrouplist(user, gid, groups, grpcnt); +#else + int retval; + become_root(); + retval = getgrouplist_internals(user, gid, groups, grpcnt); + unbecome_root(); +#endif +} diff --git a/source3/lib/util_getent.c b/source3/lib/util_getent.c index 5d2fcd7652..6699ce3e92 100644 --- a/source3/lib/util_getent.c +++ b/source3/lib/util_getent.c @@ -299,38 +299,3 @@ void free_userlist(struct sys_userlist *list_head) SAFE_FREE(old_head); } } - - -/* - return a full list of groups for a user - - returns the number of groups the user is a member of. The return will include the - users primary group. - - remember to free the resulting gid_t array - - NOTE! you must be root to call this function on some systems -*/ -int getgroups_user(const char *user, gid_t **groups) -{ - struct passwd *pwd; - int ngrp, max_grp; - - pwd = getpwnam(user); - if (!pwd) return -1; - - max_grp = groups_max(); - (*groups) = (gid_t *)malloc(sizeof(gid_t) * max_grp); - if (! *groups) { - errno = ENOMEM; - return -1; - } - - ngrp = getgrouplist(user, pwd->pw_gid, *groups, &max_grp); - if (ngrp <= 0) { - free(*groups); - return ngrp; - } - - return ngrp; -} diff --git a/source3/lib/util_smbd.c b/source3/lib/util_smbd.c new file mode 100644 index 0000000000..071f20b416 --- /dev/null +++ b/source3/lib/util_smbd.c @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions, used in smbd only + Copyright (C) Andrew Tridgell 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + This function requires sys_getgrouplist - which is only + available in smbd due to it's use of become_root() in a + legacy systems hack. +*/ + +/* + return a full list of groups for a user + + returns the number of groups the user is a member of. The return will include the + users primary group. + + remember to free the resulting gid_t array + + NOTE! uses become_root() to gain correct priviages on systems + that lack a native getgroups() call (uses initgroups and getgroups) +*/ +int getgroups_user(const char *user, gid_t **groups) +{ + struct passwd *pwd; + int ngrp, max_grp; + + pwd = getpwnam_alloc(user); + if (!pwd) return -1; + + max_grp = groups_max(); + (*groups) = (gid_t *)malloc(sizeof(gid_t) * max_grp); + if (! *groups) { + passwd_free(&pwd); + errno = ENOMEM; + return -1; + } + + ngrp = sys_getgrouplist(user, pwd->pw_gid, *groups, &max_grp); + if (ngrp <= 0) { + passwd_free(&pwd); + free(*groups); + return ngrp; + } + + passwd_free(&pwd); + return ngrp; +} |