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

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

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