From db2a97fd0a03985e7f5150e4732c848e8af7c2b9 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 28 Sep 2004 18:31:24 +0000 Subject: [PATCH] More scaffolding for dealing with multiple sudoers files: o init_parser() now takes a path used to populate the sudoers global o the sudoers global is used to print the correct file in yyerror() o when switching to a new sudoers file, perserve old file name and line number --- parse.c | 3 +-- parse.h | 1 + parse.lex | 42 ++++++++++++++++++++++++++++++++---------- parse.yacc | 9 ++++++--- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/parse.c b/parse.c index f6abd1329..38c54a216 100644 --- a/parse.c +++ b/parse.c @@ -96,7 +96,6 @@ extern FILE *yyin, *yyout; * Prototypes */ static int has_meta __P((char *)); - void init_parser __P((void)); /* * Look up the user in the sudoers file and check to see if they are @@ -113,7 +112,7 @@ sudoers_lookup(pwflag) yyout = stdout; /* Allocate space for data structures in the parser. */ - init_parser(); + init_parser(_PATH_SUDOERS); /* If pwcheck *could* be "all" or "any", keep more state. */ if (pwflag > 0) diff --git a/parse.h b/parse.h index aa9cb55a5..4f98e9117 100644 --- a/parse.h +++ b/parse.h @@ -101,5 +101,6 @@ int hostname_matches __P((char *, char *, char *)); int netgr_matches __P((char *, char *, char *, char *)); int userpw_matches __P((char *, char *, struct passwd *)); int usergr_matches __P((char *, char *, struct passwd *)); +void init_parser __P((char *)); #endif /* _SUDO_PARSE_H */ diff --git a/parse.lex b/parse.lex index bb9596123..c7f868303 100644 --- a/parse.lex +++ b/parse.lex @@ -62,6 +62,7 @@ static const char rcsid[] = "$Sudo$"; extern YYSTYPE yylval; extern int clearaliases; int sudolineno = 1; +char *sudoers; static int sawspace = 0; static int arg_len = 0; static int arg_size = 0; @@ -69,7 +70,7 @@ static int arg_size = 0; static int fill __P((char *, int)); static int fill_cmnd __P((char *, int)); static int fill_args __P((char *, int, int)); -static int buffer_frob __P((const char *)); +static int buffer_frob __P((char *)); extern void reset_aliases __P((void)); extern void yyerror __P((const char *)); @@ -181,6 +182,7 @@ DEFVAR [a-z_]+ ^#include[ \t]+.*\n { char *cp, *ep; + ++sudolineno; /* pull out path from #include line */ for (cp = yytext + 9; isspace(*cp); cp++) continue; @@ -505,24 +507,35 @@ fill_args(s, len, addspace) return(TRUE); } -#define MAX_INCLUDE_DEPTH 128 -int +struct sudoers_state { + YY_BUFFER_STATE bs; + char *path; + int lineno; +}; + +#define MAX_SUDOERS_DEPTH 128 + +static int buffer_frob(path) - const char *path; + char *path; { static size_t stacksize, depth; - static YY_BUFFER_STATE *bufstack; + static struct sudoers_state *state; FILE *fp; if (path != NULL) { - /* push */ + /* push current state */ + if ((path = strdup(path)) == NULL) { + yyerror("unable to allocate memory"); + return(FALSE); + } if (depth >= stacksize) { - if (depth > MAX_INCLUDE_DEPTH) { + if (depth > MAX_SUDOERS_DEPTH) { yyerror("too many levels of includes"); return(FALSE); } stacksize += 16; - if ((bufstack = realloc(bufstack, stacksize)) == NULL) { + if ((state = realloc(state, sizeof(state) * stacksize)) == NULL) { yyerror("unable to allocate memory"); return(FALSE); } @@ -531,15 +544,24 @@ buffer_frob(path) yyerror(path); return(FALSE); } - bufstack[depth++] = YY_CURRENT_BUFFER; + state[depth].bs = YY_CURRENT_BUFFER; + state[depth].path = sudoers; + state[depth].lineno = sudolineno; + depth++; + sudolineno = 1; + sudoers = path; yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); } else { /* pop */ if (depth == 0) return(FALSE); + depth--; fclose(YY_CURRENT_BUFFER->yy_input_file); yy_delete_buffer(YY_CURRENT_BUFFER); - yy_switch_to_buffer(bufstack[--depth]); + yy_switch_to_buffer(state[depth].bs); + free(sudoers); + sudoers = state[depth].path; + sudolineno = state[depth].lineno; } return(TRUE); } diff --git a/parse.yacc b/parse.yacc index 9349ff71e..cb159e141 100644 --- a/parse.yacc +++ b/parse.yacc @@ -78,6 +78,7 @@ static const char rcsid[] = "$Sudo$"; * Globals */ extern int sudolineno, parse_error; +extern char *sudoers; int errorlineno = -1; int clearaliases = TRUE; int printmatches = FALSE; @@ -198,7 +199,6 @@ static void expand_ga_list __P((void)); static void expand_match_list __P((void)); static aliasinfo *find_alias __P((char *, int)); static int more_aliases __P((void)); - void init_parser __P((void)); void yyerror __P((const char *)); void @@ -210,7 +210,7 @@ yyerror(s) errorlineno = sudolineno ? sudolineno - 1 : 0; if (s && !quiet) { #ifndef TRACELEXER - (void) fprintf(stderr, ">>> sudoers file: %s, line %d <<<\n", s, + (void) fprintf(stderr, ">>> %s: %s, line %d <<<\n", sudoers, s, sudolineno ? sudolineno - 1 : 0); #else (void) fprintf(stderr, "<*> "); @@ -1250,7 +1250,7 @@ expand_match_list() * for various data structures. */ void -init_parser() +init_parser(char *path) { /* Free up old data structures if we run the parser more than once. */ @@ -1262,6 +1262,7 @@ init_parser() used_runas = FALSE; errorlineno = -1; sudolineno = 1; + free(sudoers); } /* Allocate space for the matching stack. */ @@ -1271,4 +1272,6 @@ init_parser() /* Allocate space for the match list (for `sudo -l'). */ if (printmatches == TRUE) expand_match_list(); + + sudoers = estrdup(path); } -- 2.50.1