Annotation of embedaddon/sudo/plugins/sudoers/gram.y, revision 1.1
1.1 ! misho 1: %{
! 2: /*
! 3: * Copyright (c) 1996, 1998-2005, 2007-2011
! 4: * Todd C. Miller <Todd.Miller@courtesan.com>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 18: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 19: *
! 20: * Sponsored in part by the Defense Advanced Research Projects
! 21: * Agency (DARPA) and Air Force Research Laboratory, Air Force
! 22: * Materiel Command, USAF, under agreement number F39502-99-1-0512.
! 23: */
! 24:
! 25: #include <config.h>
! 26:
! 27: #include <sys/types.h>
! 28: #include <sys/param.h>
! 29: #include <stdio.h>
! 30: #ifdef STDC_HEADERS
! 31: # include <stdlib.h>
! 32: # include <stddef.h>
! 33: #else
! 34: # ifdef HAVE_STDLIB_H
! 35: # include <stdlib.h>
! 36: # endif
! 37: #endif /* STDC_HEADERS */
! 38: #ifdef HAVE_STRING_H
! 39: # include <string.h>
! 40: #endif /* HAVE_STRING_H */
! 41: #ifdef HAVE_STRINGS_H
! 42: # include <strings.h>
! 43: #endif /* HAVE_STRINGS_H */
! 44: #ifdef HAVE_UNISTD_H
! 45: # include <unistd.h>
! 46: #endif /* HAVE_UNISTD_H */
! 47: #if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
! 48: # include <alloca.h>
! 49: #endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */
! 50: #include <limits.h>
! 51:
! 52: #include "sudoers.h" /* XXX */
! 53: #include "parse.h"
! 54: #include "toke.h"
! 55:
! 56: /*
! 57: * We must define SIZE_MAX for yacc's skeleton.c.
! 58: * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t
! 59: * could be signed (as it is on SunOS 4.x).
! 60: */
! 61: #ifndef SIZE_MAX
! 62: # ifdef SIZE_T_MAX
! 63: # define SIZE_MAX SIZE_T_MAX
! 64: # else
! 65: # define SIZE_MAX INT_MAX
! 66: # endif /* SIZE_T_MAX */
! 67: #endif /* SIZE_MAX */
! 68:
! 69: /*
! 70: * Globals
! 71: */
! 72: extern int sudolineno;
! 73: extern char *sudoers;
! 74: static int verbose = FALSE;
! 75: int parse_error = FALSE;
! 76: int pedantic = FALSE;
! 77: int errorlineno = -1;
! 78: char *errorfile = NULL;
! 79:
! 80: struct defaults_list defaults;
! 81: struct userspec_list userspecs;
! 82:
! 83: /*
! 84: * Local protoypes
! 85: */
! 86: static void add_defaults(int, struct member *, struct defaults *);
! 87: static void add_userspec(struct member *, struct privilege *);
! 88: static struct defaults *new_default(char *, char *, int);
! 89: static struct member *new_member(char *, int);
! 90: void yyerror(const char *);
! 91:
! 92: void
! 93: yyerror(const char *s)
! 94: {
! 95: /* Save the line the first error occurred on. */
! 96: if (errorlineno == -1) {
! 97: errorlineno = sudolineno ? sudolineno - 1 : 0;
! 98: errorfile = estrdup(sudoers);
! 99: }
! 100: if (trace_print != NULL) {
! 101: LEXTRACE("<*> ");
! 102: } else if (verbose && s != NULL) {
! 103: warningx(_(">>> %s: %s near line %d <<<"), sudoers, s,
! 104: sudolineno ? sudolineno - 1 : 0);
! 105: }
! 106: parse_error = TRUE;
! 107: }
! 108: %}
! 109:
! 110: %union {
! 111: struct cmndspec *cmndspec;
! 112: struct defaults *defaults;
! 113: struct member *member;
! 114: struct runascontainer *runas;
! 115: struct privilege *privilege;
! 116: struct sudo_command command;
! 117: struct cmndtag tag;
! 118: struct selinux_info seinfo;
! 119: char *string;
! 120: int tok;
! 121: }
! 122:
! 123: %start file /* special start symbol */
! 124: %token <command> COMMAND /* absolute pathname w/ optional args */
! 125: %token <string> ALIAS /* an UPPERCASE alias name */
! 126: %token <string> DEFVAR /* a Defaults variable name */
! 127: %token <string> NTWKADDR /* ipv4 or ipv6 address */
! 128: %token <string> NETGROUP /* a netgroup (+NAME) */
! 129: %token <string> USERGROUP /* a usergroup (%NAME) */
! 130: %token <string> WORD /* a word */
! 131: %token <tok> DEFAULTS /* Defaults entry */
! 132: %token <tok> DEFAULTS_HOST /* Host-specific defaults entry */
! 133: %token <tok> DEFAULTS_USER /* User-specific defaults entry */
! 134: %token <tok> DEFAULTS_RUNAS /* Runas-specific defaults entry */
! 135: %token <tok> DEFAULTS_CMND /* Command-specific defaults entry */
! 136: %token <tok> NOPASSWD /* no passwd req for command */
! 137: %token <tok> PASSWD /* passwd req for command (default) */
! 138: %token <tok> NOEXEC /* preload dummy execve() for cmnd */
! 139: %token <tok> EXEC /* don't preload dummy execve() */
! 140: %token <tok> SETENV /* user may set environment for cmnd */
! 141: %token <tok> NOSETENV /* user may not set environment */
! 142: %token <tok> LOG_INPUT /* log user's cmnd input */
! 143: %token <tok> NOLOG_INPUT /* don't log user's cmnd input */
! 144: %token <tok> LOG_OUTPUT /* log cmnd output */
! 145: %token <tok> NOLOG_OUTPUT /* don't log cmnd output */
! 146: %token <tok> ALL /* ALL keyword */
! 147: %token <tok> COMMENT /* comment and/or carriage return */
! 148: %token <tok> HOSTALIAS /* Host_Alias keyword */
! 149: %token <tok> CMNDALIAS /* Cmnd_Alias keyword */
! 150: %token <tok> USERALIAS /* User_Alias keyword */
! 151: %token <tok> RUNASALIAS /* Runas_Alias keyword */
! 152: %token <tok> ':' '=' ',' '!' '+' '-' /* union member tokens */
! 153: %token <tok> '(' ')' /* runas tokens */
! 154: %token <tok> ERROR
! 155: %token <tok> TYPE /* SELinux type */
! 156: %token <tok> ROLE /* SELinux role */
! 157:
! 158: %type <cmndspec> cmndspec
! 159: %type <cmndspec> cmndspeclist
! 160: %type <defaults> defaults_entry
! 161: %type <defaults> defaults_list
! 162: %type <member> cmnd
! 163: %type <member> opcmnd
! 164: %type <member> cmndlist
! 165: %type <member> host
! 166: %type <member> hostlist
! 167: %type <member> ophost
! 168: %type <member> opuser
! 169: %type <member> user
! 170: %type <member> userlist
! 171: %type <member> opgroup
! 172: %type <member> group
! 173: %type <member> grouplist
! 174: %type <runas> runasspec
! 175: %type <runas> runaslist
! 176: %type <privilege> privilege
! 177: %type <privilege> privileges
! 178: %type <tag> cmndtag
! 179: %type <seinfo> selinux
! 180: %type <string> rolespec
! 181: %type <string> typespec
! 182:
! 183: %%
! 184:
! 185: file : { ; }
! 186: | line
! 187: ;
! 188:
! 189: line : entry
! 190: | line entry
! 191: ;
! 192:
! 193: entry : COMMENT {
! 194: ;
! 195: }
! 196: | error COMMENT {
! 197: yyerrok;
! 198: }
! 199: | userlist privileges {
! 200: add_userspec($1, $2);
! 201: }
! 202: | USERALIAS useraliases {
! 203: ;
! 204: }
! 205: | HOSTALIAS hostaliases {
! 206: ;
! 207: }
! 208: | CMNDALIAS cmndaliases {
! 209: ;
! 210: }
! 211: | RUNASALIAS runasaliases {
! 212: ;
! 213: }
! 214: | DEFAULTS defaults_list {
! 215: add_defaults(DEFAULTS, NULL, $2);
! 216: }
! 217: | DEFAULTS_USER userlist defaults_list {
! 218: add_defaults(DEFAULTS_USER, $2, $3);
! 219: }
! 220: | DEFAULTS_RUNAS userlist defaults_list {
! 221: add_defaults(DEFAULTS_RUNAS, $2, $3);
! 222: }
! 223: | DEFAULTS_HOST hostlist defaults_list {
! 224: add_defaults(DEFAULTS_HOST, $2, $3);
! 225: }
! 226: | DEFAULTS_CMND cmndlist defaults_list {
! 227: add_defaults(DEFAULTS_CMND, $2, $3);
! 228: }
! 229: ;
! 230:
! 231: defaults_list : defaults_entry
! 232: | defaults_list ',' defaults_entry {
! 233: list_append($1, $3);
! 234: $$ = $1;
! 235: }
! 236: ;
! 237:
! 238: defaults_entry : DEFVAR {
! 239: $$ = new_default($1, NULL, TRUE);
! 240: }
! 241: | '!' DEFVAR {
! 242: $$ = new_default($2, NULL, FALSE);
! 243: }
! 244: | DEFVAR '=' WORD {
! 245: $$ = new_default($1, $3, TRUE);
! 246: }
! 247: | DEFVAR '+' WORD {
! 248: $$ = new_default($1, $3, '+');
! 249: }
! 250: | DEFVAR '-' WORD {
! 251: $$ = new_default($1, $3, '-');
! 252: }
! 253: ;
! 254:
! 255: privileges : privilege
! 256: | privileges ':' privilege {
! 257: list_append($1, $3);
! 258: $$ = $1;
! 259: }
! 260: ;
! 261:
! 262: privilege : hostlist '=' cmndspeclist {
! 263: struct privilege *p = emalloc(sizeof(*p));
! 264: list2tq(&p->hostlist, $1);
! 265: list2tq(&p->cmndlist, $3);
! 266: p->prev = p;
! 267: p->next = NULL;
! 268: $$ = p;
! 269: }
! 270: ;
! 271:
! 272: ophost : host {
! 273: $$ = $1;
! 274: $$->negated = FALSE;
! 275: }
! 276: | '!' host {
! 277: $$ = $2;
! 278: $$->negated = TRUE;
! 279: }
! 280: ;
! 281:
! 282: host : ALIAS {
! 283: $$ = new_member($1, ALIAS);
! 284: }
! 285: | ALL {
! 286: $$ = new_member(NULL, ALL);
! 287: }
! 288: | NETGROUP {
! 289: $$ = new_member($1, NETGROUP);
! 290: }
! 291: | NTWKADDR {
! 292: $$ = new_member($1, NTWKADDR);
! 293: }
! 294: | WORD {
! 295: $$ = new_member($1, WORD);
! 296: }
! 297: ;
! 298:
! 299: cmndspeclist : cmndspec
! 300: | cmndspeclist ',' cmndspec {
! 301: list_append($1, $3);
! 302: #ifdef HAVE_SELINUX
! 303: /* propagate role and type */
! 304: if ($3->role == NULL)
! 305: $3->role = $3->prev->role;
! 306: if ($3->type == NULL)
! 307: $3->type = $3->prev->type;
! 308: #endif /* HAVE_SELINUX */
! 309: /* propagate tags and runas list */
! 310: if ($3->tags.nopasswd == UNSPEC)
! 311: $3->tags.nopasswd = $3->prev->tags.nopasswd;
! 312: if ($3->tags.noexec == UNSPEC)
! 313: $3->tags.noexec = $3->prev->tags.noexec;
! 314: if ($3->tags.setenv == UNSPEC &&
! 315: $3->prev->tags.setenv != IMPLIED)
! 316: $3->tags.setenv = $3->prev->tags.setenv;
! 317: if ($3->tags.log_input == UNSPEC)
! 318: $3->tags.log_input = $3->prev->tags.log_input;
! 319: if ($3->tags.log_output == UNSPEC)
! 320: $3->tags.log_output = $3->prev->tags.log_output;
! 321: if ((tq_empty(&$3->runasuserlist) &&
! 322: tq_empty(&$3->runasgrouplist)) &&
! 323: (!tq_empty(&$3->prev->runasuserlist) ||
! 324: !tq_empty(&$3->prev->runasgrouplist))) {
! 325: $3->runasuserlist = $3->prev->runasuserlist;
! 326: $3->runasgrouplist = $3->prev->runasgrouplist;
! 327: }
! 328: $$ = $1;
! 329: }
! 330: ;
! 331:
! 332: cmndspec : runasspec selinux cmndtag opcmnd {
! 333: struct cmndspec *cs = emalloc(sizeof(*cs));
! 334: if ($1 != NULL) {
! 335: list2tq(&cs->runasuserlist, $1->runasusers);
! 336: list2tq(&cs->runasgrouplist, $1->runasgroups);
! 337: efree($1);
! 338: } else {
! 339: tq_init(&cs->runasuserlist);
! 340: tq_init(&cs->runasgrouplist);
! 341: }
! 342: #ifdef HAVE_SELINUX
! 343: cs->role = $2.role;
! 344: cs->type = $2.type;
! 345: #endif
! 346: cs->tags = $3;
! 347: cs->cmnd = $4;
! 348: cs->prev = cs;
! 349: cs->next = NULL;
! 350: /* sudo "ALL" implies the SETENV tag */
! 351: if (cs->cmnd->type == ALL && !cs->cmnd->negated &&
! 352: cs->tags.setenv == UNSPEC)
! 353: cs->tags.setenv = IMPLIED;
! 354: $$ = cs;
! 355: }
! 356: ;
! 357:
! 358: opcmnd : cmnd {
! 359: $$ = $1;
! 360: $$->negated = FALSE;
! 361: }
! 362: | '!' cmnd {
! 363: $$ = $2;
! 364: $$->negated = TRUE;
! 365: }
! 366: ;
! 367:
! 368: rolespec : ROLE '=' WORD {
! 369: $$ = $3;
! 370: }
! 371: ;
! 372:
! 373: typespec : TYPE '=' WORD {
! 374: $$ = $3;
! 375: }
! 376: ;
! 377:
! 378: selinux : /* empty */ {
! 379: $$.role = NULL;
! 380: $$.type = NULL;
! 381: }
! 382: | rolespec {
! 383: $$.role = $1;
! 384: $$.type = NULL;
! 385: }
! 386: | typespec {
! 387: $$.type = $1;
! 388: $$.role = NULL;
! 389: }
! 390: | rolespec typespec {
! 391: $$.role = $1;
! 392: $$.type = $2;
! 393: }
! 394: | typespec rolespec {
! 395: $$.type = $1;
! 396: $$.role = $2;
! 397: }
! 398: ;
! 399:
! 400: runasspec : /* empty */ {
! 401: $$ = NULL;
! 402: }
! 403: | '(' runaslist ')' {
! 404: $$ = $2;
! 405: }
! 406: ;
! 407:
! 408: runaslist : userlist {
! 409: $$ = emalloc(sizeof(struct runascontainer));
! 410: $$->runasusers = $1;
! 411: $$->runasgroups = NULL;
! 412: }
! 413: | userlist ':' grouplist {
! 414: $$ = emalloc(sizeof(struct runascontainer));
! 415: $$->runasusers = $1;
! 416: $$->runasgroups = $3;
! 417: }
! 418: | ':' grouplist {
! 419: $$ = emalloc(sizeof(struct runascontainer));
! 420: $$->runasusers = NULL;
! 421: $$->runasgroups = $2;
! 422: }
! 423: ;
! 424:
! 425: cmndtag : /* empty */ {
! 426: $$.nopasswd = $$.noexec = $$.setenv =
! 427: $$.log_input = $$.log_output = UNSPEC;
! 428: }
! 429: | cmndtag NOPASSWD {
! 430: $$.nopasswd = TRUE;
! 431: }
! 432: | cmndtag PASSWD {
! 433: $$.nopasswd = FALSE;
! 434: }
! 435: | cmndtag NOEXEC {
! 436: $$.noexec = TRUE;
! 437: }
! 438: | cmndtag EXEC {
! 439: $$.noexec = FALSE;
! 440: }
! 441: | cmndtag SETENV {
! 442: $$.setenv = TRUE;
! 443: }
! 444: | cmndtag NOSETENV {
! 445: $$.setenv = FALSE;
! 446: }
! 447: | cmndtag LOG_INPUT {
! 448: $$.log_input = TRUE;
! 449: }
! 450: | cmndtag NOLOG_INPUT {
! 451: $$.log_input = FALSE;
! 452: }
! 453: | cmndtag LOG_OUTPUT {
! 454: $$.log_output = TRUE;
! 455: }
! 456: | cmndtag NOLOG_OUTPUT {
! 457: $$.log_output = FALSE;
! 458: }
! 459: ;
! 460:
! 461: cmnd : ALL {
! 462: $$ = new_member(NULL, ALL);
! 463: }
! 464: | ALIAS {
! 465: $$ = new_member($1, ALIAS);
! 466: }
! 467: | COMMAND {
! 468: struct sudo_command *c = emalloc(sizeof(*c));
! 469: c->cmnd = $1.cmnd;
! 470: c->args = $1.args;
! 471: $$ = new_member((char *)c, COMMAND);
! 472: }
! 473: ;
! 474:
! 475: hostaliases : hostalias
! 476: | hostaliases ':' hostalias
! 477: ;
! 478:
! 479: hostalias : ALIAS '=' hostlist {
! 480: char *s;
! 481: if ((s = alias_add($1, HOSTALIAS, $3)) != NULL) {
! 482: yyerror(s);
! 483: YYERROR;
! 484: }
! 485: }
! 486: ;
! 487:
! 488: hostlist : ophost
! 489: | hostlist ',' ophost {
! 490: list_append($1, $3);
! 491: $$ = $1;
! 492: }
! 493: ;
! 494:
! 495: cmndaliases : cmndalias
! 496: | cmndaliases ':' cmndalias
! 497: ;
! 498:
! 499: cmndalias : ALIAS '=' cmndlist {
! 500: char *s;
! 501: if ((s = alias_add($1, CMNDALIAS, $3)) != NULL) {
! 502: yyerror(s);
! 503: YYERROR;
! 504: }
! 505: }
! 506: ;
! 507:
! 508: cmndlist : opcmnd
! 509: | cmndlist ',' opcmnd {
! 510: list_append($1, $3);
! 511: $$ = $1;
! 512: }
! 513: ;
! 514:
! 515: runasaliases : runasalias
! 516: | runasaliases ':' runasalias
! 517: ;
! 518:
! 519: runasalias : ALIAS '=' userlist {
! 520: char *s;
! 521: if ((s = alias_add($1, RUNASALIAS, $3)) != NULL) {
! 522: yyerror(s);
! 523: YYERROR;
! 524: }
! 525: }
! 526: ;
! 527:
! 528: useraliases : useralias
! 529: | useraliases ':' useralias
! 530: ;
! 531:
! 532: useralias : ALIAS '=' userlist {
! 533: char *s;
! 534: if ((s = alias_add($1, USERALIAS, $3)) != NULL) {
! 535: yyerror(s);
! 536: YYERROR;
! 537: }
! 538: }
! 539: ;
! 540:
! 541: userlist : opuser
! 542: | userlist ',' opuser {
! 543: list_append($1, $3);
! 544: $$ = $1;
! 545: }
! 546: ;
! 547:
! 548: opuser : user {
! 549: $$ = $1;
! 550: $$->negated = FALSE;
! 551: }
! 552: | '!' user {
! 553: $$ = $2;
! 554: $$->negated = TRUE;
! 555: }
! 556: ;
! 557:
! 558: user : ALIAS {
! 559: $$ = new_member($1, ALIAS);
! 560: }
! 561: | ALL {
! 562: $$ = new_member(NULL, ALL);
! 563: }
! 564: | NETGROUP {
! 565: $$ = new_member($1, NETGROUP);
! 566: }
! 567: | USERGROUP {
! 568: $$ = new_member($1, USERGROUP);
! 569: }
! 570: | WORD {
! 571: $$ = new_member($1, WORD);
! 572: }
! 573: ;
! 574:
! 575: grouplist : opgroup
! 576: | grouplist ',' opgroup {
! 577: list_append($1, $3);
! 578: $$ = $1;
! 579: }
! 580: ;
! 581:
! 582: opgroup : group {
! 583: $$ = $1;
! 584: $$->negated = FALSE;
! 585: }
! 586: | '!' group {
! 587: $$ = $2;
! 588: $$->negated = TRUE;
! 589: }
! 590: ;
! 591:
! 592: group : ALIAS {
! 593: $$ = new_member($1, ALIAS);
! 594: }
! 595: | ALL {
! 596: $$ = new_member(NULL, ALL);
! 597: }
! 598: | WORD {
! 599: $$ = new_member($1, WORD);
! 600: }
! 601: ;
! 602:
! 603: %%
! 604: static struct defaults *
! 605: new_default(char *var, char *val, int op)
! 606: {
! 607: struct defaults *d;
! 608:
! 609: d = emalloc(sizeof(struct defaults));
! 610: d->var = var;
! 611: d->val = val;
! 612: tq_init(&d->binding);
! 613: d->type = 0;
! 614: d->op = op;
! 615: d->prev = d;
! 616: d->next = NULL;
! 617:
! 618: return d;
! 619: }
! 620:
! 621: static struct member *
! 622: new_member(char *name, int type)
! 623: {
! 624: struct member *m;
! 625:
! 626: m = emalloc(sizeof(struct member));
! 627: m->name = name;
! 628: m->type = type;
! 629: m->prev = m;
! 630: m->next = NULL;
! 631:
! 632: return m;
! 633: }
! 634:
! 635: /*
! 636: * Add a list of defaults structures to the defaults list.
! 637: * The binding, if non-NULL, specifies a list of hosts, users, or
! 638: * runas users the entries apply to (specified by the type).
! 639: */
! 640: static void
! 641: add_defaults(int type, struct member *bmem, struct defaults *defs)
! 642: {
! 643: struct defaults *d;
! 644: struct member_list binding;
! 645:
! 646: /*
! 647: * We can only call list2tq once on bmem as it will zero
! 648: * out the prev pointer when it consumes bmem.
! 649: */
! 650: list2tq(&binding, bmem);
! 651:
! 652: /*
! 653: * Set type and binding (who it applies to) for new entries.
! 654: */
! 655: for (d = defs; d != NULL; d = d->next) {
! 656: d->type = type;
! 657: d->binding = binding;
! 658: }
! 659: tq_append(&defaults, defs);
! 660: }
! 661:
! 662: /*
! 663: * Allocate a new struct userspec, populate it, and insert it at the
! 664: * and of the userspecs list.
! 665: */
! 666: static void
! 667: add_userspec(struct member *members, struct privilege *privs)
! 668: {
! 669: struct userspec *u;
! 670:
! 671: u = emalloc(sizeof(*u));
! 672: list2tq(&u->users, members);
! 673: list2tq(&u->privileges, privs);
! 674: u->prev = u;
! 675: u->next = NULL;
! 676: tq_append(&userspecs, u);
! 677: }
! 678:
! 679: /*
! 680: * Free up space used by data structures from a previous parser run and sets
! 681: * the current sudoers file to path.
! 682: */
! 683: void
! 684: init_parser(const char *path, int quiet)
! 685: {
! 686: struct defaults *d;
! 687: struct member *m, *binding;
! 688: struct userspec *us;
! 689: struct privilege *priv;
! 690: struct cmndspec *cs;
! 691: struct sudo_command *c;
! 692:
! 693: while ((us = tq_pop(&userspecs)) != NULL) {
! 694: while ((m = tq_pop(&us->users)) != NULL) {
! 695: efree(m->name);
! 696: efree(m);
! 697: }
! 698: while ((priv = tq_pop(&us->privileges)) != NULL) {
! 699: struct member *runasuser = NULL, *runasgroup = NULL;
! 700: #ifdef HAVE_SELINUX
! 701: char *role = NULL, *type = NULL;
! 702: #endif /* HAVE_SELINUX */
! 703:
! 704: while ((m = tq_pop(&priv->hostlist)) != NULL) {
! 705: efree(m->name);
! 706: efree(m);
! 707: }
! 708: while ((cs = tq_pop(&priv->cmndlist)) != NULL) {
! 709: #ifdef HAVE_SELINUX
! 710: /* Only free the first instance of a role/type. */
! 711: if (cs->role != role) {
! 712: role = cs->role;
! 713: efree(cs->role);
! 714: }
! 715: if (cs->type != type) {
! 716: type = cs->type;
! 717: efree(cs->type);
! 718: }
! 719: #endif /* HAVE_SELINUX */
! 720: if (tq_last(&cs->runasuserlist) != runasuser) {
! 721: runasuser = tq_last(&cs->runasuserlist);
! 722: while ((m = tq_pop(&cs->runasuserlist)) != NULL) {
! 723: efree(m->name);
! 724: efree(m);
! 725: }
! 726: }
! 727: if (tq_last(&cs->runasgrouplist) != runasgroup) {
! 728: runasgroup = tq_last(&cs->runasgrouplist);
! 729: while ((m = tq_pop(&cs->runasgrouplist)) != NULL) {
! 730: efree(m->name);
! 731: efree(m);
! 732: }
! 733: }
! 734: if (cs->cmnd->type == COMMAND) {
! 735: c = (struct sudo_command *) cs->cmnd->name;
! 736: efree(c->cmnd);
! 737: efree(c->args);
! 738: }
! 739: efree(cs->cmnd->name);
! 740: efree(cs->cmnd);
! 741: efree(cs);
! 742: }
! 743: efree(priv);
! 744: }
! 745: efree(us);
! 746: }
! 747: tq_init(&userspecs);
! 748:
! 749: binding = NULL;
! 750: while ((d = tq_pop(&defaults)) != NULL) {
! 751: if (tq_last(&d->binding) != binding) {
! 752: binding = tq_last(&d->binding);
! 753: while ((m = tq_pop(&d->binding)) != NULL) {
! 754: if (m->type == COMMAND) {
! 755: c = (struct sudo_command *) m->name;
! 756: efree(c->cmnd);
! 757: efree(c->args);
! 758: }
! 759: efree(m->name);
! 760: efree(m);
! 761: }
! 762: }
! 763: efree(d->var);
! 764: efree(d->val);
! 765: efree(d);
! 766: }
! 767: tq_init(&defaults);
! 768:
! 769: init_aliases();
! 770:
! 771: init_lexer();
! 772:
! 773: efree(sudoers);
! 774: sudoers = path ? estrdup(path) : NULL;
! 775:
! 776: parse_error = FALSE;
! 777: errorlineno = -1;
! 778: errorfile = NULL;
! 779: verbose = !quiet;
! 780: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>