Annotation of embedaddon/sudo/plugins/sudoers/pwutil_impl.c, revision 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>