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

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

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