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>