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

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

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