[BACK]Return to parse.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Annotation of src/usr.bin/sudo/parse.c, Revision 1.22

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