Add support for logging to the log server

This commit is contained in:
Todd C. Miller
2019-11-15 13:41:51 -07:00
parent 5793023ffd
commit 82237194dd
13 changed files with 1843 additions and 174 deletions

View File

@@ -359,7 +359,9 @@ plugins/sudoers/insults.h
plugins/sudoers/interfaces.c
plugins/sudoers/interfaces.h
plugins/sudoers/iolog.c
plugins/sudoers/iolog_client.c
plugins/sudoers/iolog_path_escapes.c
plugins/sudoers/iolog_plugin.h
plugins/sudoers/ldap.c
plugins/sudoers/ldap_conf.c
plugins/sudoers/ldap_util.c

View File

@@ -54,9 +54,10 @@ INSTALL_BACKUP = @INSTALL_BACKUP@
# Libraries
LIBUTIL = $(top_builddir)/lib/util/libsudo_util.la
LIBIOLOG = $(top_builddir)/lib/iolog/libsudo_iolog.la
LIBLOGSRV = $(top_builddir)/lib/logsrv/liblogsrv.la
LIBS = $(LIBUTIL)
NET_LIBS = @NET_LIBS@
SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(NET_LIBS) $(LIBIOLOG)
SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(NET_LIBS) $(LIBIOLOG) $(LIBLOGSRV)
REPLAY_LIBS = @REPLAY_LIBS@ $(LIBIOLOG)
VISUDO_LIBS = $(NET_LIBS)
CVTSUDOERS_LIBS = $(NET_LIBS)
@@ -158,17 +159,17 @@ LIBPARSESUDOERS_OBJS = alias.lo audit.lo base64.lo defaults.lo digestname.lo \
filedigest.lo gentime.lo gmtoff.lo gram.lo hexchar.lo \
match.lo match_addr.lo match_command.lo match_digest.lo \
pwutil.lo pwutil_impl.lo rcstr.lo redblack.lo \
sudoers_debug.lo timeout.lo timestr.lo toke.lo \
toke_util.lo
strlist.lo sudoers_debug.lo timeout.lo timestr.lo \
toke.lo toke_util.lo
LIBPARSESUDOERS_IOBJS = $(LIBPARSESUDOERS_OBJS:.lo=.i) passwd.i
SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo editor.lo env.lo \
env_pattern.lo file.lo find_path.lo fmtsudoers.lo gc.lo \
goodpath.lo group_plugin.lo interfaces.lo iolog.lo \
iolog_path_escapes.lo locale.lo logging.lo logwrap.lo \
parse.lo policy.lo prompt.lo set_perms.lo starttime.lo \
sudo_nss.lo sudoers.lo timestamp.lo @SUDOERS_OBJS@
iolog_path_escapes.lo locale.lo iolog_client.lo logging.lo \
logwrap.lo parse.lo policy.lo prompt.lo set_perms.lo \
starttime.lo sudo_nss.lo sudoers.lo timestamp.lo @SUDOERS_OBJS@
SUDOERS_IOBJS = $(SUDOERS_OBJS:.lo=.i)
@@ -179,17 +180,17 @@ VISUDO_IOBJS = sudo_printf.i visudo.i
CVTSUDOERS_OBJS = cvtsudoers.o cvtsudoers_json.o cvtsudoers_ldif.o \
cvtsudoers_pwutil.o fmtsudoers.lo locale.lo parse_ldif.o \
strlist.o stubs.o sudo_printf.o ldap_util.lo
stubs.o sudo_printf.o ldap_util.lo
CVTSUDOERS_IOBJS = cvtsudoers.i cvtsudoers_json.i cvtsudoers_ldif.i \
cvtsudoers_pwutil.i strlist.i
cvtsudoers_pwutil.i
REPLAY_OBJS = getdate.o sudoreplay.o
REPLAY_IOBJS = $(REPLAY_OBJS:.o=.i)
TEST_OBJS = fmtsudoers.lo group_plugin.lo interfaces.lo ldap_util.lo \
locale.lo net_ifs.o parse_ldif.o strlist.o sudo_printf.o \
locale.lo net_ifs.o parse_ldif.o sudo_printf.o \
testsudoers.o tsgetgrpw.o
IOBJS = $(LIBPARSESUDOERS_IOBJS) $(SUDOERS_IOBJS) $(VISUDO_IOBJS) \
@@ -214,8 +215,9 @@ CHECK_GENTIME_OBJS = check_gentime.o gentime.lo gmtoff.lo sudoers_debug.lo
CHECK_HEXCHAR_OBJS = check_hexchar.o hexchar.lo sudoers_debug.lo
CHECK_IOLOG_PLUGIN_OBJS = check_iolog_plugin.o iolog.lo locale.lo pwutil.lo \
pwutil_impl.lo redblack.lo sudoers_debug.lo
CHECK_IOLOG_PLUGIN_OBJS = check_iolog_plugin.o iolog.lo iolog_client.lo \
locale.lo pwutil.lo pwutil_impl.lo redblack.lo \
strlist.lo sudoers_debug.lo
CHECK_SYMBOLS_OBJS = check_symbols.o
@@ -266,7 +268,7 @@ Makefile: $(srcdir)/Makefile.in
libparsesudoers.la: $(LIBPARSESUDOERS_OBJS)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBPARSESUDOERS_OBJS) -no-install
sudoers.la: $(SUDOERS_OBJS) $(LIBUTIL) $(LIBIOLOG) libparsesudoers.la @LT_LDDEP@
sudoers.la: $(SUDOERS_OBJS) $(LIBUTIL) $(LIBIOLOG) $(LIBLOGSRV) libparsesudoers.la @LT_LDDEP@
case "$(LT_LDFLAGS)" in \
*-no-install*) \
$(LIBTOOL) $(LTFLAGS) @LT_STATIC@ --mode=link $(CC) $(LDFLAGS) $(LT_LDFLAGS) -o $@ $(SUDOERS_OBJS) libparsesudoers.la $(SUDOERS_LIBS) -module;; \
@@ -310,8 +312,8 @@ check_gentime: $(CHECK_GENTIME_OBJS) $(LIBUTIL)
check_hexchar: $(CHECK_HEXCHAR_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_HEXCHAR_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
check_iolog_plugin: $(CHECK_IOLOG_PLUGIN_OBJS) $(LIBUTIL) $(LIBIOLOG)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PLUGIN_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBIOLOG)
check_iolog_plugin: $(CHECK_IOLOG_PLUGIN_OBJS) $(LIBUTIL) $(LIBIOLOG) $(LIBLOGSRV)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PLUGIN_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBIOLOG) $(LIBLOGSRV)
check_starttime: $(CHECK_STARTTIME_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_STARTTIME_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
@@ -1494,25 +1496,57 @@ interfaces.i: $(srcdir)/interfaces.c $(devdir)/def_data.h \
interfaces.plog: interfaces.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/interfaces.c --i-file $< --output-file $@
iolog.lo: $(srcdir)/iolog.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
$(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
$(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
$(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(srcdir)/iolog_plugin.h $(srcdir)/logging.h $(srcdir)/parse.h \
$(srcdir)/strlist.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
$(top_builddir)/pathnames.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog.c
iolog.i: $(srcdir)/iolog.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
$(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
$(incdir)/sudo_iolog.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/defaults.h \
$(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(srcdir)/iolog_plugin.h $(srcdir)/logging.h $(srcdir)/parse.h \
$(srcdir)/strlist.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
$(top_builddir)/pathnames.h
$(CC) -E -o $@ $(CPPFLAGS) $<
iolog.plog: iolog.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog.c --i-file $< --output-file $@
iolog_client.lo: $(srcdir)/iolog_client.c $(devdir)/def_data.h \
$(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
$(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(srcdir)/defaults.h \
$(srcdir)/iolog_plugin.h $(srcdir)/logging.h \
$(srcdir)/parse.h $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_client.c
iolog_client.i: $(srcdir)/iolog_client.c $(devdir)/def_data.h \
$(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
$(incdir)/log_server.pb-c.h $(incdir)/protobuf-c/protobuf-c.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
$(incdir)/sudo_debug.h $(incdir)/sudo_event.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(srcdir)/defaults.h \
$(srcdir)/iolog_plugin.h $(srcdir)/logging.h \
$(srcdir)/parse.h $(srcdir)/strlist.h $(srcdir)/sudo_nss.h \
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(CC) -E -o $@ $(CPPFLAGS) $<
iolog_client.plog: iolog_client.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_client.c --i-file $< --output-file $@
iolog_path_escapes.lo: $(srcdir)/iolog_path_escapes.c $(devdir)/def_data.h \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
@@ -2201,11 +2235,11 @@ starttime.i: $(srcdir)/starttime.c $(devdir)/def_data.h \
$(CC) -E -o $@ $(CPPFLAGS) $<
starttime.plog: starttime.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/starttime.c --i-file $< --output-file $@
strlist.o: $(srcdir)/strlist.c $(incdir)/compat/stdbool.h \
strlist.lo: $(srcdir)/strlist.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/strlist.h \
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/strlist.c
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/strlist.c
strlist.i: $(srcdir)/strlist.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/strlist.h \

View File

@@ -505,6 +505,14 @@ struct sudo_defs_types sudo_defs_table[] = {
"log_denied", T_FLAG,
N_("Log when a command is denied by sudoers"),
NULL,
}, {
"log_server", T_LIST|T_BOOL,
N_("Sudo log server(s) to connect to with optional port"),
NULL,
}, {
"log_server_timeout", T_TIMEOUT|T_BOOL,
N_("Sudo log server timeout in seconds: %u"),
NULL,
}, {
NULL, 0, NULL
}

View File

@@ -232,6 +232,10 @@
#define def_log_allowed (sudo_defs_table[I_LOG_ALLOWED].sd_un.flag)
#define I_LOG_DENIED 116
#define def_log_denied (sudo_defs_table[I_LOG_DENIED].sd_un.flag)
#define I_LOG_SERVER 117
#define def_log_server (sudo_defs_table[I_LOG_SERVER].sd_un.list)
#define I_LOG_SERVER_TIMEOUT 118
#define def_log_server_timeout (sudo_defs_table[I_LOG_SERVER_TIMEOUT].sd_un.ival)
enum def_tuple {
never,

View File

@@ -366,3 +366,9 @@ log_allowed
log_denied
T_FLAG
"Log when a command is denied by sudoers"
log_server
T_LIST|T_BOOL
"Sudo log server(s) to connect to with optional port"
log_server_timeout
T_TIMEOUT|T_BOOL
"Sudo log server timeout in seconds: %u"

View File

@@ -562,6 +562,7 @@ init_defaults(void)
#ifdef HAVE_ZLIB_H
def_compress_io = true;
#endif
def_log_server_timeout = 30;
def_ignore_audit_errors = true;
def_ignore_iolog_errors = false;
def_ignore_logfile_errors = true;

View File

@@ -43,23 +43,7 @@
#include "sudoers.h"
#include "sudo_iolog.h"
/* XXX - separate sudoers.h and iolog.h? */
#undef runas_pw
#undef runas_gr
struct iolog_details {
const char *cwd;
const char *tty;
const char *user;
const char *command;
const char *iolog_path;
struct passwd *runas_pw;
struct group *runas_gr;
int lines;
int cols;
bool ignore_iolog_errors;
};
#include "iolog_plugin.h"
static struct iolog_file iolog_files[] = {
{ false }, /* IOFD_STDIN */
@@ -70,6 +54,7 @@ static struct iolog_file iolog_files[] = {
{ true, }, /* IOFD_TIMING */
};
static struct client_closure client_closure = CLIENT_CLOSURE_INITIALIZER(client_closure);
static struct iolog_details iolog_details;
static bool warned = false;
static struct timespec last_time;
@@ -77,6 +62,8 @@ static struct timespec last_time;
/* sudoers_io is declared at the end of this file. */
extern __dso_public struct io_plugin sudoers_io;
#define iolog_remote (client_closure.sock != -1)
/*
* Sudoers callback for maxseq Defaults setting.
*/
@@ -162,10 +149,47 @@ cb_iolog_mode(const union sudo_defs_val *sd_un)
}
/*
* Pull out I/O log related data from user_info and command_info arrays.
* Returns true if I/O logging is enabled, else false.
* Convert a comma-separated list to a string list.
*/
static bool
static struct sudoers_str_list *
deserialize_stringlist(const char *s)
{
struct sudoers_str_list *strlist;
struct sudoers_string *str;
const char *s_end = s + strlen(s);
const char *cp, *ep;
debug_decl(deserialize_stringlist, SUDOERS_DEBUG_UTIL)
if ((strlist = str_list_alloc()) == NULL)
debug_return_ptr(NULL);
for (cp = sudo_strsplit(s, s_end, ",", &ep); cp != NULL;
cp = sudo_strsplit(NULL, s_end, ",", &ep)) {
if (cp == ep)
continue;
if ((str = malloc(sizeof(*str))) == NULL)
goto bad;
if ((str->str = strndup(cp, (ep - cp))) == NULL) {
free(str);
goto bad;
}
STAILQ_INSERT_TAIL(strlist, str, entries);
}
if (STAILQ_EMPTY(strlist))
goto bad;
debug_return_ptr(strlist);
bad:
str_list_free(strlist);
debug_return_ptr(NULL);
}
/*
* Pull out I/O log related data from user_info and command_info arrays.
* Returns true if I/O logging is enabled, false if not and -1 on error.
*/
static int
iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
char * const command_info[])
{
@@ -197,6 +221,12 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
continue;
}
break;
case 'h':
if (strncmp(*cur, "host=", sizeof("host=") - 1) == 0) {
details->host = *cur + sizeof("host=") - 1;
continue;
}
break;
case 'l':
if (strncmp(*cur, "lines=", sizeof("lines=") - 1) == 0) {
int n = sudo_strtonum(*cur + sizeof("lines=") - 1, 1, INT_MAX,
@@ -319,6 +349,21 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
continue;
}
break;
case 'l':
if (strncmp(*cur, "log_servers=", sizeof("log_servers=") - 1) == 0) {
details->log_servers =
deserialize_stringlist(*cur + sizeof("log_servers=") - 1);
if (!details->log_servers)
goto oom;
continue;
}
if (strncmp(*cur, "log_server_timeout=", sizeof("log_server_timeout=") - 1) == 0) {
details->server_timeout.tv_sec =
sudo_strtonum(*cur + sizeof("log_server_timeout=") - 1, 1,
TIME_T_MAX, NULL);
continue;
}
break;
case 'm':
if (strncmp(*cur, "maxseq=", sizeof("maxseq=") - 1) == 0) {
union sudo_defs_val sd_un;
@@ -385,10 +430,14 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
details->runas_gr = sudo_fakegrnam(idbuf);
}
}
debug_return_bool(
debug_return_int(
iolog_files[IOFD_STDIN].enabled || iolog_files[IOFD_STDOUT].enabled ||
iolog_files[IOFD_STDERR].enabled || iolog_files[IOFD_TTYIN].enabled ||
iolog_files[IOFD_TTYOUT].enabled);
oom:
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
str_list_free(details->log_servers);
debug_return_int(-1);
}
/*
@@ -396,8 +445,7 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
* This file is not compressed.
*/
static bool
write_info_log(int dfd, char *iolog_dir, struct iolog_details *details,
char * const argv[])
write_info_log(int dfd, char *iolog_dir, struct iolog_details *details)
{
struct iolog_info iolog_info;
debug_decl(write_info_log, SUDOERS_DEBUG_UTIL)
@@ -414,7 +462,7 @@ write_info_log(int dfd, char *iolog_dir, struct iolog_details *details,
iolog_info.lines = details->lines;
iolog_info.cols = details->cols;
if (!iolog_write_info_file(dfd, iolog_dir, &iolog_info, argv)) {
if (!iolog_write_info_file(dfd, iolog_dir, &iolog_info, details->argv)) {
log_warning(SLOG_SEND_MAIL,
N_("unable to write to I/O log file: %s"), strerror(errno));
warned = true;
@@ -424,55 +472,13 @@ write_info_log(int dfd, char *iolog_dir, struct iolog_details *details,
}
static int
sudoers_io_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[], char * const args[])
sudoers_io_open_local(void)
{
struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files);
char iolog_path[PATH_MAX], sessid[7];
char * const *cur;
const char *cp, *plugin_path = NULL;
size_t len;
int i, ret = -1;
int iolog_dir_fd = -1;
debug_decl(sudoers_io_open, SUDOERS_DEBUG_PLUGIN)
sudo_conv = conversation;
sudo_printf = plugin_printf;
/* If we have no command (because -V was specified) just return. */
if (argc == 0)
debug_return_int(true);
bindtextdomain("sudoers", LOCALEDIR);
/* Initialize the debug subsystem. */
for (cur = settings; (cp = *cur) != NULL; cur++) {
if (strncmp(cp, "debug_flags=", sizeof("debug_flags=") - 1) == 0) {
cp += sizeof("debug_flags=") - 1;
if (!sudoers_debug_parse_flags(&debug_files, cp))
debug_return_int(-1);
continue;
}
if (strncmp(cp, "plugin_path=", sizeof("plugin_path=") - 1) == 0) {
plugin_path = cp + sizeof("plugin_path=") - 1;
continue;
}
}
if (!sudoers_debug_register(plugin_path, &debug_files)) {
ret = -1;
goto done;
}
/*
* Pull iolog settings out of command_info.
*/
if (!iolog_deserialize_info(&iolog_details, user_info, command_info)) {
ret = false;
goto done;
}
int i, ret = -1;
debug_decl(sudoers_io_open_local, SUDOERS_DEBUG_PLUGIN)
/* If no I/O log path defined we need to figure it out ourselves. */
if (iolog_details.iolog_path == NULL) {
@@ -517,7 +523,7 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
}
/* Write log file with user and command details. */
if (!write_info_log(iolog_dir_fd, iolog_path, &iolog_details, argv))
if (!write_info_log(iolog_dir_fd, iolog_path, &iolog_details))
goto done;
/* Create the timing and I/O log files. */
@@ -529,6 +535,107 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
}
}
ret = true;
done:
if (iolog_dir_fd != -1)
close(iolog_dir_fd);
debug_return_int(ret);
}
static int
sudoers_io_open_remote(void)
{
int sock, ret = -1;
debug_decl(sudoers_io_open_remote, SUDOERS_DEBUG_PLUGIN)
/* Connect to log server. */
sock = log_server_connect(iolog_details.log_servers,
&iolog_details.server_timeout);
if (sock == -1) {
/* TODO: support offline logs if server unreachable */
sudo_warnx(U_("unable to connect to log server"));
ret = -1;
goto done;
}
if (!client_closure_fill(&client_closure, sock, &iolog_details, &sudoers_io)) {
close(sock);
ret = -1;
goto done;
}
/* Enable reader for server hello */
ret = client_closure.read_ev->add(client_closure.read_ev,
&iolog_details.server_timeout);
if (ret == -1)
sudo_warn(U_("unable to add event to queue"));
done:
debug_return_int(ret);
}
static int
sudoers_io_open(unsigned int version, sudo_conv_t conversation,
sudo_printf_t plugin_printf, char * const settings[],
char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[], char * const args[])
{
struct sudo_conf_debug_file_list debug_files = TAILQ_HEAD_INITIALIZER(debug_files);
char * const *cur;
const char *cp, *plugin_path = NULL;
int ret = -1;
debug_decl(sudoers_io_open, SUDOERS_DEBUG_PLUGIN)
sudo_conv = conversation;
sudo_printf = plugin_printf;
/* If we have no command (because -V was specified) just return. */
if (argc == 0)
debug_return_int(true);
bindtextdomain("sudoers", LOCALEDIR);
/* Initialize the debug subsystem. */
for (cur = settings; (cp = *cur) != NULL; cur++) {
if (strncmp(cp, "debug_flags=", sizeof("debug_flags=") - 1) == 0) {
cp += sizeof("debug_flags=") - 1;
if (!sudoers_debug_parse_flags(&debug_files, cp))
debug_return_int(-1);
continue;
}
if (strncmp(cp, "plugin_path=", sizeof("plugin_path=") - 1) == 0) {
plugin_path = cp + sizeof("plugin_path=") - 1;
continue;
}
}
if (!sudoers_debug_register(plugin_path, &debug_files)) {
ret = -1;
goto done;
}
/*
* Pull iolog settings out of command_info.
*/
ret = iolog_deserialize_info(&iolog_details, user_info, command_info);
if (ret != true)
goto done;
iolog_details.user_env = user_env;
iolog_details.argv = argv;
iolog_details.argc = argc;
/*
* Create local I/O log file or connect to remote log server.
*/
if (sudoers_io.event_alloc != NULL && iolog_details.log_servers != NULL)
ret = sudoers_io_open_remote();
else
ret = sudoers_io_open_local();
if (ret != true)
goto done;
/*
* Clear I/O log function pointers for disabled log functions.
*/
@@ -548,18 +655,19 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
"%s: unable to get time of day", __func__);
goto done;
}
ret = true;
if (iolog_remote)
client_closure.start_time = last_time;
done:
if (iolog_dir_fd != -1)
close(iolog_dir_fd);
if (ret != true) {
client_closure_free(&client_closure);
if (iolog_details.runas_pw)
sudo_pw_delref(iolog_details.runas_pw);
if (iolog_details.runas_gr)
sudo_gr_delref(iolog_details.runas_gr);
sudo_freepwcache();
sudo_freegrcache();
}
/* Ignore errors if they occur if the policy says so. */
if (ret == -1 && iolog_details.ignore_iolog_errors)
@@ -575,11 +683,35 @@ sudoers_io_close(int exit_status, int error)
int i;
debug_decl(sudoers_io_close, SUDOERS_DEBUG_PLUGIN)
if (iolog_remote) {
if (client_closure.disabled)
goto done;
if (!fmt_exit_message(&client_closure, exit_status, error))
goto done;
/*
* Main sudo event loop exited, use our own mini event loop
* to flush the write queue and read the final commit messages.
*/
if (!client_loop(&client_closure))
goto done;
} else {
for (i = 0; i < IOFD_MAX; i++) {
if (iolog_files[i].fd.v == NULL)
continue;
iolog_close(&iolog_files[i], &errstr);
}
}
done:
client_closure_free(&client_closure);
if (iolog_details.runas_pw)
sudo_pw_delref(iolog_details.runas_pw);
if (iolog_details.runas_gr)
sudo_gr_delref(iolog_details.runas_gr);
sudo_freepwcache();
sudo_freegrcache();
if (errstr != NULL && !warned) {
/* Only warn about I/O log file errors once. */
@@ -605,52 +737,128 @@ sudoers_io_version(int verbose)
}
/*
* Generic I/O logging function. Called by the I/O logging entry points.
* Write an I/O log entry to the local file system.
* Returns 1 on success and -1 on error.
* Fills in errstr on error.
*/
static int
sudoers_io_log(struct iolog_file *iol, const char *buf, unsigned int len,
int event)
sudoers_io_log_local(int event, const char *buf, unsigned int len,
struct timespec *delay, const char **errstr)
{
struct timespec now, delay;
struct iolog_file *iol;
char tbuf[1024];
const char *errstr = NULL;
int ret = -1;
debug_decl(sudoers_io_log, SUDOERS_DEBUG_PLUGIN)
debug_decl(sudoers_io_log_local, SUDOERS_DEBUG_PLUGIN)
if (event < 0 || event >= IOFD_MAX) {
*errstr = NULL;
sudo_warnx(U_("unexpected I/O event %d"), event);
debug_return_int(-1);
}
iol = &iolog_files[event];
if (!iol->enabled) {
*errstr = NULL;
sudo_warnx(U_("%s: internal error, I/O log file for event %d not open"),
__func__, event);
debug_return_int(-1);
}
/* Write I/O log file entry. */
if (iolog_write(iol, buf, len, errstr) == -1)
goto done;
/* Write timing file entry. */
len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %lld.%09ld %u\n",
event, (long long)delay->tv_sec, delay->tv_nsec, len);
if (len >= sizeof(tbuf)) {
/* Not actually possible due to the size of tbuf[]. */
*errstr = strerror(EOVERFLOW);
goto done;
}
if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, errstr) == -1)
goto done;
/* Success. */
ret = 1;
done:
debug_return_int(ret);
}
/*
* Schedule an I/O log entry to be written to the log server.
* Returns 1 on success and -1 on error.
* Fills in errstr on error.
*/
static int
sudoers_io_log_remote(int event, const char *buf, unsigned int len,
struct timespec *delay, const char **errstr)
{
int type, ret = -1;
debug_decl(sudoers_io_log_remote, SUDOERS_DEBUG_PLUGIN)
if (client_closure.disabled)
debug_return_int(1);
/* Track elapsed time for comparison with commit points. */
sudo_timespecadd(delay, &client_closure.elapsed, &client_closure.elapsed);
switch (event) {
case IO_EVENT_STDIN:
type = CLIENT_MESSAGE__TYPE_STDIN_BUF;
break;
case IO_EVENT_STDOUT:
type = CLIENT_MESSAGE__TYPE_STDOUT_BUF;
break;
case IO_EVENT_STDERR:
type = CLIENT_MESSAGE__TYPE_STDERR_BUF;
break;
case IO_EVENT_TTYIN:
type = CLIENT_MESSAGE__TYPE_TTYIN_BUF;
break;
case IO_EVENT_TTYOUT:
type = CLIENT_MESSAGE__TYPE_TTYOUT_BUF;
break;
default:
sudo_warnx(U_("unexpected I/O event %d"), event);
goto done;
}
if (fmt_io_buf(&client_closure, type, buf, len, delay)) {
ret = client_closure.write_ev->add(client_closure.write_ev,
&iolog_details.server_timeout);
if (ret == -1)
sudo_warn(U_("unable to add event to queue"));
}
done:
debug_return_int(ret);
}
/*
* Generic I/O logging function. Called by the I/O logging entry points.
* Returns 1 on success and -1 on error.
*/
static int
sudoers_io_log(const char *buf, unsigned int len, int event)
{
struct timespec now, delay;
const char *errstr = NULL;
int ret = -1;
debug_decl(sudoers_io_log, SUDOERS_DEBUG_PLUGIN)
if (sudo_gettime_awake(&now) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to get time of day", __func__);
errstr = strerror(errno);
goto bad;
}
/* Write I/O log file entry. */
if (iolog_write(iol, buf, len, &errstr) == -1)
goto done;
/* Write timing file entry. */
sudo_timespecsub(&now, &last_time, &delay);
len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %lld.%09ld %u\n",
event, (long long)delay.tv_sec, delay.tv_nsec, len);
if (len >= sizeof(tbuf)) {
/* Not actually possible due to the size of tbuf[]. */
errstr = strerror(EOVERFLOW);
goto done;
}
if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, &errstr) == -1)
goto done;
/* Success. */
ret = 1;
if (iolog_remote)
ret = sudoers_io_log_remote(event, buf, len, &delay, &errstr);
else
ret = sudoers_io_log_local(event, buf, len, &delay, &errstr);
done:
last_time.tv_sec = now.tv_sec;
last_time.tv_nsec = now.tv_nsec;
@@ -674,39 +882,87 @@ bad:
static int
sudoers_io_log_stdin(const char *buf, unsigned int len)
{
return sudoers_io_log(&iolog_files[IOFD_STDIN], buf, len, IO_EVENT_STDIN);
return sudoers_io_log(buf, len, IO_EVENT_STDIN);
}
static int
sudoers_io_log_stdout(const char *buf, unsigned int len)
{
return sudoers_io_log(&iolog_files[IOFD_STDOUT], buf, len, IO_EVENT_STDOUT);
return sudoers_io_log(buf, len, IO_EVENT_STDOUT);
}
static int
sudoers_io_log_stderr(const char *buf, unsigned int len)
{
return sudoers_io_log(&iolog_files[IOFD_STDERR], buf, len, IO_EVENT_STDERR);
return sudoers_io_log(buf, len, IO_EVENT_STDERR);
}
static int
sudoers_io_log_ttyin(const char *buf, unsigned int len)
{
return sudoers_io_log(&iolog_files[IOFD_TTYIN], buf, len, IO_EVENT_TTYIN);
return sudoers_io_log(buf, len, IO_EVENT_TTYIN);
}
static int
sudoers_io_log_ttyout(const char *buf, unsigned int len)
{
return sudoers_io_log(&iolog_files[IOFD_TTYOUT], buf, len, IO_EVENT_TTYOUT);
return sudoers_io_log(buf, len, IO_EVENT_TTYOUT);
}
static int
sudoers_io_change_winsize_local(unsigned int lines, unsigned int cols,
struct timespec *delay, const char **errstr)
{
char tbuf[1024];
int len, ret = -1;
debug_decl(sudoers_io_change_winsize_local, SUDOERS_DEBUG_PLUGIN)
/* Write window change event to the timing file. */
len = snprintf(tbuf, sizeof(tbuf), "%d %lld.%09ld %u %u\n",
IO_EVENT_WINSIZE, (long long)delay->tv_sec, delay->tv_nsec,
lines, cols);
if (len < 0 || len >= ssizeof(tbuf)) {
/* Not actually possible due to the size of tbuf[]. */
*errstr = strerror(EOVERFLOW);
goto done;
}
if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, errstr) == -1)
goto done;
/* Success. */
ret = 1;
done:
debug_return_int(ret);
}
static int
sudoers_io_change_winsize_remote(unsigned int lines, unsigned int cols,
struct timespec *delay, const char **errstr)
{
int ret = -1;
debug_decl(sudoers_io_change_winsize_remote, SUDOERS_DEBUG_PLUGIN)
if (client_closure.disabled)
debug_return_int(1);
/* Track elapsed time for comparison with commit points. */
sudo_timespecadd(delay, &client_closure.elapsed, &client_closure.elapsed);
if (fmt_winsize(&client_closure, lines, cols, delay)) {
ret = client_closure.write_ev->add(client_closure.write_ev,
&iolog_details.server_timeout);
if (ret == -1)
sudo_warn(U_("unable to add event to queue"));
}
debug_return_int(ret);
}
static int
sudoers_io_change_winsize(unsigned int lines, unsigned int cols)
{
struct timespec now, delay;
unsigned int len;
char tbuf[1024];
const char *errstr = NULL;
int ret = -1;
debug_decl(sudoers_io_change_winsize, SUDOERS_DEBUG_PLUGIN)
@@ -717,23 +973,13 @@ sudoers_io_change_winsize(unsigned int lines, unsigned int cols)
errstr = strerror(errno);
goto bad;
}
/* Write window change event to the timing file. */
sudo_timespecsub(&now, &last_time, &delay);
len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %lld.%09ld %u %u\n",
IO_EVENT_WINSIZE, (long long)delay.tv_sec, delay.tv_nsec, lines, cols);
if (len >= sizeof(tbuf)) {
/* Not actually possible due to the size of tbuf[]. */
errstr = strerror(EOVERFLOW);
goto done;
}
if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, &errstr) == -1)
goto done;
/* Success. */
ret = 1;
if (iolog_remote)
ret = sudoers_io_change_winsize_remote(lines, cols, &delay, &errstr);
else
ret = sudoers_io_change_winsize_local(lines, cols, &delay, &errstr);
done:
last_time.tv_sec = now.tv_sec;
last_time.tv_nsec = now.tv_nsec;
@@ -754,13 +1000,61 @@ bad:
debug_return_int(ret);
}
static int
sudoers_io_suspend_local(const char *signame, struct timespec *delay,
const char **errstr)
{
unsigned int len;
char tbuf[1024];
int ret = -1;
debug_decl(sudoers_io_suspend_local, SUDOERS_DEBUG_PLUGIN)
/* Write suspend event to the timing file. */
len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %lld.%09ld %s\n",
IO_EVENT_SUSPEND, (long long)delay->tv_sec, delay->tv_nsec, signame);
if (len >= sizeof(tbuf)) {
/* Not actually possible due to the size of tbuf[]. */
*errstr = strerror(EOVERFLOW);
goto done;
}
if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, errstr) == -1)
goto done;
/* Success. */
ret = 1;
done:
debug_return_int(ret);
}
static int
sudoers_io_suspend_remote(const char *signame, struct timespec *delay,
const char **errstr)
{
int ret = -1;
debug_decl(sudoers_io_suspend_remote, SUDOERS_DEBUG_PLUGIN)
if (client_closure.disabled)
debug_return_int(1);
/* Track elapsed time for comparison with commit points. */
sudo_timespecadd(delay, &client_closure.elapsed, &client_closure.elapsed);
if (fmt_suspend(&client_closure, signame, delay)) {
ret = client_closure.write_ev->add(client_closure.write_ev,
&iolog_details.server_timeout);
if (ret == -1)
sudo_warn(U_("unable to add event to queue"));
}
debug_return_int(ret);
}
static int
sudoers_io_suspend(int signo)
{
struct timespec now, delay;
unsigned int len;
char signame[SIG2STR_MAX];
char tbuf[1024];
const char *errstr = NULL;
int ret = -1;
debug_decl(sudoers_io_suspend, SUDOERS_DEBUG_PLUGIN)
@@ -777,23 +1071,14 @@ sudoers_io_suspend(int signo)
errstr = strerror(errno);
goto bad;
}
sudo_timespecsub(&now, &last_time, &delay);
/* Write suspend event to the timing file. */
sudo_timespecsub(&now, &last_time, &delay);
len = (unsigned int)snprintf(tbuf, sizeof(tbuf), "%d %lld.%09ld %s\n",
IO_EVENT_SUSPEND, (long long)delay.tv_sec, delay.tv_nsec, signame);
if (len >= sizeof(tbuf)) {
/* Not actually possible due to the size of tbuf[]. */
errstr = strerror(EOVERFLOW);
goto done;
}
if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, &errstr) == -1)
goto done;
if (iolog_remote)
ret = sudoers_io_suspend_remote(signame, &delay, &errstr);
else
ret = sudoers_io_suspend_local(signame, &delay, &errstr);
/* Success. */
ret = 1;
done:
last_time.tv_sec = now.tv_sec;
last_time.tv_nsec = now.tv_nsec;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 2019 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.
*/
#ifndef SUDOERS_IOLOG_CLIENT_H
#define SUDOERS_IOLOG_CLIENT_H
#include "log_server.pb-c.h"
#include "strlist.h"
#if PROTOBUF_C_VERSION_NUMBER < 1003000
# error protobuf-c version 1.30 or higher required
#endif
/* Default port to listen on */
#define DEFAULT_PORT_STR "30344"
/* Maximum message size (2Mb) */
#define MESSAGE_SIZE_MAX (2 * 1024 * 1024)
/* TODO - share with logsrvd/sendlog */
struct connection_buffer {
TAILQ_ENTRY(connection_buffer) entries;
uint8_t *data;
unsigned int size;
unsigned int len;
unsigned int off;
};
TAILQ_HEAD(connection_buffer_list, connection_buffer);
/* XXX - remove dependency on sudoers.h? */
#undef runas_pw
#undef runas_gr
struct iolog_details {
const char *cwd;
const char *host;
const char *tty;
const char *user;
const char *command;
const char *iolog_path;
struct passwd *runas_pw;
struct group *runas_gr;
char * const *argv;
char * const *user_env;
struct sudoers_str_list *log_servers;
struct timespec server_timeout;
int argc;
int lines;
int cols;
bool ignore_iolog_errors;
};
enum client_state {
ERROR,
RECV_HELLO,
SEND_RESTART, /* TODO: currently unimplemented */
SEND_ACCEPT,
SEND_IO,
SEND_EXIT,
CLOSING,
FINISHED
};
/* Remote connection closure, non-zero fields must come first. */
struct client_closure {
int sock;
enum client_state state;
bool disabled;
struct connection_buffer_list write_bufs;
struct connection_buffer_list free_bufs;
struct connection_buffer read_buf;
struct sudo_plugin_event *read_ev;
struct sudo_plugin_event *write_ev;
struct iolog_details *log_details;
struct timespec start_time;
struct timespec elapsed;
struct timespec committed;
char *iolog_id;
};
#define CLIENT_CLOSURE_INITIALIZER(_c) \
{ \
-1, \
ERROR, \
false, \
TAILQ_HEAD_INITIALIZER((_c).write_bufs), \
TAILQ_HEAD_INITIALIZER((_c).free_bufs) \
}
/* iolog_client.c */
bool client_closure_fill(struct client_closure *closure, int sock, struct iolog_details *details, struct io_plugin *sudoers_io);
bool client_loop(struct client_closure *closure);
bool fmt_accept_message(struct client_closure *closure);
bool fmt_client_message(struct client_closure *closure, ClientMessage *msg);
bool fmt_exit_message(struct client_closure *closure, int exit_status, int error);
bool fmt_io_buf(struct client_closure *closure, int type, const char *buf, unsigned int len, struct timespec *delay);
bool fmt_suspend(struct client_closure *closure, const char *signame, struct timespec *delay);
bool fmt_winsize(struct client_closure *closure, unsigned int lines, unsigned int cols, struct timespec *delay);
int log_server_connect(struct sudoers_str_list *servers, struct timespec *timo);
void client_closure_free(struct client_closure *closure);
#endif /* SUDOERS_IOLOG_CLIENT_H */

