File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / gram.y
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:12:54 2014 UTC (10 years, 3 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_10p3_0, v1_8_10p3, HEAD
sudo v 1.8.10p3

    1: %{
    2: /*
    3:  * Copyright (c) 1996, 1998-2005, 2007-2013
    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 */
   46: #ifdef HAVE_INTTYPES_H
   47: # include <inttypes.h>
   48: #endif
   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: bool sudoers_warnings = true;
   75: bool parse_error = false;
   76: int errorlineno = -1;
   77: const char *errorfile = NULL;
   78: 
   79: struct defaults_list defaults = TAILQ_HEAD_INITIALIZER(defaults);
   80: struct userspec_list userspecs = TAILQ_HEAD_INITIALIZER(userspecs);
   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);
   89: static struct sudo_digest *new_digest(int, const char *);
   90: %}
   91: 
   92: %union {
   93:     struct cmndspec *cmndspec;
   94:     struct defaults *defaults;
   95:     struct member *member;
   96:     struct runascontainer *runas;
   97:     struct privilege *privilege;
   98:     struct sudo_digest *digest;
   99:     struct sudo_command command;
  100:     struct cmndtag tag;
  101:     struct selinux_info seinfo;
  102:     struct solaris_privs_info privinfo;
  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 */
  115: %token <string>  DIGEST			/* a SHA-2 digest */
  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 */
  142: %token <tok>	 PRIVS			/* Solaris privileges */
  143: %token <tok>	 LIMITPRIVS		/* Solaris limit privileges */
  144: %token <tok>	 MYSELF			/* run as myself, not another user */
  145: %token <tok>	 SHA224			/* sha224 digest */
  146: %token <tok>	 SHA256			/* sha256 digest */
  147: %token <tok>	 SHA384			/* sha384 digest */
  148: %token <tok>	 SHA512			/* sha512 digest */
  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
  156: %type <member>	  digcmnd
  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
  175: %type <privinfo>  solarisprivs
  176: %type <string>	  privsspec
  177: %type <string>	  limitprivsspec
  178: %type <digest>	  digest
  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 {
  230: 			    HLTQ_CONCAT($1, $3, entries);
  231: 			    $$ = $1;
  232: 			}
  233: 		;
  234: 
  235: defaults_entry	:	DEFVAR {
  236: 			    $$ = new_default($1, NULL, true);
  237: 			}
  238: 		|	'!' DEFVAR {
  239: 			    $$ = new_default($2, NULL, false);
  240: 			}
  241: 		|	DEFVAR '=' WORD {
  242: 			    $$ = new_default($1, $3, true);
  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 {
  254: 			    HLTQ_CONCAT($1, $3, entries);
  255: 			    $$ = $1;
  256: 			}
  257: 		;
  258: 
  259: privilege	:	hostlist '=' cmndspeclist {
  260: 			    struct privilege *p = ecalloc(1, sizeof(*p));
  261: 			    HLTQ_TO_TAILQ(&p->hostlist, $1, entries);
  262: 			    HLTQ_TO_TAILQ(&p->cmndlist, $3, entries);
  263: 			    HLTQ_INIT(p, entries);
  264: 			    $$ = p;
  265: 			}
  266: 		;
  267: 
  268: ophost		:	host {
  269: 			    $$ = $1;
  270: 			    $$->negated = false;
  271: 			}
  272: 		|	'!' host {
  273: 			    $$ = $2;
  274: 			    $$->negated = true;
  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 {
  297: 			    struct cmndspec *prev;
  298: 			    prev = HLTQ_LAST($1, cmndspec, entries);
  299: 			    HLTQ_CONCAT($1, $3, entries);
  300: #ifdef HAVE_SELINUX
  301: 			    /* propagate role and type */
  302: 			    if ($3->role == NULL)
  303: 				$3->role = prev->role;
  304: 			    if ($3->type == NULL)
  305: 				$3->type = prev->type;
  306: #endif /* HAVE_SELINUX */
  307: #ifdef HAVE_PRIV_SET
  308: 			    /* propagate privs & limitprivs */
  309: 			    if ($3->privs == NULL)
  310: 			        $3->privs = prev->privs;
  311: 			    if ($3->limitprivs == NULL)
  312: 			        $3->limitprivs = prev->limitprivs;
  313: #endif /* HAVE_PRIV_SET */
  314: 			    /* propagate tags and runas list */
  315: 			    if ($3->tags.nopasswd == UNSPEC)
  316: 				$3->tags.nopasswd = prev->tags.nopasswd;
  317: 			    if ($3->tags.noexec == UNSPEC)
  318: 				$3->tags.noexec = prev->tags.noexec;
  319: 			    if ($3->tags.setenv == UNSPEC &&
  320: 				prev->tags.setenv != IMPLIED)
  321: 				$3->tags.setenv = prev->tags.setenv;
  322: 			    if ($3->tags.log_input == UNSPEC)
  323: 				$3->tags.log_input = prev->tags.log_input;
  324: 			    if ($3->tags.log_output == UNSPEC)
  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;
  332: 			    }
  333: 			    $$ = $1;
  334: 			}
  335: 		;
  336: 
  337: cmndspec	:	runasspec selinux solarisprivs cmndtag digcmnd {
  338: 			    struct cmndspec *cs = ecalloc(1, sizeof(*cs));
  339: 			    if ($1 != NULL) {
  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: 				}
  352: 				efree($1);
  353: 			    }
  354: #ifdef HAVE_SELINUX
  355: 			    cs->role = $2.role;
  356: 			    cs->type = $2.type;
  357: #endif
  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;
  364: 			    HLTQ_INIT(cs, entries);
  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: 
  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: 
  398: opcmnd		:	cmnd {
  399: 			    $$ = $1;
  400: 			    $$->negated = false;
  401: 			}
  402: 		|	'!' cmnd {
  403: 			    $$ = $2;
  404: 			    $$->negated = true;
  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: 
  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;
  456: 			}
  457: 		|	limitprivsspec {
  458: 			    $$.privs = NULL;
  459: 			    $$.limitprivs = $1;
  460: 			}
  461: 		|	privsspec limitprivsspec {
  462: 			    $$.privs = $1;
  463: 			    $$.limitprivs = $2;
  464: 			}
  465: 		|	limitprivsspec privsspec {
  466: 			    $$.limitprivs = $1;
  467: 			    $$.privs = $2;
  468: 			}
  469: 		;
  470: 
  471: runasspec	:	/* empty */ {
  472: 			    $$ = NULL;
  473: 			}
  474: 		|	'(' runaslist ')' {
  475: 			    $$ = $2;
  476: 			}
  477: 		;
  478: 
  479: runaslist	:	/* empty */ {
  480: 			    $$ = ecalloc(1, sizeof(struct runascontainer));
  481: 			    $$->runasusers = new_member(NULL, MYSELF);
  482: 			    /* $$->runasgroups = NULL; */
  483: 			}
  484: 		|	userlist {
  485: 			    $$ = ecalloc(1, sizeof(struct runascontainer));
  486: 			    $$->runasusers = $1;
  487: 			    /* $$->runasgroups = NULL; */
  488: 			}
  489: 		|	userlist ':' grouplist {
  490: 			    $$ = ecalloc(1, sizeof(struct runascontainer));
  491: 			    $$->runasusers = $1;
  492: 			    $$->runasgroups = $3;
  493: 			}
  494: 		|	':' grouplist {
  495: 			    $$ = ecalloc(1, sizeof(struct runascontainer));
  496: 			    /* $$->runasusers = NULL; */
  497: 			    $$->runasgroups = $2;
  498: 			}
  499: 		|	':' {
  500: 			    $$ = ecalloc(1, sizeof(struct runascontainer));
  501: 			    $$->runasusers = new_member(NULL, MYSELF);
  502: 			    /* $$->runasgroups = NULL; */
  503: 			}
  504: 		;
  505: 
  506: cmndtag		:	/* empty */ {
  507: 			    $$.nopasswd = $$.noexec = $$.setenv =
  508: 				$$.log_input = $$.log_output = UNSPEC;
  509: 			}
  510: 		|	cmndtag NOPASSWD {
  511: 			    $$.nopasswd = true;
  512: 			}
  513: 		|	cmndtag PASSWD {
  514: 			    $$.nopasswd = false;
  515: 			}
  516: 		|	cmndtag NOEXEC {
  517: 			    $$.noexec = true;
  518: 			}
  519: 		|	cmndtag EXEC {
  520: 			    $$.noexec = false;
  521: 			}
  522: 		|	cmndtag SETENV {
  523: 			    $$.setenv = true;
  524: 			}
  525: 		|	cmndtag NOSETENV {
  526: 			    $$.setenv = false;
  527: 			}
  528: 		|	cmndtag LOG_INPUT {
  529: 			    $$.log_input = true;
  530: 			}
  531: 		|	cmndtag NOLOG_INPUT {
  532: 			    $$.log_input = false;
  533: 			}
  534: 		|	cmndtag LOG_OUTPUT {
  535: 			    $$.log_output = true;
  536: 			}
  537: 		|	cmndtag NOLOG_OUTPUT {
  538: 			    $$.log_output = false;
  539: 			}
  540: 		;
  541: 
  542: cmnd		:	ALL {
  543: 			    $$ = new_member(NULL, ALL);
  544: 			}
  545: 		|	ALIAS {
  546: 			    $$ = new_member($1, ALIAS);
  547: 			}
  548: 		|	COMMAND {
  549: 			    struct sudo_command *c = ecalloc(1, sizeof(*c));
  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) {
  563: 				sudoerserror(s);
  564: 				YYERROR;
  565: 			    }
  566: 			}
  567: 		;
  568: 
  569: hostlist	:	ophost
  570: 		|	hostlist ',' ophost {
  571: 			    HLTQ_CONCAT($1, $3, entries);
  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) {
  583: 				sudoerserror(s);
  584: 				YYERROR;
  585: 			    }
  586: 			}
  587: 		;
  588: 
  589: cmndlist	:	digcmnd
  590: 		|	cmndlist ',' digcmnd {
  591: 			    HLTQ_CONCAT($1, $3, entries);
  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) {
  603: 				sudoerserror(s);
  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) {
  616: 				sudoerserror(s);
  617: 				YYERROR;
  618: 			    }
  619: 			}
  620: 		;
  621: 
  622: userlist	:	opuser
  623: 		|	userlist ',' opuser {
  624: 			    HLTQ_CONCAT($1, $3, entries);
  625: 			    $$ = $1;
  626: 			}
  627: 		;
  628: 
  629: opuser		:	user {
  630: 			    $$ = $1;
  631: 			    $$->negated = false;
  632: 			}
  633: 		|	'!' user {
  634: 			    $$ = $2;
  635: 			    $$->negated = true;
  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 {
  658: 			    HLTQ_CONCAT($1, $3, entries);
  659: 			    $$ = $1;
  660: 			}
  661: 		;
  662: 
  663: opgroup		:	group {
  664: 			    $$ = $1;
  665: 			    $$->negated = false;
  666: 			}
  667: 		|	'!' group {
  668: 			    $$ = $2;
  669: 			    $$->negated = true;
  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: %%
  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: 
  717: static struct defaults *
  718: new_default(char *var, char *val, int op)
  719: {
  720:     struct defaults *d;
  721:     debug_decl(new_default, SUDO_DEBUG_PARSER)
  722: 
  723:     d = ecalloc(1, sizeof(struct defaults));
  724:     d->var = var;
  725:     d->val = val;
  726:     /* d->type = 0; */
  727:     d->op = op;
  728:     /* d->binding = NULL */
  729:     HLTQ_INIT(d, entries);
  730: 
  731:     debug_return_ptr(d);
  732: }
  733: 
  734: static struct member *
  735: new_member(char *name, int type)
  736: {
  737:     struct member *m;
  738:     debug_decl(new_member, SUDO_DEBUG_PARSER)
  739: 
  740:     m = ecalloc(1, sizeof(struct member));
  741:     m->name = name;
  742:     m->type = type;
  743:     HLTQ_INIT(m, entries);
  744: 
  745:     debug_return_ptr(m);
  746: }
  747: 
  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: 
  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;
  770:     struct member_list *binding;
  771:     debug_decl(add_defaults, SUDO_DEBUG_PARSER)
  772: 
  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);
  792:     }
  793: 
  794:     debug_return;
  795: }
  796: 
  797: /*
  798:  * Allocate a new struct userspec, populate it, and insert it at the
  799:  * end of the userspecs list.
  800:  */
  801: static void
  802: add_userspec(struct member *members, struct privilege *privs)
  803: {
  804:     struct userspec *u;
  805:     debug_decl(add_userspec, SUDO_DEBUG_PARSER)
  806: 
  807:     u = ecalloc(1, sizeof(*u));
  808:     HLTQ_TO_TAILQ(&u->users, members, entries);
  809:     HLTQ_TO_TAILQ(&u->privileges, privs, entries);
  810:     TAILQ_INSERT_TAIL(&userspecs, u, entries);
  811: 
  812:     debug_return;
  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
  820: init_parser(const char *path, bool quiet)
  821: {
  822:     struct member_list *binding;
  823:     struct defaults *d, *d_next;
  824:     struct userspec *us, *us_next;
  825:     debug_decl(init_parser, SUDO_DEBUG_PARSER)
  826: 
  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) {
  832: 	    efree(m->name);
  833: 	    efree(m);
  834: 	}
  835: 	TAILQ_FOREACH_SAFE(priv, &us->privileges, entries, priv_next) {
  836: 	    struct member_list *runasuserlist = NULL, *runasgrouplist = NULL;
  837: 	    struct cmndspec *cs, *cs_next;
  838: #ifdef HAVE_SELINUX
  839: 	    char *role = NULL, *type = NULL;
  840: #endif /* HAVE_SELINUX */
  841: #ifdef HAVE_PRIV_SET
  842: 	    char *privs = NULL, *limitprivs = NULL;
  843: #endif /* HAVE_PRIV_SET */
  844: 
  845: 	    TAILQ_FOREACH_SAFE(m, &priv->hostlist, entries, m_next) {
  846: 		efree(m->name);
  847: 		efree(m);
  848: 	    }
  849: 	    TAILQ_FOREACH_SAFE(cs, &priv->cmndlist, entries, cs_next) {
  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 */
  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 */
  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) {
  876: 			efree(m->name);
  877: 			efree(m);
  878: 		    }
  879: 		    efree(runasuserlist);
  880: 		}
  881: 		if (cs->runasgrouplist && cs->runasgrouplist != runasgrouplist) {
  882: 		    runasgrouplist = cs->runasgrouplist;
  883: 		    TAILQ_FOREACH_SAFE(m, runasgrouplist, entries, m_next) {
  884: 			efree(m->name);
  885: 			efree(m);
  886: 		    }
  887: 		    efree(runasgrouplist);
  888: 		}
  889: 		if (cs->cmnd->type == COMMAND) {
  890: 			struct sudo_command *c =
  891: 			    (struct sudo_command *) cs->cmnd->name;
  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:     }
  903:     TAILQ_INIT(&userspecs);
  904: 
  905:     binding = NULL;
  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) {
  912: 		if (m->type == COMMAND) {
  913: 			struct sudo_command *c =
  914: 			    (struct sudo_command *) m->name;
  915: 			efree(c->cmnd);
  916: 			efree(c->args);
  917: 		}
  918: 		efree(m->name);
  919: 		efree(m);
  920: 	    }
  921: 	    efree(d->binding);
  922: 	}
  923: 	efree(d->var);
  924: 	efree(d->val);
  925: 	efree(d);
  926:     }
  927:     TAILQ_INIT(&defaults);
  928: 
  929:     init_aliases();
  930: 
  931:     init_lexer();
  932: 
  933:     efree(sudoers);
  934:     sudoers = path ? estrdup(path) : NULL;
  935: 
  936:     parse_error = false;
  937:     errorlineno = -1;
  938:     errorfile = sudoers;
  939:     sudoers_warnings = !quiet;
  940: 
  941:     debug_return;
  942: }

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