|
version 1.1.1.1, 2012/02/21 16:23:02
|
version 1.1.1.5, 2014/06/15 16:12:54
|
|
Line 1
|
Line 1
|
| %{ |
%{ |
| /* |
/* |
| * Copyright (c) 1996, 1998-2005, 2007-2011 | * Copyright (c) 1996, 1998-2005, 2007-2013 |
| * 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 26
|
Line 26
|
| #include <config.h> |
#include <config.h> |
| |
|
| #include <sys/types.h> |
#include <sys/types.h> |
| #include <sys/param.h> |
|
| #include <sys/stat.h> |
#include <sys/stat.h> |
| #include <stdio.h> |
#include <stdio.h> |
| #ifdef STDC_HEADERS |
#ifdef STDC_HEADERS |
|
Line 43
|
Line 42
|
| #ifdef HAVE_STRINGS_H |
#ifdef HAVE_STRINGS_H |
| # include <strings.h> |
# include <strings.h> |
| #endif /* HAVE_STRINGS_H */ |
#endif /* HAVE_STRINGS_H */ |
| |
#if defined(HAVE_STDINT_H) |
| |
# include <stdint.h> |
| |
#elif defined(HAVE_INTTYPES_H) |
| |
# include <inttypes.h> |
| |
#endif |
| #ifdef HAVE_UNISTD_H |
#ifdef HAVE_UNISTD_H |
| # include <unistd.h> |
# include <unistd.h> |
| #endif /* HAVE_UNISTD_H */ |
#endif /* HAVE_UNISTD_H */ |
|
Line 71
|
Line 75
|
| #include "parse.h" |
#include "parse.h" |
| #include "toke.h" |
#include "toke.h" |
| #include <gram.h> |
#include <gram.h> |
| |
#include "lbuf.h" |
| |
#include "sha2.h" |
| |
#include "secure_path.h" |
| |
|
| extern YYSTYPE yylval; | int sudolineno; /* current sudoers line number. */ |
| extern int parse_error; | int last_token; /* last token that was parsed. */ |
| int sudolineno; | char *sudoers; /* sudoers file being parsed. */ |
| 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 int digest_len; |
| | |
| | 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(sudoerstext, sudoersleng, 1, sudoersout)) |
| | |
| | #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 109 DEFVAR [a-z_]+
|
Line 125 DEFVAR [a-z_]+
|
| %option noinput |
%option noinput |
| %option nounput |
%option nounput |
| %option noyywrap |
%option noyywrap |
| |
%option prefix="sudoers" |
| |
|
| %s GOTDEFS |
%s GOTDEFS |
| %x GOTCMND |
%x GOTCMND |
| %x STARTDEFS |
%x STARTDEFS |
| %x INDEFS |
%x INDEFS |
| %x INSTR |
%x INSTR |
| |
%s WANTDIGEST |
| |
|
| %% |
%% |
| <GOTDEFS>[[:blank:]]*,[[:blank:]]* { |
<GOTDEFS>[[:blank:]]*,[[:blank:]]* { |
| LEXTRACE(", "); |
LEXTRACE(", "); |
| return ','; | LEXRETURN(','); |
| } /* return ',' */ |
} /* return ',' */ |
| |
|
| <GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS; |
<GOTDEFS>[[:blank:]]+ BEGIN STARTDEFS; |
|
Line 127 DEFVAR [a-z_]+
|
Line 145 DEFVAR [a-z_]+
|
| <STARTDEFS>{DEFVAR} { |
<STARTDEFS>{DEFVAR} { |
| BEGIN INDEFS; |
BEGIN INDEFS; |
| LEXTRACE("DEFVAR "); |
LEXTRACE("DEFVAR "); |
| if (!fill(yytext, yyleng)) | if (!fill(sudoerstext, sudoersleng)) |
| 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 '-' */ |
| |
|
| \" { |
\" { |
| LEXTRACE("BEGINSTR "); |
LEXTRACE("BEGINSTR "); |
| yylval.string = NULL; | sudoerslval.string = NULL; |
| prev_state = YY_START; |
prev_state = YY_START; |
| BEGIN INSTR; |
BEGIN INSTR; |
| } |
} |
| |
|
| {ENVAR} { |
{ENVAR} { |
| LEXTRACE("WORD(2) "); |
LEXTRACE("WORD(2) "); |
| if (!fill(yytext, yyleng)) | if (!fill(sudoerstext, sudoersleng)) |
| 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; |
| } |
} |
| |
|
| \" { |
\" { |
| LEXTRACE("ENDSTR "); |
LEXTRACE("ENDSTR "); |
| BEGIN prev_state; |
BEGIN prev_state; |
| |
|
| if (yylval.string == NULL) { | if (sudoerslval.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 (sudoerslval.string[0]) { |
| case '%': |
case '%': |
| if (yylval.string[1] == '\0' || | if (sudoerslval.string[1] == '\0' || |
| (yylval.string[1] == ':' && | (sudoerslval.string[1] == ':' && |
| yylval.string[2] == '\0')) { | sudoerslval.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 (sudoerslval.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); |
| } |
} |
| |
|
| \\ { |
\\ { |
| LEXTRACE("BACKSLASH "); |
LEXTRACE("BACKSLASH "); |
| if (!append(yytext, yyleng)) | if (!append(sudoerstext, sudoersleng)) |
| yyterminate(); |
yyterminate(); |
| } |
} |
| |
|
| ([^\"\n\\]|\\\")+ { |
([^\"\n\\]|\\\")+ { |
| LEXTRACE("STRBODY "); |
LEXTRACE("STRBODY "); |
| if (!append(yytext, yyleng)) | if (!append(sudoerstext, sudoersleng)) |
| yyterminate(); |
yyterminate(); |
| } |
} |
| } |
} |
|
Line 225 DEFVAR [a-z_]+
|
Line 243 DEFVAR [a-z_]+
|
| \\[\*\?\[\]\!] { |
\\[\*\?\[\]\!] { |
| /* quoted fnmatch glob char, pass verbatim */ |
/* quoted fnmatch glob char, pass verbatim */ |
| LEXTRACE("QUOTEDCHAR "); |
LEXTRACE("QUOTEDCHAR "); |
| if (!fill_args(yytext, 2, sawspace)) | if (!fill_args(sudoerstext, 2, sawspace)) |
| yyterminate(); |
yyterminate(); |
| sawspace = FALSE; | sawspace = false; |
| } |
} |
| |
|
| \\[:\\,= \t#] { |
\\[:\\,= \t#] { |
| /* quoted sudoers special char, strip backslash */ |
/* quoted sudoers special char, strip backslash */ |
| LEXTRACE("QUOTEDCHAR "); |
LEXTRACE("QUOTEDCHAR "); |
| if (!fill_args(yytext + 1, 1, sawspace)) | if (!fill_args(sudoerstext + 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(sudoerstext, sudoersleng, sawspace)) |
| yyterminate(); |
yyterminate(); |
| sawspace = FALSE; | sawspace = false; |
| } /* a command line arg */ |
} /* a command line arg */ |
| } |
} |
| |
|
| <INITIAL>^#include[[:blank:]]+\/.*\n { | <WANTDIGEST>[[:xdigit:]]+ { |
| | /* Only return DIGEST if the length is correct. */ |
| | if (sudoersleng == digest_len * 2) { |
| | if (!fill(sudoerstext, sudoersleng)) |
| | yyterminate(); |
| | BEGIN INITIAL; |
| | LEXTRACE("DIGEST "); |
| | LEXRETURN(DIGEST); |
| | } |
| | BEGIN INITIAL; |
| | yyless(sudoersleng); |
| | } /* hex digest */ |
| | |
| | <WANTDIGEST>[A-Za-z0-9\+/=]+ { |
| | /* Only return DIGEST if the length is correct. */ |
| | int len; |
| | if (sudoerstext[sudoersleng - 1] == '=') { |
| | /* use padding */ |
| | len = 4 * ((digest_len + 2) / 3); |
| | } else { |
| | /* no padding */ |
| | len = (4 * digest_len + 2) / 3; |
| | } |
| | if (sudoersleng == len) { |
| | if (!fill(sudoerstext, sudoersleng)) |
| | yyterminate(); |
| | BEGIN INITIAL; |
| | LEXTRACE("DIGEST "); |
| | LEXRETURN(DIGEST); |
| | } |
| | BEGIN INITIAL; |
| | yyless(sudoersleng); |
| | } /* base64 digest */ |
| | |
| | <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(sudoerstext)) == NULL) |
| yyterminate(); |
yyterminate(); |
| |
|
| LEXTRACE("INCLUDE\n"); |
LEXTRACE("INCLUDE\n"); |
|
Line 270 DEFVAR [a-z_]+
|
Line 322 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(sudoerstext)) == NULL) |
| yyterminate(); |
yyterminate(); |
| |
|
| LEXTRACE("INCLUDEDIR\n"); |
LEXTRACE("INCLUDEDIR\n"); |
|
Line 297 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)sudoerstext[n]); n++) |
| continue; |
continue; |
| n += sizeof("Defaults") - 1; |
n += sizeof("Defaults") - 1; |
| if ((deftype = yytext[n++]) != '\0') { | if ((deftype = sudoerstext[n++]) != '\0') { |
| while (isblank((unsigned char)yytext[n])) | while (isblank((unsigned char)sudoerstext[n])) |
| n++; |
n++; |
| } |
} |
| BEGIN GOTDEFS; |
BEGIN GOTDEFS; |
|
Line 312 DEFVAR [a-z_]+
|
Line 364 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 388 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)sudoerstext[n]); n++) |
| continue; |
continue; |
| switch (yytext[n]) { | switch (sudoerstext[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} { |
| /* netgroup */ |
/* netgroup */ |
| if (!fill(yytext, yyleng)) | if (!fill(sudoerstext, sudoersleng)) |
| yyterminate(); |
yyterminate(); |
| LEXTRACE("NETGROUP "); |
LEXTRACE("NETGROUP "); |
| return NETGROUP; | LEXRETURN(NETGROUP); |
| } |
} |
| |
|
| \%:?({WORD}|{ID}) { |
\%:?({WORD}|{ID}) { |
| /* group */ |
/* group */ |
| if (!fill(yytext, yyleng)) | if (!fill(sudoerstext, sudoersleng)) |
| yyterminate(); |
yyterminate(); |
| LEXTRACE("USERGROUP "); |
LEXTRACE("USERGROUP "); |
| return USERGROUP; | LEXRETURN(USERGROUP); |
| } |
} |
| |
|
| {IPV4ADDR}(\/{IPV4ADDR})? { |
{IPV4ADDR}(\/{IPV4ADDR})? { |
| if (!fill(yytext, yyleng)) | if (!fill(sudoerstext, sudoersleng)) |
| 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(sudoerstext, sudoersleng)) |
| yyterminate(); |
yyterminate(); |
| LEXTRACE("NTWKADDR "); |
LEXTRACE("NTWKADDR "); |
| return NTWKADDR; | LEXRETURN(NTWKADDR); |
| } |
} |
| |
|
| {IPV6ADDR}(\/{IPV6ADDR})? { |
{IPV6ADDR}(\/{IPV6ADDR})? { |
| if (!ipv6_valid(yytext)) { | if (!ipv6_valid(sudoerstext)) { |
| LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
| return ERROR; | LEXRETURN(ERROR); |
| } |
} |
| if (!fill(yytext, yyleng)) | if (!fill(sudoerstext, sudoersleng)) |
| 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(sudoerstext)) { |
| LEXTRACE("ERROR "); |
LEXTRACE("ERROR "); |
| return ERROR; | LEXRETURN(ERROR); |
| } |
} |
| if (!fill(yytext, yyleng)) | if (!fill(sudoerstext, sudoersleng)) |
| 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 537 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(sudoerstext, sudoersleng)) |
| if (!fill(yytext, yyleng)) | |
| yyterminate(); |
yyterminate(); |
| LEXTRACE("ALIAS "); |
LEXTRACE("ALIAS "); |
| return ALIAS; | LEXRETURN(ALIAS); |
| } |
} |
| |
|
| <GOTDEFS>({PATH}|sudoedit) { |
<GOTDEFS>({PATH}|sudoedit) { |
| |
/* XXX - no way to specify digest for command */ |
| /* no command args allowed for Defaults!/path */ |
/* no command args allowed for Defaults!/path */ |
| if (!fill_cmnd(yytext, yyleng)) | if (!fill_cmnd(sudoerstext, sudoersleng)) |
| yyterminate(); |
yyterminate(); |
| LEXTRACE("COMMAND "); |
LEXTRACE("COMMAND "); |
| return COMMAND; | LEXRETURN(COMMAND); |
| } |
} |
| |
|
| |
sha224 { |
| |
digest_len = SHA224_DIGEST_LENGTH; |
| |
BEGIN WANTDIGEST; |
| |
LEXTRACE("SHA224 "); |
| |
LEXRETURN(SHA224); |
| |
} |
| |
|
| |
sha256 { |
| |
digest_len = SHA256_DIGEST_LENGTH; |
| |
BEGIN WANTDIGEST; |
| |
LEXTRACE("SHA256 "); |
| |
LEXRETURN(SHA256); |
| |
} |
| |
|
| |
sha384 { |
| |
digest_len = SHA384_DIGEST_LENGTH; |
| |
BEGIN WANTDIGEST; |
| |
LEXTRACE("SHA384 "); |
| |
LEXRETURN(SHA384); |
| |
} |
| |
|
| |
sha512 { |
| |
digest_len = SHA512_DIGEST_LENGTH; |
| |
BEGIN WANTDIGEST; |
| |
LEXTRACE("SHA512 "); |
| |
LEXRETURN(SHA512); |
| |
} |
| |
|
| sudoedit { |
sudoedit { |
| BEGIN GOTCMND; |
BEGIN GOTCMND; |
| LEXTRACE("COMMAND "); |
LEXTRACE("COMMAND "); |
| if (!fill_cmnd(yytext, yyleng)) | if (!fill_cmnd(sudoerstext, sudoersleng)) |
| yyterminate(); |
yyterminate(); |
| } /* sudo -e */ |
} /* sudo -e */ |
| |
|
| {PATH} { |
{PATH} { |
| /* directories can't have args... */ |
/* directories can't have args... */ |
| if (yytext[yyleng - 1] == '/') { | if (sudoerstext[sudoersleng - 1] == '/') { |
| LEXTRACE("COMMAND "); |
LEXTRACE("COMMAND "); |
| if (!fill_cmnd(yytext, yyleng)) | if (!fill_cmnd(sudoerstext, sudoersleng)) |
| yyterminate(); |
yyterminate(); |
| return COMMAND; | LEXRETURN(COMMAND); |
| } else { |
} else { |
| BEGIN GOTCMND; |
BEGIN GOTCMND; |
| LEXTRACE("COMMAND "); |
LEXTRACE("COMMAND "); |
| if (!fill_cmnd(yytext, yyleng)) | if (!fill_cmnd(sudoerstext, sudoersleng)) |
| yyterminate(); |
yyterminate(); |
| } |
} |
| } /* a pathname */ |
} /* a pathname */ |
| |
|
| <INITIAL,GOTDEFS>\" { |
<INITIAL,GOTDEFS>\" { |
| LEXTRACE("BEGINSTR "); |
LEXTRACE("BEGINSTR "); |
| yylval.string = NULL; | sudoerslval.string = NULL; |
| prev_state = YY_START; |
prev_state = YY_START; |
| BEGIN INSTR; |
BEGIN INSTR; |
| } |
} |
| |
|
| <INITIAL,GOTDEFS>({ID}|{WORD}) { |
<INITIAL,GOTDEFS>({ID}|{WORD}) { |
| /* a word */ |
/* a word */ |
| if (!fill(yytext, yyleng)) | if (!fill(sudoerstext, sudoersleng)) |
| 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 (sudoersleng & 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; | if (sudoerstext[sudoersleng - 1] == '\n') { |
| ++sudolineno; | /* comment ending in a newline */ |
| continued = FALSE; | BEGIN INITIAL; |
| | sudolineno++; |
| | continued = false; |
| | } else if (!feof(yyin)) { |
| | LEXTRACE("ERROR "); |
| | LEXRETURN(ERROR); |
| | } |
| 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 625 sudoedit {
|
Line 727 sudoedit {
|
| |
|
| %% |
%% |
| struct path_list { |
struct path_list { |
| |
SLIST_ENTRY(path_list) entries; |
| char *path; |
char *path; |
| struct path_list *next; |
|
| }; |
}; |
| |
|
| |
SLIST_HEAD(path_list_head, path_list); |
| |
|
| struct include_stack { |
struct include_stack { |
| YY_BUFFER_STATE bs; |
YY_BUFFER_STATE bs; |
| char *path; |
char *path; |
| struct path_list *more; /* more files in case of includedir */ | struct path_list_head more; /* more files in case of includedir */ |
| int lineno; |
int lineno; |
| int keepopen; | bool keepopen; |
| }; |
}; |
| |
|
| |
/* |
| |
* Compare two struct path_list structs in reverse order. |
| |
*/ |
| static int |
static int |
| pl_compare(const void *v1, const void *v2) |
pl_compare(const void *v1, const void *v2) |
| { |
{ |
| const struct path_list * const *p1 = v1; |
const struct path_list * const *p1 = v1; |
| const struct path_list * const *p2 = v2; |
const struct path_list * const *p2 = v2; |
| |
|
| return strcmp((*p1)->path, (*p2)->path); | return strcmp((*p2)->path, (*p1)->path); |
| } |
} |
| |
|
| static char * |
static char * |
| switch_dir(struct include_stack *stack, char *dirpath) |
switch_dir(struct include_stack *stack, char *dirpath) |
| { |
{ |
| DIR *dir; |
DIR *dir; |
| int i, count = 0; | unsigned int i, count = 0; |
| | unsigned int max_paths = 32; |
| char *path = NULL; |
char *path = NULL; |
| struct dirent *dent; |
struct dirent *dent; |
| struct stat sb; |
struct stat sb; |
| struct path_list *pl, *first = NULL; | struct path_list *pl, **paths = 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) { |
| char *errbuf; | warning("%s", dirpath); |
| if (asprintf(&errbuf, _("%s: %s"), dirpath, strerror(errno)) != -1) { | sudoerserror(NULL); |
| yyerror(errbuf); | |
| free(errbuf); | |
| } else { | |
| yyerror(_("unable to allocate memory")); | |
| } | |
| } |
} |
| goto done; |
goto done; |
| } |
} |
| |
paths = malloc(sizeof(*paths) * max_paths); |
| |
if (paths == NULL) { |
| |
closedir(dir); |
| |
goto bad; |
| |
} |
| while ((dent = readdir(dir))) { |
while ((dent = readdir(dir))) { |
| /* Ignore files that end in '~' or have a '.' in them. */ |
/* Ignore files that end in '~' or have a '.' in them. */ |
| if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' |
if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' |
|
Line 688 switch_dir(struct include_stack *stack, char *dirpath)
|
Line 796 switch_dir(struct include_stack *stack, char *dirpath)
|
| if (pl == NULL) |
if (pl == NULL) |
| goto bad; |
goto bad; |
| pl->path = path; |
pl->path = path; |
| pl->next = first; | if (count >= max_paths) { |
| first = pl; | struct path_list **tmp; |
| count++; | max_paths <<= 1; |
| | tmp = realloc(paths, sizeof(*paths) * max_paths); |
| | if (tmp == NULL) { |
| | closedir(dir); |
| | goto bad; |
| | } |
| | paths = tmp; |
| | } |
| | paths[count++] = pl; |
| | path = NULL; |
| } |
} |
| closedir(dir); |
closedir(dir); |
| |
|
| if (count == 0) |
if (count == 0) |
| goto done; |
goto done; |
| |
|
| /* Sort the list as an array. */ | /* Sort the list as an array in reverse order. */ |
| sorted = malloc(sizeof(*sorted) * count); | qsort(paths, count, sizeof(*paths), pl_compare); |
| if (sorted == NULL) | |
| goto bad; | /* Build up the list in sorted order. */ |
| pl = first; | |
| for (i = 0; i < count; i++) { |
for (i = 0; i < count; i++) { |
| sorted[i] = pl; | SLIST_INSERT_HEAD(&stack->more, paths[i], entries); |
| pl = pl->next; | |
| } |
} |
| qsort(sorted, count, sizeof(*sorted), pl_compare); |
|
| |
|
| /* Apply sorting to the list. */ |
|
| first = sorted[0]; |
|
| sorted[count - 1]->next = NULL; |
|
| for (i = 1; i < count; i++) |
|
| sorted[i - 1]->next = sorted[i]; |
|
| efree(sorted); |
|
| |
|
| /* Pull out the first element for parsing, leave the rest for later. */ |
/* Pull out the first element for parsing, leave the rest for later. */ |
| if (count) { | pl = SLIST_FIRST(&stack->more); |
| path = first->path; | SLIST_REMOVE_HEAD(&stack->more, entries); |
| pl = first->next; | path = pl->path; |
| efree(first); | efree(pl); |
| stack->more = pl; | |
| } else { | |
| path = NULL; | |
| } | |
| done: |
done: |
| |
efree(paths); |
| efree(dirpath); |
efree(dirpath); |
| return path; | debug_return_str(path); |
| bad: |
bad: |
| while (first != NULL) { | for (i = 0; i < count; i++) { |
| pl = first; | efree(paths[i]->path); |
| first = pl->next; | efree(paths[i]); |
| free(pl->path); | |
| free(pl); | |
| } |
} |
| efree(sorted); | efree(paths); |
| 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 847 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--; |
| while ((pl = istack[idepth].more) != NULL) { | while ((pl = SLIST_FIRST(&istack[idepth].more)) != NULL) { |
| istack[idepth].more = pl->next; | SLIST_REMOVE_HEAD(&istack[idepth].more, entries); |
| efree(pl->path); |
efree(pl->path); |
| efree(pl); |
efree(pl); |
| } |
} |
| efree(istack[idepth].path); |
efree(istack[idepth].path); |
| if (idepth && !istack[idepth].keepopen) |
if (idepth && !istack[idepth].keepopen) |
| fclose(istack[idepth].bs->yy_input_file); |
fclose(istack[idepth].bs->yy_input_file); |
| yy_delete_buffer(istack[idepth].bs); | sudoers_delete_buffer(istack[idepth].bs); |
| } |
} |
| efree(istack); |
efree(istack); |
| 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) { |
| |
struct include_stack *new_istack; |
| |
|
| if (idepth > MAX_SUDOERS_DEPTH) { |
if (idepth > MAX_SUDOERS_DEPTH) { |
| yyerror(_("too many levels of includes")); | sudoerserror(N_("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, | new_istack = (struct include_stack *) realloc(istack, |
| sizeof(*istack) * istacksize); |
sizeof(*istack) * istacksize); |
| if (istack == NULL) { | if (new_istack == NULL) { |
| yyerror(_("unable to allocate memory")); | warning(NULL); |
| return FALSE; | sudoerserror(NULL); |
| | debug_return_bool(false); |
| } |
} |
| |
istack = new_istack; |
| } |
} |
| |
SLIST_INIT(&istack[idepth].more); |
| 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(U_("%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(U_("%s is world writable"), path); |
| |
} |
| |
debug_return_bool(false); |
| |
case SUDO_PATH_GROUP_WRITABLE: |
| |
if (sudoers_warnings) { |
| |
warningx(U_("%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 sudoerserror() 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 = SLIST_FIRST(&istack[idepth].more)) == NULL) |
| return FALSE; | debug_return_bool(false); |
| | SLIST_REMOVE_HEAD(&istack[idepth].more, entries); |
| path = pl->path; |
path = pl->path; |
| 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) { | sudoerserror(NULL); |
| yyerror(errbuf); | debug_return_bool(false); |
| free(errbuf); | |
| } else { | |
| yyerror(_("unable to allocate memory")); | |
| } | |
| return FALSE; | |
| } |
} |
| istack[idepth].more = NULL; |
|
| } |
} |
| /* Push the old (current) file and open the new one. */ |
/* Push the old (current) file and open the new one. */ |
| istack[idepth].path = sudoers; /* push old path */ |
istack[idepth].path = sudoers; /* push old path */ |
|
Line 829 _push_include(char *path, int isdir)
|
Line 969 _push_include(char *path, int isdir)
|
| idepth++; |
idepth++; |
| sudolineno = 1; |
sudolineno = 1; |
| sudoers = path; |
sudoers = path; |
| yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); | sudoers_switch_to_buffer(sudoers_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); | sudoers_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 = SLIST_FIRST(&istack[idepth - 1].more)) != NULL) { |
| fp = open_sudoers(pl->path, FALSE, &keepopen); | SLIST_REMOVE_HEAD(&istack[idepth - 1].more, entries); |
| | fp = open_sudoers(pl->path, false, &keepopen); |
| if (fp != NULL) { |
if (fp != NULL) { |
| istack[idepth - 1].more = pl->next; |
|
| efree(sudoers); |
efree(sudoers); |
| sudoers = pl->path; |
sudoers = pl->path; |
| sudolineno = 1; |
sudolineno = 1; |
| yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); | sudoers_switch_to_buffer(sudoers_create_buffer(fp, YY_BUF_SIZE)); |
| efree(pl); |
efree(pl); |
| break; |
break; |
| } |
} |
| /* Unable to open path in include dir, go to next one. */ |
/* Unable to open path in include dir, go to next one. */ |
| istack[idepth - 1].more = pl->next; |
|
| efree(pl->path); |
efree(pl->path); |
| efree(pl); |
efree(pl); |
| } |
} |
| /* If no path list, just pop the last dir on the stack. */ |
/* If no path list, just pop the last dir on the stack. */ |
| if (pl == NULL) { |
if (pl == NULL) { |
| idepth--; |
idepth--; |
| yy_switch_to_buffer(istack[idepth].bs); | sudoers_switch_to_buffer(istack[idepth].bs); |
| efree(sudoers); |
efree(sudoers); |
| sudoers = istack[idepth].path; |
sudoers = istack[idepth].path; |
| 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 1039 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); |
| yyerror(_("unable to allocate memory")); | if (path == NULL) { |
| return NULL; | warning(NULL); |
| | sudoerserror(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 1071 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 */ |