[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.24

1.1       millert     1: /*
1.24    ! millert     2:  * Copyright (c) 2004-2005, 2007-2009 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.24    ! millert    52: __unused static const char rcsid[] = "$Sudo: parse.c,v 1.242 2009/05/25 12:02:41 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);
1.24    ! millert    92:     nss->handle = open_sudoers(_PATH_SUDOERS, FALSE, NULL);
1.20      millert    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:                }
1.24    ! millert   331:            } else if (tq_empty(&cs->runasgrouplist)) {
        !           332:                lbuf_append(lbuf, def_runas_default, NULL);
1.20      millert   333:            } else {
1.24    ! millert   334:                lbuf_append(lbuf, pw->pw_name, NULL);
1.20      millert   335:            }
                    336:            if (!tq_empty(&cs->runasgrouplist)) {
                    337:                lbuf_append(lbuf, " : ", NULL);
                    338:                tq_foreach_fwd(&cs->runasgrouplist, m) {
                    339:                    if (m != tq_first(&cs->runasgrouplist))
                    340:                        lbuf_append(lbuf, ", ", NULL);
                    341:                    print_member(lbuf, m->name, m->type, m->negated,
                    342:                        RUNASALIAS);
                    343:                }
1.1       millert   344:            }
1.20      millert   345:            lbuf_append(lbuf, ") ", NULL);
                    346:            sudo_file_append_cmnd(cs, &tags, lbuf);
                    347:            nfound++;
1.1       millert   348:        }
1.20      millert   349:        lbuf_print(lbuf);               /* forces a newline */
1.1       millert   350:     }
1.20      millert   351:     return(nfound);
1.1       millert   352: }
                    353:
1.15      millert   354: static int
1.20      millert   355: sudo_file_display_priv_long(pw, us, lbuf)
                    356:     struct passwd *pw;
                    357:     struct userspec *us;
                    358:     struct lbuf *lbuf;
1.1       millert   359: {
1.20      millert   360:     struct cmndspec *cs;
                    361:     struct member *m;
                    362:     struct privilege *priv;
                    363:     struct cmndtag tags;
                    364:     int nfound = 0;
                    365:
                    366:     tq_foreach_fwd(&us->privileges, priv) {
                    367:        tags.noexec = UNSPEC;
                    368:        tags.setenv = UNSPEC;
                    369:        tags.nopasswd = UNSPEC;
                    370:        lbuf_print(lbuf);       /* force a newline */
                    371:        lbuf_append(lbuf, "Sudoers entry:", NULL);
                    372:        lbuf_print(lbuf);
                    373:        tq_foreach_fwd(&priv->cmndlist, cs) {
                    374:            lbuf_append(lbuf, "    RunAsUsers: ", NULL);
                    375:            if (!tq_empty(&cs->runasuserlist)) {
                    376:                tq_foreach_fwd(&cs->runasuserlist, m) {
                    377:                    if (m != tq_first(&cs->runasuserlist))
                    378:                        lbuf_append(lbuf, ", ", NULL);
                    379:                    print_member(lbuf, m->name, m->type, m->negated,
                    380:                        RUNASALIAS);
                    381:                }
1.24    ! millert   382:            } else if (tq_empty(&cs->runasgrouplist)) {
        !           383:                lbuf_append(lbuf, def_runas_default, NULL);
1.20      millert   384:            } else {
1.24    ! millert   385:                lbuf_append(lbuf, pw->pw_name, NULL);
1.20      millert   386:            }
                    387:            lbuf_print(lbuf);
                    388:            if (!tq_empty(&cs->runasgrouplist)) {
                    389:                lbuf_append(lbuf, "    RunAsGroups: ", NULL);
                    390:                tq_foreach_fwd(&cs->runasgrouplist, m) {
                    391:                    if (m != tq_first(&cs->runasgrouplist))
                    392:                        lbuf_append(lbuf, ", ", NULL);
                    393:                    print_member(lbuf, m->name, m->type, m->negated,
                    394:                        RUNASALIAS);
1.15      millert   395:                }
1.20      millert   396:                lbuf_print(lbuf);
                    397:            }
                    398:            lbuf_append(lbuf, "    Commands: ", NULL);
                    399:            lbuf_print(lbuf);
                    400:            lbuf_append(lbuf, "\t", NULL);
                    401:            sudo_file_append_cmnd(cs, &tags, lbuf);
                    402:            lbuf_print(lbuf);
                    403:            nfound++;
1.15      millert   404:        }
                    405:     }
1.20      millert   406:     return(nfound);
1.15      millert   407: }
                    408:
