3 * Copyright (c) 1996, 1998-2004 Todd C. Miller <Todd.Miller@courtesan.com>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
17 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
18 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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.
27 #include <sys/types.h>
28 #include <sys/param.h>
37 #endif /* STDC_HEADERS */
41 # ifdef HAVE_STRINGS_H
44 #endif /* HAVE_STRING_H */
47 #endif /* HAVE_UNISTD_H */
48 #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
50 #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
57 static const char rcsid[] = "$Sudo: parse.lex,v 1.132 2004/05/17 20:51:13 millert Exp $";
60 #undef yywrap /* guard against a yywrap macro */
62 extern YYSTYPE yylval;
63 extern int clearaliases;
65 static int sawspace = 0;
66 static int arg_len = 0;
67 static int arg_size = 0;
69 static void fill __P((char *, int));
70 static void fill_cmnd __P((char *, int));
71 static void fill_args __P((char *, int, int));
72 extern void reset_aliases __P((void));
73 extern void yyerror __P((char *));
75 /* realloc() to size + COMMANDARGINC to make room for command args */
76 #define COMMANDARGINC 64
79 #define LEXTRACE(msg) fputs(msg, stderr)
85 OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5])
86 DOTTEDQUAD {OCTET}(\.{OCTET}){3}
87 HOSTNAME [[:alnum:]_-]+
88 WORD ([^#>@!=:,\(\) \t\n\\]|\\[^\n])+
89 ENVAR ([^#!=, \t\n\\]|\\[^\n])([^#=, \t\n\\]|\\[^\n])*
92 /* XXX - convert GOTRUNAS to exclusive state (GOTDEFS cannot be) */
100 <GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS;
102 <STARTDEFS>{DEFVAR} {
105 fill(yytext, yyleng);
132 LEXTRACE("WORD(1) ");
133 fill(yytext + 1, yyleng - 2);
138 LEXTRACE("WORD(2) ");
139 fill(yytext, yyleng);
146 /* quoted fnmatch glob char, pass verbatim */
147 LEXTRACE("QUOTEDCHAR ");
148 fill_args(yytext, 2, sawspace);
153 /* quoted sudoers special char, strip backslash */
154 LEXTRACE("QUOTEDCHAR ");
155 fill_args(yytext + 1, 1, sawspace);
163 } /* end of command line args */
167 fill_args(yytext, yyleng, sawspace);
169 } /* a command line arg */
172 <INITIAL>^Defaults[:@>]? {
176 LEXTRACE("DEFAULTS_USER ");
177 return(DEFAULTS_USER);
179 LEXTRACE("DEFAULTS_RUNAS ");
180 return(DEFAULTS_RUNAS);
182 LEXTRACE("DEFAULTS_HOST ");
183 return(DEFAULTS_HOST);
185 LEXTRACE("DEFAULTS ");
190 <INITIAL>^(Host|Cmnd|User|Runas)_Alias {
191 fill(yytext, yyleng);
194 LEXTRACE("HOSTALIAS ");
197 LEXTRACE("CMNDALIAS ");
200 LEXTRACE("USERALIAS ");
203 LEXTRACE("RUNASALIAS ");
209 NOPASSWD[[:blank:]]*: {
210 /* cmnd does not require passwd for this user */
211 LEXTRACE("NOPASSWD ");
215 PASSWD[[:blank:]]*: {
216 /* cmnd requires passwd for this user */
221 NOEXEC[[:blank:]]*: {
233 fill(yytext, yyleng);
234 LEXTRACE("NETGROUP ");
240 fill(yytext, yyleng);
245 {DOTTEDQUAD}(\/{DOTTEDQUAD})? {
246 fill(yytext, yyleng);
247 LEXTRACE("NTWKADDR ");
251 {DOTTEDQUAD}\/([12][0-9]*|3[0-2]*) {
252 fill(yytext, yyleng);
253 LEXTRACE("NTWKADDR ");
263 [[:upper:]][[:upper:][:digit:]_]* {
264 if (strcmp(yytext, "ALL") == 0) {
268 fill(yytext, yyleng);
274 <GOTRUNAS>(#[0-9-]+|{WORD}) {
275 /* username/uid that user can run command as */
276 fill(yytext, yyleng);
277 LEXTRACE("WORD(3) ");
287 LEXTRACE("COMMAND ");
288 fill_cmnd(yytext, yyleng);
291 \/(\\[\,:= \t#]|[^\,:=\\ \t\n#])+ {
292 /* directories can't have args... */
293 if (yytext[yyleng - 1] == '/') {
294 LEXTRACE("COMMAND ");
295 fill_cmnd(yytext, yyleng);
299 LEXTRACE("COMMAND ");
300 fill_cmnd(yytext, yyleng);
304 <INITIAL,GOTDEFS>{WORD} {
306 fill(yytext, yyleng);
307 LEXTRACE("WORD(4) ");
328 return('!'); /* return '!' */
336 } /* return newline */
338 <*>[[:blank:]]+ { /* throw away space/tabs */
339 sawspace = TRUE; /* but remember for fill_args */
342 <*>\\[[:blank:]]*\n {
343 sawspace = TRUE; /* remember for fill_args */
346 } /* throw away EOL after \ */
348 <INITIAL,STARTDEFS,INDEFS>#.*\n {
353 } /* return comments */
361 if (YY_START != INITIAL) {
377 yylval.string = (char *) malloc(len + 1);
378 if (yylval.string == NULL) {
379 yyerror("unable to allocate memory");
383 /* Copy the string and collapse any escaped characters. */
384 for (i = 0, j = 0; i < len; i++, j++) {
385 if (s[i] == '\\' && i != len - 1)
386 yylval.string[j] = s[++i];
388 yylval.string[j] = s[i];
390 yylval.string[j] = '\0';
398 arg_len = arg_size = 0;
400 yylval.command.cmnd = (char *) malloc(++len);
401 if (yylval.command.cmnd == NULL) {
402 yyerror("unable to allocate memory");
406 /* copy the string and NULL-terminate it (escapes handled by fnmatch) */
407 (void) strlcpy(yylval.command.cmnd, s, len);
409 yylval.command.args = NULL;
413 fill_args(s, len, addspace)
421 if (yylval.command.args == NULL) {
425 new_len = arg_len + len + addspace;
427 if (new_len >= arg_size) {
428 /* Allocate more space than we need for subsequent args */
429 while (new_len >= (arg_size += COMMANDARGINC))
432 p = yylval.command.args ?
433 (char *) realloc(yylval.command.args, arg_size) :
434 (char *) malloc(arg_size);
436 if (yylval.command.args != NULL)
437 free(yylval.command.args);
438 yyerror("unable to allocate memory");
441 yylval.command.args = p;
444 /* Efficiently append the arg (with a leading space if needed). */
445 p = yylval.command.args + arg_len;
448 if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len)
449 yyerror("fill_args: buffer overflow"); /* paranoia */
457 /* Free space used by the aliases unless called by testsudoers. */