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