File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / parse.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:26:49 2012 UTC (12 years, 2 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_5p1, HEAD
sudo 1.8.5p1

    1: /*
    2:  * Copyright (c) 2004-2005, 2007-2012 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;
   74: extern bool parse_error;
   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: {
   85:     debug_decl(sudo_file_open, SUDO_DEBUG_NSS)
   86: 
   87:     if (def_ignore_local_sudoers)
   88: 	debug_return_int(-1);
   89:     nss->handle = open_sudoers(sudoers_file, false, NULL);
   90:     debug_return_int(nss->handle ? 0 : -1);
   91: }
   92: 
   93: int
   94: sudo_file_close(struct sudo_nss *nss)
   95: {
   96:     debug_decl(sudo_file_close, SUDO_DEBUG_NSS)
   97: 
   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:     }
  105:     debug_return_int(0);
  106: }
  107: 
  108: /*
  109:  * Parse the specified sudoers file.
  110:  */
  111: int
  112: sudo_file_parse(struct sudo_nss *nss)
  113: {
  114:     debug_decl(sudo_file_close, SUDO_DEBUG_NSS)
  115: 
  116:     if (nss->handle == NULL)
  117: 	debug_return_int(-1);
  118: 
  119:     init_parser(sudoers_file, 0);
  120:     yyin = nss->handle;
  121:     if (yyparse() != 0 || parse_error) {
  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);
  129:     }
  130:     debug_return_int(0);
  131: }
  132: 
  133: /*
  134:  * Wrapper around update_defaults() for nsswitch code.
  135:  */
  136: int
  137: sudo_file_setdefs(struct sudo_nss *nss)
  138: {
  139:     debug_decl(sudo_file_setdefs, SUDO_DEBUG_NSS)
  140: 
  141:     if (nss->handle == NULL)
  142: 	debug_return_int(-1);
  143: 
  144:     if (!update_defaults(SETDEF_GENERIC|SETDEF_HOST|SETDEF_USER))
  145: 	debug_return_int(-1);
  146:     debug_return_int(0);
  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;
  161:     debug_decl(sudo_file_lookup, SUDO_DEBUG_NSS)
  162: 
  163:     if (nss->handle == NULL)
  164: 	debug_return_int(validated);
  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;
  176: 	nopass = (pwcheck == all) ? true : false;
  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;
  195: 		    if ((pwcheck == any && cs->tags.nopasswd == true) ||
  196: 			(pwcheck == all && cs->tags.nopasswd != true))
  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);
  208: 	else if (pwcheck == never || nopass == true)
  209: 	    def_authenticate = false;
  210: 	debug_return_int(validated);
  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();
  271:     debug_return_int(validated);
  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;
  282:     debug_decl(sudo_file_append_cmnd, SUDO_DEBUG_NSS)
  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);
  313:     debug_return;
  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;
  325:     debug_decl(sudo_file_display_priv_short, SUDO_DEBUG_NSS)
  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:     }
  367:     debug_return_int(nfound);
  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;
  379:     debug_decl(sudo_file_display_priv_long, SUDO_DEBUG_NSS)
  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:     }
  421:     debug_return_int(nfound);
  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;
  430:     debug_decl(sudo_file_display_priv, SUDO_DEBUG_NSS)
  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:
  445:     debug_return_int(nfound);
  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;
  458:     debug_decl(sudo_file_display_defaults, SUDO_DEBUG_NSS)
  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,
  493: 		d->op == false ? "!" : "", d->var);
  494: 	prefix = ", ";
  495: 	nfound++;
  496:     }
  497: done:
  498:     debug_return_int(nfound);
  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;
  509:     debug_decl(sudo_file_display_bound_defaults, SUDO_DEBUG_NSS)
  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: 
  515:     debug_return_int(nfound);
  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;
  528:     debug_decl(display_bound_defaults, SUDO_DEBUG_NSS)
  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:
  548: 	    debug_return_int(-1);
  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
  572: 	    lbuf_append(lbuf, "%s%s", d->op == false ? "!" : "", d->var);
  573:     }
  574: 
  575:     debug_return_int(nfound);
  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;
  587:     debug_decl(sudo_file_display_cmnd, SUDO_DEBUG_NSS)
  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:
  621:     debug_return_int(rval);
  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;
  634:     debug_decl(_print_member, SUDO_DEBUG_NSS)
  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:     }
  665:     debug_return;
  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>