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