View File

@@ -506,6 +506,45 @@ bad:
debug_return_int(MODE_ERROR);
}
/*
* Convert struct list_members to a comma-separated string with
* the given variable name.
*/
static char *
serialize_list(const char *varname, struct list_members *members)
{
struct list_member *lm, *next;
size_t len, result_size;
char *result;
debug_decl(serialize_list, SUDOERS_DEBUG_PLUGIN)
result_size = strlen(varname) + 1;
SLIST_FOREACH(lm, members, entries) {
result_size += strlen(lm->value) + 1;
}
if ((result = malloc(result_size)) == NULL)
goto bad;
/* No need to check len for overflow here. */
len = strlcpy(result, varname, result_size);
result[len++] = '=';
result[len] = '\0';
SLIST_FOREACH_SAFE(lm, members, entries, next) {
len = strlcat(result, lm->value, result_size);
if (len + (next != NULL) >= result_size) {
sudo_warnx(U_("internal error, %s overflow"), __func__);
goto bad;
}
if (next != NULL) {
result[len++] = ',';
result[len] = '\0';
}
}
debug_return_str(result);
bad:
free(result);
debug_return_str(NULL);
}
/*
* Setup the execution environment.
* Builds up the command_info list and sets argv and envp.
@@ -686,6 +725,15 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask,
if ((command_info[info_len++] = sudo_new_key_val("iolog_group", def_iolog_group)) == NULL)
goto oom;
}
if (!SLIST_EMPTY(&def_log_server)) {
char *log_servers = serialize_list("log_servers", &def_log_server);
if (log_servers == NULL)
goto oom;
command_info[info_len++] = log_servers;
if (asprintf(&command_info[info_len++], "log_server_timeout=%u", def_log_server_timeout) == -1)
goto oom;
}
if (def_command_timeout > 0 || user_timeout > 0) {
int timeout = user_timeout;
if (timeout == 0 || def_command_timeout < timeout)

View File

@@ -438,6 +438,7 @@ exec_nopty(struct command_details *details, struct command_status *cstat)
sudo_debug_printf(SUDO_DEBUG_ERROR, "event loop exited prematurely");
/* kill command */
terminate_command(ec.cmnd_pid, true);
ec.cmnd_pid = -1;
}
#ifdef HAVE_SELINUX

View File

@@ -1581,7 +1581,12 @@ exec_pty(struct command_details *details, struct command_status *cstat)
if (sudo_ev_got_break(ec.evbase)) {
/* error from callback or monitor died */
sudo_debug_printf(SUDO_DEBUG_ERROR, "event loop exited prematurely");
/* XXX - may need to terminate command if cmnd_pid != -1 */
/* kill command */
terminate_command(ec.cmnd_pid, true);
ec.cmnd_pid = -1;
/* TODO: need way to pass an error to the sudo front end */
cstat->type = CMD_WSTATUS;
cstat->val = W_EXITCODE(1, SIGKILL);
}
/* Flush any remaining output, free I/O bufs and events, do logout. */

View File

@@ -1479,6 +1479,7 @@ sudo_plugin_event_alloc(void)
ev_int->public.fd = plugin_event_fd;
ev_int->public.timeleft = plugin_event_timeleft;
ev_int->public.setbase = plugin_event_setbase;
ev_int->public.loopbreak = plugin_event_loopbreak;
ev_int->public.free = plugin_event_free;
/* Clear private portion in case caller tries to use us uninitialized. */