From: Todd C. Miller Date: Tue, 23 Oct 2012 18:27:52 +0000 (-0400) Subject: Move expand_prompt() into its own source file for easier unit testing. X-Git-Tag: SUDO_1_8_7~1^2~370 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2b23d2b12c807f29fbfe3ff3274345fc983f153a;p=sudo Move expand_prompt() into its own source file for easier unit testing. --- diff --git a/MANIFEST b/MANIFEST index 8f1ca8d5a..52684388c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -223,6 +223,7 @@ plugins/sudoers/po/vi.mo plugins/sudoers/po/vi.po plugins/sudoers/po/zh_CN.mo plugins/sudoers/po/zh_CN.po +plugins/sudoers/prompt.c plugins/sudoers/pwutil.c plugins/sudoers/pwutil.h plugins/sudoers/pwutil_impl.c diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 2b5f8d98b..b1258cf91 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -127,10 +127,10 @@ LIBPARSESUDOERS_OBJS = alias.lo audit.lo defaults.lo gram.lo match.lo \ match_addr.lo pwutil.lo pwutil_impl.lo timestr.lo \ toke.lo toke_util.lo redblack.lo -SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo env.lo goodpath.lo \ - group_plugin.lo find_path.lo interfaces.lo logging.lo \ - logwrap.lo parse.lo set_perms.lo sudoers.lo sudo_nss.lo \ - timestamp.lo iolog.lo iolog_path.lo @SUDOERS_OBJS@ +SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo env.lo find_path.lo \ + goodpath.lo group_plugin.lo interfaces.lo iolog.lo \ + iolog_path.lo logging.lo logwrap.lo parse.lo prompt.lo \ + set_perms.lo sudo_nss.lo sudoers.lo timestamp.lo @SUDOERS_OBJS@ VISUDO_OBJS = visudo.o goodpath.o find_path.o error.o @@ -671,6 +671,13 @@ plugin_error.lo: $(srcdir)/plugin_error.c $(top_builddir)/config.h \ $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h \ $(incdir)/sudo_plugin.h $(incdir)/gettext.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(DEFS) $(srcdir)/plugin_error.c +prompt.lo: $(srcdir)/prompt.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ + $(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \ + $(incdir)/missing.h $(incdir)/error.h $(incdir)/alloc.h \ + $(incdir)/list.h $(incdir)/fileops.h $(srcdir)/defaults.h \ + $(devdir)/def_data.h $(srcdir)/logging.h $(srcdir)/sudo_nss.h \ + $(incdir)/sudo_plugin.h $(incdir)/sudo_debug.h $(incdir)/gettext.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(DEFS) $(srcdir)/prompt.c pwutil.lo: $(srcdir)/pwutil.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ $(top_srcdir)/compat/stdbool.h $(top_builddir)/pathnames.h \ $(incdir)/missing.h $(incdir)/error.h $(incdir)/alloc.h \ diff --git a/plugins/sudoers/check.c b/plugins/sudoers/check.c index 34146a156..978dad2c0 100644 --- a/plugins/sudoers/check.c +++ b/plugins/sudoers/check.c @@ -50,7 +50,6 @@ #include "timestamp.h" #include "check.h" -static char *expand_prompt(char *, char *, char *); static bool display_lecture(int); static struct passwd *get_authpw(void); @@ -182,134 +181,6 @@ display_lecture(int status) debug_return_int(true); } -/* - * Expand %h and %u escapes in the prompt and pass back the dynamically - * allocated result. Returns the same string if there are no escapes. - */ -static char * -expand_prompt(char *old_prompt, char *user, char *host) -{ - size_t len, n; - int subst; - char *p, *np, *new_prompt, *endp; - debug_decl(expand_prompt, SUDO_DEBUG_AUTH) - - /* How much space do we need to malloc for the prompt? */ - subst = 0; - for (p = old_prompt, len = strlen(old_prompt); *p; p++) { - if (p[0] =='%') { - switch (p[1]) { - case 'h': - p++; - len += strlen(user_shost) - 2; - subst = 1; - break; - case 'H': - p++; - len += strlen(user_host) - 2; - subst = 1; - break; - case 'p': - p++; - if (def_rootpw) - len += 2; - else if (def_targetpw || def_runaspw) - len += strlen(runas_pw->pw_name) - 2; - else - len += strlen(user_name) - 2; - subst = 1; - break; - case 'u': - p++; - len += strlen(user_name) - 2; - subst = 1; - break; - case 'U': - p++; - len += strlen(runas_pw->pw_name) - 2; - subst = 1; - break; - case '%': - p++; - len--; - subst = 1; - break; - default: - break; - } - } - } - - if (subst) { - new_prompt = emalloc(++len); - endp = new_prompt + len; - for (p = old_prompt, np = new_prompt; *p; p++) { - if (p[0] =='%') { - switch (p[1]) { - case 'h': - p++; - n = strlcpy(np, user_shost, np - endp); - if (n >= np - endp) - goto oflow; - np += n; - continue; - case 'H': - p++; - n = strlcpy(np, user_host, np - endp); - if (n >= np - endp) - goto oflow; - np += n; - continue; - case 'p': - p++; - if (def_rootpw) - n = strlcpy(np, "root", np - endp); - else if (def_targetpw || def_runaspw) - n = strlcpy(np, runas_pw->pw_name, np - endp); - else - n = strlcpy(np, user_name, np - endp); - if (n >= np - endp) - goto oflow; - np += n; - continue; - case 'u': - p++; - n = strlcpy(np, user_name, np - endp); - if (n >= np - endp) - goto oflow; - np += n; - continue; - case 'U': - p++; - n = strlcpy(np, runas_pw->pw_name, np - endp); - if (n >= np - endp) - goto oflow; - np += n; - continue; - case '%': - /* convert %% -> % */ - p++; - break; - default: - /* no conversion */ - break; - } - } - *np++ = *p; - if (np >= endp) - goto oflow; - } - *np = '\0'; - } else - new_prompt = old_prompt; - - debug_return_str(new_prompt); - -oflow: - /* We pre-allocate enough space, so this should never happen. */ - errorx(1, _("internal error, %s overflow"), "expand_prompt()"); -} - /* * Checks if the user is exempt from supplying a password. */ diff --git a/plugins/sudoers/prompt.c b/plugins/sudoers/prompt.c new file mode 100644 index 000000000..b5f3d0e9b --- /dev/null +++ b/plugins/sudoers/prompt.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1993-1996,1998-2005, 2007-2012 + * 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. + * + * 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 */ +#include +#include + +#include "sudoers.h" + +/* + * Expand %h and %u escapes in the prompt and pass back the dynamically + * allocated result. Returns the same string if there are no escapes. + */ +char * +expand_prompt(char *old_prompt, char *user, char *host) +{ + size_t len, n; + int subst; + char *p, *np, *new_prompt, *endp; + debug_decl(expand_prompt, SUDO_DEBUG_AUTH) + + /* How much space do we need to malloc for the prompt? */ + subst = 0; + for (p = old_prompt, len = strlen(old_prompt); *p; p++) { + if (p[0] =='%') { + switch (p[1]) { + case 'h': + p++; + len += strlen(user_shost) - 2; + subst = 1; + break; + case 'H': + p++; + len += strlen(user_host) - 2; + subst = 1; + break; + case 'p': + p++; + if (def_rootpw) + len += 2; + else if (def_targetpw || def_runaspw) + len += strlen(runas_pw->pw_name) - 2; + else + len += strlen(user_name) - 2; + subst = 1; + break; + case 'u': + p++; + len += strlen(user_name) - 2; + subst = 1; + break; + case 'U': + p++; + len += strlen(runas_pw->pw_name) - 2; + subst = 1; + break; + case '%': + p++; + len--; + subst = 1; + break; + default: + break; + } + } + } + + if (subst) { + new_prompt = emalloc(++len); + endp = new_prompt + len; + for (p = old_prompt, np = new_prompt; *p; p++) { + if (p[0] =='%') { + switch (p[1]) { + case 'h': + p++; + n = strlcpy(np, user_shost, np - endp); + if (n >= np - endp) + goto oflow; + np += n; + continue; + case 'H': + p++; + n = strlcpy(np, user_host, np - endp); + if (n >= np - endp) + goto oflow; + np += n; + continue; + case 'p': + p++; + if (def_rootpw) + n = strlcpy(np, "root", np - endp); + else if (def_targetpw || def_runaspw) + n = strlcpy(np, runas_pw->pw_name, np - endp); + else + n = strlcpy(np, user_name, np - endp); + if (n >= np - endp) + goto oflow; + np += n; + continue; + case 'u': + p++; + n = strlcpy(np, user_name, np - endp); + if (n >= np - endp) + goto oflow; + np += n; + continue; + case 'U': + p++; + n = strlcpy(np, runas_pw->pw_name, np - endp); + if (n >= np - endp) + goto oflow; + np += n; + continue; + case '%': + /* convert %% -> % */ + p++; + break; + default: + /* no conversion */ + break; + } + } + *np++ = *p; + if (np >= endp) + goto oflow; + } + *np = '\0'; + } else + new_prompt = old_prompt; + + debug_return_str(new_prompt); + +oflow: + /* We pre-allocate enough space, so this should never happen. */ + errorx(1, _("internal error, %s overflow"), "expand_prompt()"); +} diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index b592da09f..d066c03ad 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -230,11 +230,13 @@ bool sudo_goodpath(const char *, struct stat *); int find_path(char *, char **, struct stat *, char *, int); /* check.c */ -int check_user(int, int); +int check_user(int validate, int mode); bool user_is_exempt(void); +char *expand_prompt(char *old_prompt, char *user, char *host); /* timestamp.c */ void remove_timestamp(bool); +bool set_lectured(void); /* sudo_auth.c */ int verify_user(struct passwd *pw, char *prompt, int validated);