Return to gram.y CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers |
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: }