attached is the first in a series of patches that is intended to
remove the current limitation on group membership.

this patch should remove the dependancy on the definition of
NGROUPS_MAX as a static constant and implement it as a writable
sysconf variable of the same.  it should also make the necessary
changes to the codebase to support those.

i need some guidance as to what i should re-define NGROUPS_MAX to be
(so that code that depends on it can continue to operate, i'm thinking
just make it 16 but perhaps it would be worth extending the default
while we're at it to something like 64??).  i also need feedback on
any braindamage in the current changes.

the next step will be to extend the kernel groups and map them back
to the user structs / calls.   finally i'll extend the user groups
and implement those calls.

nb: not tested the code (it builds) ... was intending to test it on
my XEN box but only just realised that Xen on amd64 isn't working.
:-(

happy for any questions that may help guide the process.
Index: contrib/openpam/lib/openpam_borrow_cred.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/contrib/openpam/lib/openpam_borrow_cred.c,v
retrieving revision 1.1.1.9
diff -b -u -r1.1.1.9 openpam_borrow_cred.c
--- contrib/openpam/lib/openpam_borrow_cred.c   21 Dec 2007 11:49:29 -0000      
1.1.1.9
+++ contrib/openpam/lib/openpam_borrow_cred.c   4 Feb 2009 16:38:46 -0000
@@ -60,6 +60,7 @@
        struct pam_saved_cred *scred;
        const void *scredp;
        int r;
+       int ngroups ;
 
        ENTERI(pwd->pw_uid);
        r = pam_get_data(pamh, PAM_SAVED_CRED, &scredp);
@@ -73,26 +74,55 @@
                    (int)geteuid());
                RETURNC(PAM_PERM_DENIED);
        }
-       scred = calloc(1, sizeof *scred);
-       if (scred == NULL)
-               RETURNC(PAM_BUF_ERR);
-       scred->euid = geteuid();
-       scred->egid = getegid();
-       r = getgroups(NGROUPS_MAX, scred->groups);
-       if (r < 0) {
-               FREE(scred);
-               RETURNC(PAM_SYSTEM_ERR);
-       }
-       scred->ngroups = r;
+/* get the maximum number of system groups */
+#if _POSIX_VERSION > 199212
+       ngroups = sysconf( _SC_NGROUPS_MAX ) ;
+#elif defined(NGROUPS_MAX)
+       ngroups = NGROUPS_MAX ;
+#else
+       ngroups = _NGROUPS_COMPAT ;
+#endif
+/* initally allocate enough memory for max_groups */
+       scred = malloc( sizeof(struct pam_saved_cred) +
+                       ngroups*sizeof(gid_t) ) ;
+       if( scred == NULL )
+               RETURNC( PAM_BUF_ERR ) ;
+/* set the save values */
+       scred->euid = geteuid() ;
+       scred->egid = getegid() ;
+/* save groups into our (probably) oversized memory allocation */
+       r = getgroups( ngroups, scred->groups ) ;
+       if( r < 0 ) {
+               FREE( scred ) ; /* call PAM's free macro */
+               RETURNC( PAM_SYSTEM_ERR ) ;
+       } ;
+       scred->ngroups = r ;
+       ngroups = r < ngroups ? r : ngroups ; /* choose the smallest */
+                               /* ... number of groups to allocate */
+       ngroups = ngroups < _NGROUPS_COMPAT ? ngroups : _NGROUPS_COMPAT ;
+                               /* but keep it within expected minimum value */
+                               /*      XXX: we don't really want this but 
until we get
+                                *      educated on the implications this is 
probably safe
+                                *      and certainaly compatible */
+/* realloc, releasing unneeded memory */
+       scred = realloc( (void*)scred,
+                       sizeof(struct pam_saved_cred)+ngroups*sizeof(gid_t) ) ;
+                               /* nb: we ignore failure and try to store the 
larger
+                                * ... structure as initially requested. 
catching the
+                                * ... error in 'pam_set_data' if neccessary. */
+/* save the credentials to PAM user data area */
        r = pam_set_data(pamh, PAM_SAVED_CRED, scred, &openpam_free_data);
        if (r != PAM_SUCCESS) {
                FREE(scred);
                RETURNC(r);
        }
+/* set the new credentials */
        if (geteuid() == pwd->pw_uid)
                RETURNC(PAM_SUCCESS);
        if (initgroups(pwd->pw_name, pwd->pw_gid) < 0 ||
-             setegid(pwd->pw_gid) < 0 || seteuid(pwd->pw_uid) < 0) {
+                       setegid(pwd->pw_gid) < 0 || seteuid(pwd->pw_uid) < 0)
+       {
+       /* if any of the set calls failed, then restore and fail */
                openpam_restore_cred(pamh);
                RETURNC(PAM_SYSTEM_ERR);
        }
Index: contrib/openpam/lib/openpam_impl.h
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/contrib/openpam/lib/openpam_impl.h,v
retrieving revision 1.1.1.17
diff -b -u -r1.1.1.17 openpam_impl.h
--- contrib/openpam/lib/openpam_impl.h  21 Dec 2007 11:49:29 -0000      1.1.1.17
+++ contrib/openpam/lib/openpam_impl.h  5 Feb 2009 15:41:19 -0000
@@ -110,13 +110,17 @@
        int              env_size;
 };
 
