From 1f3ea50afd89baf6c6557b42a3971e67bc838f6b Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sat, 3 Aug 2013 08:30:06 -0600 Subject: [PATCH] Implement memset_s() and use it instead of zero_bytes(). A new constant, SUDO_CONV_REPL_MAX, is defined by the plugin API as the max conversation reply length. This constant can be used as a max value for memset_s() when clearing passwords filled in by the conversation function. --- MANIFEST | 2 +- common/Makefile.in | 5 +- common/zero_bytes.c | 36 ---- compat/Makefile.in | 2 + compat/memset_s.c | 71 ++++++++ config.h.in | 9 + configure | 48 +++++ configure.in | 6 +- doc/sudo_plugin.cat | 9 +- doc/sudo_plugin.man.in | 290 +++++++++++++++++------------- doc/sudo_plugin.mdoc.in | 16 +- include/missing.h | 3 + include/sudo_plugin.h | 11 ++ mkdep.pl | 2 +- plugins/sudoers/Makefile.in | 2 +- plugins/sudoers/auth/aix_auth.c | 4 +- plugins/sudoers/auth/bsdauth.c | 2 +- plugins/sudoers/auth/fwtk.c | 8 +- plugins/sudoers/auth/pam.c | 7 +- plugins/sudoers/auth/passwd.c | 2 +- plugins/sudoers/auth/secureware.c | 2 +- plugins/sudoers/auth/sudo_auth.c | 2 +- plugins/sudoers/defaults.c | 2 +- plugins/sudoers/logging.c | 2 +- plugins/sudoers/sha2.c | 11 +- plugins/sudoers/sudoers.c | 2 +- plugins/sudoers/sudoers.h | 11 -- plugins/sudoers/tsgetgrpw.c | 4 +- plugins/sudoers/visudo.c | 2 +- src/Makefile.in | 3 +- src/conversation.c | 4 +- src/sudo.h | 11 -- src/sudo_edit.c | 4 +- src/tgetpass.c | 9 +- 34 files changed, 371 insertions(+), 233 deletions(-) delete mode 100644 common/zero_bytes.c create mode 100644 compat/memset_s.c diff --git a/MANIFEST b/MANIFEST index 93403d078..ef7aac108 100644 --- a/MANIFEST +++ b/MANIFEST @@ -45,7 +45,6 @@ common/sudo_debug.c common/sudo_printf.c common/term.c common/ttysize.c -common/zero_bytes.c compat/Makefile.in compat/charclass.h compat/closefrom.c @@ -66,6 +65,7 @@ compat/glob.c compat/glob.h compat/isblank.c compat/memrchr.c +compat/memset_s.c compat/mksiglist.c compat/mksiglist.h compat/mksigname.c diff --git a/common/Makefile.in b/common/Makefile.in index b24912e69..d5ce67fe9 100644 --- a/common/Makefile.in +++ b/common/Makefile.in @@ -68,7 +68,7 @@ SHELL = @SHELL@ LTOBJS = alloc.lo atobool.lo error.lo fileops.lo fmt_string.lo lbuf.lo list.lo \ secure_path.lo setgroups.lo sudo_conf.lo sudo_debug.lo sudo_printf.lo \ - term.lo ttysize.lo zero_bytes.lo @COMMON_OBJS@ + term.lo ttysize.lo @COMMON_OBJS@ PARSELN_TEST_OBJS = parseln_test.lo @@ -218,6 +218,3 @@ term.lo: $(srcdir)/term.c $(top_builddir)/config.h $(incdir)/missing.h \ ttysize.lo: $(srcdir)/ttysize.c $(top_builddir)/config.h $(incdir)/missing.h \ $(incdir)/sudo_debug.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/ttysize.c -zero_bytes.lo: $(srcdir)/zero_bytes.c $(top_builddir)/config.h \ - $(incdir)/missing.h - $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/zero_bytes.c diff --git a/common/zero_bytes.c b/common/zero_bytes.c deleted file mode 100644 index f6f22bc4d..000000000 --- a/common/zero_bytes.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2003-2005, 2007, 2010 - * 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. - */ - -#include - -#include - -#include "missing.h" - -/* - * Like bzero(3) but with a volatile pointer. The hope is that - * the compiler will not be able to optimize away this function. - */ -void -zero_bytes(volatile void *v, size_t n) -{ - volatile char *p, *ep; - - for (p = v, ep = p + n; p < ep; p++) - *p = 0; - return; -} diff --git a/compat/Makefile.in b/compat/Makefile.in index 751b6c07c..1650dc5f8 100644 --- a/compat/Makefile.in +++ b/compat/Makefile.in @@ -199,6 +199,8 @@ isblank.lo: $(srcdir)/isblank.c $(top_builddir)/config.h $(incdir)/missing.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/isblank.c memrchr.lo: $(srcdir)/memrchr.c $(top_builddir)/config.h $(incdir)/missing.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/memrchr.c +memset_s.lo: $(srcdir)/memset_s.c $(top_builddir)/config.h $(incdir)/missing.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/memset_s.c mksiglist.lo: $(srcdir)/mksiglist.c $(top_builddir)/config.h \ $(incdir)/missing.h $(top_srcdir)/compat/mksiglist.h $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/mksiglist.c diff --git a/compat/memset_s.c b/compat/memset_s.c new file mode 100644 index 000000000..59070d585 --- /dev/null +++ b/compat/memset_s.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013 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. + */ + +#include + +#include +#include +#include +#if defined(HAVE_STDINT_H) +# include +#elif defined(HAVE_INTTYPES_H) +# include +#endif + +#include "missing.h" + +#ifndef RSIZE_MAX +# if defined(SIZE_MAX) +# define RSIZE_MAX (SIZE_MAX >> 1) +# elif defined(__LP64__) +# define RSIZE_MAX 0x7fffffffffffffffUL +# else +# define RSIZE_MAX 0x7fffffffU +# endif +#endif + +/* + * Simple implementation of C11 memset_s() function. + * We use a volatile pointer when updating the byte string. + * Most compilers will avoid optimizing away access to a + * volatile pointer, even if the pointer appears to be unused + * after the call. + * + * Note that C11 does not specify the return value on error, only + * that it be non-zero. We use EINVAL for all errors. + */ +errno_t +memset_s(void *v, rsize_t smax, int c, rsize_t n) +{ + errno_t ret = 0; + volatile unsigned char *s = v; + + /* Fatal runtime-constraint violations. */ + if (s == NULL || smax > RSIZE_MAX) { + ret = errno = EINVAL; + goto done; + } + /* Non-fatal runtime-constraint violation, n must not exceed smax. */ + if (n > smax) { + n = smax; + ret = errno = EINVAL; + } + /* Updating through a volatile pointer should not be optimized away. */ + while (n--) + *s++ = (unsigned char)c; +done: + return ret; +} diff --git a/config.h.in b/config.h.in index 4a129d5d0..33d2c6fd8 100644 --- a/config.h.in +++ b/config.h.in @@ -373,6 +373,9 @@ /* Define to 1 if you have the `memrchr' function. */ #undef HAVE_MEMRCHR +/* Define to 1 if you have the `memset_s' function. */ +#undef HAVE_MEMSET_S + /* Define to 1 if you have the `mkdtemp' function. */ #undef HAVE_MKDTEMP @@ -948,6 +951,9 @@ /* Define to `int' if does not define. */ #undef dev_t +/* Define to `int' if does not define. */ +#undef errno_t + /* Define to `int' if doesn't define. */ #undef gid_t @@ -960,6 +966,9 @@ /* Define to an OS-specific initialization function or `os_init_common'. */ #undef os_init +/* Define to `size_t' if does not define. */ +#undef rsize_t + /* Define to `int' if does not define. */ #undef sig_atomic_t diff --git a/configure b/configure index a9983f576..b72443b69 100755 --- a/configure +++ b/configure @@ -15979,6 +15979,19 @@ fi fi + + case "${CPPFLAGS}" in + *"-D__STDC_WANT_LIB_EXT1__=1"|*"-D__STDC_WANT_LIB_EXT1__=1 ") + ;; + *) + if test X"${CPPFLAGS}" = X""; then + CPPFLAGS="-D__STDC_WANT_LIB_EXT1__=1" + else + CPPFLAGS="${CPPFLAGS} -D__STDC_WANT_LIB_EXT1__=1" + fi + ;; + esac + ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" if test "x$ac_cv_type_mode_t" = xyes; then : @@ -16299,6 +16312,28 @@ else fi +ac_fn_c_check_type "$LINENO" "rsize_t" "ac_cv_type_rsize_t" "$ac_includes_default" +if test "x$ac_cv_type_rsize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define rsize_t size_t +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "errno_t" "ac_cv_type_errno_t" "$ac_includes_default" +if test "x$ac_cv_type_errno_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define errno_t int +_ACEOF + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking max length of uid_t" >&5 $as_echo_n "checking max length of uid_t... " >&6; } @@ -17543,6 +17578,19 @@ esac fi +ac_fn_c_check_func "$LINENO" "memset_s" "ac_cv_func_memset_s" +if test "x$ac_cv_func_memset_s" = xyes; then : + $as_echo "#define HAVE_MEMSET_S 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" memset_s.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memset_s.$ac_objext" + ;; +esac + +fi + ac_fn_c_check_func "$LINENO" "pw_dup" "ac_cv_func_pw_dup" if test "x$ac_cv_func_pw_dup" = xyes; then : $as_echo "#define HAVE_PW_DUP 1" >>confdefs.h diff --git a/configure.in b/configure.in index 57901280d..6d66bd984 100644 --- a/configure.in +++ b/configure.in @@ -2143,7 +2143,9 @@ if test ${with_project-'no'} != "no"; then fi dnl dnl typedef checks +dnl We need to define __STDC_WANT_LIB_EXT1__ for errno_t and rsize_t dnl +SUDO_APPEND_CPPFLAGS(-D__STDC_WANT_LIB_EXT1__=1) AC_TYPE_MODE_T AC_TYPE_UID_T AC_CHECK_TYPE([__signed char], [], [AC_CHECK_TYPE([signed char], [AC_DEFINE(__signed, signed)], [AC_DEFINE(__signed, [])])]) @@ -2173,6 +2175,8 @@ AC_CHECK_TYPE(uint64_t, unsigned long long) AC_CHECK_TYPE(socklen_t, [], [AC_DEFINE(socklen_t, unsigned int)], [ AC_INCLUDES_DEFAULT #include ]) +AC_CHECK_TYPE(rsize_t, size_t) +AC_CHECK_TYPE(errno_t, int) SUDO_UID_T_LEN SUDO_SOCK_SA_LEN dnl @@ -2348,7 +2352,7 @@ SUDO_FUNC_FNMATCH([AC_DEFINE(HAVE_FNMATCH)], [AC_LIBOBJ(fnmatch) COMPAT_TEST_PROGS="${COMPAT_TEST_PROGS}${COMPAT_TEST_PROGS+ }fnm_test" ]) SUDO_FUNC_ISBLANK -AC_REPLACE_FUNCS(getopt_long memrchr pw_dup strlcpy strlcat) +AC_REPLACE_FUNCS(getopt_long memrchr memset_s pw_dup strlcpy strlcat) AC_CHECK_FUNCS(nanosleep, [], [ # On Solaris, nanosleep is in librt AC_CHECK_LIB(rt, nanosleep, [REPLAY_LIBS="${REPLAY_LIBS} -lrt"], [AC_LIBOBJ(nanosleep)]) diff --git a/doc/sudo_plugin.cat b/doc/sudo_plugin.cat index f7fe8fb24..237509786 100644 --- a/doc/sudo_plugin.cat +++ b/doc/sudo_plugin.cat @@ -1229,6 +1229,8 @@ DDEESSCCRRIIPPTTIIOONN const char *msg; }; + #define SUDO_CONV_REPL_MAX 255 + struct sudo_conv_reply { char *reply; }; @@ -1246,7 +1248,12 @@ DDEESSCCRRIIPPTTIIOONN sudo_conv_message and sudo_conv_reply structures. There must be a struct sudo_conv_message and struct sudo_conv_reply for each message in the conversation. The plugin is responsible for freeing the reply buffer - filled in to the struct sudo_conv_reply, if any. + located in each struct sudo_conv_reply, if it is not NULL. + SUDO_CONV_REPL_MAX represents the maximum length of the reply buffer (not + including the trailing NUL character). In practical terms, this is the + longest password ssuuddoo will support. It is also useful as a maximum value + for the mmeemmsseett__ss() function when clearing passwords filled in by the + conversation function. The pprriinnttff()-style function uses the same underlying mechanism as the ccoonnvveerrssaattiioonn() function but only supports SUDO_CONV_INFO_MSG, diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in index 32a336eb3..e3eae46e2 100644 --- a/doc/sudo_plugin.man.in +++ b/doc/sudo_plugin.man.in @@ -107,15 +107,15 @@ to determine the API version the plugin was built against. .TP 6n open +.RS .nf -.RS 6n +.RS 0n int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t plugin_printf, char * const settings[], char * const user_info[], char * const user_env[], char * const plugin_options[]); .RE .fi -.RS 6n .sp Returns 1 on success, 0 on failure, \-1 if a general error occurred, or \-2 if there was a usage error. @@ -156,7 +156,7 @@ settings A vector of user-supplied \fBsudo\fR settings in the form of -\(lqname=value\(rq +``name=value'' strings. The vector is terminated by a \fRNULL\fR @@ -171,23 +171,20 @@ When parsing the plugin should split on the \fBfirst\fR equal sign -(\(oq=\(cq) +(`=') since the \fIname\fR field will never include one itself but the \fIvalue\fR might. -.PP -.RS 6n -.PD 0 +.RS .TP 6n bsdauth_type=string Authentication type, if specified by the \fB\-a\fR flag, to use on systems where BSD authentication is supported. -.PD .TP 6n closefrom=number If specified, the user has requested via the @@ -218,7 +215,7 @@ plugin is \fIsubsystem\fR@\fIpriority\fR but the plugin is free to use a different format so long as it does not include a comma -(\(oq,\&\(cq). +(`,\&'). There is not currently a way to specify a set of debug flags specific to the plugin--the flags are shared by \fBsudo\fR @@ -274,13 +271,13 @@ sudo.conf(@mansectform@). network_addrs=list A space-separated list of IP network addresses and netmasks in the form -\(lqaddr/netmask\(rq, +``addr/netmask'', e.g.\& -\(lq192.168.1.2/255.255.255.0\(rq. +``192.168.1.2/255.255.255.0''. The address and netmask pairs may be either IPv4 or IPv6, depending on what the operating system supports. If the address contains a colon -(\(oq:\&\(cq), +(`:\&'), it is an IPv6 address, else it is IPv4. .TP 6n noninteractive=bool @@ -315,9 +312,9 @@ based on the runas user. .TP 6n progname=string The command name that sudo was run as, typically -\(lqsudo\(rq +``sudo'' or -\(lqsudoedit\(rq. +``sudoedit''. .TP 6n prompt=string The prompt to use when requesting a password, if specified via @@ -391,11 +388,13 @@ section. .PP Additional settings may be added in the future so the plugin should silently ignore settings that it does not recognize. +.PP .RE +.PD 0 .TP 6n user_info A vector of information about the user running the command in the form of -\(lqname=value\(rq +``name=value'' strings. The vector is terminated by a \fRNULL\fR @@ -406,21 +405,19 @@ When parsing the plugin should split on the \fBfirst\fR equal sign -(\(oq=\(cq) +(`=') since the \fIname\fR field will never include one itself but the \fIvalue\fR might. -.PP -.RS 6n -.PD 0 +.RS +.PD .TP 6n cols=int The number of columns the user's terminal supports. If there is no terminal device available, a default value of 80 is used. -.PD .TP 6n cwd=string The user's current working directory. @@ -516,7 +513,7 @@ tty=string The path to the user's terminal device. If the user has no terminal device associated with the session, the value will be empty, as in -\(lq\fRtty=\fR\(rq. +``\fRtty=\fR''. .TP 6n uid=uid_t The real user ID of the user invoking @@ -525,15 +522,14 @@ The real user ID of the user invoking user=string The name of the user invoking \fBsudo\fR. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n user_env The user's environment in the form of a \fRNULL\fR-terminated vector of -\(lqname=value\(rq +``name=value'' strings. .sp When parsing @@ -541,26 +537,26 @@ When parsing the plugin should split on the \fBfirst\fR equal sign -(\(oq=\(cq) +(`=') since the \fIname\fR field will never include one itself but the \fIvalue\fR might. -.PD 0 +.PD .PP .RE -.PD +.PD 0 .TP 6n close .br +.RS .nf -.RS 6n +.RS 0n void (*close)(int exit_status, int error); .RE .fi -.RS 6n .sp The \fBclose\fR() @@ -569,6 +565,7 @@ function is called when the command being run by finishes. .sp The function arguments are as follows: +.PD .TP 6n exit_status The command's exit status, as returned by the @@ -609,15 +606,17 @@ list, the \fBsudo\fR front end may execute the command directly instead of running it as a child process. +.PP .RE +.PD 0 .TP 6n show_version +.RS .nf -.RS 6n +.RS 0n int (*show_version)(int verbose); .RE .fi -.RS 6n .sp The \fBshow_version\fR() @@ -634,17 +633,20 @@ or function using \fRSUDO_CONV_INFO_MSG\fR. If the user requests detailed version information, the verbose flag will be set. +.PD +.PP .RE +.PD 0 .TP 6n check_policy +.RS .nf -.RS 6n +.RS 0n int (*check_policy)(int argc, char * const argv[] char *env_add[], char **command_info[], char **argv_out[], char **user_env_out[]); .RE .fi -.RS 6n .sp The \fBcheck_policy\fR() @@ -686,10 +688,10 @@ into \fIargv_out\fR, separated from the editor and its arguments by a -\(lq\fR--\fR\(rq +``\fR--\fR'' element. The -\(lq\fR--\fR\(rq +``\fR--\fR'' will be removed by \fBsudo\fR @@ -720,6 +722,7 @@ function with to present additional error information to the user. .sp The function arguments are as follows: +.PD .TP 6n argc The number of elements in @@ -742,7 +745,7 @@ Additional environment variables specified by the user on the command line in the form of a \fRNULL\fR-terminated vector of -\(lqname=value\(rq +``name=value'' strings. The plugin may reject the command if one or more variables are not allowed to be set, or it may silently ignore such variables. @@ -752,7 +755,7 @@ When parsing the plugin should split on the \fBfirst\fR equal sign -(\(oq=\(cq) +(`=') since the \fIname\fR field will never include one @@ -762,7 +765,7 @@ might. .TP 6n command_info Information about the command being run in the form of -\(lqname=value\(rq +``name=value'' strings. These values are used by \fBsudo\fR @@ -774,13 +777,10 @@ which must be terminated with a pointer. The following values are recognized by \fBsudo\fR: -.PP -.RS 6n -.PD 0 +.RS .TP 6n chroot=string The root directory to use when running the command. -.PD .TP 6n closefrom=number If specified, @@ -995,7 +995,9 @@ will base the new entry on the invoking user's existing entry. .PP Unsupported values will be ignored. +.PP .RE +.PD 0 .TP 6n argv_out The @@ -1004,25 +1006,25 @@ argument vector to pass to the execve(2) system call when executing the command. The plugin is responsible for allocating and populating the vector. +.PD .TP 6n user_env_out The \fRNULL\fR-terminated environment vector to use when executing the command. The plugin is responsible for allocating and populating the vector. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n list +.RS .nf -.RS 6n +.RS 0n int (*list)(int verbose, const char *list_user, int argc, char * const argv[]); .RE .fi -.RS 6n .sp List available privileges for the invoking user. Returns 1 on success, 0 on failure and \-1 on error. @@ -1041,6 +1043,7 @@ or \fBplugin_printf\fR() function using \fRSUDO_CONV_INFO_MSG\fR, +.PD .TP 6n verbose Flag indicating whether to list in verbose mode or not. @@ -1069,18 +1072,17 @@ execve(2) system call. If the command is permitted by the policy, the fully-qualified path to the command should be displayed along with any command line arguments. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n validate +.RS .nf -.RS 6n +.RS 0n int (*validate)(void); .RE .fi -.RS 6n .sp The \fBvalidate\fR() @@ -1110,15 +1112,18 @@ function with \fRSUDO_CONF_ERROR_MSG\fR to present additional error information to the user. +.PD +.PP .RE +.PD 0 .TP 6n invalidate +.RS .nf -.RS 6n +.RS 0n void (*invalidate)(int remove); .RE .fi -.RS 6n .sp The \fBinvalidate\fR() @@ -1145,15 +1150,18 @@ The function should be \fRNULL\fR if the plugin does not support credential caching. +.PD +.PP .RE +.PD 0 .TP 6n init_session +.RS .nf -.RS 6n +.RS 0n int (*init_session)(struct passwd *pwd, char **user_envp[); .RE .fi -.RS 6n .sp The \fBinit_session\fR() @@ -1186,7 +1194,7 @@ argument points to the environment the command will run in, in the form of a \fRNULL\fR-terminated vector of -\(lqname=value\(rq +``name=value'' strings. This is the same string passed back to the front end via the Policy Plugin's @@ -1222,16 +1230,19 @@ function with \fRSUDO_CONF_ERROR_MSG\fR to present additional error information to the user. +.PD +.PP .RE +.PD 0 .TP 6n register_hooks +.RS .nf -.RS 6n +.RS 0n void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook)); .RE .fi -.RS 6n .sp The \fBregister_hooks\fR() @@ -1274,16 +1285,19 @@ front end doesn't support API version 1.2 or higher, \fRregister_hooks\fR will not be called. +.PD +.PP .RE +.PD 0 .TP 6n deregister_hooks +.RS .nf -.RS 6n +.RS 0n void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); .RE .fi -.RS 6n .sp The \fBderegister_hooks\fR() @@ -1328,6 +1342,7 @@ version 1.2 or higher, \fRderegister_hooks\fR will not be called. .RE +.PD .PP \fIPolicy Plugin Version Macros\fR .nf @@ -1428,15 +1443,15 @@ to determine the API version the plugin was built against. .TP 6n open +.RS .nf -.RS 6n +.RS 0n int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t plugin_printf, char * const settings[], char * const user_info[], int argc, char * const argv[], char * const user_env[], char * const plugin_options[]); .RE .fi -.RS 6n .sp The \fBopen\fR() @@ -1506,7 +1521,7 @@ settings A vector of user-supplied \fBsudo\fR settings in the form of -\(lqname=value\(rq +``name=value'' strings. The vector is terminated by a \fRNULL\fR @@ -1521,7 +1536,7 @@ When parsing the plugin should split on the \fBfirst\fR equal sign -(\(oq=\(cq) +(`=') since the \fIname\fR field will never include one @@ -1535,7 +1550,7 @@ section for a list of all possible settings. .TP 6n user_info A vector of information about the user running the command in the form of -\(lqname=value\(rq +``name=value'' strings. The vector is terminated by a \fRNULL\fR @@ -1546,7 +1561,7 @@ When parsing the plugin should split on the \fBfirst\fR equal sign -(\(oq=\(cq) +(`=') since the \fIname\fR field will never include one @@ -1577,7 +1592,7 @@ user_env The user's environment in the form of a \fRNULL\fR-terminated vector of -\(lqname=value\(rq +``name=value'' strings. .sp When parsing @@ -1585,7 +1600,7 @@ When parsing the plugin should split on the \fBfirst\fR equal sign -(\(oq=\(cq) +(`=') since the \fIname\fR field will never include one @@ -1618,19 +1633,18 @@ by the front end before using \fIplugin_options\fR. Failure to do so may result in a crash. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n close .br +.RS .nf -.RS 6n +.RS 0n void (*close)(int exit_status, int error); .RE .fi -.RS 6n .sp The \fBclose\fR() @@ -1639,6 +1653,7 @@ function is called when the command being run by finishes. .sp The function arguments are as follows: +.PD .TP 6n exit_status The command's exit status, as returned by the @@ -1660,18 +1675,17 @@ system call. If the command was successfully executed, the value of \fRerror\fR is 0. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n show_version +.RS .nf -.RS 6n +.RS 0n int (*show_version)(int verbose); .RE .fi -.RS 6n .sp The \fBshow_version\fR() @@ -1688,15 +1702,18 @@ or function using \fRSUDO_CONV_INFO_MSG\fR. If the user requests detailed version information, the verbose flag will be set. +.PD +.PP .RE +.PD 0 .TP 6n log_ttyin +.RS .nf -.RS 6n +.RS 0n int (*log_ttyin)(const char *buf, unsigned int len); .RE .fi -.RS 6n .sp The \fBlog_ttyin\fR() @@ -1708,6 +1725,7 @@ Returns 1 if the data should be passed to the command, 0 if the data is rejected (which will terminate the command) or \-1 if an error occurred. .sp The function arguments are as follows: +.PD .TP 6n buf The buffer containing user input. @@ -1716,18 +1734,17 @@ len The length of \fIbuf\fR in bytes. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n log_ttyout +.RS .nf -.RS 6n +.RS 0n int (*log_ttyout)(const char *buf, unsigned int len); .RE .fi -.RS 6n .sp The \fBlog_ttyout\fR() @@ -1739,6 +1756,7 @@ Returns 1 if the data should be passed to the user, 0 if the data is rejected (which will terminate the command) or \-1 if an error occurred. .sp The function arguments are as follows: +.PD .TP 6n buf The buffer containing command output. @@ -1747,18 +1765,17 @@ len The length of \fIbuf\fR in bytes. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n log_stdin +.RS .nf -.RS 6n +.RS 0n int (*log_stdin)(const char *buf, unsigned int len); .RE .fi -.RS 6n .sp The \fBlog_stdin\fR() @@ -1772,6 +1789,7 @@ Returns 1 if the data should be passed to the command, 0 if the data is rejected (which will terminate the command) or \-1 if an error occurred. .sp The function arguments are as follows: +.PD .TP 6n buf The buffer containing user input. @@ -1780,18 +1798,17 @@ len The length of \fIbuf\fR in bytes. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n log_stdout +.RS .nf -.RS 6n +.RS 0n int (*log_stdout)(const char *buf, unsigned int len); .RE .fi -.RS 6n .sp The \fBlog_stdout\fR() @@ -1805,6 +1822,7 @@ Returns 1 if the data should be passed to the user, 0 if the data is rejected (which will terminate the command) or \-1 if an error occurred. .sp The function arguments are as follows: +.PD .TP 6n buf The buffer containing command output. @@ -1813,18 +1831,17 @@ len The length of \fIbuf\fR in bytes. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n log_stderr +.RS .nf -.RS 6n +.RS 0n int (*log_stderr)(const char *buf, unsigned int len); .RE .fi -.RS 6n .sp The \fBlog_stderr\fR() @@ -1838,6 +1855,7 @@ Returns 1 if the data should be passed to the user, 0 if the data is rejected (which will terminate the command) or \-1 if an error occurred. .sp The function arguments are as follows: +.PD .TP 6n buf The buffer containing command output. @@ -1846,16 +1864,16 @@ len The length of \fIbuf\fR in bytes. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n register_hooks See the \fIPolicy plugin API\fR section for a description of \fRregister_hooks\fR. +.PD .TP 6n deregister_hooks See the @@ -1962,9 +1980,7 @@ hook_type The \fRhook_type\fR field may be one of the following supported hook types: -.PP -.RS 6n -.PD 0 +.RS .TP 6n \fRSUDO_HOOK_SETENV\fR The C library @@ -1975,19 +1991,20 @@ The \fRhook_fn\fR field should be a function that matches the following typedef: +.RS .nf .sp -.RS 6n +.RS 0n typedef int (*sudo_hook_fn_setenv_t)(const char *name, const char *value, int overwrite, void *closure); .RE .fi -.RS 6n .sp If the registered hook does not match the typedef the results are unspecified. +.PP .RE -.PD +.PD 0 .TP 6n \fRSUDO_HOOK_UNSETENV\fR The C library @@ -1998,13 +2015,18 @@ The \fRhook_fn\fR field should be a function that matches the following typedef: +.RS .nf .sp -.RS 6n +.RS 0n typedef int (*sudo_hook_fn_unsetenv_t)(const char *name, void *closure); .RE .fi +.PD +.PP +.RE +.PD 0 .TP 6n \fRSUDO_HOOK_GETENV\fR The C library @@ -2015,18 +2037,21 @@ The \fRhook_fn\fR field should be a function that matches the following typedef: +.RS .nf .sp -.RS 6n +.RS 0n typedef int (*sudo_hook_fn_getenv_t)(const char *name, char **value, void *closure); .RE .fi -.RS 6n .sp If the registered hook does not match the typedef the results are unspecified. +.PD +.PP .RE +.PD 0 .TP 6n \fRSUDO_HOOK_PUTENV\fR The C library @@ -2037,22 +2062,22 @@ The \fRhook_fn\fR field should be a function that matches the following typedef: +.RS .nf .sp -.RS 6n +.RS 0n typedef int (*sudo_hook_fn_putenv_t)(char *string, void *closure); .RE .fi -.RS 6n .sp If the registered hook does not match the typedef the results are unspecified. .RE -.PD 0 +.PD .PP .RE -.PD +.PD 0 .TP 6n hook_fn sudo_hook_fn_t hook_fn; @@ -2073,13 +2098,11 @@ is passed as the last function parameter. This can be used to pass arbitrary data to the plugin's hook implementation. .sp The function return value may be one of the following: -.PP -.RS 6n -.PD 0 +.RS +.PD .TP 6n \fRSUDO_HOOK_RET_ERROR\fR The hook function encountered an error. -.PD .TP 6n \fRSUDO_HOOK_RET_NEXT\fR The hook completed without error, go on to the next hook (including @@ -2099,10 +2122,7 @@ hook that operates on a private copy of the environment but leaves \fRenviron\fR unchanged. -.PD 0 -.PP .RE -.PD .PP Note that it is very easy to create an infinite loop when hooking C library functions. @@ -2184,6 +2204,8 @@ struct sudo_conv_message { const char *msg; }; +#define SUDO_CONV_REPL_MAX 255 + struct sudo_conv_reply { char *reply; }; @@ -2218,9 +2240,19 @@ and \fRstruct sudo_conv_reply\fR for each message in the conversation. -The plugin is responsible for freeing the reply buffer filled in to the +The plugin is responsible for freeing the reply buffer located in each \fRstruct sudo_conv_reply\fR, -if any. +if it is not +\fRNULL\fR. +\fRSUDO_CONV_REPL_MAX\fR +represents the maximum length of the reply buffer (not including +the trailing NUL character). +In practical terms, this is the longest password +\fBsudo\fR +will support. +It is also useful as a maximum value for the +\fBmemset_s\fR() +function when clearing passwords filled in by the conversation function. .PP The \fBprintf\fR()-style @@ -2313,13 +2345,13 @@ to determine the API version the group plugin was built against. .TP 6n init +.RS .nf -.RS 6n +.RS 0n int (*init)(int version, sudo_printf_t plugin_printf, char *const argv[]); .RE .fi -.RS 6n .sp The \fBinit\fR() @@ -2362,18 +2394,17 @@ If no arguments were given, \fIargv\fR will be \fRNULL\fR. -.PD 0 .PP .RE -.PD +.PD 0 .TP 6n cleanup +.RS .nf -.RS 6n +.RS 0n void (*cleanup)(); .RE .fi -.RS 6n .sp The \fBcleanup\fR() @@ -2382,17 +2413,20 @@ function is called when has finished its group checks. The plugin should free any memory it has allocated and close open file handles. +.PD +.PP .RE +.PD 0 .TP 6n query .br +.RS .nf -.RS 6n +.RS 0n int (*query)(const char *user, const char *group, const struct passwd *pwd); .RE .fi -.RS 6n .sp The \fBquery\fR() @@ -2402,6 +2436,7 @@ is a member of \fIgroup\fR. .sp The function arguments are as follows: +.PD .TP 6n user The name of the user being looked up in the external group database. @@ -2421,10 +2456,7 @@ present in the password database, \fIpwd\fR will be \fRNULL\fR. -.PD 0 -.PP .RE -.PD .PP \fIGroup API Version Macros\fR .nf @@ -2537,7 +2569,7 @@ search the archives. .SH "DISCLAIMER" \fBsudo\fR is provided -\(lqAS IS\(rq +``AS IS'' and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. diff --git a/doc/sudo_plugin.mdoc.in b/doc/sudo_plugin.mdoc.in index 8b0810cb0..7b34f9554 100644 --- a/doc/sudo_plugin.mdoc.in +++ b/doc/sudo_plugin.mdoc.in @@ -1893,6 +1893,8 @@ struct sudo_conv_message { const char *msg; }; +#define SUDO_CONV_REPL_MAX 255 + struct sudo_conv_reply { char *reply; }; @@ -1926,9 +1928,19 @@ and .Li struct sudo_conv_reply for each message in the conversation. -The plugin is responsible for freeing the reply buffer filled in to the +The plugin is responsible for freeing the reply buffer located in each .Li struct sudo_conv_reply , -if any. +if it is not +.Dv NULL . +.Dv SUDO_CONV_REPL_MAX +represents the maximum length of the reply buffer (not including +the trailing NUL character). +In practical terms, this is the longest password +.Nm sudo +will support. +It is also useful as a maximum value for the +.Fn memset_s +function when clearing passwords filled in by the conversation function. .Pp The .Fn printf Ns No -style diff --git a/include/missing.h b/include/missing.h index 2ada306cd..3228a9af6 100644 --- a/include/missing.h +++ b/include/missing.h @@ -384,6 +384,9 @@ size_t strlcpy(char *, const char *, size_t); #ifndef HAVE_MEMRCHR void *memrchr(const void *, int, size_t); #endif +#ifndef HAVE_MEMSET_S +errno_t memset_s(void *, rsize_t, int, rsize_t); +#endif #ifndef HAVE_MKDTEMP char *mkdtemp(char *); #endif diff --git a/include/sudo_plugin.h b/include/sudo_plugin.h index deabf0c05..b6169df1a 100644 --- a/include/sudo_plugin.h +++ b/include/sudo_plugin.h @@ -47,6 +47,17 @@ struct sudo_conv_message { const char *msg; }; +/* + * Maximum length of a reply (not including the trailing NUL) when + * conversing with the user. In practical terms, this is the longest + * password sudo will support. This means that a buffer of size + * SUDO_CONV_REPL_MAX+1 is guaranteed to be able to hold any reply + * from the conversation function. It is also useful as a max value + * for memset_s() when clearing passwords returned by the conversation + * function. + */ +#define SUDO_CONV_REPL_MAX 255 + struct sudo_conv_reply { char *reply; }; diff --git a/mkdep.pl b/mkdep.pl index 8093bc58f..7e7c76747 100755 --- a/mkdep.pl +++ b/mkdep.pl @@ -70,7 +70,7 @@ sub mkdep { $makefile =~ s:\@SUDOERS_OBJS\@:bsm_audit.lo linux_audit.lo ldap.lo sssd.lo:; # XXX - fill in AUTH_OBJS from contents of the auth dir instead $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:; - $makefile =~ s:\@LTLIBOBJS\@:closefrom.lo dlopen.lo fnmatch.lo getcwd.lo getgrouplist.lo getline.lo getprogname.lo getopt_long.lo glob.lo isblank.lo memrchr.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo pw_dup.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo utimes.lo globtest.o fnm_test.o:; + $makefile =~ s:\@LTLIBOBJS\@:closefrom.lo dlopen.lo fnmatch.lo getcwd.lo getgrouplist.lo getline.lo getprogname.lo getopt_long.lo glob.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo pw_dup.lo sig2str.lo siglist.lo signame.lo snprintf.lo strlcat.lo strlcpy.lo strsignal.lo utimes.lo globtest.o fnm_test.o:; # Parse OBJS lines my %objs; diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 05fa28231..97459c7d0 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -786,7 +786,7 @@ set_perms.lo: $(srcdir)/set_perms.c $(top_builddir)/config.h \ $(incdir)/sudo_debug.h $(incdir)/gettext.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/set_perms.c sha2.lo: $(srcdir)/sha2.c $(top_builddir)/config.h \ - $(top_srcdir)/compat/endian.h $(srcdir)/sha2.h + $(top_srcdir)/compat/endian.h $(incdir)/missing.h $(srcdir)/sha2.h $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/sha2.c sha2.o: sha2.lo sia.lo: $(authdir)/sia.c $(top_builddir)/config.h $(srcdir)/sudoers.h \ diff --git a/plugins/sudoers/auth/aix_auth.c b/plugins/sudoers/auth/aix_auth.c index cc24124fb..e9f952698 100644 --- a/plugins/sudoers/auth/aix_auth.c +++ b/plugins/sudoers/auth/aix_auth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007-2012 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2013 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 @@ -65,7 +65,7 @@ sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth) efree(message); message = NULL; result = authenticate(pw->pw_name, pass, &reenter, &message); - zero_bytes(pass, strlen(pass)); + memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); prompt = message; } while (reenter); diff --git a/plugins/sudoers/auth/bsdauth.c b/plugins/sudoers/auth/bsdauth.c index e0eeb4ea3..7ddf37968 100644 --- a/plugins/sudoers/auth/bsdauth.c +++ b/plugins/sudoers/auth/bsdauth.c @@ -156,7 +156,7 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth) if (pass) { authok = auth_userresponse(as, pass, 1); - zero_bytes(pass, strlen(pass)); + memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); } /* restore old signal handler */ diff --git a/plugins/sudoers/auth/fwtk.c b/plugins/sudoers/auth/fwtk.c index b27625f7e..853ea4b3f 100644 --- a/plugins/sudoers/auth/fwtk.c +++ b/plugins/sudoers/auth/fwtk.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2008, 2010-2012 + * Copyright (c) 1999-2005, 2008, 2010-2013 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -82,7 +82,7 @@ int sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth) { char *pass; /* Password from the user */ - char buf[SUDO_PASS_MAX + 12]; /* General prupose buffer */ + char buf[SUDO_CONV_REPL_MAX + 12]; /* General prupose buffer */ char resp[128]; /* Response from the server */ int error; debug_decl(sudo_fwtk_verify, SUDO_DEBUG_AUTH) @@ -139,8 +139,8 @@ restart: warningx("%s", resp); error = AUTH_FAILURE; done: - zero_bytes(pass, strlen(pass)); - zero_bytes(buf, strlen(buf)); + memset_s(pass, SUDO_PASS_MAX, 0, strlen(pass)); + memset_s(buf, sizeof(buf), 0, sizeof(buf)); debug_return_int(error); } diff --git a/plugins/sudoers/auth/pam.c b/plugins/sudoers/auth/pam.c index 13ecbc25c..0e263b98a 100644 --- a/plugins/sudoers/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -312,7 +312,7 @@ converse(int num_msg, PAM_CONST struct pam_message **msg, if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL) debug_return_int(PAM_SYSTEM_ERR); - zero_bytes(*response, num_msg * sizeof(struct pam_response)); + memset(*response, 0, num_msg * sizeof(struct pam_response)); for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) { type = SUDO_CONV_PROMPT_ECHO_OFF; @@ -356,7 +356,7 @@ converse(int num_msg, PAM_CONST struct pam_message **msg, #endif } pr->resp = estrdup(pass); - zero_bytes(pass, strlen(pass)); + memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); break; case PAM_TEXT_INFO: if (pm->msg) @@ -380,12 +380,11 @@ done: /* Zero and free allocated memory and return an error. */ for (pr = *response, n = num_msg; n--; pr++) { if (pr->resp != NULL) { - zero_bytes(pr->resp, strlen(pr->resp)); + memset_s(pr->resp, SUDO_CONV_REPL_MAX, 0, strlen(pr->resp)); free(pr->resp); pr->resp = NULL; } } - zero_bytes(*response, num_msg * sizeof(struct pam_response)); free(*response); *response = NULL; } diff --git a/plugins/sudoers/auth/passwd.c b/plugins/sudoers/auth/passwd.c index 8f1d7defd..668c96f5e 100644 --- a/plugins/sudoers/auth/passwd.c +++ b/plugins/sudoers/auth/passwd.c @@ -114,7 +114,7 @@ sudo_passwd_cleanup(pw, auth) debug_decl(sudo_passwd_cleanup, SUDO_DEBUG_AUTH) if (pw_epasswd != NULL) { - zero_bytes(pw_epasswd, strlen(pw_epasswd)); + memset_s(pw_epasswd, SUDO_CONV_REPL_MAX, 0, strlen(pw_epasswd)); efree(pw_epasswd); } debug_return_int(AUTH_SUCCESS); diff --git a/plugins/sudoers/auth/secureware.c b/plugins/sudoers/auth/secureware.c index f5839ed13..f487f2f7a 100644 --- a/plugins/sudoers/auth/secureware.c +++ b/plugins/sudoers/auth/secureware.c @@ -106,7 +106,7 @@ sudo_secureware_cleanup(pw, auth) debug_decl(sudo_secureware_cleanup, SUDO_DEBUG_AUTH) if (pw_epasswd != NULL) { - zero_bytes(pw_epasswd, strlen(pw_epasswd)); + memset_s(pw_epasswd, SUDO_CONV_REPL_MAX, 0, strlen(pw_epasswd)); efree(pw_epasswd); } debug_return_int(AUTH_SUCCESS); diff --git a/plugins/sudoers/auth/sudo_auth.c b/plugins/sudoers/auth/sudo_auth.c index dbe53cabd..3d5a32258 100644 --- a/plugins/sudoers/auth/sudo_auth.c +++ b/plugins/sudoers/auth/sudo_auth.c @@ -254,7 +254,7 @@ verify_user(struct passwd *pw, char *prompt, int validated) goto done; } if (!standalone) - zero_bytes(p, strlen(p)); + memset_s(p, SUDO_CONV_REPL_MAX, 0, strlen(p)); pass_warn(); } diff --git a/plugins/sudoers/defaults.c b/plugins/sudoers/defaults.c index 277cf3f06..dfa232784 100644 --- a/plugins/sudoers/defaults.c +++ b/plugins/sudoers/defaults.c @@ -356,7 +356,7 @@ init_defaults(void) list_op(NULL, 0, def, freeall); break; } - zero_bytes(&def->sd_un, sizeof(def->sd_un)); + memset(&def->sd_un, 0, sizeof(def->sd_un)); } } diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c index d7256a5f3..eee0f2d5a 100644 --- a/plugins/sudoers/logging.c +++ b/plugins/sudoers/logging.c @@ -609,7 +609,7 @@ send_mail(const char *fmt, ...) closefrom(STDERR_FILENO + 1); /* Ignore SIGPIPE in case mailer exits prematurely (or is missing). */ - zero_bytes(&sa, sizeof(sa)); + memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_INTERRUPT; sa.sa_handler = SIG_IGN; diff --git a/plugins/sudoers/sha2.c b/plugins/sudoers/sha2.c index 74ede4099..45f21d87b 100644 --- a/plugins/sudoers/sha2.c +++ b/plugins/sudoers/sha2.c @@ -58,6 +58,7 @@ # include "compat/endian.h" #endif +#include "missing.h" #include "sha2.h" /* @@ -117,8 +118,6 @@ #define g(i) T[(6-i)&7] #define h(i) T[(7-i)&7] -extern void zero_bytes(volatile void *, size_t); - void SHA224Init(SHA2_CTX *ctx) { @@ -249,8 +248,8 @@ SHA256Transform(uint32_t state[8], const uint8_t data[SHA256_BLOCK_LENGTH]) state[6] += g(0); state[7] += h(0); /* Cleanup */ - zero_bytes(T, sizeof(T)); - zero_bytes(W, sizeof(W)); + memset_s(T, sizeof(T), 0, sizeof(T)); + memset_s(W, sizeof(W), 0, sizeof(W)); } #undef S0 @@ -466,8 +465,8 @@ SHA512Transform(uint64_t state[8], const uint8_t data[SHA512_BLOCK_LENGTH]) state[6] += g(0); state[7] += h(0); /* Cleanup. */ - zero_bytes(T, sizeof(T)); - zero_bytes(W, sizeof(W)); + memset_s(T, sizeof(T), 0, sizeof(T)); + memset_s(W, sizeof(W), 0, sizeof(W)); } void diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index c06907cea..244cd3b3b 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -807,7 +807,7 @@ set_fqdn(void) char *p; debug_decl(set_fqdn, SUDO_DEBUG_PLUGIN) - zero_bytes(&hint, sizeof(hint)); + memset(&hint, 0, sizeof(hint)); hint.ai_family = PF_UNSPEC; hint.ai_flags = AI_FQDN; if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) { diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 4e64a8e43..7b399e9be 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -210,14 +210,6 @@ struct sudo_user { #endif #define ROOT_GID 0 -/* - * We used to use the system definition of PASS_MAX or _PASSWD_LEN, - * but that caused problems with various alternate authentication - * methods. So, we just define our own and assume that it is >= the - * system max. - */ -#define SUDO_PASS_MAX 256 - struct lbuf; struct passwd; struct stat; @@ -287,9 +279,6 @@ void dump_auth_methods(void); /* getspwuid.c */ char *sudo_getepw(const struct passwd *); -/* zero_bytes.c */ -void zero_bytes(volatile void *, size_t); - /* sudo_nss.c */ void display_privs(struct sudo_nss_list *, struct passwd *); bool display_cmnd(struct sudo_nss_list *, struct passwd *); diff --git a/plugins/sudoers/tsgetgrpw.c b/plugins/sudoers/tsgetgrpw.c index edfc3837d..56940401d 100644 --- a/plugins/sudoers/tsgetgrpw.c +++ b/plugins/sudoers/tsgetgrpw.c @@ -130,7 +130,7 @@ next_entry: if ((colon = fgets(pwbuf, sizeof(pwbuf), pwf)) == NULL) return NULL; - zero_bytes(&pw, sizeof(pw)); + memset(&pw, 0, sizeof(pw)); if ((colon = strchr(cp = colon, ':')) == NULL) goto next_entry; *colon++ = '\0'; @@ -263,7 +263,7 @@ next_entry: if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL) return NULL; - zero_bytes(&gr, sizeof(gr)); + memset(&gr, 0, sizeof(gr)); if ((colon = strchr(cp = colon, ':')) == NULL) goto next_entry; *colon++ = '\0'; diff --git a/plugins/sudoers/visudo.c b/plugins/sudoers/visudo.c index 7756a565a..13fcf3153 100644 --- a/plugins/sudoers/visudo.c +++ b/plugins/sudoers/visudo.c @@ -741,7 +741,7 @@ setup_signals(void) /* * Setup signal handlers to cleanup nicely. */ - zero_bytes(&sa, sizeof(sa)); + memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = quit; diff --git a/src/Makefile.in b/src/Makefile.in index 3b11b7e47..53d92d488 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -311,7 +311,8 @@ tgetpass.o: $(srcdir)/tgetpass.c $(top_builddir)/config.h $(srcdir)/sudo.h \ $(top_builddir)/pathnames.h $(top_srcdir)/compat/stdbool.h \ $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h \ $(incdir)/fileops.h $(incdir)/list.h $(incdir)/sudo_conf.h \ - $(incdir)/list.h $(incdir)/sudo_debug.h $(incdir)/gettext.h + $(incdir)/list.h $(incdir)/sudo_debug.h $(incdir)/gettext.h \ + $(incdir)/sudo_plugin.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/tgetpass.c ttyname.o: $(srcdir)/ttyname.c $(top_builddir)/config.h $(srcdir)/sudo.h \ $(top_builddir)/pathnames.h $(top_srcdir)/compat/stdbool.h \ diff --git a/src/conversation.c b/src/conversation.c index bab539ef7..e61a7e306 100644 --- a/src/conversation.c +++ b/src/conversation.c @@ -81,7 +81,7 @@ sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[], if (pass == NULL) goto err; repl->reply = estrdup(pass); - zero_bytes(pass, strlen(pass)); + memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); break; case SUDO_CONV_INFO_MSG: if (msg->msg) @@ -107,7 +107,7 @@ err: do { repl = &replies[n]; if (repl->reply != NULL) { - zero_bytes(repl->reply, strlen(repl->reply)); + memset_s(repl->reply, SUDO_CONV_REPL_MAX, 0, strlen(repl->reply)); free(repl->reply); repl->reply = NULL; } diff --git a/src/sudo.h b/src/sudo.h index 26c9025a2..ce32d940c 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -75,14 +75,6 @@ #define MODE_NONINTERACTIVE 0x00800000 #define MODE_LONG_LIST 0x01000000 -/* - * We used to use the system definition of PASS_MAX or _PASSWD_LEN, - * but that caused problems with various alternate authentication - * methods. So, we just define our own and assume that it is >= the - * system max. - */ -#define SUDO_PASS_MAX 256 - /* * Flags for tgetpass() */ @@ -178,9 +170,6 @@ void cleanup(int); char *tgetpass(const char *, int, int); int tty_present(void); -/* zero_bytes.c */ -void zero_bytes(volatile void *, size_t); - /* exec.c */ int pipe_nonblock(int fds[2]); int sudo_execute(struct command_details *details, struct command_status *cstat); diff --git a/src/sudo_edit.c b/src/sudo_edit.c index 90864c604..d8ecf8b72 100644 --- a/src/sudo_edit.c +++ b/src/sudo_edit.c @@ -148,14 +148,14 @@ sudo_edit(struct command_details *command_details) * and copy the contents of the original to it. */ tf = emalloc2(nfiles, sizeof(*tf)); - zero_bytes(tf, nfiles * sizeof(*tf)); + memset(tf, 0, nfiles * sizeof(*tf)); for (i = 0, j = 0; i < nfiles; i++) { rc = -1; switch_user(command_details->euid, command_details->egid, command_details->ngroups, command_details->groups); if ((ofd = open(files[i], O_RDONLY, 0644)) != -1 || errno == ENOENT) { if (ofd == -1) { - zero_bytes(&sb, sizeof(sb)); /* new file */ + memset(&sb, 0, sizeof(sb)); /* new file */ rc = 0; } else { rc = fstat(ofd, &sb); diff --git a/src/tgetpass.c b/src/tgetpass.c index 31194b963..86160bbe8 100644 --- a/src/tgetpass.c +++ b/src/tgetpass.c @@ -53,6 +53,7 @@ #include #include "sudo.h" +#include "sudo_plugin.h" static volatile sig_atomic_t signo[NSIG]; @@ -70,7 +71,7 @@ tgetpass(const char *prompt, int timeout, int flags) sigaction_t savetstp, savettin, savettou, savepipe; char *pass; static const char *askpass; - static char buf[SUDO_PASS_MAX + 1]; + static char buf[SUDO_CONV_REPL_MAX + 1]; int i, input, output, save_errno, neednl = 0, need_restart; debug_decl(tgetpass, SUDO_DEBUG_CONV) @@ -127,7 +128,7 @@ restart: * Catch signals that would otherwise cause the user to end * up with echo turned off in the shell. */ - zero_bytes(&sa, sizeof(sa)); + memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_INTERRUPT; /* don't restart system calls */ sa.sa_handler = tgetpass_handler; @@ -207,7 +208,7 @@ restore: static char * sudo_askpass(const char *askpass, const char *prompt) { - static char buf[SUDO_PASS_MAX + 1], *pass; + static char buf[SUDO_CONV_REPL_MAX + 1], *pass; sigaction_t sa, saved_sa_pipe; int pfd[2]; pid_t pid; @@ -242,7 +243,7 @@ sudo_askpass(const char *askpass, const char *prompt) } /* Ignore SIGPIPE in case child exits prematurely */ - zero_bytes(&sa, sizeof(sa)); + memset(&sa, 0, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_INTERRUPT; sa.sa_handler = SIG_IGN;