version 1.13, 2007/08/15 14:22:39 |
version 1.14, 2007/09/05 23:55:57 |
|
|
#include <sudo.tab.h> |
#include <sudo.tab.h> |
|
|
#ifndef lint |
#ifndef lint |
__unused static const char rcsid[] = "$Sudo: parse.lex,v 1.132.2.4 2007/08/13 16:30:02 millert Exp $"; |
__unused static const char rcsid[] = "$Sudo: parse.lex,v 1.132.2.7 2007/08/25 02:48:01 millert Exp $"; |
#endif /* lint */ |
#endif /* lint */ |
|
|
#undef yywrap /* guard against a yywrap macro */ |
#undef yywrap /* guard against a yywrap macro */ |
|
|
static int arg_len = 0; |
static int arg_len = 0; |
static int arg_size = 0; |
static int arg_size = 0; |
|
|
static void fill __P((char *, int)); |
static int ipv6_valid __P((const char *s)); |
|
static void _fill __P((char *, int, int)); |
|
static void append __P((char *, int)); |
static void fill_cmnd __P((char *, int)); |
static void fill_cmnd __P((char *, int)); |
static void fill_args __P((char *, int, int)); |
static void fill_args __P((char *, int, int)); |
extern void reset_aliases __P((void)); |
extern void reset_aliases __P((void)); |
extern void yyerror __P((char *)); |
extern void yyerror __P((char *)); |
|
|
|
#define fill(a, b) _fill(a, b, 0) |
|
|
/* realloc() to size + COMMANDARGINC to make room for command args */ |
/* realloc() to size + COMMANDARGINC to make room for command args */ |
#define COMMANDARGINC 64 |
#define COMMANDARGINC 64 |
|
|
|
|
#endif |
#endif |
%} |
%} |
|
|
HEXDIGIT [0-9A-Fa-f]{1,4} |
HEX16 [0-9A-Fa-f]{1,4} |
OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]) |
OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]) |
DOTTEDQUAD {OCTET}(\.{OCTET}){3} |
IPV4ADDR {OCTET}(\.{OCTET}){3} |
IPV6ADDR \:\:|({HEXDIGIT}\:){7}{HEXDIGIT}|({HEXDIGIT}\:){5}{HEXDIGIT}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1,7}\:|({HEXDIGIT}\:){1,6}(\:{HEXDIGIT}){1}|({HEXDIGIT}\:){1,5}(\:{HEXDIGIT}){2}|({HEXDIGIT}\:){1,2}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1,4}(\:{HEXDIGIT}){3}|({HEXDIGIT}\:){1,4}(\:{HEXDIGIT}){1}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1,3}(\:{HEXDIGIT}){4}|({HEXDIGIT}\:){1,3}(\:{HEXDIGIT}){2}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1,2}(\:{HEXDIGIT}){5}|({HEXDIGIT}\:){1,2}(\:{HEXDIGIT}){3}\:{DOTTEDQUAD}|({HEXDIGIT}\:){1}(\:{HEXDIGIT}){6}|({HEXDIGIT}\:){1}(\:{HEXDIGIT}){4}\:{DOTTEDQUAD}|\:(\:{HEXDIGIT}){1,7}|\:(\:{HEXDIGIT}){1,5}\:{DOTTEDQUAD} |
IPV6ADDR ({HEX16}?:){2,7}{HEX16}?|({HEX16}?:){2,6}:{IPV4ADDR} |
|
|
HOSTNAME [[:alnum:]_-]+ |
HOSTNAME [[:alnum:]_-]+ |
WORD ([^#>@!=:,\(\) \t\n\\]|\\[^\n])+ |
WORD ([^#>@!=:,\(\) \t\n\\]|\\[^\n])+ |
ENVAR ([^#!=, \t\n\\]|\\[^\n])([^#=, \t\n\\]|\\[^\n])* |
ENVAR ([^#!=, \t\n\\\"]|\\[^\n])([^#=, \t\n\\]|\\[^\n])* |
DEFVAR [a-z_]+ |
DEFVAR [a-z_]+ |
|
|
/* XXX - convert GOTRUNAS to exclusive state (GOTDEFS cannot be) */ |
/* XXX - convert GOTRUNAS to exclusive state (GOTDEFS cannot be) */ |
|
|
%x GOTCMND |
%x GOTCMND |
%x STARTDEFS |
%x STARTDEFS |
%x INDEFS |
%x INDEFS |
|
%x INSTR |
|
|
%% |
%% |
<GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS; |
<GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS; |
|
|
return('-'); |
return('-'); |
} /* return '-' */ |
} /* return '-' */ |
|
|
\"([^\"]|\\\")+\" { |
\" { |
LEXTRACE("WORD(1) "); |
LEXTRACE("BEGINSTR "); |
fill(yytext + 1, yyleng - 2); |
yylval.string = NULL; |
return(WORD); |
BEGIN INSTR; |
} |
} |
|
|
{ENVAR} { |
{ENVAR} { |
|
|
} |
} |
} |
} |
|
|
|
<INSTR>{ |
|
\\\n[[:blank:]]* { |
|
/* Line continuation char followed by newline. */ |
|
++sudolineno; |
|
LEXTRACE("\n"); |
|
} |
|
|
|
\" { |
|
LEXTRACE("ENDSTR "); |
|
BEGIN INDEFS; |
|
return(WORD); |
|
} |
|
|
|
([^\"\n]|\\\")+ { |
|
LEXTRACE("STRBODY "); |
|
/* Push back line continuation char if present */ |
|
if (yyleng > 2 && yytext[yyleng - 1] == '\\' && |
|
isspace((unsigned char)yytext[yyleng - 2])) |
|
yyless(yyleng - 1); |
|
append(yytext, yyleng); |
|
} |
|
} |
|
|
<GOTCMND>{ |
<GOTCMND>{ |
\\[\*\?\[\]\!] { |
\\[\*\?\[\]\!] { |
/* quoted fnmatch glob char, pass verbatim */ |
/* quoted fnmatch glob char, pass verbatim */ |
|
|
return(USERGROUP); |
return(USERGROUP); |
} |
} |
|
|
{DOTTEDQUAD}(\/{DOTTEDQUAD})? { |
{IPV4ADDR}(\/{IPV4ADDR})? { |
fill(yytext, yyleng); |
fill(yytext, yyleng); |
LEXTRACE("NTWKADDR "); |
LEXTRACE("NTWKADDR "); |
return(NTWKADDR); |
return(NTWKADDR); |
} |
} |
|
|
{DOTTEDQUAD}\/([12][0-9]*|3[0-2]*) { |
{IPV4ADDR}\/([12][0-9]*|3[0-2]*) { |
fill(yytext, yyleng); |
fill(yytext, yyleng); |
LEXTRACE("NTWKADDR "); |
LEXTRACE("NTWKADDR "); |
return(NTWKADDR); |
return(NTWKADDR); |
} |
} |
|
|
{IPV6ADDR}(\/{IPV6ADDR})? { |
{IPV6ADDR}(\/{IPV6ADDR})? { |
|
if (!ipv6_valid(yytext)) { |
|
LEXTRACE("ERROR "); |
|
return(ERROR); |
|
} |
fill(yytext, yyleng); |
fill(yytext, yyleng); |
LEXTRACE("NTWKADDR "); |
LEXTRACE("NTWKADDR "); |
return(NTWKADDR); |
return(NTWKADDR); |
} |
} |
|
|
{IPV6ADDR}\/([0-9]|[1-9][0-9]|1[01][0-9]|12[0-8]) { |
{IPV6ADDR}\/([0-9]|[1-9][0-9]|1[01][0-9]|12[0-8]) { |
|
if (!ipv6_valid(yytext)) { |
|
LEXTRACE("ERROR "); |
|
return(ERROR); |
|
} |
fill(yytext, yyleng); |
fill(yytext, yyleng); |
LEXTRACE("NTWKADDR "); |
LEXTRACE("NTWKADDR "); |
return(NTWKADDR); |
return(NTWKADDR); |
|
|
return(WORD); |
return(WORD); |
} |
} |
|
|
|
<GOTRUNAS>#[^0-9-].*\n { |
|
BEGIN INITIAL; |
|
++sudolineno; |
|
LEXTRACE("\n"); |
|
return(COMMENT); |
|
} |
|
|
<GOTRUNAS>\) { |
<GOTRUNAS>\) { |
BEGIN INITIAL; |
BEGIN INITIAL; |
} |
} |
|
|
|
|
%% |
%% |
static void |
static void |
fill(s, len) |
_fill(src, len, olen) |
char *s; |
char *src; |
int len; |
int len, olen; |
{ |
{ |
int i, j; |
int i, j; |
|
char *dst; |
|
|
yylval.string = (char *) malloc(len + 1); |
dst = olen ? realloc(yylval.string, olen + len + 1) : malloc(len + 1); |
if (yylval.string == NULL) { |
if (dst == NULL) { |
yyerror("unable to allocate memory"); |
yyerror("unable to allocate memory"); |
return; |
return; |
} |
} |
|
yylval.string = dst; |
|
|
/* Copy the string and collapse any escaped characters. */ |
/* Copy the string and collapse any escaped characters. */ |
|
dst += olen; |
for (i = 0, j = 0; i < len; i++, j++) { |
for (i = 0, j = 0; i < len; i++, j++) { |
if (s[i] == '\\' && i != len - 1) |
if (src[i] == '\\' && i != len - 1) |
yylval.string[j] = s[++i]; |
dst[j] = src[++i]; |
else |
else |
yylval.string[j] = s[i]; |
dst[j] = src[i]; |
} |
} |
yylval.string[j] = '\0'; |
dst[j] = '\0'; |
} |
} |
|
|
static void |
static void |
|
append(src, len) |
|
char *src; |
|
int len; |
|
{ |
|
int olen = 0; |
|
|
|
if (yylval.string != NULL) |
|
olen = strlen(yylval.string); |
|
|
|
_fill(src, len, olen); |
|
} |
|
|
|
static void |
fill_cmnd(s, len) |
fill_cmnd(s, len) |
char *s; |
char *s; |
int len; |
int len; |
|
|
if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len) |
if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len) |
yyerror("fill_args: buffer overflow"); /* paranoia */ |
yyerror("fill_args: buffer overflow"); /* paranoia */ |
arg_len = new_len; |
arg_len = new_len; |
|
} |
|
|
|
/* |
|
* Check to make sure an IPv6 address does not contain multiple instances |
|
* of the string "::". Assumes strlen(s) >= 1. |
|
* Returns TRUE if address is valid else FALSE. |
|
*/ |
|
static int |
|
ipv6_valid(s) |
|
const char *s; |
|
{ |
|
int nmatch = 0; |
|
|
|
for (; *s != '\0'; s++) { |
|
if (s[0] == ':' && s[1] == ':') { |
|
if (++nmatch > 1) |
|
break; |
|
} |
|
if (s[0] == '/') |
|
nmatch = 0; /* reset if we hit netmask */ |
|
} |
|
|
|
return (nmatch <= 1); |
} |
} |
|
|
int |
int |