[BACK]Return to getgroupmembership.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / gen

Annotation of src/lib/libc/gen/getgroupmembership.c, Revision 1.4

1.4     ! martin      1: /*     $NetBSD: getgroupmembership.c,v 1.3 2007/02/03 16:17:15 christos Exp $  */
1.1       lukem       2:
                      3: /*-
                      4:  * Copyright (c) 2004-2005 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Luke Mewburn.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/cdefs.h>
                     33: #if defined(LIBC_SCCS) && !defined(lint)
1.4     ! martin     34: __RCSID("$NetBSD: getgroupmembership.c,v 1.3 2007/02/03 16:17:15 christos Exp $");
1.1       lukem      35: #endif /* LIBC_SCCS and not lint */
                     36:
                     37: /*
                     38:  * calculate group access list
                     39:  */
                     40:
                     41: #include "namespace.h"
                     42: #include "reentrant.h"
                     43:
                     44: #include <sys/param.h>
                     45:
                     46: #include <assert.h>
                     47: #include <errno.h>
                     48: #include <grp.h>
                     49: #include <limits.h>
                     50: #include <nsswitch.h>
                     51: #include <stdarg.h>
                     52: #include <stdio.h>
                     53: #include <stdlib.h>
                     54: #include <string.h>
                     55: #include <unistd.h>
                     56:
                     57: #ifdef HESIOD
                     58: #include <hesiod.h>
                     59: #endif
                     60:
                     61: #include "gr_private.h"
                     62:
                     63: #ifdef __weak_alias
                     64: __weak_alias(getgroupmembership,_getgroupmembership)
                     65: #endif
                     66:
                     67: /*
                     68:  * __gr_addgid
                     69:  *     Add gid to the groups array (of maxgrp size) at the position
                     70:  *     indicated by *groupc, unless it already exists or *groupc is
                     71:  *     past &groups[maxgrp].
                     72:  *     Returns 1 upon success (including duplicate suppression), 0 otherwise.
                     73:  */
                     74: static int
                     75: __gr_addgid(gid_t gid, gid_t *groups, int maxgrp, int *groupc)
                     76: {
                     77:        int     ret, dupc;
                     78:
1.3       christos   79:        _DIAGASSERT(groupc != NULL);
                     80:        _DIAGASSERT(groups != NULL);
1.1       lukem      81:
                     82:                                                /* skip duplicates */
                     83:        for (dupc = 0; dupc < MIN(maxgrp, *groupc); dupc++) {
                     84:                if (groups[dupc] == gid)
                     85:                        return 1;
                     86:        }
                     87:
                     88:        ret = 1;
                     89:        if (*groupc < maxgrp)                   /* add this gid */
                     90:                groups[*groupc] = gid;
                     91:        else
                     92:                ret = 0;
                     93:        (*groupc)++;
                     94:        return ret;
                     95: }
                     96:
                     97:
                     98: /*ARGSUSED*/
                     99: static int
                    100: _files_getgroupmembership(void *retval, void *cb_data, va_list ap)
                    101: {
                    102:        int             *result = va_arg(ap, int *);
                    103:        const char      *uname  = va_arg(ap, const char *);
                    104:        gid_t            agroup = va_arg(ap, gid_t);
                    105:        gid_t           *groups = va_arg(ap, gid_t *);
                    106:        int              maxgrp = va_arg(ap, int);
                    107:        int             *groupc = va_arg(ap, int *);
                    108:
                    109:        struct __grstate_files  state;
                    110:        struct group            grp;
                    111:        char                    grpbuf[_GETGR_R_SIZE_MAX];
                    112:        int                     rv, i;
                    113:
                    114:        _DIAGASSERT(result != NULL);
                    115:        _DIAGASSERT(uname != NULL);
                    116:        /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
                    117:        _DIAGASSERT(groupc != NULL);
                    118:
                    119:                                                /* install primary group */
                    120:        (void) __gr_addgid(agroup, groups, maxgrp, groupc);
                    121:
                    122:        memset(&state, 0, sizeof(state));
                    123:        while (__grscan_files(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
                    124:                                0, NULL, 0) == NS_SUCCESS) {
                    125:                                                /* scan members */
                    126:                for (i = 0; grp.gr_mem[i]; i++) {
                    127:                        if (strcmp(grp.gr_mem[i], uname) != 0)
                    128:                                continue;
                    129:                        if (! __gr_addgid(grp.gr_gid, groups, maxgrp, groupc))
                    130:                                *result = -1;
                    131:                        break;
                    132:                }
                    133:        }
                    134:        __grend_files(&state);
                    135:        return NS_NOTFOUND;
                    136: }
                    137:
                    138:
                    139: #ifdef HESIOD
                    140:
                    141: /*ARGSUSED*/
                    142: static int
                    143: _dns_getgroupmembership(void *retval, void *cb_data, va_list ap)
                    144: {
                    145:        int             *result = va_arg(ap, int *);
                    146:        const char      *uname  = va_arg(ap, const char *);
                    147:        gid_t            agroup = va_arg(ap, gid_t);
                    148:        gid_t           *groups = va_arg(ap, gid_t *);
                    149:        int              maxgrp = va_arg(ap, int);
                    150:        int             *groupc = va_arg(ap, int *);
                    151:
                    152:        struct __grstate_dns    state;
                    153:        struct group            grp;
                    154:        char                    grpbuf[_GETGR_R_SIZE_MAX];
                    155:        unsigned long           id;
                    156:        void                    *context;
                    157:        char                    **hp, *cp, *ep;
                    158:        int                     rv, i;
                    159:
                    160:        _DIAGASSERT(result != NULL);
                    161:        _DIAGASSERT(uname != NULL);
                    162:        /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
                    163:        _DIAGASSERT(groupc != NULL);
                    164:
                    165:                                                /* install primary group */
                    166:        (void) __gr_addgid(agroup, groups, maxgrp, groupc);
                    167:
                    168:        hp = NULL;
                    169:        rv = NS_NOTFOUND;
                    170:
                    171:        if (hesiod_init(&context) == -1)                /* setup hesiod */
                    172:                return NS_UNAVAIL;
                    173:
                    174:        hp = hesiod_resolve(context, uname, "grplist"); /* find grplist */
                    175:        if (hp == NULL) {
                    176:                if (errno != ENOENT) {                  /* wasn't "not found"*/
                    177:                        rv = NS_UNAVAIL;
                    178:                        goto dnsgroupmembers_out;
                    179:                }
                    180:                        /* grplist not found, fallback to _dns_grscan */
                    181:                memset(&state, 0, sizeof(state));
                    182:                while (__grscan_dns(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
                    183:                                        0, NULL, 0) == NS_SUCCESS) {
                    184:                                                        /* scan members */
                    185:                        for (i = 0; grp.gr_mem[i]; i++) {
                    186:                                if (strcmp(grp.gr_mem[i], uname) != 0)
                    187:                                        continue;
                    188:                                if (! __gr_addgid(grp.gr_gid, groups, maxgrp,
                    189:                                    groupc))
                    190:                                        *result = -1;
                    191:                                break;
                    192:                        }
                    193:                }
                    194:                __grend_dns(&state);
                    195:                rv = NS_NOTFOUND;
                    196:                goto dnsgroupmembers_out;
                    197:        }
                    198:
                    199:        if ((ep = strchr(hp[0], '\n')) != NULL)
                    200:                *ep = '\0';                             /* clear trailing \n */
                    201:
                    202:        for (cp = hp[0]; *cp != '\0'; ) {               /* parse grplist */
                    203:                if ((cp = strchr(cp, ':')) == NULL)     /* skip grpname */
                    204:                        break;
                    205:                cp++;
                    206:                id = strtoul(cp, &ep, 10);              /* parse gid */
                    207:                if (id > GID_MAX || (*ep != ':' && *ep != '\0')) {
                    208:                        rv = NS_UNAVAIL;
                    209:                        goto dnsgroupmembers_out;
                    210:                }
                    211:                cp = ep;
                    212:                if (*cp == ':')
                    213:                        cp++;
                    214:
                    215:                                                        /* add gid */
                    216:                if (! __gr_addgid((gid_t)id, groups, maxgrp, groupc))
                    217:                        *result = -1;
                    218:        }
                    219:
                    220:        rv = NS_NOTFOUND;
                    221:
                    222:  dnsgroupmembers_out:
                    223:        if (hp)
                    224:                hesiod_free_list(context, hp);
                    225:        hesiod_end(context);
                    226:        return rv;
                    227: }
                    228:
                    229: #endif /* HESIOD */
                    230:
                    231:
                    232: #ifdef YP
                    233:
                    234: /*ARGSUSED*/
                    235: static int
                    236: _nis_getgroupmembership(void *retval, void *cb_data, va_list ap)
                    237: {
                    238:        int             *result = va_arg(ap, int *);
                    239:        const char      *uname  = va_arg(ap, const char *);
                    240:        gid_t            agroup = va_arg(ap, gid_t);
                    241:        gid_t           *groups = va_arg(ap, gid_t *);
                    242:        int              maxgrp = va_arg(ap, int);
                    243:        int             *groupc = va_arg(ap, int *);
                    244:
                    245:        struct __grstate_nis    state;
                    246:        struct group            grp;
                    247:        char                    grpbuf[_GETGR_R_SIZE_MAX];
                    248:        int                     rv, i;
                    249:
                    250:        _DIAGASSERT(result != NULL);
                    251:        _DIAGASSERT(uname != NULL);
                    252:        /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
                    253:        _DIAGASSERT(groupc != NULL);
                    254:
                    255:                                                /* install primary group */
                    256:        (void) __gr_addgid(agroup, groups, maxgrp, groupc);
                    257:
                    258:        memset(&state, 0, sizeof(state));
                    259:        while (__grscan_nis(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
                    260:                                0, NULL, 0) == NS_SUCCESS) {
                    261:                                                /* scan members */
                    262:                for (i = 0; grp.gr_mem[i]; i++) {
                    263:                        if (strcmp(grp.gr_mem[i], uname) != 0)
                    264:                                continue;
                    265:                        if (! __gr_addgid(grp.gr_gid, groups, maxgrp, groupc))
                    266:                                *result = -1;
                    267:                        break;
                    268:                }
                    269:        }
                    270:        __grend_nis(&state);
                    271:
                    272:        return NS_NOTFOUND;
                    273: }
                    274:
                    275: #endif /* YP */
                    276:
                    277:
                    278: #ifdef _GROUP_COMPAT
                    279:
                    280: struct __compatggm {
                    281:        const char      *uname;         /* user to search for */
                    282:        gid_t           *groups;
                    283:        gid_t            agroup;
                    284:        int              maxgrp;
                    285:        int             *groupc;
                    286: };
                    287:
                    288: static int
                    289: _compat_ggm_search(void *cookie, struct group **groupres)
                    290: {
                    291:        struct __compatggm      *cp;
                    292:        int                     rerror, crv;
                    293:
                    294:        static const ns_dtab dtab[] = {
                    295:                NS_FILES_CB(__grbad_compat, "files")
                    296:                NS_DNS_CB(_dns_getgroupmembership, NULL)
                    297:                NS_NIS_CB(_nis_getgroupmembership, NULL)
                    298:                NS_COMPAT_CB(__grbad_compat, "compat")
1.2       christos  299:                NS_NULL_CB
1.1       lukem     300:        };
                    301:
                    302:        *groupres = NULL;       /* we don't care about this */
                    303:        cp = (struct __compatggm *)cookie;
                    304:
                    305:        crv = nsdispatch(NULL, dtab,
                    306:            NSDB_GROUP_COMPAT, "getgroupmembership",
                    307:            __nsdefaultnis,
                    308:            &rerror, cp->uname, cp->agroup, cp->groups, cp->maxgrp, cp->groupc);
                    309:
                    310:        if (crv == NS_SUCCESS)
                    311:                crv = NS_NOTFOUND;      /* indicate "no more +: entries" */
                    312:
                    313:        return crv;
                    314: }
                    315:
                    316: /* ARGSUSED */
                    317: static int
                    318: _compat_getgroupmembership(void *retval, void *cb_data, va_list ap)
                    319: {
                    320:        int             *result = va_arg(ap, int *);
                    321:        const char      *uname  = va_arg(ap, const char *);
                    322:        gid_t            agroup = va_arg(ap, gid_t);
                    323:        gid_t           *groups = va_arg(ap, gid_t *);
                    324:        int              maxgrp = va_arg(ap, int);
                    325:        int             *groupc = va_arg(ap, int *);
                    326:
                    327:        struct __grstate_compat state;
                    328:        struct __compatggm      ggmstate;
                    329:        struct group            grp;
                    330:        char                    grpbuf[_GETGR_R_SIZE_MAX];
                    331:        int                     rv, i;
                    332:
                    333:        _DIAGASSERT(result != NULL);
                    334:        _DIAGASSERT(uname != NULL);
                    335:        /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
                    336:        _DIAGASSERT(groupc != NULL);
                    337:
                    338:                                                /* install primary group */
                    339:        (void) __gr_addgid(agroup, groups, maxgrp, groupc);
                    340:
                    341:        memset(&state, 0, sizeof(state));
                    342:        memset(&ggmstate, 0, sizeof(ggmstate));
                    343:        ggmstate.uname = uname;
                    344:        ggmstate.groups = groups;
                    345:        ggmstate.agroup = agroup;
                    346:        ggmstate.maxgrp = maxgrp;
                    347:        ggmstate.groupc = groupc;
                    348:
                    349:        while (__grscan_compat(&rv, &grp, grpbuf, sizeof(grpbuf), &state,
                    350:                                0, NULL, 0, _compat_ggm_search, &ggmstate)
                    351:                == NS_SUCCESS) {
                    352:                                                /* scan members */
                    353:                for (i = 0; grp.gr_mem[i]; i++) {
                    354:                        if (strcmp(grp.gr_mem[i], uname) != 0)
                    355:                                continue;
                    356:                        if (! __gr_addgid(grp.gr_gid, groups, maxgrp, groupc))
                    357:                                *result = -1;
                    358:                        break;
                    359:                }
                    360:        }
                    361:
                    362:        __grend_compat(&state);
                    363:        return NS_NOTFOUND;
                    364: }
                    365:
                    366: #endif /* _GROUP_COMPAT */
                    367:
                    368:
                    369: int
                    370: getgroupmembership(const char *uname, gid_t agroup,
                    371:     gid_t *groups, int maxgrp, int *groupc)
                    372: {
                    373:        int     rerror;
                    374:
                    375:        static const ns_dtab dtab[] = {
                    376:                NS_FILES_CB(_files_getgroupmembership, NULL)
                    377:                NS_DNS_CB(_dns_getgroupmembership, NULL)
                    378:                NS_NIS_CB(_nis_getgroupmembership, NULL)
                    379:                NS_COMPAT_CB(_compat_getgroupmembership, NULL)
1.2       christos  380:                NS_NULL_CB
1.1       lukem     381:        };
                    382:
                    383:        _DIAGASSERT(uname != NULL);
                    384:        /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
                    385:        _DIAGASSERT(groupc != NULL);
                    386:
                    387:        *groupc = 0;
                    388:
                    389:        mutex_lock(&__grmutex);
                    390:                        /*
                    391:                         * Call each backend.
                    392:                         * For compatibility with getgrent(3) semantics,
                    393:                         * a backend should return NS_NOTFOUND even upon
                    394:                         * completion, to allow result merging to occur.
                    395:                         */
                    396:        (void) nsdispatch(NULL, dtab, NSDB_GROUP, "getgroupmembership",
                    397:            __nsdefaultcompat,
                    398:            &rerror, uname, agroup, groups, maxgrp, groupc);
                    399:        mutex_unlock(&__grmutex);
                    400:
                    401:        if (*groupc > maxgrp)                   /* too many groups found */
                    402:                return -1;
                    403:        else
                    404:                return 0;
                    405: }

CVSweb <webmaster@jp.NetBSD.org>