Author: jpeach Date: 2007-06-09 00:10:26 +0000 (Sat, 09 Jun 2007) New Revision: 23398
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=23398 Log: Support membership of >16 groups on Darwin by making sure we opt in to the dynamic group resolution mechanism when switching UNIX credentials. Modified: branches/SAMBA_3_0/source/configure.in branches/SAMBA_3_0/source/smbd/sec_ctx.c Changeset: Modified: branches/SAMBA_3_0/source/configure.in =================================================================== --- branches/SAMBA_3_0/source/configure.in 2007-06-08 23:13:04 UTC (rev 23397) +++ branches/SAMBA_3_0/source/configure.in 2007-06-09 00:10:26 UTC (rev 23398) @@ -3100,7 +3100,22 @@ fi fi +AC_CACHE_CHECK([for the Darwin initgroups system call], + samba_cv_DARWIN_INITGROUPS, + AC_TRY_LINK([ +#include <sys/syscall.h> +#include <unistd.h> + ], + [ syscall(SYS_initgroups, 16, NULL, NULL, 0); ], + samba_cv_DARWIN_INITGROUPS=yes, + samba_cv_DARWIN_INITGROUPS=no) +) +if test x"$samba_cv_DARWIN_INITGROUPS" = x"yes" ; then + AC_DEFINE(HAVE_DARWIN_INITGROUPS, 1, + [Whether to use the Darwin-specific initgroups system call]) +fi + AC_CACHE_CHECK([for working mmap],samba_cv_HAVE_MMAP,[ AC_TRY_RUN([#include "${srcdir-.}/tests/shared_mmap.c"], samba_cv_HAVE_MMAP=yes,samba_cv_HAVE_MMAP=no,samba_cv_HAVE_MMAP=cross)]) Modified: branches/SAMBA_3_0/source/smbd/sec_ctx.c =================================================================== --- branches/SAMBA_3_0/source/smbd/sec_ctx.c 2007-06-08 23:13:04 UTC (rev 23397) +++ branches/SAMBA_3_0/source/smbd/sec_ctx.c 2007-06-09 00:10:26 UTC (rev 23398) @@ -231,6 +231,10 @@ Change UNIX security context. Calls panic if not successful so no return value. ****************************************************************************/ +#ifndef HAVE_DARWIN_INITGROUPS + +/* Normal credential switch path. */ + static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) { /* Start context switch */ @@ -242,6 +246,51 @@ /* end context switch */ } +#else /* HAVE_DARWIN_INITGROUPS */ + +/* The Darwin groups implementation is a little unusual. The list of +* groups in the kernel credential is not exhaustive, but more like +* a cache. The full group list is held in userspace and checked +* dynamically. +* +* This is an optional mechanism, and setgroups(2) opts out +* of it. That is, if you call setgroups, then the list of groups you +* set are the only groups that are ever checked. This is not what we +* want. We want to opt in to the dynamic resolution mechanism, so we +* need to specify the uid of the user whose group list (cache) we are +* setting. +* +* The Darwin rules are: +* 1. Thou shalt setegid, initgroups and seteuid IN THAT ORDER +* 2. Thou shalt not pass more that NGROUPS_MAX to initgroups +* 3. Thou shalt leave the first entry in the groups list well alone +*/ + +#include <sys/syscall.h> + +static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups) +{ + int max = groups_max(); + + /* Start context switch */ + gain_root(); + + become_gid(gid); + + + if (syscall(SYS_initgroups, (ngroups > max) ? max : ngroups, + groups, uid) == 1) { + DEBUG(0, ("WARNING: failed to set group list " + "(%d groups) for UID %ld: %s\n", + ngroups, uid, strerror(errno))); + } + + become_uid(uid); + /* end context switch */ +} + +#endif /* HAVE_DARWIN_INITGROUPS */ + /**************************************************************************** Set the current security context to a given user. ****************************************************************************/
