summaryrefslogtreecommitdiff
path: root/parse.lex
diff options
context:
space:
mode:
authorTodd C. Miller <Todd.Miller@courtesan.com>2007-06-12 00:56:44 +0000
committerTodd C. Miller <Todd.Miller@courtesan.com>2007-06-12 00:56:44 +0000
commitd8804ada11beb5183192511ed1cd5bec812c2858 (patch)
tree9f43e3f9e0872ba55f8bd31912c433e1a082c480 /parse.lex
parenta081092f1307c1a872fe58f9a91f48dfd48eace0 (diff)
downloadsudo-d8804ada11beb5183192511ed1cd5bec812c2858.tar.gz
Add __unused to rcsids
Diffstat (limited to 'parse.lex')
-rw-r--r--parse.lex505
1 files changed, 445 insertions, 60 deletions
diff --git a/parse.lex b/parse.lex
index 1a8b03d13..275642a58 100644
--- a/parse.lex
+++ b/parse.lex
@@ -1,77 +1,462 @@
%{
/*
- * CU sudo version 1.3 (based on Root Group sudo version 1.1)
+ * Copyright (c) 1996, 1998-2004 Todd C. Miller <Todd.Miller@courtesan.com>
*
- * This software comes with no waranty whatsoever, use at your own risk.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * Please send bugs, changes, problems to sudo-bugs.cs.colorado.edu
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
-/*
- * sudo version 1.1 allows users to execute commands as root
- * Copyright (C) 1991 The Root Group, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 1, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-/*******************************************************************************
-* parse.lex, sudo project
-* David R. Hieb
-* March 18, 1991
-*
-* Lex Specification file for the sudo project.
-*******************************************************************************/
-
-#ifndef lint
-static char rcsid[] = "$Id$";
-#endif /* lint */
+#include <config.h>
#include <sys/types.h>
#include <sys/param.h>
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+# include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#include <ctype.h>
#include "sudo.h"
-#include "y.tab.h"
+#include "parse.h"
+#include <sudo.tab.h>
-#ifdef FLEX_SCANNER
-int yylineno = 0;
-#endif /* flex */
+#ifndef lint
+__unused static const char rcsid[] = "$Sudo$";
+#endif /* lint */
+
+#undef yywrap /* guard against a yywrap macro */
+
+extern YYSTYPE yylval;
+extern int clearaliases;
+int sudolineno = 1;
+static int sawspace = 0;
+static int arg_len = 0;
+static int arg_size = 0;
+
+static void fill __P((char *, int));
+static void fill_cmnd __P((char *, int));
+static void fill_args __P((char *, int, int));
+extern void reset_aliases __P((void));
+extern void yyerror __P((char *));
+
+/* realloc() to size + COMMANDARGINC to make room for command args */
+#define COMMANDARGINC 64
+
+#ifdef TRACELEXER
+#define LEXTRACE(msg) fputs(msg, stderr)
+#else
+#define LEXTRACE(msg)
+#endif
%}
+OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5])
+DOTTEDQUAD {OCTET}(\.{OCTET}){3}
+HOSTNAME [[:alnum:]_-]+
+WORD ([^#>@!=:,\(\) \t\n\\]|\\[^\n])+
+ENVAR ([^#!=, \t\n\\]|\\[^\n])([^#=, \t\n\\]|\\[^\n])*
+DEFVAR [a-z_]+
+
+/* XXX - convert GOTRUNAS to exclusive state (GOTDEFS cannot be) */
+%s GOTRUNAS
+%s GOTDEFS
+%x GOTCMND
+%x STARTDEFS
+%x INDEFS
+
%%
-[ \t]+ { ; } /* throw away space/tabs */
-\\\n {
-#ifdef FLEX_SCANNER
- ++yylineno
-#endif /* flex */
- ; } /* throw away EOL after \ */
-\, { return ','; } /* return ',' */
-\! { return '!'; } /* return '!' */
-= { return '='; } /* return '=' */
-: { return ':'; } /* return ':' */
-\n {
-#ifdef FLEX_SCANNER
- ++yylineno;
-#endif /* flex */
- return COMMENT; } /* return newline */
-#.*\n { return COMMENT; } /* return comments */
-[@$%^&*()"'`/_+]* { return ERROR; } /* return error */
-[?;<>\[\]{}|~.-]* { return ERROR; } /* return error */
-^[a-zA-Z0-9_-]+ { fill(); return IDENT1;} /* user/{Host,Cmnd}_Alias */
-[a-zA-Z0-9_.+-]+ { fill(); return IDENT2;} /* host_type/ALIASES */
-(\/[a-zA-Z0-9_.+-]+)+\/? { fill(); return IDENT3;} /* absolute command path */
+<GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS;
+
+<STARTDEFS>{DEFVAR} {
+ BEGIN INDEFS;
+ LEXTRACE("DEFVAR ");
+ fill(yytext, yyleng);
+ return(DEFVAR);
+ }
+
+<INDEFS>{
+ , {
+ BEGIN STARTDEFS;
+ LEXTRACE(", ");
+ return(',');
+ } /* return ',' */
+
+ = {
+ LEXTRACE("= ");
+ return('=');
+ } /* return '=' */
+
+ \+= {
+ LEXTRACE("+= ");
+ return('+');
+ } /* return '+' */
+
+ -= {
+ LEXTRACE("-= ");
+ return('-');
+ } /* return '-' */
+
+ \"([^\"]|\\\")+\" {
+ LEXTRACE("WORD(1) ");
+ fill(yytext + 1, yyleng - 2);
+ return(WORD);
+ }
+
+ {ENVAR} {
+ LEXTRACE("WORD(2) ");
+ fill(yytext, yyleng);
+ return(WORD);
+ }
+}
+
+<GOTCMND>{
+ \\[\*\?\[\]\!] {
+ /* quoted fnmatch glob char, pass verbatim */
+ LEXTRACE("QUOTEDCHAR ");
+ fill_args(yytext, 2, sawspace);
+ sawspace = FALSE;
+ }
+
+ \\[:\\,= \t#] {
+ /* quoted sudoers special char, strip backslash */
+ LEXTRACE("QUOTEDCHAR ");
+ fill_args(yytext + 1, 1, sawspace);
+ sawspace = FALSE;
+ }
+
+ [#:\,=\n] {
+ BEGIN INITIAL;
+ unput(*yytext);
+ return(COMMAND);
+ } /* end of command line args */
+
+ [^\\:, \t\n]+ {
+ LEXTRACE("ARG ");
+ fill_args(yytext, yyleng, sawspace);
+ sawspace = FALSE;
+ } /* a command line arg */
+}
+
+<INITIAL>^Defaults[:@>]? {
+ BEGIN GOTDEFS;
+ switch (yytext[8]) {
+ case ':':
+ LEXTRACE("DEFAULTS_USER ");
+ return(DEFAULTS_USER);
+ case '>':
+ LEXTRACE("DEFAULTS_RUNAS ");
+ return(DEFAULTS_RUNAS);
+ case '@':
+ LEXTRACE("DEFAULTS_HOST ");
+ return(DEFAULTS_HOST);
+ default:
+ LEXTRACE("DEFAULTS ");
+ return(DEFAULTS);
+ }
+ }
+
+<INITIAL>^(Host|Cmnd|User|Runas)_Alias {
+ fill(yytext, yyleng);
+ switch (*yytext) {
+ case 'H':
+ LEXTRACE("HOSTALIAS ");
+ return(HOSTALIAS);
+ case 'C':
+ LEXTRACE("CMNDALIAS ");
+ return(CMNDALIAS);
+ case 'U':
+ LEXTRACE("USERALIAS ");
+ return(USERALIAS);
+ case 'R':
+ LEXTRACE("RUNASALIAS ");
+ BEGIN GOTRUNAS;
+ return(RUNASALIAS);
+ }
+ }
+
+NOPASSWD[[:blank:]]*: {
+ /* cmnd does not require passwd for this user */
+ LEXTRACE("NOPASSWD ");
+ return(NOPASSWD);
+ }
+
+PASSWD[[:blank:]]*: {
+ /* cmnd requires passwd for this user */
+ LEXTRACE("PASSWD ");
+ return(PASSWD);
+ }
+
+NOEXEC[[:blank:]]*: {
+ LEXTRACE("NOEXEC ");
+ return(NOEXEC);
+ }
+
+EXEC[[:blank:]]*: {
+ LEXTRACE("EXEC ");
+ return(EXEC);
+ }
+
+\+{WORD} {
+ /* netgroup */
+ fill(yytext, yyleng);
+ LEXTRACE("NETGROUP ");
+ return(NETGROUP);
+ }
+
+\%{WORD} {
+ /* UN*X group */
+ fill(yytext, yyleng);
+ LEXTRACE("GROUP ");
+ return(USERGROUP);
+ }
+
+{DOTTEDQUAD}(\/{DOTTEDQUAD})? {
+ fill(yytext, yyleng);
+ LEXTRACE("NTWKADDR ");
+ return(NTWKADDR);
+ }
+
+{DOTTEDQUAD}\/([12][0-9]*|3[0-2]*) {
+ fill(yytext, yyleng);
+ LEXTRACE("NTWKADDR ");
+ return(NTWKADDR);
+ }
+
+<INITIAL>\( {
+ BEGIN GOTRUNAS;
+ LEXTRACE("RUNAS ");
+ return (RUNAS);
+ }
+
+[[:upper:]][[:upper:][:digit:]_]* {
+ if (strcmp(yytext, "ALL") == 0) {
+ LEXTRACE("ALL ");
+ return(ALL);
+ } else {
+ fill(yytext, yyleng);
+ LEXTRACE("ALIAS ");
+ return(ALIAS);
+ }
+ }
+
+<GOTRUNAS>(#[0-9-]+|{WORD}) {
+ /* username/uid that user can run command as */
+ fill(yytext, yyleng);
+ LEXTRACE("WORD(3) ");
+ return(WORD);
+ }
+
+<GOTRUNAS>\) {
+ BEGIN INITIAL;
+ }
+
+sudoedit {
+ BEGIN GOTCMND;
+ LEXTRACE("COMMAND ");
+ fill_cmnd(yytext, yyleng);
+ } /* sudo -e */
+
+\/(\\[\,:= \t#]|[^\,:=\\ \t\n#])+ {
+ /* directories can't have args... */
+ if (yytext[yyleng - 1] == '/') {
+ LEXTRACE("COMMAND ");
+ fill_cmnd(yytext, yyleng);
+ return(COMMAND);
+ } else {
+ BEGIN GOTCMND;
+ LEXTRACE("COMMAND ");
+ fill_cmnd(yytext, yyleng);
+ }
+ } /* a pathname */
+
+<INITIAL,GOTDEFS>{WORD} {
+ /* a word */
+ fill(yytext, yyleng);
+ LEXTRACE("WORD(4) ");
+ return(WORD);
+ }
+
+, {
+ LEXTRACE(", ");
+ return(',');
+ } /* return ',' */
+
+= {
+ LEXTRACE("= ");
+ return('=');
+ } /* return '=' */
+
+: {
+ LEXTRACE(": ");
+ return(':');
+ } /* return ':' */
+
+<*>!+ {
+ if (yyleng % 2 == 1)
+ return('!'); /* return '!' */
+ }
+
+<*>\n {
+ BEGIN INITIAL;
+ ++sudolineno;
+ LEXTRACE("\n");
+ return(COMMENT);
+ } /* return newline */
+
+<*>[[:blank:]]+ { /* throw away space/tabs */
+ sawspace = TRUE; /* but remember for fill_args */
+ }
+
+<*>\\[[:blank:]]*\n {
+ sawspace = TRUE; /* remember for fill_args */
+ ++sudolineno;
+ LEXTRACE("\n\t");
+ } /* throw away EOL after \ */
+
+<INITIAL,STARTDEFS,INDEFS>#.*\n {
+ BEGIN INITIAL;
+ ++sudolineno;
+ LEXTRACE("\n");
+ return(COMMENT);
+ } /* return comments */
+
+<*>. {
+ LEXTRACE("ERROR ");
+ return(ERROR);
+ } /* parse error */
+
+<*><<EOF>> {
+ if (YY_START != INITIAL) {
+ BEGIN INITIAL;
+ LEXTRACE("ERROR ");
+ return(ERROR);
+ }
+ yyterminate();
+ }
+
%%
-fill() {
-strcpy(yylval.char_val, yytext);
+static void
+fill(s, len)
+ char *s;
+ int len;
+{
+ int i, j;
+
+ yylval.string = (char *) malloc(len + 1);
+ if (yylval.string == NULL) {
+ yyerror("unable to allocate memory");
+ return;
+ }
+
+ /* Copy the string and collapse any escaped characters. */
+ for (i = 0, j = 0; i < len; i++, j++) {
+ if (s[i] == '\\' && i != len - 1)
+ yylval.string[j] = s[++i];
+ else
+ yylval.string[j] = s[i];
+ }
+ yylval.string[j] = '\0';
+}
+
+static void
+fill_cmnd(s, len)
+ char *s;
+ int len;
+{
+ arg_len = arg_size = 0;
+
+ yylval.command.cmnd = (char *) malloc(++len);
+ if (yylval.command.cmnd == NULL) {
+ yyerror("unable to allocate memory");
+ return;
+ }
+
+ /* copy the string and NULL-terminate it (escapes handled by fnmatch) */
+ (void) strlcpy(yylval.command.cmnd, s, len);
+
+ yylval.command.args = NULL;
+}
+
+static void
+fill_args(s, len, addspace)
+ char *s;
+ int len;
+ int addspace;
+{
+ int new_len;
+ char *p;
+
+ if (yylval.command.args == NULL) {
+ addspace = 0;
+ new_len = len;
+ } else
+ new_len = arg_len + len + addspace;
+
+ if (new_len >= arg_size) {
+ /* Allocate more space than we need for subsequent args */
+ while (new_len >= (arg_size += COMMANDARGINC))
+ ;
+
+ p = yylval.command.args ?
+ (char *) realloc(yylval.command.args, arg_size) :
+ (char *) malloc(arg_size);
+ if (p == NULL) {
+ if (yylval.command.args != NULL)
+ free(yylval.command.args);
+ yyerror("unable to allocate memory");
+ return;
+ } else
+ yylval.command.args = p;
+ }
+
+ /* Efficiently append the arg (with a leading space if needed). */
+ p = yylval.command.args + arg_len;
+ if (addspace)
+ *p++ = ' ';
+ if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len)
+ yyerror("fill_args: buffer overflow"); /* paranoia */
+ arg_len = new_len;
+}
+
+int
+yywrap()
+{
+
+ /* Free space used by the aliases unless called by testsudoers. */
+ if (clearaliases)
+ reset_aliases();
+
+ return(TRUE);
}