From: Todd C. Miller Date: Mon, 7 Feb 2011 15:29:34 +0000 (-0500) Subject: Split tokenizer utility functions out into toke_util.c X-Git-Tag: SUDO_1_7_5~20 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9242f669af5adb6f1bc0f8c68e1b9e8b2f123906;p=sudo Split tokenizer utility functions out into toke_util.c --HG-- branch : 1.7 --- diff --git a/Makefile.in b/Makefile.in index 4d985d898..aec42400d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -113,8 +113,8 @@ SRCS = aix.c alias.c alloc.c audit.c boottime.c bsm_audit.c check.c \ pwutil.c set_perms.c setsid.c sigaction.c snprintf.c strcasecmp.c \ strerror.c strlcat.c strlcpy.c strsignal.c sudo.c sudo_noexec.c \ sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c toke.c toke.l \ - tsgetgrpw.c utimes.c vasgroups.c visudo.c zero_bytes.c redblack.c \ - selinux.c sesh.c sudoreplay.c getdate.c getdate.y getline.c \ + toke_util.c tsgetgrpw.c utimes.c vasgroups.c visudo.c zero_bytes.c \ + redblack.c selinux.c sesh.c sudoreplay.c getdate.c getdate.y getline.c \ timestr.c $(AUTH_SRCS) AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \ @@ -125,14 +125,14 @@ AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \ HDRS = alloc.h bsm_audit.h def_data.h defaults.h error.h ins_2001.h \ ins_classic.h ins_csops.h ins_goons.h insults.h interfaces.h lbuf.h \ linux_audit.h list.h logging.h missing.h mksiglist.h nonunix.h \ - redblack.h parse.h sudo.h sudo_exec.h sudo_nss.h gram.h \ + redblack.h parse.h sudo.h sudo_exec.h sudo_nss.h gram.h toke.h \ auth/sudo_auth.h emul/charclass.h emul/fnmatch.h emul/glob.h \ emul/timespec.h emul/utime.h AUTH_OBJS = sudo_auth.o @AUTH_OBJS@ COMMON_OBJS = alias.o alloc.o defaults.o error.o gram.o \ - list.o match.o pwutil.o timestr.o toke.o redblack.o \ + list.o match.o pwutil.o timestr.o toke.o toke_util.o redblack.o \ term.o zero_bytes.o @COMMON_OBJS@ SUDO_OBJS = $(AUTH_OBJS) @SUDO_OBJS@ audit.o boottime.o check.o env.o \ @@ -390,8 +390,10 @@ tgetpass.o: $(srcdir)/tgetpass.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tgetpass.c timestr.o: $(srcdir)/timestr.c $(srcdir)/missing.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/timestr.c -toke.o: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h +toke.o: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/toke.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/toke.c +toke_util.o: $(devdir)/toke_util.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/toke.h $(devdir)/gram.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/toke_util.c tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tsgetgrpw.c utimes.o: $(srcdir)/utimes.c $(srcdir)/missing.h $(srcdir)/emul/utime.h config.h diff --git a/toke.h b/toke.h new file mode 100644 index 000000000..6200826b2 --- /dev/null +++ b/toke.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SUDO_TOKE_H +#define _SUDO_TOKE_H + +int append(char *, int); +int fill_args(char *, int, int); +int fill_cmnd(char *, int); +int fill_txt(char *, int, int); +int ipv6_valid(const char *s); +void yyerror(const char *); + +/* realloc() to size + COMMANDARGINC to make room for command args */ +#define COMMANDARGINC 64 + +#endif /* _SUDO_TOKE_H */ diff --git a/toke.l b/toke.l index 9a475bc4e..1c1245235 100644 --- a/toke.l +++ b/toke.l @@ -68,6 +68,7 @@ #include #include "sudo.h" #include "parse.h" +#include "toke.h" #include extern YYSTYPE yylval; @@ -76,27 +77,16 @@ int sudolineno = 1; char *sudoers; static int sawspace = 0; static int prev_state = INITIAL; -static int arg_len = 0; -static int arg_size = 0; -static int append __P((char *, int)); -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 fill(a, b) fill_txt(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 - #ifdef TRACELEXER #define LEXTRACE(msg) fputs(msg, stderr) #else @@ -561,177 +551,6 @@ sudoedit { } %% -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); - if (dst == NULL) { - yyerror("unable to allocate memory"); - return FALSE; - } - yylval.string = dst; - - /* 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; -} - -static int -append(src, len) - char *src; - int len; -{ - int olen = 0; - - if (yylval.string != NULL) - olen = strlen(yylval.string); - - return _fill(src, len, olen); -} - -#define SPECIAL(c) \ - ((c) == ',' || (c) == ':' || (c) == '=' || (c) == ' ' || (c) == '\t' || (c) == '#') - -static int -fill_cmnd(src, len) - char *src; - int len; -{ - char *dst; - int i; - - arg_len = arg_size = 0; - - dst = yylval.command.cmnd = (char *) malloc(len + 1); - if (yylval.command.cmnd == NULL) { - yyerror("unable to allocate memory"); - return FALSE; - } - - /* Copy the string and collapse any escaped sudo-specific characters. */ - for (i = 0; i < len; i++) { - if (src[i] == '\\' && i != len - 1 && SPECIAL(src[i + 1])) - *dst++ = src[++i]; - else - *dst++ = src[i]; - } - *dst = '\0'; - - yylval.command.args = NULL; - return TRUE; -} - -static int -fill_args(s, len, addspace) - char *s; - int len; - int addspace; -{ - int new_len; - char *p; - - if (yylval.command.args == NULL) { - addspace = 0; - new_len = len; - } else - new_len = arg_len + len + addspace; - - if (new_len >= arg_size) { - /* Allocate more space than we need for subsequent args */ - while (new_len >= (arg_size += COMMANDARGINC)) - ; - - p = yylval.command.args ? - (char *) realloc(yylval.command.args, arg_size) : - (char *) malloc(arg_size); - if (p == NULL) { - efree(yylval.command.args); - yyerror("unable to allocate memory"); - return FALSE; - } else - yylval.command.args = p; - } - - /* Efficiently append the arg (with a leading space if needed). */ - p = yylval.command.args + arg_len; - if (addspace) - *p++ = ' '; - if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len) { - yyerror("fill_args: buffer overflow"); /* paranoia */ - return FALSE; - } - arg_len = new_len; - return TRUE; -} - struct path_list { char *path; struct path_list *next; @@ -1022,26 +841,3 @@ parse_include(base) return path; } - -/* - * 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; -} diff --git a/toke_util.c b/toke_util.c new file mode 100644 index 000000000..99e755223 --- /dev/null +++ b/toke_util.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 1996, 1998-2005, 2007-2011 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +# include +#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ +#include +#include "sudo.h" +#include "parse.h" +#include "toke.h" +#include + +static int arg_len = 0; +static int arg_size = 0; + +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; +} + +int +fill_txt(src, len, olen) + char *src; + int len, olen; +{ + char *dst; + + dst = olen ? realloc(yylval.string, olen + len + 1) : malloc(len + 1); + if (dst == NULL) { + yyerror("unable to allocate memory"); + return FALSE; + } + yylval.string = dst; + + /* 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; +} + +int +append(src, len) + char *src; + int len; +{ + int olen = 0; + + if (yylval.string != NULL) + olen = strlen(yylval.string); + + return fill_txt(src, len, olen); +} + +#define SPECIAL(c) \ + ((c) == ',' || (c) == ':' || (c) == '=' || (c) == ' ' || (c) == '\t' || (c) == '#') + +int +fill_cmnd(src, len) + char *src; + int len; +{ + char *dst; + int i; + + arg_len = arg_size = 0; + + dst = yylval.command.cmnd = (char *) malloc(len + 1); + if (yylval.command.cmnd == NULL) { + yyerror("unable to allocate memory"); + return FALSE; + } + + /* Copy the string and collapse any escaped sudo-specific characters. */ + for (i = 0; i < len; i++) { + if (src[i] == '\\' && i != len - 1 && SPECIAL(src[i + 1])) + *dst++ = src[++i]; + else + *dst++ = src[i]; + } + *dst = '\0'; + + yylval.command.args = NULL; + return TRUE; +} + +int +fill_args(s, len, addspace) + char *s; + int len; + int addspace; +{ + int new_len; + char *p; + + if (yylval.command.args == NULL) { + addspace = 0; + new_len = len; + } else + new_len = arg_len + len + addspace; + + if (new_len >= arg_size) { + /* Allocate more space than we need for subsequent args */ + while (new_len >= (arg_size += COMMANDARGINC)) + ; + + p = yylval.command.args ? + (char *) realloc(yylval.command.args, arg_size) : + (char *) malloc(arg_size); + if (p == NULL) { + efree(yylval.command.args); + yyerror("unable to allocate memory"); + return FALSE; + } else + yylval.command.args = p; + } + + /* Efficiently append the arg (with a leading space if needed). */ + p = yylval.command.args + arg_len; + if (addspace) + *p++ = ' '; + if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len) { + yyerror("fill_args: buffer overflow"); /* paranoia */ + return FALSE; + } + arg_len = new_len; + return TRUE; +} + +/* + * 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. + */ +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; +}