Diff for /embedaddon/sudo/compat/getgrouplist.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 16:23:02 version 1.1.1.2, 2013/07/22 10:46:11
Line 1 Line 1
 /*  /*
 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com> * Copyright (c) 2010, 2011, 2013 Todd C. Miller <Todd.Miller@courtesan.com>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 16 Line 16
   
 #include <config.h>  #include <config.h>
   
   #ifndef HAVE_GETGROUPLIST
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <stdio.h>  #include <stdio.h>
 #ifdef STDC_HEADERS  #ifdef STDC_HEADERS
Line 33 Line 35
 # include <strings.h>  # include <strings.h>
 #endif /* HAVE_STRINGS_H */  #endif /* HAVE_STRINGS_H */
 #include <grp.h>  #include <grp.h>
   #ifdef HAVE_NSS_SEARCH
   # include <limits.h>
   # include <nsswitch.h>
   # ifdef HAVE_NSS_DBDEFS_H
   #  include <nss_dbdefs.h>
   # else
   #  include "compat/nss_dbdefs.h"
   # endif
   #endif
   
 #include "missing.h"  #include "missing.h"
   
#ifdef HAVE_GETGRSET#if defined(HAVE_GETGRSET)
 /*  /*
  * BSD-compatible getgrouplist(3) using getgrset(3)   * BSD-compatible getgrouplist(3) using getgrset(3)
  */   */
Line 70  getgrouplist(const char *name, gid_t basegid, gid_t *g Line 81  getgrouplist(const char *name, gid_t basegid, gid_t *g
     rval = 0;      rval = 0;
   
 done:  done:
    efree(grset);    free(grset);
 #ifdef HAVE_SETAUTHDB  #ifdef HAVE_SETAUTHDB
     aix_restoreauthdb();      aix_restoreauthdb();
 #endif  #endif
Line 79  done: Line 90  done:
     return rval;      return rval;
 }  }
   
