Annotation of embedaddon/sudo/plugins/sudoers/pwutil_impl.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (c) 1996, 1998-2005, 2007-2013
                      3:  *     Todd C. Miller <Todd.Miller@courtesan.com>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  *
                     17:  * Sponsored in part by the Defense Advanced Research Projects
                     18:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
                     19:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
                     20:  */
                     21: 
                     22: #include <config.h>
                     23: 
                     24: #include <sys/types.h>
                     25: #include <stdio.h>
                     26: #ifdef STDC_HEADERS
                     27: # include <stdlib.h>
                     28: # include <stddef.h>
                     29: #else
                     30: # ifdef HAVE_STDLIB_H
                     31: #  include <stdlib.h>
                     32: # endif
                     33: #endif /* STDC_HEADERS */
                     34: #ifdef HAVE_STRING_H
                     35: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
                     36: #  include <memory.h>
                     37: # endif
                     38: # include <string.h>
                     39: #endif /* HAVE_STRING_H */
                     40: #ifdef HAVE_STRINGS_H
                     41: # include <strings.h>
                     42: #endif /* HAVE_STRINGS_H */
                     43: #ifdef HAVE_UNISTD_H
                     44: # include <unistd.h>
                     45: #endif /* HAVE_UNISTD_H */
                     46: #include <limits.h>
                     47: #include <pwd.h>
                     48: #include <grp.h>
                     49: 
                     50: #include "sudoers.h"
                     51: #include "pwutil.h"
                     52: 
                     53: #ifndef LOGIN_NAME_MAX
                     54: # ifdef _POSIX_LOGIN_NAME_MAX
                     55: #  define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX
                     56: # else
                     57: #  define LOGIN_NAME_MAX 9
                     58: # endif
                     59: #endif /* LOGIN_NAME_MAX */
                     60: 
                     61: #define FIELD_SIZE(src, name, size)                    \
                     62: do {                                                   \
                     63:        if (src->name) {                                \
                     64:                size = strlen(src->name) + 1;           \
                     65:                total += size;                          \
                     66:        }                                               \
                     67: } while (0)
                     68: 
                     69: #define FIELD_COPY(src, dst, name, size)               \
                     70: do {                                                   \
                     71:        if (src->name) {                                \
                     72:                memcpy(cp, src->name, size);            \
                     73:                dst->name = cp;                         \
                     74:                cp += size;                             \
                     75:        }                                               \
                     76: } while (0)
                     77: 
                     78: /*
                     79:  * Dynamically allocate space for a struct item plus the key and data
                     80:  * elements.  If name is non-NULL it is used as the key, else the
                     81:  * uid is the key.  Fills in datum from struct password.
                     82:  */
                     83: struct cache_item *
                     84: sudo_make_pwitem(uid_t uid, const char *name)
                     85: {
                     86:     char *cp;
                     87:     const char *pw_shell;
                     88:     size_t nsize, psize, csize, gsize, dsize, ssize, total;
                     89:     struct cache_item_pw *pwitem;
                     90:     struct passwd *pw, *newpw;
                     91:     debug_decl(sudo_make_pwitem, SUDO_DEBUG_NSS)
                     92: 
                     93:     /* Look up by name or uid. */
                     94:     pw = name ? getpwnam(name) : getpwuid(uid);
                     95:     if (pw == NULL)
                     96:        debug_return_ptr(NULL);
                     97: 
                     98:     /* If shell field is empty, expand to _PATH_BSHELL. */
                     99:     pw_shell = (pw->pw_shell == NULL || pw->pw_shell[0] == '\0')
                    100:        ? _PATH_BSHELL : pw->pw_shell;
                    101: 
                    102:     /* Allocate in one big chunk for easy freeing. */
                    103:     nsize = psize = csize = gsize = dsize = ssize = 0;
                    104:     total = sizeof(*pwitem);
                    105:     FIELD_SIZE(pw, pw_name, nsize);
                    106:     FIELD_SIZE(pw, pw_passwd, psize);
                    107: #ifdef HAVE_LOGIN_CAP_H
                    108:     FIELD_SIZE(pw, pw_class, csize);
                    109: #endif
                    110:     FIELD_SIZE(pw, pw_gecos, gsize);
                    111:     FIELD_SIZE(pw, pw_dir, dsize);
                    112:     /* Treat shell specially since we expand "" -> _PATH_BSHELL */
                    113:     ssize = strlen(pw_shell) + 1;
                    114:     total += ssize;
                    115:     if (name != NULL)
                    116:        total += strlen(name) + 1;
                    117: 
                    118:     /* Allocate space for struct item, struct passwd and the strings. */
                    119:     pwitem = ecalloc(1, total);
                    120:     newpw = &pwitem->pw;
                    121: 
                    122:     /*
                    123:      * Copy in passwd contents and make strings relative to space
                    124:      * at the end of the struct.
                    125:      */
                    126:     memcpy(newpw, pw, sizeof(*pw));
                    127:     cp = (char *)(pwitem + 1);
                    128:     FIELD_COPY(pw, newpw, pw_name, nsize);
                    129:     FIELD_COPY(pw, newpw, pw_passwd, psize);
                    130: #ifdef HAVE_LOGIN_CAP_H
                    131:     FIELD_COPY(pw, newpw, pw_class, csize);
                    132: #endif
                    133:     FIELD_COPY(pw, newpw, pw_gecos, gsize);
                    134:     FIELD_COPY(pw, newpw, pw_dir, dsize);
                    135:     /* Treat shell specially since we expand "" -> _PATH_BSHELL */
                    136:     memcpy(cp, pw_shell, ssize);
                    137:     newpw->pw_shell = cp;
                    138:     cp += ssize;
                    139: 
                    140:     /* Set key and datum. */
                    141:     if (name != NULL) {
                    142:        memcpy(cp, name, strlen(name) + 1);
                    143:        pwitem->cache.k.name = cp;
                    144:     } else {
                    145:        pwitem->cache.k.uid = pw->pw_uid;
                    146:     }
                    147:     pwitem->cache.d.pw = newpw;
                    148:     pwitem->cache.refcnt = 1;
                    149: 
                    150:     debug_return_ptr(&pwitem->cache);
                    151: }
                    152: 
                    153: /*
                    154:  * Dynamically allocate space for a struct item plus the key and data
                    155:  * elements.  If name is non-NULL it is used as the key, else the
                    156:  * gid is the key.  Fills in datum from struct group.
                    157:  */
                    158: struct cache_item *
                    159: sudo_make_gritem(gid_t gid, const char *name)
                    160: {
                    161:     char *cp;
                    162:     size_t nsize, psize, nmem, total, len;
                    163:     struct cache_item_gr *gritem;
                    164:     struct group *gr, *newgr;
                    165:     debug_decl(sudo_make_gritem, SUDO_DEBUG_NSS)
                    166: 
                    167:     /* Look up by name or gid. */
                    168:     gr = name ? getgrnam(name) : getgrgid(gid);
                    169:     if (gr == NULL)
                    170:        debug_return_ptr(NULL);
                    171: 
                    172:     /* Allocate in one big chunk for easy freeing. */
                    173:     nsize = psize = nmem = 0;
                    174:     total = sizeof(*gritem);
                    175:     FIELD_SIZE(gr, gr_name, nsize);
                    176:     FIELD_SIZE(gr, gr_passwd, psize);
                    177:     if (gr->gr_mem) {
                    178:        for (nmem = 0; gr->gr_mem[nmem] != NULL; nmem++)
                    179:            total += strlen(gr->gr_mem[nmem]) + 1;
                    180:        nmem++;
                    181:        total += sizeof(char *) * nmem;
                    182:     }
                    183:     if (name != NULL)
                    184:        total += strlen(name) + 1;
                    185: 
                    186:     gritem = ecalloc(1, total);
                    187: 
                    188:     /*
                    189:      * Copy in group contents and make strings relative to space
                    190:      * at the end of the buffer.  Note that gr_mem must come
                    191:      * immediately after struct group to guarantee proper alignment.
                    192:      */
                    193:     newgr = &gritem->gr;
                    194:     memcpy(newgr, gr, sizeof(*gr));
                    195:     cp = (char *)(gritem + 1);
                    196:     if (gr->gr_mem) {
                    197:        newgr->gr_mem = (char **)cp;
                    198:        cp += sizeof(char *) * nmem;
                    199:        for (nmem = 0; gr->gr_mem[nmem] != NULL; nmem++) {
                    200:            len = strlen(gr->gr_mem[nmem]) + 1;
                    201:            memcpy(cp, gr->gr_mem[nmem], len);
                    202:            newgr->gr_mem[nmem] = cp;
                    203:            cp += len;
                    204:        }
                    205:        newgr->gr_mem[nmem] = NULL;
                    206:     }
                    207:     FIELD_COPY(gr, newgr, gr_passwd, psize);
                    208:     FIELD_COPY(gr, newgr, gr_name, nsize);
                    209: 
                    210:     /* Set key and datum. */
                    211:     if (name != NULL) {
                    212:        memcpy(cp, name, strlen(name) + 1);
                    213:        gritem->cache.k.name = cp;
                    214:     } else {
                    215:        gritem->cache.k.gid = gr->gr_gid;
                    216:     }
                    217:     gritem->cache.d.gr = newgr;
                    218:     gritem->cache.refcnt = 1;
                    219: 
                    220:     debug_return_ptr(&gritem->cache);
                    221: }
                    222: 
                    223: /*
                    224:  * Dynamically allocate space for a struct item plus the key and data
                    225:  * elements.  Fills in datum from user_gids or from getgrouplist(3).
                    226:  */
                    227: struct cache_item *
                    228: sudo_make_grlist_item(struct passwd *pw, char * const *unused1,
                    229:     char * const *unused2)
                    230: {
                    231:     char *cp;
                    232:     size_t i, nsize, ngroups, total, len;
                    233:     struct cache_item_grlist *grlitem;
                    234:     struct group_list *grlist;
                    235:     GETGROUPS_T *gids;
                    236:     struct group *grp;
                    237:     int ngids, groupname_len;
                    238:     debug_decl(sudo_make_grlist_item, SUDO_DEBUG_NSS)
                    239: 
                    240:     if (pw == sudo_user.pw && sudo_user.gids != NULL) {
                    241:        gids = user_gids;
                    242:        ngids = user_ngids;
                    243:        user_gids = NULL;
                    244:        user_ngids = 0;
                    245:     } else {
                    246:        if (sudo_user.max_groups != -1) {
                    247:            ngids = sudo_user.max_groups;
                    248:            gids = emalloc2(ngids, sizeof(GETGROUPS_T));
                    249:            (void)getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids);
                    250:        } else {
                    251: #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
                    252:            ngids = (int)sysconf(_SC_NGROUPS_MAX) * 2;
                    253:            if (ngids < 0)
                    254: #endif
                    255:                ngids = NGROUPS_MAX * 2;
                    256:            gids = emalloc2(ngids, sizeof(GETGROUPS_T));
                    257:            if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1) {
                    258:                efree(gids);
                    259:                gids = emalloc2(ngids, sizeof(GETGROUPS_T));
                    260:                if (getgrouplist(pw->pw_name, pw->pw_gid, gids, &ngids) == -1)
                    261:                    ngids = -1;
                    262:            }
                    263:        }
                    264:     }
                    265:     if (ngids <= 0) {
                    266:        efree(gids);
                    267:        debug_return_ptr(NULL);
                    268:     }
                    269: 
                    270: #ifdef HAVE_SETAUTHDB
                    271:     aix_setauthdb((char *) pw->pw_name);
                    272: #endif
                    273: 
                    274: #if defined(HAVE_SYSCONF) && defined(_SC_LOGIN_NAME_MAX)
                    275:     groupname_len = MAX((int)sysconf(_SC_LOGIN_NAME_MAX), 32);
                    276: #else
                    277:     groupname_len = MAX(LOGIN_NAME_MAX, 32);
                    278: #endif
                    279: 
                    280:     /* Allocate in one big chunk for easy freeing. */
                    281:     nsize = strlen(pw->pw_name) + 1;
                    282:     total = sizeof(*grlitem) + nsize;
                    283:     total += sizeof(char *) * ngids;
                    284:     total += sizeof(gid_t *) * ngids;
                    285:     total += groupname_len * ngids;
                    286: 
                    287: again:
                    288:     grlitem = ecalloc(1, total);
                    289: 
                    290:     /*
                    291:      * Copy in group list and make pointers relative to space
                    292:      * at the end of the buffer.  Note that the groups array must come
                    293:      * immediately after struct group to guarantee proper alignment.
                    294:      */
                    295:     grlist = &grlitem->grlist;
                    296:     cp = (char *)(grlitem + 1);
                    297:     grlist->groups = (char **)cp;
                    298:     cp += sizeof(char *) * ngids;
                    299:     grlist->gids = (gid_t *)cp;
                    300:     cp += sizeof(gid_t) * ngids;
                    301: 
                    302:     /* Set key and datum. */
                    303:     memcpy(cp, pw->pw_name, nsize);
                    304:     grlitem->cache.k.name = cp;
                    305:     grlitem->cache.d.grlist = grlist;
                    306:     grlitem->cache.refcnt = 1;
                    307:     cp += nsize;
                    308: 
                    309:     /*
                    310:      * Store group IDs.
                    311:      */
                    312:     for (i = 0; i < ngids; i++)
                    313:        grlist->gids[i] = gids[i];
                    314:     grlist->ngids = ngids;
                    315: 
                    316:     /*
                    317:      * Resolve and store group names by ID.
                    318:      */
                    319:     ngroups = 0;
                    320:     for (i = 0; i < ngids; i++) {
                    321:        if ((grp = sudo_getgrgid(gids[i])) != NULL) {
                    322:            len = strlen(grp->gr_name) + 1;
                    323:            if (cp - (char *)grlitem + len > total) {
                    324:                total += len + groupname_len;
                    325:                efree(grlitem);
                    326:                sudo_gr_delref(grp);
                    327:                goto again;
                    328:            }
                    329:            memcpy(cp, grp->gr_name, len);
                    330:            grlist->groups[ngroups++] = cp;
                    331:            cp += len;
                    332:            sudo_gr_delref(grp);
                    333:        }
                    334:     }
                    335:     grlist->ngroups = ngroups;
                    336:     efree(gids);
                    337: 
                    338: #ifdef HAVE_SETAUTHDB
                    339:     aix_restoreauthdb();
                    340: #endif
                    341: 
                    342:     debug_return_ptr(&grlitem->cache);
                    343: }

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