Annotation of embedaddon/sudo/plugins/sudoers/parse.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2004-2005, 2007-2011 Todd C. Miller <Todd.Miller@courtesan.com>
        !             3:  *
        !             4:  * Permission to use, copy, modify, and distribute this software for any
        !             5:  * purpose with or without fee is hereby granted, provided that the above
        !             6:  * copyright notice and this permission notice appear in all copies.
        !             7:  *
        !             8:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !             9:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            10:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            11:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            12:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            13:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            14:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            15:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
        !            16:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            17:  */
        !            18: 
        !            19: #include <config.h>
        !            20: 
        !            21: #include <sys/types.h>
        !            22: #include <sys/param.h>
        !            23: #include <stdio.h>
        !            24: #ifdef STDC_HEADERS
        !            25: # include <stdlib.h>
        !            26: # include <stddef.h>
        !            27: #else
        !            28: # ifdef HAVE_STDLIB_H
        !            29: #  include <stdlib.h>
        !            30: # endif
        !            31: #endif /* STDC_HEADERS */
        !            32: #ifdef HAVE_STRING_H
        !            33: # include <string.h>
        !            34: #endif /* HAVE_STRING_H */
        !            35: #ifdef HAVE_STRINGS_H
        !            36: # include <strings.h>
        !            37: #endif /* HAVE_STRINGS_H */
        !            38: #ifdef HAVE_UNISTD_H
        !            39: # include <unistd.h>
        !            40: #endif /* HAVE_UNISTD_H */
        !            41: #include <ctype.h>
        !            42: #include <pwd.h>
        !            43: #include <grp.h>
        !            44: 
        !            45: #include "sudoers.h"
        !            46: #include "parse.h"
        !            47: #include "lbuf.h"
        !            48: #include <gram.h>
        !            49: 
        !            50: /* Characters that must be quoted in sudoers */
        !            51: #define SUDOERS_QUOTED ":\\,=#\""
        !            52: 
        !            53: /* sudoers nsswitch routines */
        !            54: struct sudo_nss sudo_nss_file = {
        !            55:     &sudo_nss_file,
        !            56:     NULL,
        !            57:     sudo_file_open,
        !            58:     sudo_file_close,
        !            59:     sudo_file_parse,
        !            60:     sudo_file_setdefs,
        !            61:     sudo_file_lookup,
        !            62:     sudo_file_display_cmnd,
        !            63:     sudo_file_display_defaults,
        !            64:     sudo_file_display_bound_defaults,
        !            65:     sudo_file_display_privs
        !            66: };
        !            67: 
        !            68: /*
        !            69:  * Parser externs.
        !            70:  */
        !            71: extern FILE *yyin;
        !            72: extern char *errorfile;
        !            73: extern int errorlineno, parse_error;
        !            74: 
        !            75: /*
        !            76:  * Local prototypes.
        !            77:  */
        !            78: static void print_member(struct lbuf *, char *, int, int, int);
        !            79: static int display_bound_defaults(int, struct lbuf *);
        !            80: 
        !            81: int
        !            82: sudo_file_open(struct sudo_nss *nss)
        !            83: {
        !            84:     if (def_ignore_local_sudoers)
        !            85:        return -1;
        !            86:     nss->handle = open_sudoers(sudoers_file, FALSE, NULL);
        !            87:     return nss->handle ? 0 : -1;
        !            88: }
        !            89: 
        !            90: int
        !            91: sudo_file_close(struct sudo_nss *nss)
        !            92: {
        !            93:     /* Free parser data structures and close sudoers file. */
        !            94:     init_parser(NULL, 0);
        !            95:     if (nss->handle != NULL) {
        !            96:        fclose(nss->handle);
        !            97:        nss->handle = NULL;
        !            98:        yyin = NULL;
        !            99:     }
        !           100:     return 0;
        !           101: }
        !           102: 
        !           103: /*
        !           104:  * Parse the specified sudoers file.
        !           105:  */
        !           106: int
        !           107: sudo_file_parse(struct sudo_nss *nss)
        !           108: {
        !           109:     if (nss->handle == NULL)
        !           110:        return -1;
        !           111: 
        !           112:     init_parser(sudoers_file, 0);
        !           113:     yyin = nss->handle;
        !           114:     if (yyparse() != 0 || parse_error) {
        !           115:        log_error(NO_EXIT, _("parse error in %s near line %d"),
        !           116:            errorfile, errorlineno);
        !           117:        return -1;
        !           118:     }
        !           119:     return 0;
        !           120: }
        !           121: 
        !           122: /*
        !           123:  * Wrapper around update_defaults() for nsswitch code.
        !           124:  */
        !           125: int
        !           126: sudo_file_setdefs(struct sudo_nss *nss)
        !           127: {
        !           128:     if (nss->handle == NULL)
        !           129:        return -1;
        !           130: 
        !           131:     if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER))
        !           132:        return -1;
        !           133:     return 0;
        !           134: }
        !           135: 
        !           136: /*
        !           137:  * Look up the user in the parsed sudoers file and check to see if they are
        !           138:  * allowed to run the specified command on this host as the target user.
        !           139:  */
        !           140: int
        !           141: sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag)
        !           142: {
        !           143:     int match, host_match, runas_match, cmnd_match;
        !           144:     struct cmndspec *cs;
        !           145:     struct cmndtag *tags = NULL;
        !           146:     struct privilege *priv;
        !           147:     struct userspec *us;
        !           148: 
        !           149:     if (nss->handle == NULL)
        !           150:        return validated;
        !           151: 
        !           152:     /*
        !           153:      * Only check the actual command if pwflag is not set.
        !           154:      * It is set for the "validate", "list" and "kill" pseudo-commands.
        !           155:      * Always check the host and user.
        !           156:      */
        !           157:     if (pwflag) {
        !           158:        int nopass;
        !           159:        enum def_tuple pwcheck;
        !           160: 
        !           161:        pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
        !           162:        nopass = (pwcheck == all) ? TRUE : FALSE;
        !           163: 
        !           164:        if (list_pw == NULL)
        !           165:            SET(validated, FLAG_NO_CHECK);
        !           166:        CLR(validated, FLAG_NO_USER);
        !           167:        CLR(validated, FLAG_NO_HOST);
        !           168:        match = DENY;
        !           169:        tq_foreach_fwd(&userspecs, us) {
        !           170:            if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
        !           171:                continue;
        !           172:            tq_foreach_fwd(&us->privileges, priv) {
        !           173:                if (hostlist_matches(&priv->hostlist) != ALLOW)
        !           174:                    continue;
        !           175:                tq_foreach_fwd(&priv->cmndlist, cs) {
        !           176:                    /* Only check the command when listing another user. */
        !           177:                    if (user_uid == 0 || list_pw == NULL ||
        !           178:                        user_uid == list_pw->pw_uid ||
        !           179:                        cmnd_matches(cs->cmnd) == ALLOW)
        !           180:                            match = ALLOW;
        !           181:                    if ((pwcheck == any && cs->tags.nopasswd == TRUE) ||
        !           182:                        (pwcheck == all && cs->tags.nopasswd != TRUE))
        !           183:                        nopass = cs->tags.nopasswd;
        !           184:                }
        !           185:            }
        !           186:        }
        !           187:        if (match == ALLOW || user_uid == 0) {
        !           188:            /* User has an entry for this host. */
        !           189:            SET(validated, VALIDATE_OK);
        !           190:        } else if (match == DENY)
        !           191:            SET(validated, VALIDATE_NOT_OK);
        !           192:        if (pwcheck == always && def_authenticate)
        !           193:            SET(validated, FLAG_CHECK_USER);
        !           194:        else if (pwcheck == never || nopass == TRUE)
        !           195:            def_authenticate = FALSE;
        !           196:        return validated;
        !           197:     }
        !           198: 
        !           199:     /* Need to be runas user while stat'ing things. */
        !           200:     set_perms(PERM_RUNAS);
        !           201: 
        !           202:     match = UNSPEC;
        !           203:     tq_foreach_rev(&userspecs, us) {
        !           204:        if (userlist_matches(sudo_user.pw, &us->users) != ALLOW)
        !           205:            continue;
        !           206:        CLR(validated, FLAG_NO_USER);
        !           207:        tq_foreach_rev(&us->privileges, priv) {
        !           208:            host_match = hostlist_matches(&priv->hostlist);
        !           209:            if (host_match == ALLOW)
        !           210:                CLR(validated, FLAG_NO_HOST);
        !           211:            else
        !           212:                continue;
        !           213:            tq_foreach_rev(&priv->cmndlist, cs) {
        !           214:                runas_match = runaslist_matches(&cs->runasuserlist,
        !           215:                    &cs->runasgrouplist);
        !           216:                if (runas_match == ALLOW) {
        !           217:                    cmnd_match = cmnd_matches(cs->cmnd);
        !           218:                    if (cmnd_match != UNSPEC) {
        !           219:                        match = cmnd_match;
        !           220:                        tags = &cs->tags;
        !           221: #ifdef HAVE_SELINUX
        !           222:                        /* Set role and type if not specified on command line. */
        !           223:                        if (user_role == NULL)
        !           224:                            user_role = cs->role ? estrdup(cs->role) : def_role;
        !           225:                        if (user_type == NULL)
        !           226:                            user_type = cs->type ? estrdup(cs->type) : def_type;
        !           227: #endif /* HAVE_SELINUX */
        !           228:                        goto matched2;
        !           229:                    }
        !           230:                }
        !           231:            }
        !           232:        }
        !           233:     }
        !           234:     matched2:
        !           235:     if (match == ALLOW) {
        !           236:        SET(validated, VALIDATE_OK);
        !           237:        CLR(validated, VALIDATE_NOT_OK);
        !           238:        if (tags != NULL) {
        !           239:            if (tags->nopasswd != UNSPEC)
        !           240:                def_authenticate = !tags->nopasswd;
        !           241:            if (tags->noexec != UNSPEC)
        !           242:                def_noexec = tags->noexec;
        !           243:            if (tags->setenv != UNSPEC)
        !           244:                def_setenv = tags->setenv;
        !           245:            if (tags->log_input != UNSPEC)
        !           246:                def_log_input = tags->log_input;
        !           247:            if (tags->log_output != UNSPEC)
        !           248:                def_log_output = tags->log_output;
        !           249:        }
        !           250:     } else if (match == DENY) {
        !           251:        SET(validated, VALIDATE_NOT_OK);
        !           252:        CLR(validated, VALIDATE_OK);
        !           253:        if (tags != NULL && tags->nopasswd != UNSPEC)
        !           254:            def_authenticate = !tags->nopasswd;
        !           255:     }
        !           256:     restore_perms();
        !           257:     return validated;
        !           258: }
        !           259: 
        !           260: #define        TAG_CHANGED(t) \
        !           261:        (cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags->t)
        !           262: 
        !           263: static void
        !           264: sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags,
        !           265:     struct lbuf *lbuf)
        !           266: {
        !           267:     struct member *m;
        !           268: 
        !           269: #ifdef HAVE_SELINUX
        !           270:     if (cs->role)
        !           271:        lbuf_append(lbuf, "ROLE=%s ", cs->role);
        !           272:     if (cs->type)
        !           273:        lbuf_append(lbuf, "TYPE=%s ", cs->type);
        !           274: #endif /* HAVE_SELINUX */
        !           275:     if (TAG_CHANGED(setenv)) {
        !           276:        lbuf_append(lbuf, cs->tags.setenv ? "SETENV: " : "NOSETENV: ");
        !           277:        tags->setenv = cs->tags.setenv;
        !           278:     }
        !           279:     if (TAG_CHANGED(noexec)) {
        !           280:        lbuf_append(lbuf, cs->tags.noexec ? "NOEXEC: " : "EXEC: ");
        !           281:        tags->noexec = cs->tags.noexec;
        !           282:     }
        !           283:     if (TAG_CHANGED(nopasswd)) {
        !           284:        lbuf_append(lbuf, cs->tags.nopasswd ? "NOPASSWD: " : "PASSWD: ");
        !           285:        tags->nopasswd = cs->tags.nopasswd;
        !           286:     }
        !           287:     if (TAG_CHANGED(log_input)) {
        !           288:        lbuf_append(lbuf, cs->tags.log_input ? "LOG_INPUT: " : "NOLOG_INPUT: ");
        !           289:        tags->log_input = cs->tags.log_input;
        !           290:     }
        !           291:     if (TAG_CHANGED(log_output)) {
        !           292:        lbuf_append(lbuf, cs->tags.log_output ? "LOG_OUTPUT: " : "NOLOG_OUTPUT: ");
        !           293:        tags->log_output = cs->tags.log_output;
        !           294:     }
        !           295:     m = cs->cmnd;
        !           296:     print_member(lbuf, m->name, m->type, m->negated,
        !           297:        CMNDALIAS);
        !           298: }
        !           299: 
        !           300: static int
        !           301: sudo_file_display_priv_short(struct passwd *pw, struct userspec *us,
        !           302:     struct lbuf *lbuf)
        !           303: {
        !           304:     struct cmndspec *cs;
        !           305:     struct member *m;
        !           306:     struct privilege *priv;
        !           307:     struct cmndtag tags;
        !           308:     int nfound = 0;
        !           309: 
        !           310:     tq_foreach_fwd(&us->privileges, priv) {
        !           311:        if (hostlist_matches(&priv->hostlist) != ALLOW)
        !           312:            continue;
        !           313:        tags.noexec = UNSPEC;
        !           314:        tags.setenv = UNSPEC;
        !           315:        tags.nopasswd = UNSPEC;
        !           316:        tags.log_input = UNSPEC;
        !           317:        tags.log_output = UNSPEC;
        !           318:        lbuf_append(lbuf, "    ");
        !           319:        tq_foreach_fwd(&priv->cmndlist, cs) {
        !           320:            if (cs != tq_first(&priv->cmndlist))
        !           321:                lbuf_append(lbuf, ", ");
        !           322:            lbuf_append(lbuf, "(");
        !           323:            if (!tq_empty(&cs->runasuserlist)) {
        !           324:                tq_foreach_fwd(&cs->runasuserlist, m) {
        !           325:                    if (m != tq_first(&cs->runasuserlist))
        !           326:                        lbuf_append(lbuf, ", ");
        !           327:                    print_member(lbuf, m->name, m->type, m->negated,
        !           328:                        RUNASALIAS);
        !           329:                }
        !           330:            } else if (tq_empty(&cs->runasgrouplist)) {
        !           331:                lbuf_append(lbuf, "%s", def_runas_default);
        !           332:            } else {
        !           333:                lbuf_append(lbuf, "%s", pw->pw_name);
        !           334:            }
        !           335:            if (!tq_empty(&cs->runasgrouplist)) {
        !           336:                lbuf_append(lbuf, " : ");
        !           337:                tq_foreach_fwd(&cs->runasgrouplist, m) {
        !           338:                    if (m != tq_first(&cs->runasgrouplist))
        !           339:                        lbuf_append(lbuf, ", ");
        !           340:                    print_member(lbuf, m->name, m->type, m->negated,
        !           341:                        RUNASALIAS);
        !           342:                }
        !           343:            }
        !           344:            lbuf_append(lbuf, ") ");
        !           345:            sudo_file_append_cmnd(cs, &tags, lbuf);
        !           346:            nfound++;
        !           347:        }
        !           348:        lbuf_append(lbuf, "\n");
        !           349:     }
        !           350:     return nfound;
        !           351: }
        !           352: 
        !           353: static int
        !           354: sudo_file_display_priv_long(struct passwd *pw, struct userspec *us,
        !           355:     struct lbuf *lbuf)
        !           356: {
        !           357:     struct cmndspec *cs;
        !           358:     struct member *m;
        !           359:     struct privilege *priv;
        !           360:     struct cmndtag tags;
        !           361:     int nfound = 0;
        !           362: 
        !           363:     tq_foreach_fwd(&us->privileges, priv) {
        !           364:        if (hostlist_matches(&priv->hostlist) != ALLOW)
        !           365:            continue;
        !           366:        tags.noexec = UNSPEC;
        !           367:        tags.setenv = UNSPEC;
        !           368:        tags.nopasswd = UNSPEC;
        !           369:        tags.log_input = UNSPEC;
        !           370:        tags.log_output = UNSPEC;
        !           371:        lbuf_append(lbuf, _("\nSudoers entry:\n"));
        !           372:        tq_foreach_fwd(&priv->cmndlist, cs) {
        !           373:            lbuf_append(lbuf, _("    RunAsUsers: "));
        !           374:            if (!tq_empty(&cs->runasuserlist)) {
        !           375:                tq_foreach_fwd(&cs->runasuserlist, m) {
        !           376:                    if (m != tq_first(&cs->runasuserlist))
        !           377:                        lbuf_append(lbuf, ", ");
        !           378:                    print_member(lbuf, m->name, m->type, m->negated,
        !           379:                        RUNASALIAS);
        !           380:                }
        !           381:            } else if (tq_empty(&cs->runasgrouplist)) {
        !           382:                lbuf_append(lbuf, "%s", def_runas_default);
        !           383:            } else {
        !           384:                lbuf_append(lbuf, "%s", pw->pw_name);
        !           385:            }
        !           386:            lbuf_append(lbuf, "\n");
        !           387:            if (!tq_empty(&cs->runasgrouplist)) {
        !           388:                lbuf_append(lbuf, _("    RunAsGroups: "));
        !           389:                tq_foreach_fwd(&cs->runasgrouplist, m) {
        !           390:                    if (m != tq_first(&cs->runasgrouplist))
        !           391:                        lbuf_append(lbuf, ", ");
        !           392:                    print_member(lbuf, m->name, m->type, m->negated,
        !           393:                        RUNASALIAS);
        !           394:                }
        !           395:                lbuf_append(lbuf, "\n");
        !           396:            }
        !           397:            lbuf_append(lbuf, _("    Commands:\n\t"));
        !           398:            sudo_file_append_cmnd(cs, &tags, lbuf);
        !           399:            lbuf_append(lbuf, "\n");
        !           400:            nfound++;
        !           401:        }
        !           402:     }
        !           403:     return nfound;
        !           404: }
        !           405: 
        !           406: int
        !           407: sudo_file_display_privs(struct sudo_nss *nss, struct passwd *pw,
        !           408:     struct lbuf *lbuf)
        !           409: {
        !           410:     struct userspec *us;
        !           411:     int nfound = 0;
        !           412: 
        !           413:     if (nss->handle == NULL)
        !           414:        goto done;
        !           415: 
        !           416:     tq_foreach_fwd(&userspecs, us) {
        !           417:        if (userlist_matches(pw, &us->users) != ALLOW)
        !           418:            continue;
        !           419: 
        !           420:        if (long_list)
        !           421:            nfound += sudo_file_display_priv_long(pw, us, lbuf);
        !           422:        else
        !           423:            nfound += sudo_file_display_priv_short(pw, us, lbuf);
        !           424:     }
        !           425: done:
        !           426:     return nfound;
        !           427: }
        !           428: 
        !           429: /*
        !           430:  * Display matching Defaults entries for the given user on this host.
        !           431:  */
        !           432: int
        !           433: sudo_file_display_defaults(struct sudo_nss *nss, struct passwd *pw,
        !           434:     struct lbuf *lbuf)
        !           435: {
        !           436:     struct defaults *d;
        !           437:     char *prefix;
        !           438:     int nfound = 0;
        !           439: 
        !           440:     if (nss->handle == NULL)
        !           441:        goto done;
        !           442: 
        !           443:     if (lbuf->len == 0 || isspace((unsigned char)lbuf->buf[lbuf->len - 1]))
        !           444:        prefix = "    ";
        !           445:     else
        !           446:        prefix = ", ";
        !           447: 
        !           448:     tq_foreach_fwd(&defaults, d) {
        !           449:        switch (d->type) {
        !           450:            case DEFAULTS_HOST:
        !           451:                if (hostlist_matches(&d->binding) != ALLOW)
        !           452:                    continue;
        !           453:                break;
        !           454:            case DEFAULTS_USER:
        !           455:                if (userlist_matches(pw, &d->binding) != ALLOW)
        !           456:                    continue;
        !           457:                break;
        !           458:            case DEFAULTS_RUNAS:
        !           459:            case DEFAULTS_CMND:
        !           460:                continue;
        !           461:        }
        !           462:        if (d->val != NULL) {
        !           463:            lbuf_append(lbuf, "%s%s%s", prefix, d->var,
        !           464:                d->op == '+' ? "+=" : d->op == '-' ? "-=" : "=");
        !           465:            if (strpbrk(d->val, " \t") != NULL) {
        !           466:                lbuf_append(lbuf, "\"");
        !           467:                lbuf_append_quoted(lbuf, "\"", "%s", d->val);
        !           468:                lbuf_append(lbuf, "\"");
        !           469:            } else
        !           470:                lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", d->val);
        !           471:        } else
        !           472:            lbuf_append(lbuf, "%s%s%s", prefix,
        !           473:                d->op == FALSE ? "!" : "", d->var);
        !           474:        prefix = ", ";
        !           475:        nfound++;
        !           476:     }
        !           477: done:
        !           478:     return nfound;
        !           479: }
        !           480: 
        !           481: /*
        !           482:  * Display Defaults entries that are per-runas or per-command
        !           483:  */
        !           484: int
        !           485: sudo_file_display_bound_defaults(struct sudo_nss *nss, struct passwd *pw,
        !           486:     struct lbuf *lbuf)
        !           487: {
        !           488:     int nfound = 0;
        !           489: 
        !           490:     /* XXX - should only print ones that match what the user can do. */
        !           491:     nfound += display_bound_defaults(DEFAULTS_RUNAS, lbuf);
        !           492:     nfound += display_bound_defaults(DEFAULTS_CMND, lbuf);
        !           493: 
        !           494:     return nfound;
        !           495: }
        !           496: 
        !           497: /*
        !           498:  * Display Defaults entries of the given type.
        !           499:  */
        !           500: static int
        !           501: display_bound_defaults(int dtype, struct lbuf *lbuf)
        !           502: {
        !           503:     struct defaults *d;
        !           504:     struct member *m, *binding = NULL;
        !           505:     char *dsep;
        !           506:     int atype, nfound = 0;
        !           507: 
        !           508:     switch (dtype) {
        !           509:        case DEFAULTS_HOST:
        !           510:            atype = HOSTALIAS;
        !           511:            dsep = "@";
        !           512:            break;
        !           513:        case DEFAULTS_USER:
        !           514:            atype = USERALIAS;
        !           515:            dsep = ":";
        !           516:            break;
        !           517:        case DEFAULTS_RUNAS:
        !           518:            atype = RUNASALIAS;
        !           519:            dsep = ">";
        !           520:            break;
        !           521:        case DEFAULTS_CMND:
        !           522:            atype = CMNDALIAS;
        !           523:            dsep = "!";
        !           524:            break;
        !           525:        default:
        !           526:            return -1;
        !           527:     }
        !           528:     tq_foreach_fwd(&defaults, d) {
        !           529:        if (d->type != dtype)
        !           530:            continue;
        !           531: 
        !           532:        nfound++;
        !           533:        if (binding != tq_first(&d->binding)) {
        !           534:            binding = tq_first(&d->binding);
        !           535:            if (nfound != 1)
        !           536:                lbuf_append(lbuf, "\n");
        !           537:            lbuf_append(lbuf, "    Defaults%s", dsep);
        !           538:            for (m = binding; m != NULL; m = m->next) {
        !           539:                if (m != binding)
        !           540:                    lbuf_append(lbuf, ",");
        !           541:                print_member(lbuf, m->name, m->type, m->negated, atype);
        !           542:                lbuf_append(lbuf, " ");
        !           543:            }
        !           544:        } else
        !           545:            lbuf_append(lbuf, ", ");
        !           546:        if (d->val != NULL) {
        !           547:            lbuf_append(lbuf, "%s%s%s", d->var, d->op == '+' ? "+=" :
        !           548:                d->op == '-' ? "-=" : "=", d->val);
        !           549:        } else
        !           550:            lbuf_append(lbuf, "%s%s", d->op == FALSE ? "!" : "", d->var);
        !           551:     }
        !           552: 
        !           553:     return nfound;
        !           554: }
        !           555: 
        !           556: int
        !           557: sudo_file_display_cmnd(struct sudo_nss *nss, struct passwd *pw)
        !           558: {
        !           559:     struct cmndspec *cs;
        !           560:     struct member *match;
        !           561:     struct privilege *priv;
        !           562:     struct userspec *us;
        !           563:     int rval = 1;
        !           564:     int host_match, runas_match, cmnd_match;
        !           565: 
        !           566:     if (nss->handle == NULL)
        !           567:        goto done;
        !           568: 
        !           569:     match = NULL;
        !           570:     tq_foreach_rev(&userspecs, us) {
        !           571:        if (userlist_matches(pw, &us->users) != ALLOW)
        !           572:            continue;
        !           573: 
        !           574:        tq_foreach_rev(&us->privileges, priv) {
        !           575:            host_match = hostlist_matches(&priv->hostlist);
        !           576:            if (host_match != ALLOW)
        !           577:                continue;
        !           578:            tq_foreach_rev(&priv->cmndlist, cs) {
        !           579:                runas_match = runaslist_matches(&cs->runasuserlist,
        !           580:                    &cs->runasgrouplist);
        !           581:                if (runas_match == ALLOW) {
        !           582:                    cmnd_match = cmnd_matches(cs->cmnd);
        !           583:                    if (cmnd_match != UNSPEC) {
        !           584:                        match = host_match && runas_match ? cs->cmnd : NULL;
        !           585:                        goto matched;
        !           586:                    }
        !           587:                }
        !           588:            }
        !           589:        }
        !           590:     }
        !           591:     matched:
        !           592:     if (match != NULL && !match->negated) {
        !           593:        sudo_printf(SUDO_CONV_INFO_MSG, "%s%s%s\n",
        !           594:            safe_cmnd, user_args ? " " : "", user_args ? user_args : "");
        !           595:        rval = 0;
        !           596:     }
        !           597: done:
        !           598:     return rval;
        !           599: }
        !           600: 
        !           601: /*
        !           602:  * Print the contents of a struct member to stdout
        !           603:  */
        !           604: static void
        !           605: _print_member(struct lbuf *lbuf, char *name, int type, int negated,
        !           606:     int alias_type)
        !           607: {
        !           608:     struct alias *a;
        !           609:     struct member *m;
        !           610:     struct sudo_command *c;
        !           611: 
        !           612:     switch (type) {
        !           613:        case ALL:
        !           614:            lbuf_append(lbuf, "%sALL", negated ? "!" : "");
        !           615:            break;
        !           616:        case COMMAND:
        !           617:            c = (struct sudo_command *) name;
        !           618:            if (negated)
        !           619:                lbuf_append(lbuf, "!");
        !           620:            lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", c->cmnd);
        !           621:            if (c->args) {
        !           622:                lbuf_append(lbuf, " ");
        !           623:                lbuf_append_quoted(lbuf, SUDOERS_QUOTED, "%s", c->args);
        !           624:            }
        !           625:            break;
        !           626:        case ALIAS:
        !           627:            if ((a = alias_find(name, alias_type)) != NULL) {
        !           628:                tq_foreach_fwd(&a->members, m) {
        !           629:                    if (m != tq_first(&a->members))
        !           630:                        lbuf_append(lbuf, ", ");
        !           631:                    _print_member(lbuf, m->name, m->type,
        !           632:                        negated ? !m->negated : m->negated, alias_type);
        !           633:                }
        !           634:                break;
        !           635:            }
        !           636:            /* FALLTHROUGH */
        !           637:        default:
        !           638:            lbuf_append(lbuf, "%s%s", negated ? "!" : "", name);
        !           639:            break;
        !           640:     }
        !           641: }
        !           642: 
        !           643: static void
        !           644: print_member(struct lbuf *lbuf, char *name, int type, int negated,
        !           645:     int alias_type)
        !           646: {
        !           647:     alias_seqno++;
        !           648:     _print_member(lbuf, name, type, negated, alias_type);
        !           649: }

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