Annotation of embedaddon/sudo/plugins/sudoers/gram.y, revision 1.1.1.3

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>