Annotation of src/usr.bin/sudo/parse.lex, Revision 1.6
1.1 millert 1: %{
2: /*
1.4 millert 3: * Copyright (c) 1996, 1998-2001 Todd C. Miller <Todd.Miller@courtesan.com>
1.1 millert 4: * All rights reserved.
5: *
1.6 ! millert 6: * This code is derived from software contributed by Chris Jepeway.
1.1 millert 7: *
8: * This code is derived from software contributed by Chris Jepeway
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: *
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: *
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: *
20: * 3. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * 4. Products derived from this software may not be called "Sudo" nor
24: * may "Sudo" appear in their names without specific prior written
25: * permission from the author.
26: *
27: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
28: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
30: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
33: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
35: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: #include "config.h"
40:
1.4 millert 41: #include <sys/types.h>
42: #include <sys/param.h>
43: #include <stdio.h>
1.1 millert 44: #ifdef STDC_HEADERS
1.4 millert 45: # include <stdlib.h>
46: # include <stddef.h>
47: #else
48: # ifdef HAVE_STDLIB_H
49: # include <stdlib.h>
50: # endif
1.1 millert 51: #endif /* STDC_HEADERS */
1.4 millert 52: #ifdef HAVE_STRING_H
53: # include <string.h>
54: #else
55: # ifdef HAVE_STRINGS_H
56: # include <strings.h>
57: # endif
58: #endif /* HAVE_STRING_H */
1.1 millert 59: #ifdef HAVE_UNISTD_H
1.4 millert 60: # include <unistd.h>
1.1 millert 61: #endif /* HAVE_UNISTD_H */
62: #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
1.4 millert 63: # include <malloc.h>
1.1 millert 64: #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
65: #include <ctype.h>
66: #include "sudo.h"
67: #include "parse.h"
1.4 millert 68: #include <sudo.tab.h>
1.1 millert 69:
70: #ifndef lint
1.6 ! millert 71: static const char rcsid[] = "$Sudo: parse.lex,v 1.119 2002/03/16 00:44:47 millert Exp $";
1.1 millert 72: #endif /* lint */
73:
74: #undef yywrap /* guard against a yywrap macro */
75:
76: extern YYSTYPE yylval;
77: extern int clearaliases;
78: int sudolineno = 1;
79: static int sawspace = 0;
80: static int arg_len = 0;
81: static int arg_size = 0;
82:
83: static void fill __P((char *, int));
84: static void fill_cmnd __P((char *, int));
85: static void fill_args __P((char *, int, int));
86: extern void reset_aliases __P((void));
87: extern void yyerror __P((char *));
88:
89: /* realloc() to size + COMMANDARGINC to make room for command args */
90: #define COMMANDARGINC 64
91:
92: #ifdef TRACELEXER
93: #define LEXTRACE(msg) fputs(msg, stderr)
94: #else
95: #define LEXTRACE(msg)
96: #endif
97: %}
98:
99: OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5])
100: DOTTEDQUAD {OCTET}(\.{OCTET}){3}
101: HOSTNAME [[:alnum:]_-]+
1.4 millert 102: WORD ([^#@!=:,\(\) \t\n\\]|\\[^\n])+
103: ENVAR ([^#!=, \t\n\\]|\\[^\n])([^#=, \t\n\\]|\\[^\n])*
104: DEFVAR [a-z_]+
1.1 millert 105:
1.4 millert 106: /* XXX - convert GOTRUNAS to exclusive state (GOTDEFS cannot be) */
1.1 millert 107: %s GOTRUNAS
108: %s GOTDEFS
1.4 millert 109: %x GOTCMND
110: %x STARTDEFS
111: %x INDEFS
1.1 millert 112:
113: %%
1.4 millert 114: <GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS;
115:
116: <STARTDEFS>{DEFVAR} {
117: BEGIN INDEFS;
118: LEXTRACE("DEFVAR ");
119: fill(yytext, yyleng);
120: return(DEFVAR);
1.1 millert 121: }
122:
1.4 millert 123: <INDEFS>{
124: , {
125: BEGIN STARTDEFS;
126: LEXTRACE(", ");
127: return(',');
128: } /* return ',' */
129:
130: = {
131: LEXTRACE("= ");
132: return('=');
133: } /* return '=' */
1.1 millert 134:
1.4 millert 135: \+= {
136: LEXTRACE("+= ");
137: return('+');
138: } /* return '+' */
139:
140: -= {
141: LEXTRACE("-= ");
142: return('-');
143: } /* return '-' */
1.1 millert 144:
1.4 millert 145: \"([^\"]|\\\")+\" {
1.1 millert 146: LEXTRACE("WORD(1) ");
147: fill(yytext + 1, yyleng - 2);
148: return(WORD);
149: }
150:
1.4 millert 151: {ENVAR} {
152: LEXTRACE("WORD(2) ");
153: fill(yytext, yyleng);
154: return(WORD);
155: }
156: }
157:
158: <GOTCMND>{
1.5 millert 159: \\[:\\,= \t#] {
1.4 millert 160: LEXTRACE("QUOTEDCHAR ");
161: fill_args(yytext + 1, 1, sawspace);
162: sawspace = FALSE;
1.1 millert 163: }
164:
1.4 millert 165: [#:\,=\n] {
1.1 millert 166: BEGIN INITIAL;
167: unput(*yytext);
168: return(COMMAND);
169: } /* end of command line args */
170:
1.5 millert 171: [^\\:, \t\n]+ {
1.1 millert 172: LEXTRACE("ARG ");
173: fill_args(yytext, yyleng, sawspace);
174: sawspace = FALSE;
1.4 millert 175: } /* a command line arg */
176: }
1.1 millert 177:
1.4 millert 178: <INITIAL>^Defaults[:@]? {
179: BEGIN GOTDEFS;
180: switch (yytext[8]) {
181: case ':':
182: LEXTRACE("DEFAULTS_USER ");
183: return(DEFAULTS_USER);
184: case '@':
185: LEXTRACE("DEFAULTS_HOST ");
186: return(DEFAULTS_HOST);
187: default:
188: LEXTRACE("DEFAULTS ");
189: return(DEFAULTS);
190: }
191: }
1.1 millert 192:
1.4 millert 193: <INITIAL>^(Host|Cmnd|User|Runas)_Alias {
194: fill(yytext, yyleng);
195: switch (*yytext) {
196: case 'H':
197: LEXTRACE("HOSTALIAS ");
198: return(HOSTALIAS);
199: case 'C':
200: LEXTRACE("CMNDALIAS ");
201: return(CMNDALIAS);
202: case 'U':
203: LEXTRACE("USERALIAS ");
204: return(USERALIAS);
205: case 'R':
206: LEXTRACE("RUNASALIAS ");
207: BEGIN GOTRUNAS;
208: return(RUNASALIAS);
209: }
1.1 millert 210: }
211:
212: NOPASSWD[[:blank:]]*: {
213: /* cmnd does not require passwd for this user */
214: LEXTRACE("NOPASSWD ");
215: return(NOPASSWD);
216: }
217:
218: PASSWD[[:blank:]]*: {
219: /* cmnd requires passwd for this user */
220: LEXTRACE("PASSWD ");
221: return(PASSWD);
222: }
223:
224: \+{WORD} {
225: /* netgroup */
226: fill(yytext, yyleng);
227: LEXTRACE("NETGROUP ");
228: return(NETGROUP);
229: }
230:
231: \%{WORD} {
232: /* UN*X group */
233: fill(yytext, yyleng);
234: LEXTRACE("GROUP ");
235: return(USERGROUP);
236: }
237:
238: {DOTTEDQUAD}(\/{DOTTEDQUAD})? {
239: fill(yytext, yyleng);
240: LEXTRACE("NTWKADDR ");
241: return(NTWKADDR);
242: }
243:
244: {DOTTEDQUAD}\/([12][0-9]*|3[0-2]*) {
245: fill(yytext, yyleng);
246: LEXTRACE("NTWKADDR ");
247: return(NTWKADDR);
248: }
249:
250: <INITIAL>\( {
251: BEGIN GOTRUNAS;
252: LEXTRACE("RUNAS ");
253: return (RUNAS);
254: }
255:
1.4 millert 256: [[:upper:]][[:upper:][:digit:]_]* {
1.1 millert 257: if (strcmp(yytext, "ALL") == 0) {
258: LEXTRACE("ALL ");
259: return(ALL);
260: } else {
261: fill(yytext, yyleng);
262: LEXTRACE("ALIAS ");
263: return(ALIAS);
264: }
265: }
266:
1.4 millert 267: <GOTRUNAS>(#[0-9-]+|{WORD}) {
1.1 millert 268: /* username/uid that user can run command as */
269: fill(yytext, yyleng);
1.4 millert 270: LEXTRACE("WORD(3) ");
1.1 millert 271: return(WORD);
272: }
273:
274: <GOTRUNAS>\) {
275: BEGIN INITIAL;
276: }
277:
1.4 millert 278: \/(\\[\,:= \t#]|[^\,:=\\ \t\n#])+ {
1.1 millert 279: /* directories can't have args... */
280: if (yytext[yyleng - 1] == '/') {
281: LEXTRACE("COMMAND ");
282: fill_cmnd(yytext, yyleng);
283: return(COMMAND);
284: } else {
285: BEGIN GOTCMND;
286: LEXTRACE("COMMAND ");
287: fill_cmnd(yytext, yyleng);
288: }
289: } /* a pathname */
290:
1.4 millert 291: <INITIAL,GOTDEFS>{WORD} {
1.1 millert 292: /* a word */
293: fill(yytext, yyleng);
294: LEXTRACE("WORD(4) ");
295: return(WORD);
296: }
297:
1.4 millert 298: , {
299: LEXTRACE(", ");
300: return(',');
301: } /* return ',' */
302:
303: = {
304: LEXTRACE("= ");
305: return('=');
306: } /* return '=' */
307:
308: : {
309: LEXTRACE(": ");
310: return(':');
311: } /* return ':' */
312:
313: <*>!+ {
314: if (yyleng % 2 == 1)
315: return('!'); /* return '!' */
316: }
317:
318: <*>\n {
319: BEGIN INITIAL;
320: ++sudolineno;
321: LEXTRACE("\n");
322: return(COMMENT);
323: } /* return newline */
324:
325: <*>[[:blank:]]+ { /* throw away space/tabs */
326: sawspace = TRUE; /* but remember for fill_args */
327: }
328:
329: <*>\\[[:blank:]]*\n {
330: sawspace = TRUE; /* remember for fill_args */
331: ++sudolineno;
332: LEXTRACE("\n\t");
333: } /* throw away EOL after \ */
334:
335: <INITIAL,STARTDEFS,INDEFS>#.*\n {
336: BEGIN INITIAL;
337: ++sudolineno;
338: LEXTRACE("\n");
339: return(COMMENT);
340: } /* return comments */
341:
342: <*>. {
1.1 millert 343: LEXTRACE("ERROR ");
344: return(ERROR);
345: } /* parse error */
346:
347: %%
348: static void
349: fill(s, len)
350: char *s;
351: int len;
352: {
353: int i, j;
354:
355: yylval.string = (char *) malloc(len + 1);
356: if (yylval.string == NULL)
357: yyerror("unable to allocate memory");
358:
359: /* Copy the string and collapse any escaped characters. */
360: for (i = 0, j = 0; i < len; i++, j++) {
361: if (s[i] == '\\' && i != len - 1)
362: yylval.string[j] = s[++i];
363: else
364: yylval.string[j] = s[i];
365: }
366: yylval.string[j] = '\0';
367: }
368:
369: static void
370: fill_cmnd(s, len)
371: char *s;
372: int len;
373: {
374: arg_len = arg_size = 0;
375:
376: yylval.command.cmnd = (char *) malloc(len + 1);
377: if (yylval.command.cmnd == NULL)
378: yyerror("unable to allocate memory");
379:
1.4 millert 380: /* copy the string and NULL-terminate it (escapes handled by fnmatch) */
1.1 millert 381: (void) strncpy(yylval.command.cmnd, s, len);
382: yylval.command.cmnd[len] = '\0';
383:
384: yylval.command.args = NULL;
385: }
386:
387: static void
388: fill_args(s, len, addspace)
389: char *s;
390: int len;
391: int addspace;
392: {
393: int new_len;
394: char *p;
395:
396: /*
397: * If first arg, malloc() some room, else if we don't
398: * have enough space realloc() some more.
399: */
400: if (yylval.command.args == NULL) {
401: addspace = 0;
402: new_len = len;
403:
404: while (new_len >= (arg_size += COMMANDARGINC))
405: ;
406:
407: yylval.command.args = (char *) malloc(arg_size);
408: if (yylval.command.args == NULL)
409: yyerror("unable to allocate memory");
410: } else {
411: new_len = arg_len + len + addspace;
412:
413: if (new_len >= arg_size) {
414: /* Allocate more space than we need for subsequent args */
415: while (new_len >= (arg_size += COMMANDARGINC))
416: ;
417:
418: if ((p = (char *) realloc(yylval.command.args, arg_size)) == NULL) {
419: free(yylval.command.args);
420: yyerror("unable to allocate memory");
421: } else
422: yylval.command.args = p;
423: }
424: }
425:
426: /* Efficiently append the arg (with a leading space if needed). */
427: p = yylval.command.args + arg_len;
428: if (addspace)
429: *p++ = ' ';
430: (void) strcpy(p, s);
431: arg_len = new_len;
432: }
433:
434: int
435: yywrap()
436: {
437:
438: /* Free space used by the aliases unless called by testsudoers. */
439: if (clearaliases)
440: reset_aliases();
441:
442: return(TRUE);
443: }