-#ifdef NGROUPS_MAX
+#if _POSIX_VERSION > 199212
 #define PAM_SAVED_CRED "pam_saved_cred"
 struct pam_saved_cred {
        uid_t    euid;
        gid_t    egid;
-       gid_t    groups[NGROUPS_MAX];
        int      ngroups;
+       gid_t    groups[];
+                               /* keep this last so that we can simply
+                               .. over-allocate the amount of space
+                               .. nb: don't use sizeof' unless you adjust
+                               .. for the number of groups */
 };
 #endif
 
Index: include/rpc/auth_unix.h
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/include/rpc/auth_unix.h,v
retrieving revision 1.11
diff -b -u -r1.11 auth_unix.h
--- include/rpc/auth_unix.h     23 Mar 2002 17:24:55 -0000      1.11
+++ include/rpc/auth_unix.h     14 Jan 2009 11:15:21 -0000
@@ -52,7 +52,7 @@
 #define MAX_MACHINE_NAME 255
 
 /* gids compose part of a credential; there may not be more than 16 of them */
-#define NGRPS 16
+#define AUTH_UNIX_NGROUPS 16
 
 /*
  * Unix style credentials.
Index: lib/libc/rpc/auth_unix.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/auth_unix.c,v
retrieving revision 1.18
diff -b -u -r1.18 auth_unix.c
--- lib/libc/rpc/auth_unix.c    14 Jun 2007 20:07:35 -0000      1.18
+++ lib/libc/rpc/auth_unix.c    4 Feb 2009 15:31:57 -0000
@@ -182,27 +182,48 @@
  * Returns an auth handle with parameters determined by doing lots of
  * syscalls.
  */
-AUTH *
+AUTH*
 authunix_create_default()
 {
-       int len;
        char machname[MAXHOSTNAMELEN + 1];
+       AUTH* auth_unix ;
        uid_t uid;
        gid_t gid;
-       gid_t gids[NGROUPS_MAX];
-
-       if (gethostname(machname, sizeof machname) == -1)
-               abort();
-       machname[sizeof(machname) - 1] = 0;
+       gid_t *gids ;
+       uint ngroups ;
+       uint max_ngroups ;
+
+/* get hostname or fail */
+       if( gethostname(machname,sizeof(machname)) == -1 )
+               abort() ;
+       machname[sizeof(machname)-1] = 0 ; /* add a null terminator */
+/*     set uid/gid from current effective values */
        uid = geteuid();
        gid = getegid();
-       if ((len = getgroups(NGROUPS_MAX, gids)) < 0)
-               abort();
-       if (len > NGRPS)
-               len = NGRPS;
-       /* XXX: interface problem; those should all have been unsigned */
-       return (authunix_create(machname, (int)uid, (int)gid, len,
-           (int *)gids));
+/*     set the group set */
+#if _POSIX_VERSION > 199212
+       max_ngroups = sysconf( _SC_NGROUPS_MAX ) ;
+#elif defined(NGROUPS_MAX)
+       max_ngroups = NGROUPS_MAX ;
+#else
+       max_ngroups = 16 ;
+#endif
+       gids = (gid_t*)calloc( max_ngroups, sizeof(gid_t) ) ;
+       if( gids == NULL )
+               abort () ;
+       if( (ngroups=getgroups(max_ngroups,gids)) < 0 ) {
+               free( gids ) ;
+               abort() ;
+       }
+/* clip the groups to a transmissable size */
+       if( ngroups > AUTH_UNIX_NGROUPS )
+               ngroups = AUTH_UNIX_NGROUPS ;
+/* XXX: interface problem; those should all have been unsigned */
+       auth_unix = authunix_create( machname,
+                       (int)uid, (int)gid, (int)ngroups,
+                       (int*)gids ) ;
+       free( (void*)gids ) ;
+       return( auth_unix ) ;
 }
 
 /*
Index: lib/libc/rpc/authunix_prot.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/authunix_prot.c,v
retrieving revision 1.10
diff -b -u -r1.10 authunix_prot.c
--- lib/libc/rpc/authunix_prot.c        20 Nov 2007 01:51:20 -0000      1.10
+++ lib/libc/rpc/authunix_prot.c        4 Feb 2009 16:03:29 -0000
@@ -67,13 +67,14 @@
 
        paup_gids = &p->aup_gids;
 
-       if (xdr_u_long(xdrs, &(p->aup_time))
-           && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
-           && xdr_int(xdrs, &(p->aup_uid))
-           && xdr_int(xdrs, &(p->aup_gid))
-           && xdr_array(xdrs, (char **) paup_gids,
-                   &(p->aup_len), NGRPS, sizeof(int), (xdrproc_t)xdr_int) ) {
-               return (TRUE);
+       if( xdr_u_long(xdrs,&(p->aup_time)) &&
+                       xdr_string(xdrs,&(p->aup_machname),MAX_MACHINE_NAME) &&
+                       xdr_int(xdrs,&(p->aup_uid)) &&
+                       xdr_int(xdrs,&(p->aup_gid)) &&
+                       xdr_array(xdrs,(char**)paup_gids,&(p->aup_len),
+                                       
AUTH_UNIX_NGROUPS,sizeof(int),(xdrproc_t)xdr_int) )
+       {
+               return( TRUE ) ;
        }
-       return (FALSE);
+       return( FALSE ) ;
 }
Index: lib/libc/rpc/netname.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/netname.c,v
retrieving revision 1.8
diff -b -u -r1.8 netname.c
--- lib/libc/rpc/netname.c      16 Oct 2004 06:11:35 -0000      1.8
+++ lib/libc/rpc/netname.c      14 Jan 2009 01:29:47 -0000
@@ -61,6 +61,7 @@
 #ifndef MAXHOSTNAMELEN
 #define MAXHOSTNAMELEN 256
 #endif
+
 #ifndef NGROUPS
 #define NGROUPS 16
 #endif
Index: lib/libc/rpc/netnamer.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/netnamer.c,v
retrieving revision 1.12
diff -b -u -r1.12 netnamer.c
--- lib/libc/rpc/netnamer.c     10 Mar 2005 00:58:21 -0000      1.12
+++ lib/libc/rpc/netnamer.c     3 Feb 2009 17:55:48 -0000
@@ -69,7 +69,6 @@
 #ifndef NGROUPS
 #define NGROUPS 16
 #endif
-
 /*
  * Convert network-name into unix credential
  */
