version 1.1, 2012/02/21 16:23:02
|
version 1.1.1.3, 2012/10/09 09:29:52
|
Line 1
|
Line 1
|
%{ |
%{ |
/* |
/* |
* Copyright (c) 1996, 1998-2005, 2007-2011 | * Copyright (c) 1996, 1998-2005, 2007-2012 |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* Todd C. Miller <Todd.Miller@courtesan.com> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
Line 71
|
Line 71
|
#include "parse.h" |
#include "parse.h" |
#include "toke.h" |
#include "toke.h" |
#include <gram.h> |
#include <gram.h> |
|
#include "lbuf.h" |
|
#include "secure_path.h" |
|
|
extern YYSTYPE yylval; |
extern YYSTYPE yylval; |
extern int parse_error; | extern bool parse_error; |
| extern bool sudoers_warnings; |
int sudolineno; |
int sudolineno; |
|
int last_token; |
char *sudoers; |
char *sudoers; |
|
|
static int continued, prev_state, sawspace; | /* Default sudoers path, mode and owner (may be set via sudo.conf) */ |
| const char *sudoers_file = _PATH_SUDOERS; |
| mode_t sudoers_mode = SUDOERS_MODE; |
| uid_t sudoers_uid = SUDOERS_UID; |
| gid_t sudoers_gid = SUDOERS_GID; |
|
|
static int _push_include(char *, int); | static bool continued, sawspace; |
static int pop_include(void); | static int prev_state; |
| |
| static bool _push_include(char *, bool); |
| static bool pop_include(void); |
static char *parse_include(char *); |
static char *parse_include(char *); |
|
|
#ifdef TRACELEXER |
|
static int sudoers_trace_print(const char *msg); |
|
#else |
|
# define sudoers_trace_print NULL |
|
#endif |
|
int (*trace_print)(const char *msg) = sudoers_trace_print; |
int (*trace_print)(const char *msg) = sudoers_trace_print; |
|
|
#define push_include(_p) (_push_include((_p), FALSE)) | #define LEXRETURN(n) do { \ |
#define push_includedir(_p) (_push_include((_p), TRUE)) | last_token = (n); \ |
| return (n); \ |
| } while (0) |
| |
| #define ECHO ignore_result(fwrite(yytext, yyleng, 1, yyout)) |
| |
| #define push_include(_p) (_push_include((_p), false)) |
| #define push_includedir(_p) (_push_include((_p), true)) |
%} |
%} |
|
|
HEX16 [0-9A-Fa-f]{1,4} |
HEX16 [0-9A-Fa-f]{1,4} |
Line 119 DEFVAR [a-z_]+
|
Line 132 DEFVAR [a-z_]+
|
%% |
%% |
<GOTDEFS>[[:blank:]]*,[[:blank:]]* { |
<GOTDEFS>[[:blank:]]*,[[:blank:]]* { |
LEXTRACE(", "); |
LEXTRACE(", "); |
return ','; | LEXRETURN(','); |
} /* return ',' */ |
} /* return ',' */ |
|
|
<GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS; |
<GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS; |
Line 129 DEFVAR [a-z_]+
|
Line 142 DEFVAR [a-z_]+
|
LEXTRACE("DEFVAR "); |
LEXTRACE("DEFVAR "); |
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
return DEFVAR; | LEXRETURN(DEFVAR); |
} |
} |
|
|
<INDEFS>{ |
<INDEFS>{ |
, { |
, { |
BEGIN STARTDEFS; |
BEGIN STARTDEFS; |
LEXTRACE(", "); |
LEXTRACE(", "); |
return ','; | LEXRETURN(','); |
} /* return ',' */ |
} /* return ',' */ |
|
|
= { |
= { |
LEXTRACE("= "); |
LEXTRACE("= "); |
return '='; | LEXRETURN('='); |
} /* return '=' */ |
} /* return '=' */ |
|
|
\+= { |
\+= { |
LEXTRACE("+= "); |
LEXTRACE("+= "); |
return '+'; | LEXRETURN('+'); |
} /* return '+' */ |
} /* return '+' */ |
|
|
-= { |
-= { |
LEXTRACE("-= "); |
LEXTRACE("-= "); |
return '-'; | LEXRETURN('-'); |
} /* return '-' */ |
} /* return '-' */ |
|
|
\" { |
\" { |
Line 165 DEFVAR [a-z_]+
|
Line 178 DEFVAR [a-z_]+
|
LEXTRACE("WORD(2) "); |
LEXTRACE("WORD(2) "); |
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
return WORD; | LEXRETURN(WORD); |
} |
} |
} |
} |
|
|
<INSTR>{ |
<INSTR>{ |
\\[[:blank:]]*\n[[:blank:]]* { |
\\[[:blank:]]*\n[[:blank:]]* { |
/* Line continuation char followed by newline. */ |
/* Line continuation char followed by newline. */ |
++sudolineno; | sudolineno++; |
continued = TRUE; | continued = true; |
} |
} |
|
|
\" { |
\" { |
Line 182 DEFVAR [a-z_]+
|
Line 195 DEFVAR [a-z_]+
|
|
|
if (yylval.string == NULL) { |
if (yylval.string == NULL) { |
LEXTRACE("ERROR "); /* empty string */ |
LEXTRACE("ERROR "); /* empty string */ |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
if (prev_state == INITIAL) { |
if (prev_state == INITIAL) { |
switch (yylval.string[0]) { |
switch (yylval.string[0]) { |
Line 191 DEFVAR [a-z_]+
|
Line 204 DEFVAR [a-z_]+
|
(yylval.string[1] == ':' && |
(yylval.string[1] == ':' && |
yylval.string[2] == '\0')) { |
yylval.string[2] == '\0')) { |
LEXTRACE("ERROR "); /* empty group */ |
LEXTRACE("ERROR "); /* empty group */ |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
LEXTRACE("USERGROUP "); |
LEXTRACE("USERGROUP "); |
return USERGROUP; | LEXRETURN(USERGROUP); |
case '+': |
case '+': |
if (yylval.string[1] == '\0') { |
if (yylval.string[1] == '\0') { |
LEXTRACE("ERROR "); /* empty netgroup */ |
LEXTRACE("ERROR "); /* empty netgroup */ |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
LEXTRACE("NETGROUP "); |
LEXTRACE("NETGROUP "); |
return NETGROUP; | LEXRETURN(NETGROUP); |
} |
} |
} |
} |
LEXTRACE("WORD(4) "); |
LEXTRACE("WORD(4) "); |
return WORD; | LEXRETURN(WORD); |
} |
} |
|
|
\\ { |
\\ { |
Line 227 DEFVAR [a-z_]+
|
Line 240 DEFVAR [a-z_]+
|
LEXTRACE("QUOTEDCHAR "); |
LEXTRACE("QUOTEDCHAR "); |
if (!fill_args(yytext, 2, sawspace)) |
if (!fill_args(yytext, 2, sawspace)) |
yyterminate(); |
yyterminate(); |
sawspace = FALSE; | sawspace = false; |
} |
} |
|
|
\\[:\\,= \t#] { |
\\[:\\,= \t#] { |
Line 235 DEFVAR [a-z_]+
|
Line 248 DEFVAR [a-z_]+
|
LEXTRACE("QUOTEDCHAR "); |
LEXTRACE("QUOTEDCHAR "); |
if (!fill_args(yytext + 1, 1, sawspace)) |
if (!fill_args(yytext + 1, 1, sawspace)) |
yyterminate(); |
yyterminate(); |
sawspace = FALSE; | sawspace = false; |
} |
} |
|
|
[#:\,=\n] { |
[#:\,=\n] { |
BEGIN INITIAL; |
BEGIN INITIAL; |
yyless(0); |
yyless(0); |
return COMMAND; | LEXRETURN(COMMAND); |
} /* end of command line args */ |
} /* end of command line args */ |
|
|
[^#\\:, \t\n]+ { |
[^#\\:, \t\n]+ { |
LEXTRACE("ARG "); |
LEXTRACE("ARG "); |
if (!fill_args(yytext, yyleng, sawspace)) |
if (!fill_args(yytext, yyleng, sawspace)) |
yyterminate(); |
yyterminate(); |
sawspace = FALSE; | sawspace = false; |
} /* a command line arg */ |
} /* a command line arg */ |
} |
} |
|
|
<INITIAL>^#include[[:blank:]]+\/.*\n { | <INITIAL>^#include[[:blank:]]+.*\n { |
char *path; |
char *path; |
|
|
if (continued) { |
if (continued) { |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
|
|
if ((path = parse_include(yytext)) == NULL) |
if ((path = parse_include(yytext)) == NULL) |
Line 270 DEFVAR [a-z_]+
|
Line 283 DEFVAR [a-z_]+
|
yyterminate(); |
yyterminate(); |
} |
} |
|
|
<INITIAL>^#includedir[[:blank:]]+\/.*\n { | <INITIAL>^#includedir[[:blank:]]+.*\n { |
char *path; |
char *path; |
|
|
if (continued) { |
if (continued) { |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
|
|
if ((path = parse_include(yytext)) == NULL) |
if ((path = parse_include(yytext)) == NULL) |
Line 297 DEFVAR [a-z_]+
|
Line 310 DEFVAR [a-z_]+
|
|
|
if (continued) { |
if (continued) { |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
|
|
for (n = 0; isblank((unsigned char)yytext[n]); n++) |
for (n = 0; isblank((unsigned char)yytext[n]); n++) |
Line 312 DEFVAR [a-z_]+
|
Line 325 DEFVAR [a-z_]+
|
case ':': |
case ':': |
yyless(n); |
yyless(n); |
LEXTRACE("DEFAULTS_USER "); |
LEXTRACE("DEFAULTS_USER "); |
return DEFAULTS_USER; | LEXRETURN(DEFAULTS_USER); |
case '>': |
case '>': |
yyless(n); |
yyless(n); |
LEXTRACE("DEFAULTS_RUNAS "); |
LEXTRACE("DEFAULTS_RUNAS "); |
return DEFAULTS_RUNAS; | LEXRETURN(DEFAULTS_RUNAS); |
case '@': |
case '@': |
yyless(n); |
yyless(n); |
LEXTRACE("DEFAULTS_HOST "); |
LEXTRACE("DEFAULTS_HOST "); |
return DEFAULTS_HOST; | LEXRETURN(DEFAULTS_HOST); |
case '!': |
case '!': |
yyless(n); |
yyless(n); |
LEXTRACE("DEFAULTS_CMND "); |
LEXTRACE("DEFAULTS_CMND "); |
return DEFAULTS_CMND; | LEXRETURN(DEFAULTS_CMND); |
default: |
default: |
LEXTRACE("DEFAULTS "); |
LEXTRACE("DEFAULTS "); |
return DEFAULTS; | LEXRETURN(DEFAULTS); |
} |
} |
} |
} |
|
|
Line 336 DEFVAR [a-z_]+
|
Line 349 DEFVAR [a-z_]+
|
|
|
if (continued) { |
if (continued) { |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
|
|
for (n = 0; isblank((unsigned char)yytext[n]); n++) |
for (n = 0; isblank((unsigned char)yytext[n]); n++) |
Line 344 DEFVAR [a-z_]+
|
Line 357 DEFVAR [a-z_]+
|
switch (yytext[n]) { |
switch (yytext[n]) { |
case 'H': |
case 'H': |
LEXTRACE("HOSTALIAS "); |
LEXTRACE("HOSTALIAS "); |
return HOSTALIAS; | LEXRETURN(HOSTALIAS); |
case 'C': |
case 'C': |
LEXTRACE("CMNDALIAS "); |
LEXTRACE("CMNDALIAS "); |
return CMNDALIAS; | LEXRETURN(CMNDALIAS); |
case 'U': |
case 'U': |
LEXTRACE("USERALIAS "); |
LEXTRACE("USERALIAS "); |
return USERALIAS; | LEXRETURN(USERALIAS); |
case 'R': |
case 'R': |
LEXTRACE("RUNASALIAS "); |
LEXTRACE("RUNASALIAS "); |
return RUNASALIAS; | LEXRETURN(RUNASALIAS); |
} |
} |
} |
} |
|
|
NOPASSWD[[:blank:]]*: { |
NOPASSWD[[:blank:]]*: { |
/* cmnd does not require passwd for this user */ |
/* cmnd does not require passwd for this user */ |
LEXTRACE("NOPASSWD "); |
LEXTRACE("NOPASSWD "); |
return NOPASSWD; | LEXRETURN(NOPASSWD); |
} |
} |
|
|
PASSWD[[:blank:]]*: { |
PASSWD[[:blank:]]*: { |
/* cmnd requires passwd for this user */ |
/* cmnd requires passwd for this user */ |
LEXTRACE("PASSWD "); |
LEXTRACE("PASSWD "); |
return PASSWD; | LEXRETURN(PASSWD); |
} |
} |
|
|
NOEXEC[[:blank:]]*: { |
NOEXEC[[:blank:]]*: { |
LEXTRACE("NOEXEC "); |
LEXTRACE("NOEXEC "); |
return NOEXEC; | LEXRETURN(NOEXEC); |
} |
} |
|
|
EXEC[[:blank:]]*: { |
EXEC[[:blank:]]*: { |
LEXTRACE("EXEC "); |
LEXTRACE("EXEC "); |
return EXEC; | LEXRETURN(EXEC); |
} |
} |
|
|
SETENV[[:blank:]]*: { |
SETENV[[:blank:]]*: { |
LEXTRACE("SETENV "); |
LEXTRACE("SETENV "); |
return SETENV; | LEXRETURN(SETENV); |
} |
} |
|
|
NOSETENV[[:blank:]]*: { |
NOSETENV[[:blank:]]*: { |
LEXTRACE("NOSETENV "); |
LEXTRACE("NOSETENV "); |
return NOSETENV; | LEXRETURN(NOSETENV); |
} |
} |
|
|
LOG_OUTPUT[[:blank:]]*: { |
LOG_OUTPUT[[:blank:]]*: { |
LEXTRACE("LOG_OUTPUT "); |
LEXTRACE("LOG_OUTPUT "); |
return LOG_OUTPUT; | LEXRETURN(LOG_OUTPUT); |
} |
} |
|
|
NOLOG_OUTPUT[[:blank:]]*: { |
NOLOG_OUTPUT[[:blank:]]*: { |
LEXTRACE("NOLOG_OUTPUT "); |
LEXTRACE("NOLOG_OUTPUT "); |
return NOLOG_OUTPUT; | LEXRETURN(NOLOG_OUTPUT); |
} |
} |
|
|
LOG_INPUT[[:blank:]]*: { |
LOG_INPUT[[:blank:]]*: { |
LEXTRACE("LOG_INPUT "); |
LEXTRACE("LOG_INPUT "); |
return LOG_INPUT; | LEXRETURN(LOG_INPUT); |
} |
} |
|
|
NOLOG_INPUT[[:blank:]]*: { |
NOLOG_INPUT[[:blank:]]*: { |
LEXTRACE("NOLOG_INPUT "); |
LEXTRACE("NOLOG_INPUT "); |
return NOLOG_INPUT; | LEXRETURN(NOLOG_INPUT); |
} |
} |
|
|
<INITIAL,GOTDEFS>(\+|\%|\%:) { |
<INITIAL,GOTDEFS>(\+|\%|\%:) { |
/* empty group or netgroup */ |
/* empty group or netgroup */ |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
|
|
\+{WORD} { |
\+{WORD} { |
Line 420 NOLOG_INPUT[[:blank:]]*: {
|
Line 433 NOLOG_INPUT[[:blank:]]*: {
|
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
LEXTRACE("NETGROUP "); |
LEXTRACE("NETGROUP "); |
return NETGROUP; | LEXRETURN(NETGROUP); |
} |
} |
|
|
\%:?({WORD}|{ID}) { |
\%:?({WORD}|{ID}) { |
Line 428 NOLOG_INPUT[[:blank:]]*: {
|
Line 441 NOLOG_INPUT[[:blank:]]*: {
|
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
LEXTRACE("USERGROUP "); |
LEXTRACE("USERGROUP "); |
return USERGROUP; | LEXRETURN(USERGROUP); |
} |
} |
|
|
{IPV4ADDR}(\/{IPV4ADDR})? { |
{IPV4ADDR}(\/{IPV4ADDR})? { |
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
LEXTRACE("NTWKADDR "); |
LEXTRACE("NTWKADDR "); |
return NTWKADDR; | LEXRETURN(NTWKADDR); |
} |
} |
|
|
{IPV4ADDR}\/([12]?[0-9]|3[0-2]) { |
{IPV4ADDR}\/([12]?[0-9]|3[0-2]) { |
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
LEXTRACE("NTWKADDR "); |
LEXTRACE("NTWKADDR "); |
return NTWKADDR; | LEXRETURN(NTWKADDR); |
} |
} |
|
|
{IPV6ADDR}(\/{IPV6ADDR})? { |
{IPV6ADDR}(\/{IPV6ADDR})? { |
if (!ipv6_valid(yytext)) { |
if (!ipv6_valid(yytext)) { |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
LEXTRACE("NTWKADDR "); |
LEXTRACE("NTWKADDR "); |
return NTWKADDR; | LEXRETURN(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)) { |
if (!ipv6_valid(yytext)) { |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
LEXTRACE("NTWKADDR "); |
LEXTRACE("NTWKADDR "); |
return NTWKADDR; | LEXRETURN(NTWKADDR); |
} |
} |
|
|
ALL { |
ALL { |
LEXTRACE("ALL "); |
LEXTRACE("ALL "); |
return ALL; | LEXRETURN(ALL); |
|
|
} |
} |
|
|
<INITIAL>ROLE { |
<INITIAL>ROLE { |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
LEXTRACE("ROLE "); |
LEXTRACE("ROLE "); |
return ROLE; | LEXRETURN(ROLE); |
#else |
#else |
goto got_alias; |
goto got_alias; |
#endif |
#endif |
Line 485 ALL {
|
Line 498 ALL {
|
<INITIAL>TYPE { |
<INITIAL>TYPE { |
#ifdef HAVE_SELINUX |
#ifdef HAVE_SELINUX |
LEXTRACE("TYPE "); |
LEXTRACE("TYPE "); |
return TYPE; | LEXRETURN(TYPE); |
#else |
#else |
goto got_alias; |
goto got_alias; |
#endif |
#endif |
} |
} |
|
<INITIAL>PRIVS { |
|
#ifdef HAVE_PRIV_SET |
|
LEXTRACE("PRIVS "); |
|
LEXRETURN(PRIVS); |
|
#else |
|
goto got_alias; |
|
#endif |
|
} |
|
|
|
<INITIAL>LIMITPRIVS { |
|
#ifdef HAVE_PRIV_SET |
|
LEXTRACE("LIMITPRIVS "); |
|
LEXRETURN(LIMITPRIVS); |
|
#else |
|
goto got_alias; |
|
#endif |
|
} |
|
|
[[:upper:]][[:upper:][:digit:]_]* { |
[[:upper:]][[:upper:][:digit:]_]* { |
#ifndef HAVE_SELINUX |
|
got_alias: |
got_alias: |
#endif |
|
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
LEXTRACE("ALIAS "); |
LEXTRACE("ALIAS "); |
return ALIAS; | LEXRETURN(ALIAS); |
} |
} |
|
|
<GOTDEFS>({PATH}|sudoedit) { |
<GOTDEFS>({PATH}|sudoedit) { |
Line 506 ALL {
|
Line 534 ALL {
|
if (!fill_cmnd(yytext, yyleng)) |
if (!fill_cmnd(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
LEXTRACE("COMMAND "); |
LEXTRACE("COMMAND "); |
return COMMAND; | LEXRETURN(COMMAND); |
} |
} |
|
|
sudoedit { |
sudoedit { |
Line 522 sudoedit {
|
Line 550 sudoedit {
|
LEXTRACE("COMMAND "); |
LEXTRACE("COMMAND "); |
if (!fill_cmnd(yytext, yyleng)) |
if (!fill_cmnd(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
return COMMAND; | LEXRETURN(COMMAND); |
} else { |
} else { |
BEGIN GOTCMND; |
BEGIN GOTCMND; |
LEXTRACE("COMMAND "); |
LEXTRACE("COMMAND "); |
Line 543 sudoedit {
|
Line 571 sudoedit {
|
if (!fill(yytext, yyleng)) |
if (!fill(yytext, yyleng)) |
yyterminate(); |
yyterminate(); |
LEXTRACE("WORD(5) "); |
LEXTRACE("WORD(5) "); |
return WORD; | LEXRETURN(WORD); |
} |
} |
|
|
\( { |
\( { |
LEXTRACE("( "); |
LEXTRACE("( "); |
return '('; | LEXRETURN('('); |
} |
} |
|
|
\) { |
\) { |
LEXTRACE(") "); |
LEXTRACE(") "); |
return ')'; | LEXRETURN(')'); |
} |
} |
|
|
, { |
, { |
LEXTRACE(", "); |
LEXTRACE(", "); |
return ','; | LEXRETURN(','); |
} /* return ',' */ |
} /* return ',' */ |
|
|
= { |
= { |
LEXTRACE("= "); |
LEXTRACE("= "); |
return '='; | LEXRETURN('='); |
} /* return '=' */ |
} /* return '=' */ |
|
|
: { |
: { |
LEXTRACE(": "); |
LEXTRACE(": "); |
return ':'; | LEXRETURN(':'); |
} /* return ':' */ |
} /* return ':' */ |
|
|
<*>!+ { |
<*>!+ { |
if (yyleng & 1) { |
if (yyleng & 1) { |
LEXTRACE("!"); |
LEXTRACE("!"); |
return '!'; /* return '!' */ | LEXRETURN('!'); /* return '!' */ |
} |
} |
} |
} |
|
|
<*>\n { |
<*>\n { |
if (YY_START == INSTR) { |
if (YY_START == INSTR) { |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; /* line break in string */ | LEXRETURN(ERROR); /* line break in string */ |
} |
} |
BEGIN INITIAL; |
BEGIN INITIAL; |
++sudolineno; | sudolineno++; |
continued = FALSE; | continued = false; |
LEXTRACE("\n"); |
LEXTRACE("\n"); |
return COMMENT; | LEXRETURN(COMMENT); |
} /* return newline */ |
} /* return newline */ |
|
|
<*>[[:blank:]]+ { /* throw away space/tabs */ |
<*>[[:blank:]]+ { /* throw away space/tabs */ |
sawspace = TRUE; /* but remember for fill_args */ | sawspace = true; /* but remember for fill_args */ |
} |
} |
|
|
<*>\\[[:blank:]]*\n { |
<*>\\[[:blank:]]*\n { |
sawspace = TRUE; /* remember for fill_args */ | sawspace = true; /* remember for fill_args */ |
++sudolineno; | sudolineno++; |
continued = TRUE; | continued = true; |
} /* throw away EOL after \ */ |
} /* throw away EOL after \ */ |
|
|
<INITIAL,STARTDEFS,INDEFS>#(-[^\n0-9].*|[^\n0-9-].*)?\n { |
<INITIAL,STARTDEFS,INDEFS>#(-[^\n0-9].*|[^\n0-9-].*)?\n { |
BEGIN INITIAL; |
BEGIN INITIAL; |
++sudolineno; | sudolineno++; |
continued = FALSE; | continued = false; |
LEXTRACE("#\n"); |
LEXTRACE("#\n"); |
return COMMENT; | LEXRETURN(COMMENT); |
} /* comment, not uid/gid */ |
} /* comment, not uid/gid */ |
|
|
<*>. { |
<*>. { |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; | LEXRETURN(ERROR); |
} /* parse error */ |
} /* parse error */ |
|
|
<*><<EOF>> { |
<*><<EOF>> { |
if (YY_START != INITIAL) { |
if (YY_START != INITIAL) { |
BEGIN INITIAL; |
BEGIN INITIAL; |
LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
return ERROR; | LEXRETURN(ERROR); |
} |
} |
if (!pop_include()) |
if (!pop_include()) |
yyterminate(); |
yyterminate(); |
Line 634 struct include_stack {
|
Line 662 struct include_stack {
|
char *path; |
char *path; |
struct path_list *more; /* more files in case of includedir */ |
struct path_list *more; /* more files in case of includedir */ |
int lineno; |
int lineno; |
int keepopen; | bool keepopen; |
}; |
}; |
|
|
static int |
static int |
Line 656 switch_dir(struct include_stack *stack, char *dirpath)
|
Line 684 switch_dir(struct include_stack *stack, char *dirpath)
|
struct stat sb; |
struct stat sb; |
struct path_list *pl, *first = NULL; |
struct path_list *pl, *first = NULL; |
struct path_list **sorted = NULL; |
struct path_list **sorted = NULL; |
|
debug_decl(switch_dir, SUDO_DEBUG_PARSER) |
|
|
if (!(dir = opendir(dirpath))) { |
if (!(dir = opendir(dirpath))) { |
if (errno != ENOENT) { |
if (errno != ENOENT) { |
Line 726 switch_dir(struct include_stack *stack, char *dirpath)
|
Line 755 switch_dir(struct include_stack *stack, char *dirpath)
|
} |
} |
done: |
done: |
efree(dirpath); |
efree(dirpath); |
return path; | debug_return_str(path); |
bad: |
bad: |
while (first != NULL) { |
while (first != NULL) { |
pl = first; |
pl = first; |
Line 737 bad:
|
Line 766 bad:
|
efree(sorted); |
efree(sorted); |
efree(dirpath); |
efree(dirpath); |
efree(path); |
efree(path); |
return NULL; | debug_return_str(NULL); |
} |
} |
|
|
#define MAX_SUDOERS_DEPTH 128 |
#define MAX_SUDOERS_DEPTH 128 |
Line 745 bad:
|
Line 774 bad:
|
|
|
static size_t istacksize, idepth; |
static size_t istacksize, idepth; |
static struct include_stack *istack; |
static struct include_stack *istack; |
static int keepopen; | static bool keepopen; |
|
|
void |
void |
init_lexer(void) |
init_lexer(void) |
{ |
{ |
struct path_list *pl; |
struct path_list *pl; |
|
debug_decl(init_lexer, SUDO_DEBUG_PARSER) |
|
|
while (idepth) { |
while (idepth) { |
idepth--; |
idepth--; |
Line 768 init_lexer(void)
|
Line 798 init_lexer(void)
|
istack = NULL; |
istack = NULL; |
istacksize = idepth = 0; |
istacksize = idepth = 0; |
sudolineno = 1; |
sudolineno = 1; |
keepopen = FALSE; | keepopen = false; |
sawspace = FALSE; | sawspace = false; |
continued = FALSE; | continued = false; |
prev_state = INITIAL; |
prev_state = INITIAL; |
|
|
|
debug_return; |
} |
} |
|
|
static int | static bool |
_push_include(char *path, int isdir) | _push_include(char *path, bool isdir) |
{ |
{ |
struct path_list *pl; |
struct path_list *pl; |
FILE *fp; |
FILE *fp; |
|
debug_decl(_push_include, SUDO_DEBUG_PARSER) |
|
|
/* push current state onto stack */ |
/* push current state onto stack */ |
if (idepth >= istacksize) { |
if (idepth >= istacksize) { |
if (idepth > MAX_SUDOERS_DEPTH) { |
if (idepth > MAX_SUDOERS_DEPTH) { |
yyerror(_("too many levels of includes")); |
yyerror(_("too many levels of includes")); |
return FALSE; | debug_return_bool(false); |
} |
} |
istacksize += SUDOERS_STACK_INCREMENT; |
istacksize += SUDOERS_STACK_INCREMENT; |
istack = (struct include_stack *) realloc(istack, |
istack = (struct include_stack *) realloc(istack, |
sizeof(*istack) * istacksize); |
sizeof(*istack) * istacksize); |
if (istack == NULL) { |
if (istack == NULL) { |
yyerror(_("unable to allocate memory")); |
yyerror(_("unable to allocate memory")); |
return FALSE; | debug_return_bool(false); |
} |
} |
} |
} |
if (isdir) { |
if (isdir) { |
|
struct stat sb; |
|
switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) { |
|
case SUDO_PATH_SECURE: |
|
break; |
|
case SUDO_PATH_MISSING: |
|
debug_return_bool(false); |
|
case SUDO_PATH_BAD_TYPE: |
|
errno = ENOTDIR; |
|
if (sudoers_warnings) { |
|
warning("%s", path); |
|
} |
|
debug_return_bool(false); |
|
case SUDO_PATH_WRONG_OWNER: |
|
if (sudoers_warnings) { |
|
warningx(_("%s is owned by uid %u, should be %u"), |
|
path, (unsigned int) sb.st_uid, |
|
(unsigned int) sudoers_uid); |
|
} |
|
debug_return_bool(false); |
|
case SUDO_PATH_WORLD_WRITABLE: |
|
if (sudoers_warnings) { |
|
warningx(_("%s is world writable"), path); |
|
} |
|
debug_return_bool(false); |
|
case SUDO_PATH_GROUP_WRITABLE: |
|
if (sudoers_warnings) { |
|
warningx(_("%s is owned by gid %u, should be %u"), |
|
path, (unsigned int) sb.st_gid, |
|
(unsigned int) sudoers_gid); |
|
} |
|
debug_return_bool(false); |
|
default: |
|
/* NOTREACHED */ |
|
debug_return_bool(false); |
|
} |
if (!(path = switch_dir(&istack[idepth], path))) { |
if (!(path = switch_dir(&istack[idepth], path))) { |
/* switch_dir() called yyerror() for us */ |
/* switch_dir() called yyerror() for us */ |
return FALSE; | debug_return_bool(false); |
} |
} |
while ((fp = open_sudoers(path, FALSE, &keepopen)) == NULL) { | while ((fp = open_sudoers(path, false, &keepopen)) == NULL) { |
/* Unable to open path in includedir, go to next one, if any. */ |
/* Unable to open path in includedir, go to next one, if any. */ |
efree(path); |
efree(path); |
if ((pl = istack[idepth].more) == NULL) |
if ((pl = istack[idepth].more) == NULL) |
return FALSE; | debug_return_bool(false); |
path = pl->path; |
path = pl->path; |
istack[idepth].more = pl->next; |
istack[idepth].more = pl->next; |
efree(pl); |
efree(pl); |
} |
} |
} else { |
} else { |
if ((fp = open_sudoers(path, TRUE, &keepopen)) == NULL) { | if ((fp = open_sudoers(path, true, &keepopen)) == NULL) { |
char *errbuf; | /* The error was already printed by open_sudoers() */ |
if (asprintf(&errbuf, _("%s: %s"), path, strerror(errno)) != -1) { | yyerror(NULL); |
yyerror(errbuf); | debug_return_bool(false); |
free(errbuf); | |
} else { | |
yyerror(_("unable to allocate memory")); | |
} | |
return FALSE; | |
} |
} |
istack[idepth].more = NULL; |
istack[idepth].more = NULL; |
} |
} |
Line 831 _push_include(char *path, int isdir)
|
Line 894 _push_include(char *path, int isdir)
|
sudoers = path; |
sudoers = path; |
yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); |
yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); |
|
|
return TRUE; | debug_return_bool(true); |
} |
} |
|
|
static int | static bool |
pop_include(void) |
pop_include(void) |
{ |
{ |
struct path_list *pl; |
struct path_list *pl; |
FILE *fp; |
FILE *fp; |
|
debug_decl(pop_include, SUDO_DEBUG_PARSER) |
|
|
if (idepth == 0) |
if (idepth == 0) |
return FALSE; | debug_return_bool(false); |
|
|
if (!keepopen) |
if (!keepopen) |
fclose(YY_CURRENT_BUFFER->yy_input_file); |
fclose(YY_CURRENT_BUFFER->yy_input_file); |
yy_delete_buffer(YY_CURRENT_BUFFER); |
yy_delete_buffer(YY_CURRENT_BUFFER); |
/* If we are in an include dir, move to the next file. */ |
/* If we are in an include dir, move to the next file. */ |
while ((pl = istack[idepth - 1].more) != NULL) { |
while ((pl = istack[idepth - 1].more) != NULL) { |
fp = open_sudoers(pl->path, FALSE, &keepopen); | fp = open_sudoers(pl->path, false, &keepopen); |
if (fp != NULL) { |
if (fp != NULL) { |
istack[idepth - 1].more = pl->next; |
istack[idepth - 1].more = pl->next; |
efree(sudoers); |
efree(sudoers); |
Line 872 pop_include(void)
|
Line 936 pop_include(void)
|
sudolineno = istack[idepth].lineno; |
sudolineno = istack[idepth].lineno; |
keepopen = istack[idepth].keepopen; |
keepopen = istack[idepth].keepopen; |
} |
} |
return TRUE; | debug_return_bool(true); |
} |
} |
|
|
static char * |
static char * |
parse_include(char *base) |
parse_include(char *base) |
{ |
{ |
char *cp, *ep, *path; | char *cp, *ep, *path, *pp; |
int len = 0, subst = 0; | int dirlen = 0, len = 0, subst = 0; |
size_t shost_len = 0; |
size_t shost_len = 0; |
|
debug_decl(parse_include, SUDO_DEBUG_PARSER) |
|
|
/* Pull out path from #include line. */ |
/* Pull out path from #include line. */ |
cp = base + sizeof("#include"); |
cp = base + sizeof("#include"); |
Line 898 parse_include(char *base)
|
Line 963 parse_include(char *base)
|
ep++; |
ep++; |
} |
} |
|
|
/* Make a copy of path and return it. */ | /* Relative paths are located in the same dir as the sudoers file. */ |
| if (*cp != '/') { |
| char *dirend = strrchr(sudoers, '/'); |
| if (dirend != NULL) |
| dirlen = (int)(dirend - sudoers) + 1; |
| } |
| |
| /* Make a copy of the fully-qualified path and return it. */ |
len += (int)(ep - cp); |
len += (int)(ep - cp); |
if ((path = malloc(len + 1)) == NULL) { | path = pp = malloc(len + dirlen + 1); |
| if (path == NULL) { |
yyerror(_("unable to allocate memory")); |
yyerror(_("unable to allocate memory")); |
return NULL; | debug_return_str(NULL); |
} |
} |
|
if (dirlen) { |
|
memcpy(path, sudoers, dirlen); |
|
pp += dirlen; |
|
} |
if (subst) { |
if (subst) { |
/* substitute for %h */ |
/* substitute for %h */ |
char *pp = path; |
|
while (cp < ep) { |
while (cp < ep) { |
if (cp[0] == '%' && cp[1] == 'h') { |
if (cp[0] == '%' && cp[1] == 'h') { |
memcpy(pp, user_shost, shost_len); |
memcpy(pp, user_shost, shost_len); |
Line 918 parse_include(char *base)
|
Line 994 parse_include(char *base)
|
} |
} |
*pp = '\0'; |
*pp = '\0'; |
} else { |
} else { |
memcpy(path, cp, len); | memcpy(pp, cp, len); |
path[len] = '\0'; | pp[len] = '\0'; |
} |
} |
|
|
/* Push any excess characters (e.g. comment, newline) back to the lexer */ |
/* Push any excess characters (e.g. comment, newline) back to the lexer */ |
if (*ep != '\0') |
if (*ep != '\0') |
yyless((int)(ep - base)); |
yyless((int)(ep - base)); |
|
|
return path; | debug_return_str(path); |
} |
} |
|
|
#ifdef TRACELEXER |
#ifdef TRACELEXER |
static int | int |
sudoers_trace_print(const char *msg) |
sudoers_trace_print(const char *msg) |
{ |
{ |
return fputs(msg, stderr); |
return fputs(msg, stderr); |
|
} |
|
#else |
|
int |
|
sudoers_trace_print(const char *msg) |
|
{ |
|
static bool initialized; |
|
static struct lbuf lbuf; |
|
|
|
if (!initialized) { |
|
initialized = true; |
|
lbuf_init(&lbuf, NULL, 0, NULL, 0); |
|
} |
|
|
|
lbuf_append(&lbuf, "%s", msg); |
|
/* XXX - assumes a final newline */ |
|
if (strchr(msg, '\n') != NULL) |
|
{ |
|
sudo_debug_printf2(NULL, NULL, 0, SUDO_DEBUG_PARSER|SUDO_DEBUG_DEBUG, |
|
"%s:%d %s", sudoers, sudolineno, lbuf.buf); |
|
lbuf.len = 0; |
|
} |
|
return 0; |
} |
} |
#endif /* TRACELEXER */ |
#endif /* TRACELEXER */ |