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.
This commit is contained in:
Todd C. Miller
2013-08-03 08:30:06 -06:00
parent 8c867be419
commit 1f3ea50afd
34 changed files with 371 additions and 233 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -1,36 +0,0 @@
/*
* Copyright (c) 2003-2005, 2007, 2010
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* 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 <config.h>
#include <sys/types.h>
#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;
}

View File

@@ -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

71
compat/memset_s.c Normal file
View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2013 Todd C. Miller <Todd.Miller@courtesan.com>
*
* 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 <config.h>
#include <sys/types.h>
#include <errno.h>
#include <limits.h>
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#elif defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#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;
}

View File

@@ -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 <sys/types.h> does not define. */
#undef dev_t
/* Define to `int' if <sys/types.h> does not define. */
#undef errno_t
/* Define to `int' if <sys/types.h> 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 <sys/types.h> does not define. */
#undef rsize_t
/* Define to `int' if <signal.h> does not define. */
#undef sig_atomic_t

48
configure vendored
View File

@@ -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

View File

@@ -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 <sys/socket.h>])
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)])

View File

@@ -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,

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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 \

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2005, 2007-2012 Todd C. Miller <Todd.Miller@courtesan.com>
* Copyright (c) 1999-2005, 2007-2013 Todd C. Miller <Todd.Miller@courtesan.com>
*
* 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);

View File

@@ -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 */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2005, 2008, 2010-2012
* Copyright (c) 1999-2005, 2008, 2010-2013
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* 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);
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -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));
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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) {

View File

@@ -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 *);

View File

@@ -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';

View File

@@ -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;

View File

@@ -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 \

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -53,6 +53,7 @@
#include <fcntl.h>
#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;