@@ -104,7 +103,7 @@
                        return (0);
                }
                *gidp = (gid_t) atol(p);
-               for (gidlen = 0; gidlen < NGROUPS; gidlen++) {
+               for (gidlen = 0; gidlen < _NGROUPS_RPC_MAX; gidlen++) {
                        p = strsep(&res, "\n,");
                        if (p == NULL)
                                break;
@@ -157,7 +156,7 @@
 static int
 _getgroups(uname, groups)
        char           *uname;
-       gid_t          groups[NGROUPS];
+       gid_t          groups[_NGROUPS_RPC_MAX];
 {
        gid_t           ngroups = 0;
        struct group *grp;
@@ -169,10 +168,11 @@
        while ((grp = getgrent())) {
                for (i = 0; grp->gr_mem[i]; i++)
                        if (!strcmp(grp->gr_mem[i], uname)) {
-                               if (ngroups == NGROUPS) {
+                               if( ngroups == _NGROUPS_RPC_MAX ) {
 #ifdef DEBUG
-                                       fprintf(stderr,
-                               "initgroups: %s is in too many groups\n", 
uname);
+                                       fprintf( stderr,
+                                                       "initgroups: %s is in 
too many groups\n",
+                                                       uname ) ;
 #endif
                                        goto toomany;
                                }
Index: lib/libc/rpc/svc_auth_des.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/svc_auth_des.c,v
retrieving revision 1.9
diff -b -u -r1.9 svc_auth_des.c
--- lib/libc/rpc/svc_auth_des.c 22 Mar 2002 23:18:37 -0000      1.9
+++ lib/libc/rpc/svc_auth_des.c 3 Feb 2009 17:51:01 -0000
@@ -452,7 +452,7 @@
        short uid;              /* cached uid */
        short gid;              /* cached gid */
        short grouplen; /* length of cached groups */
-       short groups[NGROUPS];  /* cached groups */
+       short groups[_NGROUPS_RPC_MAX]; /* cached groups */
 };
 
 /*
Index: lib/libc/rpc/svc_auth_unix.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/libc/rpc/svc_auth_unix.c,v
retrieving revision 1.11
diff -b -u -r1.11 svc_auth_unix.c
--- lib/libc/rpc/svc_auth_unix.c        16 Oct 2004 06:11:35 -0000      1.11
+++ lib/libc/rpc/svc_auth_unix.c        4 Feb 2009 16:04:10 -0000
@@ -68,7 +68,7 @@
        struct area {
                struct authunix_parms area_aup;
                char area_machname[MAX_MACHINE_NAME+1];
-               int area_gids[NGRPS];
+               int area_gids[AUTH_UNIX_NGROUPS] ;
        } *area;
        u_int auth_len;
        size_t str_len, gid_len;
@@ -98,7 +98,7 @@
                aup->aup_uid = (int)IXDR_GET_INT32(buf);
                aup->aup_gid = (int)IXDR_GET_INT32(buf);
                gid_len = (size_t)IXDR_GET_U_INT32(buf);
-               if (gid_len > NGRPS) {
+               if( gid_len > AUTH_UNIX_NGROUPS ) {
                        stat = AUTH_BADCRED;
                        goto done;
                }
Index: lib/librpcsec_gss/svc_rpcsec_gss.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/lib/librpcsec_gss/svc_rpcsec_gss.c,v
retrieving revision 1.4
diff -b -u -r1.4 svc_rpcsec_gss.c
--- lib/librpcsec_gss/svc_rpcsec_gss.c  3 Nov 2008 10:38:00 -0000       1.4
+++ lib/librpcsec_gss/svc_rpcsec_gss.c  5 Feb 2009 16:09:37 -0000
@@ -127,7 +127,7 @@
        rpc_gss_ucred_t         cl_ucred;       /* unix-style credentials */
        bool_t                  cl_done_callback; /* TRUE after call */
        void                    *cl_cookie;     /* user cookie from callback */
-       gid_t                   cl_gid_storage[NGRPS];
+       gid_t                   cl_gid_storage[AUTH_UNIX_NGROUPS];
        gss_OID                 cl_mech;        /* mechanism */
        gss_qop_t               cl_qop;         /* quality of protection */
        u_int                   cl_seq;         /* current sequence number */
@@ -578,7 +578,7 @@
 
        getpwuid_r(uid, &pwd, buf, sizeof(buf), &pw);
        if (pw) {
-               int len = NGRPS;
+               int len = AUTH_UNIX_NGROUPS;
                uc->uid = pw->pw_uid;
                uc->gid = pw->pw_gid;
                uc->gidlist = client->cl_gid_storage;
Index: sys/compat/svr4/svr4_misc.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/compat/svr4/svr4_misc.c,v
retrieving revision 1.101
diff -b -u -r1.101 svr4_misc.c
--- sys/compat/svr4/svr4_misc.c 21 Apr 2008 21:24:08 -0000      1.101
+++ sys/compat/svr4/svr4_misc.c 14 Jan 2009 11:58:47 -0000
@@ -710,7 +710,12 @@
                *retval = 0;
                break;
        case SVR4_CONFIG_NGROUPS:
-               *retval = NGROUPS_MAX;
+               *retval = _NGROUPS_COMPAT;
+                                       /* XXX: this should pull the value
+                                        *      from sysctl but i cannot find
+                                        *      the definitions for the similar
+                                        *      varaibles here (i.e. 'maxproc')
+                                       */
                break;
        case SVR4_CONFIG_CHILD_MAX:
                *retval = maxproc;
Index: sys/fs/portalfs/portal.h
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/fs/portalfs/portal.h,v
retrieving revision 1.10
diff -b -u -r1.10 portal.h
--- sys/fs/portalfs/portal.h    6 Jan 2005 18:10:40 -0000       1.10
+++ sys/fs/portalfs/portal.h    16 Jan 2009 23:44:50 -0000
@@ -43,7 +43,7 @@
        int             pcr_flag;               /* File open mode */
        uid_t           pcr_uid;                /* From ucred */
        short           pcr_ngroups;            /* From ucred */
-       gid_t           pcr_groups[NGROUPS];    /* From ucred */
+       gid_t           pcr_groups[_NGROUPS_COMPAT];    /* From ucred */
 };
 
 #ifdef _KERNEL
Index: sys/i386/ibcs2/ibcs2_misc.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/i386/ibcs2/ibcs2_misc.c,v
retrieving revision 1.70
diff -b -u -r1.70 ibcs2_misc.c
--- sys/i386/ibcs2/ibcs2_misc.c 13 Jan 2008 14:44:07 -0000      1.70
+++ sys/i386/ibcs2/ibcs2_misc.c 14 Jan 2009 12:24:56 -0000
@@ -659,14 +659,14 @@
        struct thread *td;
        struct ibcs2_getgroups_args *uap;
 {
-       ibcs2_gid_t iset[NGROUPS_MAX];
-       gid_t gp[NGROUPS_MAX];
+       ibcs2_gid_t iset[_NGROUPS_COMPAT];
+       gid_t gp[_NGROUPS_COMPAT];
        u_int i, ngrp;
        int error;
 
        if (uap->gidsetsize < 0)
                return (EINVAL);
-       ngrp = MIN(uap->gidsetsize, NGROUPS_MAX);
+       ngrp = MIN(uap->gidsetsize, _NGROUPS_COMPAT);
        error = kern_getgroups(td, &ngrp, gp);
        if (error)
                return (error);
@@ -685,11 +685,11 @@
        struct thread *td;
        struct ibcs2_setgroups_args *uap;
 {
-       ibcs2_gid_t iset[NGROUPS_MAX];
-       gid_t gp[NGROUPS_MAX];
+       ibcs2_gid_t iset[_NGROUPS_COMPAT];
+       gid_t gp[_NGROUPS_COMPAT];
        int error, i;
 
-       if (uap->gidsetsize < 0 || uap->gidsetsize > NGROUPS_MAX)
+       if (uap->gidsetsize < 0 || uap->gidsetsize > _NGROUPS_COMPAT)
                return (EINVAL);
        if (uap->gidsetsize && uap->gidset) {
                error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) *
@@ -789,8 +789,13 @@
                return 0;
 
        case IBCS2_SC_NGROUPS_MAX:
-               mib[1] = KERN_NGROUPS;
-               break;
+                               /*      XXX: IBCS2 compat with group limits not 
known to
+                                *      me, so i'll just return a 
compatibile/safe limit
+                                *      for now */
+               PROC_LOCK(p) ;
+               td->td_retval[0] = _NGROUPS_COMPAT ;
+               PROC_UNLOCK(p) ;
+               return( 0 ) ;
 
        case IBCS2_SC_OPEN_MAX:
                PROC_LOCK(p);
Index: sys/kern/kern_mib.c
===================================================================
RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/kern/kern_mib.c,v
retrieving revision 1.93
diff -b -u -r1.93 kern_mib.c
--- sys/kern/kern_mib.c 28 Jan 2009 19:58:05 -0000      1.93
+++ sys/kern/kern_mib.c 4 Feb 2009 13:15:06 -0000
@@ -124,8 +124,8 @@
 SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD,
     0, _POSIX_VERSION, "Version of POSIX attempting to comply to");
 
-SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD,
-    0, NGROUPS_MAX, "Maximum number of groups a user can belong to");
+SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RW,
+    0, _NGROUPS_COMPAT, "Maximum number of groups allocated to a user");
 
 SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD,
     0, 1, "Whether job control is available");
Index: sys/sys/param.h
===================================================================
RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/sys/param.h,v
retrieving revision 1.382
diff -b -u -r1.382 param.h
--- sys/sys/param.h     28 Jan 2009 17:57:16 -0000      1.382
+++ sys/sys/param.h     4 Feb 2009 14:11:55 -0000
@@ -57,7 +57,7 @@
  *             is created, otherwise 1.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 800062       /* Master, propagated to newvers */
+#define __FreeBSD_version 800060       /* Master, propagated to newvers */
 
 #ifndef LOCORE
 #include <sys/types.h>
@@ -77,7 +77,8 @@
 #define        MAXLOGNAME      17              /* max login name length (incl. 
NUL) */
 #define        MAXUPRC         CHILD_MAX       /* max simultaneous processes */
 #define        NCARGS          ARG_MAX         /* max bytes for an exec 
function */
-#define        NGROUPS         NGROUPS_MAX     /* max number groups */
+#define        NGROUPS         _NGROUPS_COMPAT
+                       /* depreciated check sysctl/sysconf for NGROUPS_MAX 
value instead */
 #define        NOFILE          OPEN_MAX        /* max open files per process */
 #define        NOGROUP         65535           /* marker for empty group set 
member */
 #define MAXHOSTNAMELEN 256             /* max hostname size */
Index: sys/sys/syslimits.h
===================================================================
RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/sys/sys/syslimits.h,v
retrieving revision 1.23
diff -b -u -r1.23 syslimits.h
--- sys/sys/syslimits.h 29 May 2007 15:14:46 -0000      1.23
+++ sys/sys/syslimits.h 3 Feb 2009 18:02:22 -0000
@@ -54,7 +54,6 @@
 #define        MAX_CANON                 255   /* max bytes in term canon 
input line */
 #define        MAX_INPUT                 255   /* max bytes in terminal input 
*/
 #define        NAME_MAX                  255   /* max bytes in a file name */
-#define        NGROUPS_MAX                16   /* max supplemental group id's 
*/
 #ifndef OPEN_MAX
 #define        OPEN_MAX                   64   /* max open files per process */
 #endif
@@ -66,9 +65,35 @@
  * We leave the following values undefined to force applications to either
  * assume conservative values or call sysconf() to get the current value.
  *
- * HOST_NAME_MAX
+ * HOST_NAME_MAX NGROUPS_MAX
  *
  * (We should do this for most of the values currently defined here,
  * but many programs are not prepared to deal with this yet.)
  */
+/*
+ * here are some reference values in respect of the obsoleted
+ * NGROUPS_MAX value.
+ *     nb: some apps appear to check NGROUPS_MAX as meaning that
+ * ... system has user groups (i.e. to #ifdef chunks of code).
+ * ... this is easy to change but maybe historically defined?
+ */
+#define        _NGROUPS_RPC_MAX 16 /* reference only */
+                       /*      nb: this is the old system max, so named
+                        *      ... because it's limit appears to
+                        *      ... have been derived from a limitation
+                        *      ... in RPC (and thereby NFS), where it's
+                        *      ... the max number of groups we can exchange */
+#define        _NGROUPS_COMPAT _NGROUPS_RPC_MAX /* reference only */
+                       /*      nb: although this is defined as equal to the rpc
+                        *      ... limit, i have defined it distintly so that
+                        *      ... we may distinguish (whilst updating) usage
+                        *      ... that is correctly explicit (i.e. should be 
16)
+                        *      ... and usage that is only 16 because of an 
expected
+                        *      ... convention.  hopefully we may remove these 
and
+                        *      ... define additional _NGROUPS_*_MAX for those 
defined
+                        *      ... uses. */
+#define        _NGROUPS_SYS_MAX 65536 /* reference only */
+                       /*      nb: the idea's to have this extensible
+                        *      ... indefinately, this is what linux have and
+                        *      ... should more than cover immediate needs */
 #endif
Index: usr.bin/catman/catman.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.bin/catman/catman.c,v
retrieving revision 1.14
diff -b -u -r1.14 catman.c
--- usr.bin/catman/catman.c     5 Dec 2005 14:22:12 -0000       1.14
+++ usr.bin/catman/catman.c     8 Feb 2009 22:51:44 -0000
@@ -93,8 +93,9 @@
 enum Ziptype {NONE, BZIP, GZIP};
 
 static uid_t uid;
-static gid_t gids[NGROUPS_MAX];
+static gid_t *gids;
 static int ngids;
+static int max_ngroups ;
 static int starting_dir;
 static char tmp_file[MAXPATHLEN];
 struct stat test_st;
@@ -789,7 +790,15 @@
                        /* NOTREACHED */
                }
        }
