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

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