#else /* HAVE_GETGRSET */#elif defined(HAVE_NSS_SEARCH)
   
   #ifndef GID_MAX
   # define GID_MAX        UID_MAX
   #endif
   
   #ifndef ALIGNBYTES
   # define ALIGNBYTES     (sizeof(long) - 1L)
   #endif
   #ifndef ALIGN
   # define ALIGN(p)       (((unsigned long)(p) + ALIGNBYTES) & ~ALIGNBYTES)
   #endif
   
   extern void _nss_initf_group(nss_db_params_t *);
   
 /*  /*
    * Convert a groups file string (instr) to a struct group (ent) using
    * buf for storage.  
    */
   static int
   str2grp(const char *instr, int inlen, void *ent, char *buf, int buflen)
   {
       struct group *grp = ent;
       char *cp, *ep, *fieldsep = buf;
       char **gr_mem, **gr_end;
       int yp = 0;
       unsigned long gid;
   
       /* Must at least have space to copy instr -> buf. */
       if (inlen >= buflen)
           return NSS_STR_PARSE_ERANGE;
   
       /* Paranoia: buf and instr should be distinct. */
       if (buf != instr) {
           memmove(buf, instr, inlen);
           buf[inlen] = '\0';
       }
   
       if ((fieldsep = strchr(cp = fieldsep, ':')) == NULL)
           return NSS_STR_PARSE_PARSE;
       *fieldsep++ = '\0';
       grp->gr_name = cp;
   
       /* Check for YP inclusion/exclusion entries. */
       if (*cp == '+' || *cp == '-') {
           /* Only the name is required for YP inclusion/exclusion entries. */
           grp->gr_passwd = "";
           grp->gr_gid = 0;
           grp->gr_mem = NULL;
           yp = 1;
       }
   
       if ((fieldsep = strchr(cp = fieldsep, ':')) == NULL)
           return yp ? NSS_STR_PARSE_SUCCESS : NSS_STR_PARSE_PARSE;
       *fieldsep++ = '\0';
       grp->gr_passwd = cp;
   
       if ((fieldsep = strchr(cp = fieldsep, ':')) == NULL)
           return yp ? NSS_STR_PARSE_SUCCESS : NSS_STR_PARSE_PARSE;
       *fieldsep++ = '\0';
       gid = strtoul(cp, &ep, 10);
       if (*cp == '\0' || *ep != '\0')
           return yp ? NSS_STR_PARSE_SUCCESS : NSS_STR_PARSE_PARSE;
   #ifdef GID_NOBODY
       if (*cp == '-' && gid != 0) {
           /* Negative gids get mapped to nobody on Solaris. */
           grp->gr_gid = GID_NOBODY;
       } else
   #endif
       if ((errno == ERANGE && gid == ULONG_MAX) ||
           gid > GID_MAX || gid != (gid_t)gid) {
           return NSS_STR_PARSE_ERANGE;
       } else {
           grp->gr_gid = (gid_t)gid;
       }
   
       /* Store group members, taking care to use proper alignment. */
       grp->gr_mem = NULL;
       if (*fieldsep != '\0') {
           grp->gr_mem = gr_mem = (char **)ALIGN(buf + inlen + 1);
           gr_end = (char **)((unsigned long)(buf + buflen) & ~ALIGNBYTES);
           for (;;) {
               if (gr_mem == gr_end)
                   return NSS_STR_PARSE_ERANGE;    /* out of space! */
               *gr_mem++ = cp;
               if (fieldsep == NULL)
                   break;
               if ((fieldsep = strchr(cp = fieldsep, ',')) != NULL)
                   *fieldsep++ = '\0';
           }
           *gr_mem = NULL;
       }
       return NSS_STR_PARSE_SUCCESS;
   }
   
   static nss_status_t
   process_cstr(const char *instr, int inlen, struct nss_groupsbymem *gbm)
   {
       const char *user = gbm->username;
       nss_status_t rval = NSS_NOTFOUND;
       nss_XbyY_buf_t *buf;
       struct group *grp;
       char **gr_mem;
       int error, i;
   
       buf = _nss_XbyY_buf_alloc(sizeof(struct group), NSS_BUFLEN_GROUP);
       if (buf == NULL)
           return NSS_UNAVAIL;
   
       /* Parse groups file string -> struct group. */
       grp = buf->result;
       error = (*gbm->str2ent)(instr, inlen, grp, buf->buffer, buf->buflen);
       if (error || grp->gr_mem == NULL)
           goto done;
   
       for (gr_mem = grp->gr_mem; *gr_mem != NULL; gr_mem++) {
           if (strcmp(*gr_mem, user) == 0) {
               /* Append to gid_array unless gr_gid is a dupe. */
               for (i = 0; i < gbm->numgids; i++) {
                   if (gbm->gid_array[i] == grp->gr_gid)
                       goto done;                  /* already present */
               }
               /* Store gid if there is space. */
               if (i < gbm->maxgids)
                   gbm->gid_array[i] = grp->gr_gid;
               /* Always increment numgids so we can detect when out of space. */
               gbm->numgids++;
               goto done;
           }
       }
   done:
       _nss_XbyY_buf_free(buf);
       return rval;
   }
   
   /*
    * BSD-compatible getgrouplist(3) using nss_search(3)
    */
   int
   getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroupsp)
   {
       struct nss_groupsbymem gbm;
       static DEFINE_NSS_DB_ROOT(db_root);
   
       /* We support BSD semantics where the first element is the base gid */
       if (*ngroupsp <= 0)
           return -1;
       groups[0] = basegid;
   
       memset(&gbm, 0, sizeof(gbm));
       gbm.username = name;
       gbm.gid_array = groups;
       gbm.maxgids = *ngroupsp;
       gbm.numgids = 1; /* for basegid */
       gbm.force_slow_way = 1;
       gbm.str2ent = str2grp;
       gbm.process_cstr = process_cstr;
   
       /*
        * Can't use nss_search return value since it may return NSS_UNAVAIL
        * when no nsswitch.conf entry (e.g. compat mode).
        */
       (void)nss_search(&db_root, _nss_initf_group, NSS_DBOP_GROUP_BYMEMBER, &gbm);
   
       if (gbm.numgids <= gbm.maxgids) {
           *ngroupsp = gbm.numgids;
           return 0;
       }
       *ngroupsp = gbm.maxgids;
       return -1;
   }
   
   #else /* !HAVE_GETGRSET && !HAVE__GETGROUPSBYMEMBER */
   
   /*
  * BSD-compatible getgrouplist(3) using getgrent(3)   * BSD-compatible getgrouplist(3) using getgrent(3)
  */   */
 int  int
Line 128  done: Line 311  done:
   
     return rval;      return rval;
 }  }
#endif /* HAVE_GETGRSET */#endif /* !HAVE_GETGRSET && !HAVE__GETGROUPSBYMEMBER */
 #endif /* HAVE_GETGROUPLIST */

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>