1.20      millert   409: int
                    410: sudo_file_display_privs(nss, pw, lbuf)
                    411:     struct sudo_nss *nss;
                    412:     struct passwd *pw;
                    413:     struct lbuf *lbuf;
                    414: {
                    415:     struct userspec *us;
                    416:     int nfound = 0;
1.15      millert   417:
1.20      millert   418:     if (nss->handle == NULL)
                    419:        return(-1);
1.1       millert   420:
1.20      millert   421:     tq_foreach_fwd(&userspecs, us) {
                    422:        /* XXX - why only check the first privilege here? */
                    423:        if (userlist_matches(pw, &us->users) != ALLOW ||
                    424:            hostlist_matches(&us->privileges.first->hostlist) != ALLOW)
1.15      millert   425:            continue;
1.20      millert   426:
                    427:        if (long_list)
                    428:            nfound += sudo_file_display_priv_long(pw, us, lbuf);
                    429:        else
                    430:            nfound += sudo_file_display_priv_short(pw, us, lbuf);
1.1       millert   431:     }
1.20      millert   432:     return(nfound);
1.15      millert   433: }
                    434:
                    435: /*
1.20      millert   436:  * Display matching Defaults entries for the given user on this host.
1.15      millert   437:  */
                    438: int
1.20      millert   439: sudo_file_display_defaults(nss, pw, lbuf)
                    440:     struct sudo_nss *nss;
                    441:     struct passwd *pw;
                    442:     struct lbuf *lbuf;
1.15      millert   443: {
1.20      millert   444:     struct defaults *d;
                    445:     char *prefix = NULL;
                    446:     int nfound = 0;
1.15      millert   447:
1.20      millert   448:     if (nss->handle == NULL)
                    449:        return(-1);
1.15      millert   450:
1.20      millert   451:     if (lbuf->len == 0)
                    452:        prefix = "    ";
                    453:     else
                    454:        prefix = ", ";
1.1       millert   455:
1.20      millert   456:     tq_foreach_fwd(&defaults, d) {
                    457:        switch (d->type) {
                    458:            case DEFAULTS_HOST:
                    459:                if (hostlist_matches(&d->binding) != ALLOW)
                    460:                    continue;
                    461:                break;
                    462:            case DEFAULTS_USER:
                    463:                if (userlist_matches(pw, &d->binding) != ALLOW)
                    464:                    continue;
                    465:                break;
                    466:            case DEFAULTS_RUNAS:
                    467:            case DEFAULTS_CMND:
                    468:                continue;
                    469:        }
                    470:        lbuf_append(lbuf, prefix, NULL);
                    471:        if (d->val != NULL) {
                    472:            lbuf_append(lbuf, d->var, d->op == '+' ? "+=" :
                    473:                d->op == '-' ? "-=" : "=", NULL);
                    474:            if (strpbrk(d->val, " \t") != NULL) {
                    475:                lbuf_append(lbuf, "\"", NULL);
                    476:                lbuf_append_quoted(lbuf, "\"", d->val, NULL);
                    477:                lbuf_append(lbuf, "\"", NULL);
                    478:            } else
                    479:                lbuf_append_quoted(lbuf, SUDOERS_QUOTED, d->val, NULL);
                    480:        } else
                    481:            lbuf_append(lbuf, d->op == FALSE ? "!" : "", d->var, NULL);
                    482:        prefix = ", ";
                    483:        nfound++;
1.4       millert   484:     }
1.20      millert   485:
                    486:     return(nfound);
1.4       millert   487: }
                    488:
                    489: /*
1.20      millert   490:  * Display Defaults entries that are per-runas or per-command
1.12      millert   491:  */
                    492: int
