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>