[BACK]Return to gram.y CVS log [TXT][DIR] Up to [local] / src / usr.bin / sudo

Annotation of src/usr.bin/sudo/gram.y, Revision 1.3

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