-       ngids = getgroups(NGROUPS_MAX, gids);
+/* allocate memory for group ids */
+#if _POSIX_VERSION > 199212
+       max_ngroups = sysconf( _SC_NGROUPS_MAX ) ;
+#elif defined(NGROUPS_MAX)
+       max_ngroups = NGROUPS_MAX ;
+#else
+       max_ngroups = _NGROUPS_COMPAT ;
+#endif
+       ngids = getgroups( max_ngroups, gids ) ;
        if ((starting_dir = open(".", 0)) < 0) {
                err(1, ".");
        }
Index: usr.bin/newgrp/newgrp.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.bin/newgrp/newgrp.c,v
retrieving revision 1.2
diff -b -u -r1.2 newgrp.c
--- usr.bin/newgrp/newgrp.c     30 Oct 2003 15:14:34 -0000      1.2
+++ usr.bin/newgrp/newgrp.c     9 Feb 2009 22:05:53 -0000
@@ -146,9 +146,10 @@
 static void
 addgroup(const char *grpname)
 {
-       gid_t grps[NGROUPS_MAX];
+       gid_t *grps;
        long lgid;
-       int dbmember, i, ngrps;
+       int dbmember, i, ngrps, max_ngroups ;
+                               /*      XXX: should 'max_ngroups' be a static 
const variable? */
        gid_t egid;
        struct group *grp;
        char *ep, *pass;
@@ -185,9 +186,21 @@
                }
        }
 