1.20      millert   493: sudo_file_display_bound_defaults(nss, pw, lbuf)
                    494:     struct sudo_nss *nss;
1.12      millert   495:     struct passwd *pw;
1.20      millert   496:     struct lbuf *lbuf;
1.12      millert   497: {
1.20      millert   498:     int nfound = 0;
                    499:
                    500:     /* XXX - should only print ones that match what the user can do. */
                    501:     nfound += display_bound_defaults(DEFAULTS_RUNAS, lbuf);
                    502:     nfound += display_bound_defaults(DEFAULTS_CMND, lbuf);
                    503:
                    504:     return(nfound);
1.12      millert   505: }
                    506:
                    507: /*
1.20      millert   508:  * Display Defaults entries of the given type.
1.1       millert   509:  */
1.20      millert   510: static int
                    511: display_bound_defaults(dtype, lbuf)
                    512:     int dtype;
                    513:     struct lbuf *lbuf;
1.1       millert   514: {
1.20      millert   515:     struct defaults *d;
                    516:     struct member *m, *binding = NULL;
                    517:     char *dname, *dsep;
                    518:     int atype, nfound = 0;
                    519:
                    520:     switch (dtype) {
                    521:        case DEFAULTS_HOST:
                    522:            atype = HOSTALIAS;
                    523:            dname = "host";
                    524:            dsep = "@";
                    525:            break;
                    526:        case DEFAULTS_USER:
                    527:            atype = USERALIAS;
                    528:            dname = "user";
                    529:            dsep = ":";
                    530:            break;
                    531:        case DEFAULTS_RUNAS:
                    532:            atype = RUNASALIAS;
                    533:            dname = "runas";
                    534:            dsep = ">";
                    535:            break;
                    536:        case DEFAULTS_CMND:
                    537:            atype = CMNDALIAS;
                    538:            dname = "cmnd";
                    539:            dsep = "!";
                    540:            break;
                    541:        default:
                    542:            return(-1);
                    543:     }
                    544:     /* printf("Per-%s Defaults entries:\n", dname); */
                    545:     tq_foreach_fwd(&defaults, d) {
                    546:        if (d->type != dtype)
                    547:            continue;
1.1       millert   548:
1.20      millert   549:        nfound++;
                    550:        if (binding != tq_first(&d->binding)) {
                    551:            binding = tq_first(&d->binding);
                    552:            lbuf_append(lbuf, "    Defaults", dsep, NULL);
                    553:            for (m = binding; m != NULL; m = m->next) {
                    554:                if (m != binding)
                    555:                    lbuf_append(lbuf, ",", NULL);
                    556:                print_member(lbuf, m->name, m->type, m->negated, atype);
                    557:                lbuf_append(lbuf, " ", NULL);
                    558:            }
                    559:        } else
                    560:            lbuf_append(lbuf, ", ", NULL);
                    561:        if (d->val != NULL) {
                    562:            lbuf_append(lbuf, d->var, d->op == '+' ? "+=" :
                    563:                d->op == '-' ? "-=" : "=", d->val, NULL);
                    564:        } else
                    565:            lbuf_append(lbuf, d->op == FALSE ? "!" : "", d->var, NULL);
1.13      millert   566:     }
1.1       millert   567:
1.20      millert   568:     return(nfound);
1.1       millert   569: }
                    570:
                    571: int
