=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/sudo/Attic/toke.l,v retrieving revision 1.3 retrieving revision 1.4 diff -c -r1.3 -r1.4 *** src/usr.bin/sudo/Attic/toke.l 2009/04/11 11:48:06 1.3 --- src/usr.bin/sudo/Attic/toke.l 2009/06/21 14:48:42 1.4 *************** *** 1,6 **** %{ /* ! * Copyright (c) 1996, 1998-2005, 2007-2008 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any --- 1,6 ---- %{ /* ! * Copyright (c) 1996, 1998-2005, 2007-2009 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any *************** *** 27,32 **** --- 27,33 ---- #include #include + #include #include #ifdef STDC_HEADERS # include *************** *** 49,61 **** #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) # include #endif /* HAVE_MALLOC_H && !STDC_HEADERS */ #include #include "sudo.h" #include "parse.h" #include #ifndef lint ! __unused static const char rcsid[] = "$Sudo: toke.l,v 1.29 2009/02/21 21:49:19 millert Exp $"; #endif /* lint */ extern YYSTYPE yylval; --- 50,78 ---- #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) # include #endif /* HAVE_MALLOC_H && !STDC_HEADERS */ + #ifdef HAVE_DIRENT_H + # include + # define NAMLEN(dirent) strlen((dirent)->d_name) + #else + # define dirent direct + # define NAMLEN(dirent) (dirent)->d_namlen + # ifdef HAVE_SYS_NDIR_H + # include + # endif + # ifdef HAVE_SYS_DIR_H + # include + # endif + # ifdef HAVE_NDIR_H + # include + # endif + #endif #include #include "sudo.h" #include "parse.h" #include #ifndef lint ! __unused static const char rcsid[] = "$Sudo: toke.l,v 1.37 2009/05/27 00:46:51 millert Exp $"; #endif /* lint */ extern YYSTYPE yylval; *************** *** 69,83 **** static int _fill __P((char *, int, int)); static int fill_cmnd __P((char *, int)); static int fill_args __P((char *, int, int)); ! static int switch_buffer __P((char *)); static int ipv6_valid __P((const char *s)); static char *parse_include __P((char *)); extern void yyerror __P((const char *)); #define fill(a, b) _fill(a, b, 0) ! #define push_include(_p) (switch_buffer((_p))) ! #define pop_include() (switch_buffer(NULL)) /* realloc() to size + COMMANDARGINC to make room for command args */ #define COMMANDARGINC 64 --- 86,101 ---- static int _fill __P((char *, int, int)); static int fill_cmnd __P((char *, int)); static int fill_args __P((char *, int, int)); ! static int _push_include __P((char *, int)); ! static int pop_include __P((void)); static int ipv6_valid __P((const char *s)); static char *parse_include __P((char *)); extern void yyerror __P((const char *)); #define fill(a, b) _fill(a, b, 0) ! #define push_include(_p) (_push_include((_p), FALSE)) ! #define push_includedir(_p) (_push_include((_p), TRUE)) /* realloc() to size + COMMANDARGINC to make room for command args */ #define COMMANDARGINC 64 *************** *** 227,232 **** --- 245,263 ---- yyterminate(); } + ^#includedir[[:blank:]]+\/.*\n { + char *path; + + if ((path = parse_include(yytext)) == NULL) + yyterminate(); + + LEXTRACE("INCLUDEDIR\n"); + + /* Push current buffer and switch to include file */ + if (!push_includedir(path)) + yyterminate(); + } + ^[[:blank:]]*Defaults([:@>\!]{WORD})? { int n; for (n = 0; isblank((unsigned char)yytext[n]); n++) *************** *** 316,322 **** return(NETGROUP); } ! \%{WORD} { /* UN*X group */ if (!fill(yytext, yyleng)) yyterminate(); --- 347,353 ---- return(NETGROUP); } ! \%:?{WORD} { /* UN*X group */ if (!fill(yytext, yyleng)) yyterminate(); *************** *** 412,422 **** } } /* a pathname */ ({ID}|{WORD}) { /* a word */ if (!fill(yytext, yyleng)) yyterminate(); ! LEXTRACE("WORD(4) "); return(WORD); } --- 443,470 ---- } } /* a pathname */ + \"[^"\n]+\" { + /* a quoted user/group name */ + if (!fill(yytext + 1, yyleng - 2)) + yyterminate(); + switch (yytext[1]) { + case '%': + LEXTRACE("USERGROUP "); + return(USERGROUP); + case '+': + LEXTRACE("NETGROUP "); + return(NETGROUP); + default: + LEXTRACE("WORD(4) "); + return(WORD); + } + } + ({ID}|{WORD}) { /* a word */ if (!fill(yytext, yyleng)) yyterminate(); ! LEXTRACE("WORD(5) "); return(WORD); } *************** *** 490,501 **** } %% static int _fill(src, len, olen) char *src; int len, olen; { - int i, j; char *dst; dst = olen ? realloc(yylval.string, olen + len + 1) : malloc(len + 1); --- 538,594 ---- } %% + static unsigned char + hexchar(s) + const char *s; + { + int i; + int result = 0; + + s += 2; /* skip \\x */ + for (i = 0; i < 2; i++) { + switch (*s) { + case 'A': + case 'a': + result += 10; + break; + case 'B': + case 'b': + result += 11; + break; + case 'C': + case 'c': + result += 12; + break; + case 'D': + case 'd': + result += 13; + break; + case 'E': + case 'e': + result += 14; + break; + case 'F': + case 'f': + result += 15; + break; + default: + result += *s - '0'; + break; + } + if (i == 0) { + result *= 16; + s++; + } + } + return((unsigned char)result); + } + static int _fill(src, len, olen) char *src; int len, olen; { char *dst; dst = olen ? realloc(yylval.string, olen + len + 1) : malloc(len + 1); *************** *** 507,519 **** /* Copy the string and collapse any escaped characters. */ dst += olen; ! for (i = 0, j = 0; i < len; i++, j++) { ! if (src[i] == '\\' && i != len - 1) ! dst[j] = src[++i]; ! else ! dst[j] = src[i]; } ! dst[j] = '\0'; return(TRUE); } --- 600,623 ---- /* Copy the string and collapse any escaped characters. */ dst += olen; ! while (len--) { ! if (*src == '\\' && len) { ! if (src[1] == 'x' && len >= 3 && ! isxdigit((unsigned char) src[2]) && ! isxdigit((unsigned char) src[3])) { ! *dst++ = hexchar(src); ! src += 4; ! len -= 3; ! } else { ! src++; ! len--; ! *dst++ = *src++; ! } ! } else { ! *dst++ = *src++; ! } } ! *dst = '\0'; return(TRUE); } *************** *** 605,667 **** return(TRUE); } ! struct sudoers_state { YY_BUFFER_STATE bs; char *path; int lineno; }; #define MAX_SUDOERS_DEPTH 128 #define SUDOERS_STACK_INCREMENT 16 static int ! switch_buffer(path) char *path; { - static size_t stacksize, depth; - static struct sudoers_state *state; - static int keepopen; FILE *fp; ! if (path != NULL) { ! /* push current state */ ! if (depth >= stacksize) { ! if (depth > MAX_SUDOERS_DEPTH) { ! yyerror("too many levels of includes"); ! return(FALSE); ! } ! stacksize += SUDOERS_STACK_INCREMENT; ! state = (struct sudoers_state *) realloc(state, ! sizeof(state) * stacksize); ! if (state == NULL) { ! yyerror("unable to allocate memory"); ! return(FALSE); ! } } ! if ((fp = open_sudoers(path, &keepopen)) == NULL) { yyerror(path); return(FALSE); } ! 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--; ! if (!keepopen) ! fclose(YY_CURRENT_BUFFER->yy_input_file); ! yy_delete_buffer(YY_CURRENT_BUFFER); ! yy_switch_to_buffer(state[depth].bs); efree(sudoers); ! sudoers = state[depth].path; ! sudolineno = state[depth].lineno; ! keepopen = FALSE; } return(TRUE); } --- 709,936 ---- return(TRUE); } ! struct path_list { ! char *path; ! struct path_list *next; ! }; ! ! struct include_stack { YY_BUFFER_STATE bs; char *path; + struct path_list *more; /* more files in case of includedir */ int lineno; + int keepopen; }; + static int + pl_compare(v1, v2) + const void *v1; + const void *v2; + { + const struct path_list * const *p1 = v1; + const struct path_list * const *p2 = v2; + + return(strcmp((*p1)->path, (*p2)->path)); + } + + static char * + switch_dir(stack, dirpath) + struct include_stack *stack; + char *dirpath; + { + DIR *dir; + int i, count = 0; + char *path = NULL; + struct dirent *dent; + struct stat sb; + struct path_list *pl, *first = NULL; + struct path_list **sorted = NULL; + + if (!(dir = opendir(dirpath))) { + yyerror(dirpath); + return(FALSE); + } + while ((dent = readdir(dir))) { + /* Ignore files that end in '~' or have a '.' in them. */ + if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' + || strchr(dent->d_name, '.') != NULL) { + continue; + } + if (asprintf(&path, "%s/%s", dirpath, dent->d_name) == -1) { + closedir(dir); + goto bad; + } + if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) { + efree(path); + continue; + } + pl = malloc(sizeof(*pl)); + if (pl == NULL) + goto bad; + pl->path = path; + pl->next = first; + first = pl; + count++; + } + closedir(dir); + + if (count == 0) + goto done; + + /* Sort the list as an array. */ + sorted = malloc(sizeof(*sorted) * count); + if (sorted == NULL) + goto bad; + pl = first; + for (i = 0; i < count; i++) { + sorted[i] = pl; + 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. */ + if (count) { + path = first->path; + pl = first->next; + efree(first); + stack->more = pl; + } else { + path = NULL; + } + done: + efree(dirpath); + return(path); + bad: + while (first != NULL) { + pl = first; + first = pl->next; + free(pl->path); + free(pl); + } + efree(sorted); + efree(dirpath); + efree(path); + return(NULL); + } + #define MAX_SUDOERS_DEPTH 128 #define SUDOERS_STACK_INCREMENT 16 + static size_t istacksize, idepth; + static struct include_stack *istack; + static int keepopen; + + void + init_lexer() + { + struct path_list *pl; + + while (idepth) { + idepth--; + while ((pl = istack[idepth].more) != NULL) { + istack[idepth].more = pl->next; + efree(pl->path); + efree(pl); + } + efree(istack[idepth].path); + if (!istack[idepth].keepopen) + fclose(istack[idepth].bs->yy_input_file); + yy_delete_buffer(istack[idepth].bs); + } + efree(istack); + istack = NULL; + istacksize = idepth = 0; + keepopen = FALSE; + } + static int ! _push_include(path, isdir) char *path; + int isdir; { FILE *fp; ! /* push current state onto stack */ ! if (idepth >= istacksize) { ! if (idepth > MAX_SUDOERS_DEPTH) { ! yyerror("too many levels of includes"); ! return(FALSE); } ! istacksize += SUDOERS_STACK_INCREMENT; ! istack = (struct include_stack *) realloc(istack, ! sizeof(istack) * istacksize); ! if (istack == NULL) { ! yyerror("unable to allocate memory"); ! return(FALSE); ! } ! } ! if (isdir) { ! if (!(path = switch_dir(&istack[idepth], path))) { yyerror(path); return(FALSE); } ! if ((fp = open_sudoers(path, FALSE, &keepopen)) == NULL) { ! yyerror(path); ! return(FALSE); /* XXX - just to go next one? */ ! } ! } else { ! if ((fp = open_sudoers(path, TRUE, &keepopen)) == NULL) { ! yyerror(path); ! return(FALSE); ! } ! istack[idepth].more = NULL; ! } ! /* Push the old (current) file and open the new one. */ ! istack[idepth].path = sudoers; /* push old path */ ! istack[idepth].bs = YY_CURRENT_BUFFER; ! istack[idepth].lineno = sudolineno; ! istack[idepth].keepopen = keepopen; ! idepth++; ! sudolineno = 1; ! sudoers = path; ! yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); ! ! return(TRUE); ! } ! ! static int ! pop_include() ! { ! struct path_list *pl; ! FILE *fp; ! ! if (idepth == 0) ! return(FALSE); ! ! if (!keepopen) ! fclose(YY_CURRENT_BUFFER->yy_input_file); ! yy_delete_buffer(YY_CURRENT_BUFFER); ! keepopen = FALSE; ! if ((pl = istack[idepth - 1].more) != NULL) { ! /* Move to next file in the dir. */ ! istack[idepth - 1].more = pl->next; ! if ((fp = open_sudoers(pl->path, FALSE, &keepopen)) == NULL) { ! yyerror(pl->path); ! return(FALSE); /* XXX - just to go next one? */ ! } ! efree(sudoers); ! sudoers = pl->path; sudolineno = 1; yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + efree(pl); } else { ! idepth--; ! yy_switch_to_buffer(istack[idepth].bs); efree(sudoers); ! sudoers = istack[idepth].path; ! sudolineno = istack[idepth].lineno; } return(TRUE); } *************** *** 676,681 **** --- 945,952 ---- /* Pull out path from #include line. */ cp = base + sizeof("#include"); + if (*cp == 'i') + cp += 3; /* includedir */ while (isblank((unsigned char) *cp)) cp++; ep = cp;