-       if ((ngrps = getgroups(NGROUPS_MAX, (gid_t *)grps)) < 0) {
+#if _POSIX_VERSION >= 199212
+       max_ngroups = sysconf( _SC_NGROUPS_MAX ) ;
+#elif defined(NGROUPS_MAX)
+       max_ngroups = NGROUPS_MAX ;
+#else
+       max_ngroups = _NGROUPS_COMPAT ;
+#endif
+       grps = (gid_t*)calloc( max_ngroups, sizeof(gid_t) ) ;
+       if( grps == NULL ) {
+               warn( "group set memory allocation" ) ;
+               return ;
+       }
+       if( (ngrps=getgroups(max_ngroups,(gid_t*)grps)) < 0 ) {
                warn("getgroups");
-               return;
+               goto error_free ;
        }
 
        /* Remove requested gid from supp. list if it exists. */
@@ -201,7 +214,7 @@
                if (setgroups(ngrps, (const gid_t *)grps) < 0) {
                        PRIV_END;
                        warn("setgroups");
-                       return;
+                       goto error_free ;
                }
                PRIV_END;
        }
@@ -210,14 +223,14 @@
        if (setgid(grp->gr_gid)) {
                PRIV_END;
                warn("setgid");
-               return;
+               goto error_free ;
        }
        PRIV_END;
        grps[0] = grp->gr_gid;
 
        /* Add old effective gid to supp. list if it does not exist. */
        if (egid != grp->gr_gid && !inarray(egid, grps, ngrps)) {
-               if (ngrps == NGROUPS_MAX)
+               if( ngrps == max_ngroups )
                        warnx("too many groups");
                else {
                        grps[ngrps++] = egid;
@@ -225,12 +238,15 @@
                        if (setgroups(ngrps, (const gid_t *)grps)) {
                                PRIV_END;
                                warn("setgroups");
-                               return;
+                               goto error_free ;
                        }
                        PRIV_END;
                }
        }
 
