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