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>