+error_free:
+       free( grps ) ;
+       return ;
 }
 
 static int
Index: usr.sbin/chown/chown.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/chown/chown.c,v
retrieving revision 1.29
diff -b -u -r1.29 chown.c
--- usr.sbin/chown/chown.c      7 Aug 2004 04:19:37 -0000       1.29
+++ usr.sbin/chown/chown.c      8 Feb 2009 16:22:31 -0000
@@ -269,7 +269,8 @@
 {
        static uid_t euid = -1;
        static int ngroups = -1;
-       gid_t groups[NGROUPS_MAX];
+       static int max_groups ;
+       gid_t *groups;
 
        /* Check for chown without being root. */
        if (errno != EPERM || (uid != (uid_t)-1 &&
@@ -279,16 +280,31 @@
        }
 
        /* Check group membership; kernel just returns EPERM. */
+#if _POSIX_VERSION >= 199212
+       max_groups = sysconf( _SC_NGROUPS_MAX ) ;
+#elif defined(NGROUPS_MAX)
+       max_groups = NGROUPS_MAX ;
+#else
+       max_groups = _NGROUPS_COMPAT ;
+#endif
+       groups = (gid_t*)calloc( max_groups, sizeof(gid_t) ) ;
+       if( groups == NULL ) {
+               warnx( "failed to allocate memory for group set" ) ;
+               goto exit_cleanup ;
+       }
        if (gid != (gid_t)-1 && ngroups == -1 &&
            euid == (uid_t)-1 && (euid = geteuid()) != 0) {
-               ngroups = getgroups(NGROUPS_MAX, groups);
+               ngroups = getgroups( max_groups, groups ) ;
                while (--ngroups >= 0 && gid != groups[ngroups]);
                if (ngroups < 0) {
                        warnx("you are not a member of group %s", gname);
-                       return;
+                       goto exit_cleanup ;
                }
        }
        warn("%s", file);
+exit_cleanup:
+       free( groups ) ;
+       return ;
 }
 
 void
Index: usr.sbin/chroot/chroot.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/chroot/chroot.c,v
retrieving revision 1.11
diff -b -u -r1.11 chroot.c
--- usr.sbin/chroot/chroot.c    7 Aug 2004 04:19:37 -0000       1.11
+++ usr.sbin/chroot/chroot.c    5 Feb 2009 23:29:48 -0000
@@ -59,6 +59,7 @@
 char   *user;          /* user to switch to before running program */
 char   *group;         /* group to switch to ... */
 char   *grouplist;     /* group list to switch to ... */
+int    max_ngroups;    /* max number of groups allowable */
 
 int
 main(argc, argv)
@@ -69,12 +70,25 @@
        struct passwd   *pw;
        char            *endp, *p;
        const char      *shell;
-       gid_t           gid, gidlist[NGROUPS_MAX];
+       gid_t           gid, *gidlist ;
        uid_t           uid;
-       int             ch, gids;
+       int             ch, gids ;
 
+/*     set some defaults */
        gid = 0;
        uid = 0;
+       user = NULL ;
+       group = NULL ;
+       grouplist = NULL ;
+#if _POSIX_VERSION >= 199212
+       max_ngroups = sysconf( _SC_NGROUPS_MAX ) ;
+#elif defined(NGROUPS_MAX)
+       max_ngroups = NGROUPS_MAX ;
+#else
+       max_ngroups = _NGROUPS_COMPAT ;
+#endif
+
+/*     process command line options */
        while ((ch = getopt(argc, argv, "G:g:u:")) != -1) {
                switch(ch) {
                case 'u':
@@ -103,9 +117,12 @@
        if (argc < 1)
                usage();
 
+/*     if a group argument was passed then process it */
        if (group != NULL) {
+       /* if the first char's a digit then assume it's a gid ... */
                if (isdigit((unsigned char)*group)) {
                        gid = (gid_t)strtoul(group, &endp, 0);
+               /*      ... and back out that assumption if it proves wrong */
                        if (*endp != '\0')
                                goto getgroup;
                } else {
@@ -117,8 +134,15 @@
                }
        }
 
-       for (gids = 0;
-           (p = strsep(&grouplist, ",")) != NULL && gids < NGROUPS_MAX; ) {
+/*     process command line group list */
+       if( grouplist != NULL ) {
+               gidlist = (gid_t*)calloc( max_ngroups, sizeof(gid_t) ) ;
+               if( gidlist == NULL )
+                       errx( 1, "inadquate memory for group list" ) ;
+               for( gids = 0 ;
+                               gids < max_ngroups &&
+                                               (p=strsep(&grouplist,",")) != 
NULL ; )
+               {
                if (*p == '\0')
                        continue;
 
@@ -135,9 +159,11 @@
                }
                gids++;
        }
-       if (p != NULL && gids == NGROUPS_MAX)
+               if( p != NULL && gids == max_ngroups )
                errx(1, "too many supplementary groups provided");
+       }
 
+/*     set user from command line option, if supplied */
        if (user != NULL) {
                if (isdigit((unsigned char)*user)) {
                        uid = (uid_t)strtoul(user, &endp, 0);
@@ -152,9 +178,11 @@
                }
        }
 
+/*     change root */
        if (chdir(argv[0]) == -1 || chroot(".") == -1)
                err(1, "%s", argv[0]);
 
+/*     set credentials */
        if (gids && setgroups(gids, gidlist) == -1)
                err(1, "setgroups");
        if (group && setgid(gid) == -1)
@@ -162,11 +190,14 @@
        if (user && setuid(uid) == -1)
                err(1, "setuid");
 
+/*     exec the remaining arguments as the chroot'd command ... */
        if (argv[1]) {
                execvp(argv[1], &argv[1]);
                err(1, "%s", argv[1]);
+               /* NOTREACHED */
        }
 
+/* ... or execute the default system shell */
        if (!(shell = getenv("SHELL")))
                shell = _PATH_BSHELL;
        execlp(shell, shell, "-i", (char *)NULL);
Index: usr.sbin/gssd/gssd.c
===================================================================
RCS file: /home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/gssd/gssd.c,v
retrieving revision 1.1
diff -b -u -r1.1 gssd.c
--- usr.sbin/gssd/gssd.c        3 Nov 2008 10:38:00 -0000       1.1
+++ usr.sbin/gssd/gssd.c        5 Feb 2009 16:16:37 -0000
@@ -464,8 +464,8 @@
                        result->uid = uid;
                        getpwuid_r(uid, &pwd, buf, sizeof(buf), &pw);
                        if (pw) {
-                               int len = NGRPS;
-                               int groups[NGRPS];
+                               int len = AUTH_UNIX_NGROUPS ;
+                               int groups[AUTH_UNIX_NGROUPS] ;
                                result->gid = pw->pw_gid;
                                getgrouplist(pw->pw_name, pw->pw_gid,
                                    groups, &len);
Index: usr.sbin/mount_portalfs/cred.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/mount_portalfs/cred.c,v
retrieving revision 1.1
diff -b -u -r1.1 cred.c
--- usr.sbin/mount_portalfs/cred.c      11 Mar 2005 08:39:58 -0000      1.1
+++ usr.sbin/mount_portalfs/cred.c      16 Jan 2009 23:49:36 -0000
@@ -46,7 +46,7 @@
 set_user_credentials(struct portal_cred *user, struct portal_cred *save)
 {
        save->pcr_uid = geteuid();
-       if ((save->pcr_ngroups = getgroups(NGROUPS_MAX, save->pcr_groups)) < 0)
+       if( (save->pcr_ngroups=getgroups(_NGROUPS_COMPAT,save->pcr_groups)) < 0 
)
                return (-1);
        if (setgroups(user->pcr_ngroups, user->pcr_groups) < 0)
                return (-1);
Index: usr.sbin/pppd/options.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/pppd/options.c,v
retrieving revision 1.26
diff -b -u -r1.26 options.c
--- usr.sbin/pppd/options.c     7 Nov 2007 10:53:38 -0000       1.26
+++ usr.sbin/pppd/options.c     10 Feb 2009 09:11:47 -0000
@@ -72,10 +72,6 @@
 char *strdup(char *);
 #endif
 
-#ifndef GIDSET_TYPE
-#define GIDSET_TYPE    gid_t
-#endif
-
 /*
  * Option variables and default values.
  */
@@ -779,23 +775,64 @@
     int fd;
 {
     uid_t uid;
-    int ngroups, i;
+       int ngroups, max_ngroups, i;
     struct stat sbuf;
-    GIDSET_TYPE groups[NGROUPS_MAX];
+       gid_t *groups;
 
+/*     get the uid */
     uid = getuid();
+/*     ... and return true if root */
+/*     XXX: needs credential check */
     if (uid == 0)
        return 1;
+
+/*     if we're not root, get some info about the file */
     if (fstat(fd, &sbuf) != 0)
        return 0;
+
+/*     test for owner match with current process */
     if (sbuf.st_uid == uid)
        return sbuf.st_mode & S_IRUSR;
+/*     ... and a group match */
     if (sbuf.st_gid == getgid())
        return sbuf.st_mode & S_IRGRP;
-    ngroups = getgroups(NGROUPS_MAX, groups);
-    for (i = 0; i < ngroups; ++i)
-       if (sbuf.st_gid == groups[i])
-           return sbuf.st_mode & S_IRGRP;
+
+/*     if we've still no luck then check the group list for permission match */
+#if _POSIX_VERSION >= 199212
+       max_ngroups = sysconf( _SC_NGROUPS_MAX ) ;
+#elif defined(NGROUPS_MAX)
+       max_ngroups = NGROUPS_MAX ;
+#else
+       max_ngroups = _NGROUPS_COMPAT ;
+#endif
+       groups = (gid_t*) calloc( max_ngroups, sizeof(gid_t) ) ;
+       if( groups == NULL ) {
+       /* if we cannot check groups correctly then assume 'fd' is unreadable
+        *      XXX: this may be false as the converse is more likely.
+        *      i.e. it would be failed readable on available groups
+        *      and granted on full list, however, we just can't be
+        *      psychic and i'm not about to code some idiotic loop that tries
+        *      to get 'some' memory for partial testing.  probably a better
+        *      recourse would be to simply die here but that seems severe
+        *      for a 'readable' test.
+        *      NB: we don't need a 'full' allocation of memory to test the
+        *      group list, only to store it.  one idea would be to do this in
+        *      'blocks'
+        */
+               option_error( 1, "unable to allocate memory for group list" ) ;
+               return( 0 ) ;
+       }
+/*     get groups */
+       ngroups = getgroups( max_ngroups, groups ) ;
+/* ... and test the group permission if matching */
+       for( i = 0 ; i < ngroups ; ++i ) {
+               if (sbuf.st_gid == groups[i]) {
+                       free( (void*)groups) ;
+                       return( sbuf.st_mode & S_IRGRP ) ;
+               }
+       }
+/* otherwise return other permissions match */
+       free( (void*)groups ) ;
     return sbuf.st_mode & S_IROTH;
 }
 
Index: usr.sbin/rpc.lockd/kern.c
===================================================================
RCS file: 
/home/__orole/dev/cabinet/zeeNi/ai/freebsd/src/usr.sbin/rpc.lockd/kern.c,v
retrieving revision 1.21
diff -b -u -r1.21 kern.c
--- usr.sbin/rpc.lockd/kern.c   17 Aug 2006 05:55:20 -0000      1.21
+++ usr.sbin/rpc.lockd/kern.c   5 Feb 2009 16:22:17 -0000
@@ -239,15 +239,15 @@
        int ngroups;
 
        ngroups = xucred->cr_ngroups - 1;
-       if (ngroups > NGRPS)
-               ngroups = NGRPS;
-        if (cl->cl_auth != NULL)
-                cl->cl_auth->ah_ops->ah_destroy(cl->cl_auth);
-        cl->cl_auth = authunix_create(hostname,
+       if( ngroups > AUTH_UNIX_NGROUPS )
+               ngroups = AUTH_UNIX_NGROUPS ;
+       if( cl->cl_auth != NULL )
+               cl->cl_auth->ah_ops->ah_destroy( cl->cl_auth ) ;
+       cl->cl_auth = authunix_create( hostname,
                         xucred->cr_uid,
                         xucred->cr_groups[0],
                         ngroups,
-                        &xucred->cr_groups[1]);
+                       &xucred->cr_groups[1] ) ;
 }
 
 
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to