1.20      millert   572: sudo_file_display_cmnd(nss, pw)
                    573:     struct sudo_nss *nss;
                    574:     struct passwd *pw;
                    575: {
                    576:     struct cmndspec *cs;
                    577:     struct member *match;
                    578:     struct privilege *priv;
                    579:     struct userspec *us;
                    580:     int rval = 1;
                    581:     int host_match, runas_match, cmnd_match;
                    582:
                    583:     if (nss->handle == NULL)
                    584:        return(rval);
                    585:
                    586:     match = NULL;
                    587:     tq_foreach_rev(&userspecs, us) {
                    588:        if (userlist_matches(pw, &us->users) != ALLOW)
                    589:            continue;
                    590:
                    591:        tq_foreach_rev(&us->privileges, priv) {
                    592:            host_match = hostlist_matches(&priv->hostlist);
                    593:            if (host_match != ALLOW)
                    594:                continue;
                    595:            tq_foreach_rev(&priv->cmndlist, cs) {
                    596:                runas_match = runaslist_matches(&cs->runasuserlist,
                    597:                    &cs->runasgrouplist);
                    598:                if (runas_match == ALLOW) {
                    599:                    cmnd_match = cmnd_matches(cs->cmnd);
                    600:                    if (cmnd_match != UNSPEC) {
                    601:                        match = host_match && runas_match ?
                    602:                            cs->cmnd : NULL;
                    603:                        goto matched;
                    604:                    }
                    605:                }
                    606:            }
1.1       millert   607:        }
                    608:     }
1.20      millert   609:     matched:
                    610:     if (match != NULL && !match->negated) {
                    611:        printf("%s%s%s\n", safe_cmnd, user_args ? " " : "",
                    612:            user_args ? user_args : "");
                    613:        rval = 0;
                    614:     }
                    615:     return(rval);
1.1       millert   616: }
                    617:
                    618: /*
1.20      millert   619:  * Print the contents of a struct member to stdout
1.1       millert   620:  */
1.20      millert   621: static void
                    622: _print_member(lbuf, name, type, negated, alias_type)
                    623:     struct lbuf *lbuf;
                    624:     char *name;
                    625:     int type, negated, alias_type;
1.1       millert   626: {
1.20      millert   627:     struct alias *a;
                    628:     struct member *m;
                    629:     struct sudo_command *c;
                    630:
                    631:     switch (type) {
                    632:        case ALL:
                    633:            lbuf_append(lbuf, negated ? "!ALL" : "ALL", NULL);
                    634:            break;
                    635:        case COMMAND:
                    636:            c = (struct sudo_command *) name;
                    637:            if (negated)
                    638:                lbuf_append(lbuf, "!", NULL);
                    639:            lbuf_append_quoted(lbuf, SUDOERS_QUOTED, c->cmnd, NULL);
                    640:            if (c->args) {
                    641:                lbuf_append(lbuf, " ", NULL);
                    642:                lbuf_append_quoted(lbuf, SUDOERS_QUOTED, c->args, NULL);
                    643:            }
                    644:            break;
                    645:        case ALIAS:
1.23      millert   646:            if ((a = alias_find(name, alias_type)) != NULL) {
1.20      millert   647:                tq_foreach_fwd(&a->members, m) {
                    648:                    if (m != tq_first(&a->members))
                    649:                        lbuf_append(lbuf, ", ", NULL);
                    650:                    _print_member(lbuf, m->name, m->type,
                    651:                        negated ? !m->negated : m->negated, alias_type);
                    652:                }
                    653:                break;
                    654:            }
                    655:            /* FALLTHROUGH */
                    656:        default:
                    657:            lbuf_append(lbuf, negated ? "!" : "", name, NULL);
                    658:            break;
1.1       millert   659:     }
1.20      millert   660: }
                    661:
                    662: static void
                    663: print_member(lbuf, name, type, negated, alias_type)
                    664:     struct lbuf *lbuf;
                    665:     char *name;
                    666:     int type, negated, alias_type;
                    667: {
                    668:     alias_seqno++;
                    669:     _print_member(lbuf, name, type, negated, alias_type);
1.1       millert   670: }