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

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

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