Add basic support for event logging using a sudo-style log format.
This commit is contained in:
3
MANIFEST
3
MANIFEST
@@ -120,6 +120,8 @@ lib/util/isblank.c
|
||||
lib/util/key_val.c
|
||||
lib/util/lbuf.c
|
||||
lib/util/locking.c
|
||||
lib/util/logfac.c
|
||||
lib/util/logpri.c
|
||||
lib/util/memrchr.c
|
||||
lib/util/memset_s.c
|
||||
lib/util/mkdir_parents.c
|
||||
@@ -243,6 +245,7 @@ logsrvd/Makefile.in
|
||||
logsrvd/log_server.pb-c.c
|
||||
logsrvd/log_server.pb-c.h
|
||||
logsrvd/log_server.proto
|
||||
logsrvd/eventlog.c
|
||||
logsrvd/iolog_writer.c
|
||||
logsrvd/logsrvd.c
|
||||
logsrvd/logsrvd.h
|
||||
|
@@ -6,12 +6,12 @@
|
||||
# The host name or IP address and port to listen on. If no port is
|
||||
# specified, port 30344 will be used.
|
||||
# The following forms are accepted:
|
||||
# listent_address = hostname
|
||||
# listent_address = hostname:port
|
||||
# listent_address = IPv4_address
|
||||
# listent_address = IPv4_address:port
|
||||
# listent_address = [IPv6_address]
|
||||
# listent_address = [IPv6_address]:port
|
||||
# listen_address = hostname
|
||||
# listen_address = hostname:port
|
||||
# listen_address = IPv4_address
|
||||
# listen_address = IPv4_address:port
|
||||
# listen_address = [IPv6_address]
|
||||
# listen_address = [IPv6_address]:port
|
||||
#
|
||||
# Multiple listen_address settings may be specified.
|
||||
# The default is to listen on all addresses.
|
||||
@@ -20,21 +20,21 @@
|
||||
[iolog]
|
||||
# The top-level directory to use when constructing the path name for the
|
||||
# I/O log directory. The session sequence number, if any, is stored here.
|
||||
iolog_dir = /var/log/sudo-io
|
||||
#iolog_dir = /var/log/sudo-io
|
||||
|
||||
# The path name, relative to iolog_dir, in which to store I/O logs.
|
||||
# Note that iolog_file may contain directory components.
|
||||
iolog_file = %{seq}
|
||||
#iolog_file = %{seq}
|
||||
|
||||
# If set, I/O log data is flushed to disk after each write instead of
|
||||
# buffering it. This makes it possible to view the logs in real-time
|
||||
# as the program is executing but may significantly reduce the effectiveness
|
||||
# of I/O log compression.
|
||||
iolog_flush = true
|
||||
#iolog_flush = true
|
||||
|
||||
# If set, I/O logs will be compressed using zlib. Enabling compression can
|
||||
# make it harder to view the logs in real-time as the program is executing.
|
||||
iolog_compress = false
|
||||
#iolog_compress = false
|
||||
|
||||
# The group name to look up when setting the group-ID on new I/O log files
|
||||
# and directories. If iolog_group is not set, the primary group-ID of the
|
||||
@@ -54,7 +54,7 @@ iolog_compress = false
|
||||
# write bits, even if they are not present in the specified mode. When
|
||||
# creating I/O log directories, search (execute) bits are added to match
|
||||
# the read and write bits specified by iolog_mode.
|
||||
iolog_mode = 0600
|
||||
#iolog_mode = 0600
|
||||
|
||||
# The maximum sequence number that will be substituted for the %{seq}
|
||||
# escape in the I/O log file (see the iolog_dir description below for
|
||||
@@ -62,4 +62,52 @@ iolog_mode = 0600
|
||||
# base 36, maxseq itself should be expressed in decimal. Values larger
|
||||
# than 2176782336 (which corresponds to the base 36 sequence number
|
||||
# ZZZZZZ) will be silently truncated to 2176782336.
|
||||
maxseq = 2176782336
|
||||
#maxseq = 2176782336
|
||||
|
||||
[eventlog]
|
||||
# Where to log accept, reject and alert events.
|
||||
# Accepted values are syslog, logfile, or none.
|
||||
# Defaults to syslog
|
||||
#log_type = syslog
|
||||
|
||||
# Event log format.
|
||||
# Currently only supports sudo-style event logs.
|
||||
#log_format = sudo
|
||||
|
||||
[syslog]
|
||||
# The maximum length of a syslog payload.
|
||||
# On many systems, syslog(3) has a relatively small log buffer.
|
||||
# IETF RFC 5424 states that syslog servers must support messages
|
||||
# of at least 480 bytes and should support messages up to 2048 bytes.
|
||||
# Messages larger than this value will be split into multiple messages.
|
||||
#maxlen = 960
|
||||
|
||||
# The syslog facility to use for event log messages.
|
||||
# The following syslog facilities are supported: authpriv (if your OS
|
||||
# supports it), auth, daemon, user, local0, local1, local2, local3, local4,
|
||||
# local5, local6, and local7.
|
||||
#facility = authpriv
|
||||
|
||||
# The syslog priority to use for event log accept messages, when
|
||||
# the command is allowed by the security policy. The following syslog
|
||||
# priorities are supported: alert, crit, debug, emerg, err, info,
|
||||
# notice, warning, and none.
|
||||
#accept_priority = notice
|
||||
|
||||
# The syslog priority to use for event log reject messages, when the
|
||||
# command is not allowed by the security policy.
|
||||
#reject_priority = alert
|
||||
|
||||
# The syslog priority to use for event log alert messages reported
|
||||
# by the security policy.
|
||||
#alert_priority = alert
|
||||
|
||||
[logfile]
|
||||
# The format string used when formatting the date and time for
|
||||
# file-based event logs. Formatting is performed via strftime(3) so
|
||||
# any format string supported by that function is allowed.
|
||||
#time_format = %h %e %T
|
||||
|
||||
# The path to the file-based event log.
|
||||
# This path must be fully-qualified and start with a '/' character.
|
||||
#path = /var/log/sudo
|
||||
|
@@ -220,6 +220,18 @@ __dso_public bool sudo_lock_file_v1(int fd, int action);
|
||||
__dso_public bool sudo_lock_region_v1(int fd, int action, off_t len);
|
||||
#define sudo_lock_region(_a, _b, _c) sudo_lock_region_v1((_a), (_b), (_c))
|
||||
|
||||
/* logfac.c */
|
||||
__dso_public bool sudo_str2logfac_v1(const char *str, int *logfac);
|
||||
#define sudo_str2logfac(_a, _b) sudo_str2logfac_v1((_a), (_b))
|
||||
__dso_public const char *sudo_logfac2str_v1(int num);
|
||||
#define sudo_logfac2str(_a) sudo_logfac2str_v1((_a))
|
||||
|
||||
/* logpri.c */
|
||||
__dso_public bool sudo_str2logpri_v1(const char *str, int *logpri);
|
||||
#define sudo_str2logpri(_a, _b) sudo_str2logpri_v1((_a), (_b))
|
||||
__dso_public const char *sudo_logpri2str_v1(int num);
|
||||
#define sudo_logpri2str(_a) sudo_logpri2str_v1((_a))
|
||||
|
||||
/* mkdir_parents.c */
|
||||
__dso_public bool sudo_mkdir_parents_v1(char *path, uid_t uid, gid_t gid, mode_t mode, bool quiet);
|
||||
#define sudo_mkdir_parents(_a, _b, _c, _d, _e) sudo_mkdir_parents_v1((_a), (_b), (_c), (_d), (_e))
|
||||
|
@@ -117,10 +117,11 @@ SHELL = @SHELL@
|
||||
|
||||
LTOBJS = @DIGEST@ event.lo fatal.lo key_val.lo gethostname.lo \
|
||||
gettime.lo getgrouplist.lo gidlist.lo lbuf.lo locking.lo \
|
||||
mkdir_parents.lo parseln.lo progname.lo secure_path.lo \
|
||||
setgroups.lo strsplit.lo strtobool.lo strtoid.lo strtomode.lo \
|
||||
strtonum.lo sudo_conf.lo sudo_debug.lo sudo_dso.lo term.lo \
|
||||
ttyname_dev.lo ttysize.lo @COMMON_OBJS@ @LTLIBOBJS@
|
||||
logfac.lo logpri.lo mkdir_parents.lo parseln.lo progname.lo \
|
||||
secure_path.lo setgroups.lo strsplit.lo strtobool.lo \
|
||||
strtoid.lo strtomode.lo strtonum.lo sudo_conf.lo \
|
||||
sudo_debug.lo sudo_dso.lo term.lo ttyname_dev.lo \
|
||||
ttysize.lo @COMMON_OBJS@ @LTLIBOBJS@
|
||||
|
||||
IOBJS = $(LTOBJS:.lo=.i)
|
||||
|
||||
@@ -771,6 +772,26 @@ locking.i: $(srcdir)/locking.c $(incdir)/compat/stdbool.h \
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
locking.plog: locking.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/locking.c --i-file $< --output-file $@
|
||||
logfac.lo: $(srcdir)/logfac.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/logfac.c
|
||||
logfac.i: $(srcdir)/logfac.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
logfac.plog: logfac.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logfac.c --i-file $< --output-file $@
|
||||
logpri.lo: $(srcdir)/logpri.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/logpri.c
|
||||
logpri.i: $(srcdir)/logpri.c $(incdir)/compat/stdbool.h \
|
||||
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(top_builddir)/config.h
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
logpri.plog: logpri.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logpri.c --i-file $< --output-file $@
|
||||
memrchr.lo: $(srcdir)/memrchr.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/memrchr.c
|
||||
memrchr.i: $(srcdir)/memrchr.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
|
||||
|
93
lib/util/logfac.c
Normal file
93
lib/util/logfac.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 1999-2005, 2007-2019
|
||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "sudo_compat.h"
|
||||
#include "sudo_debug.h"
|
||||
#include "sudo_util.h"
|
||||
|
||||
/*
|
||||
* For converting between syslog numbers and strings.
|
||||
*/
|
||||
struct strmap {
|
||||
char *name;
|
||||
int num;
|
||||
};
|
||||
|
||||
static const struct strmap facilities[] = {
|
||||
#ifdef LOG_AUTHPRIV
|
||||
{ "authpriv", LOG_AUTHPRIV },
|
||||
#endif
|
||||
{ "auth", LOG_AUTH },
|
||||
{ "daemon", LOG_DAEMON },
|
||||
{ "user", LOG_USER },
|
||||
{ "local0", LOG_LOCAL0 },
|
||||
{ "local1", LOG_LOCAL1 },
|
||||
{ "local2", LOG_LOCAL2 },
|
||||
{ "local3", LOG_LOCAL3 },
|
||||
{ "local4", LOG_LOCAL4 },
|
||||
{ "local5", LOG_LOCAL5 },
|
||||
{ "local6", LOG_LOCAL6 },
|
||||
{ "local7", LOG_LOCAL7 },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
bool
|
||||
sudo_str2logfac_v1(const char *str, int *logfac)
|
||||
{
|
||||
const struct strmap *fac;
|
||||
debug_decl(sudo_str2logfac, SUDO_DEBUG_UTIL)
|
||||
|
||||
for (fac = facilities; fac->name != NULL; fac++) {
|
||||
if (strcmp(str, fac->name) == 0) {
|
||||
*logfac = fac->num;
|
||||
debug_return_bool(true);
|
||||
}
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
const char *
|
||||
sudo_logfac2str_v1(int num)
|
||||
{
|
||||
const struct strmap *fac;
|
||||
debug_decl(sudo_logfac2str, SUDO_DEBUG_UTIL)
|
||||
|
||||
for (fac = facilities; fac->name != NULL; fac++) {
|
||||
if (fac->num == num)
|
||||
break;
|
||||
}
|
||||
debug_return_const_str(fac->name);
|
||||
}
|
88
lib/util/logpri.c
Normal file
88
lib/util/logpri.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 1999-2005, 2007-2019
|
||||
* Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "sudo_compat.h"
|
||||
#include "sudo_debug.h"
|
||||
#include "sudo_util.h"
|
||||
|
||||
/*
|
||||
* For converting between syslog numbers and strings.
|
||||
*/
|
||||
struct strmap {
|
||||
char *name;
|
||||
int num;
|
||||
};
|
||||
|
||||
static const struct strmap priorities[] = {
|
||||
{ "alert", LOG_ALERT },
|
||||
{ "crit", LOG_CRIT },
|
||||
{ "debug", LOG_DEBUG },
|
||||
{ "emerg", LOG_EMERG },
|
||||
{ "err", LOG_ERR },
|
||||
{ "info", LOG_INFO },
|
||||
{ "notice", LOG_NOTICE },
|
||||
{ "warning", LOG_WARNING },
|
||||
{ "none", -1 },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
bool
|
||||
sudo_str2logpri_v1(const char *str, int *logpri)
|
||||
{
|
||||
const struct strmap *pri;
|
||||
debug_decl(sudo_str2logpri, SUDO_DEBUG_UTIL)
|
||||
|
||||
for (pri = priorities; pri->name != NULL; pri++) {
|
||||
if (strcmp(str, pri->name) == 0) {
|
||||
*logpri = pri->num;
|
||||
debug_return_bool(true);
|
||||
}
|
||||
}
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
const char *
|
||||
sudo_logpri2str_v1(int num)
|
||||
{
|
||||
const struct strmap *pri;
|
||||
debug_decl(sudo_logpri2str, SUDO_DEBUG_UTIL)
|
||||
|
||||
for (pri = priorities; pri->name != NULL; pri++) {
|
||||
if (pri->num == num)
|
||||
break;
|
||||
}
|
||||
debug_return_const_str(pri->name);
|
||||
}
|
@@ -88,6 +88,8 @@ sudo_lbuf_init_v1
|
||||
sudo_lbuf_print_v1
|
||||
sudo_lock_file_v1
|
||||
sudo_lock_region_v1
|
||||
sudo_logfac2str_v1
|
||||
sudo_logpri2str_v1
|
||||
sudo_mkdir_parents_v1
|
||||
sudo_new_key_val_v1
|
||||
sudo_parse_gids_v1
|
||||
@@ -96,6 +98,8 @@ sudo_parseln_v2
|
||||
sudo_secure_dir_v1
|
||||
sudo_secure_file_v1
|
||||
sudo_setgroups_v1
|
||||
sudo_str2logfac_v1
|
||||
sudo_str2logpri_v1
|
||||
sudo_strsplit_v1
|
||||
sudo_strtobool_v1
|
||||
sudo_strtoid_v1
|
||||
|
@@ -107,7 +107,7 @@ SHELL = @SHELL@
|
||||
|
||||
PROGS = sudo_logsrvd sudo_sendlog
|
||||
|
||||
LOGSRVD_OBJS = iolog_writer.o logsrvd.o \
|
||||
LOGSRVD_OBJS = eventlog.o iolog_writer.o logsrvd.o \
|
||||
logsrvd_conf.o log_server.pb-c.o protobuf-c.o
|
||||
|
||||
SENDLOG_OBJS = sendlog.o log_server.pb-c.o protobuf-c.o
|
||||
@@ -211,6 +211,22 @@ realclean: distclean
|
||||
cleandir: realclean
|
||||
|
||||
# Autogenerated dependencies, do not modify
|
||||
eventlog.o: $(srcdir)/eventlog.c $(devdir)/log_server.pb-c.h \
|
||||
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
|
||||
$(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/logsrvd.h \
|
||||
$(srcdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.h
|
||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/eventlog.c
|
||||
eventlog.i: $(srcdir)/eventlog.c $(devdir)/log_server.pb-c.h \
|
||||
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
|
||||
$(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
|
||||
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/logsrvd.h \
|
||||
$(srcdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.h
|
||||
$(CC) -E -o $@ $(CPPFLAGS) $<
|
||||
eventlog.plog: eventlog.i
|
||||
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/eventlog.c --i-file $< --output-file $@
|
||||
iolog_writer.o: $(srcdir)/iolog_writer.c $(devdir)/log_server.pb-c.h \
|
||||
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
|
||||
$(incdir)/sudo_debug.h $(incdir)/sudo_iolog.h \
|
||||
|
459
logsrvd/eventlog.c
Normal file
459
logsrvd/eventlog.c
Normal file
@@ -0,0 +1,459 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*
|
||||
* Copyright (c) 1994-1996, 1998-2019 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
||||
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "log_server.pb-c.h"
|
||||
#include "sudo_gettext.h" /* must be included before sudo_compat.h */
|
||||
#include "sudo_compat.h"
|
||||
#include "sudo_fatal.h"
|
||||
#include "sudo_queue.h"
|
||||
#include "sudo_debug.h"
|
||||
#include "sudo_util.h"
|
||||
#include "sudo_iolog.h"
|
||||
#include "logsrvd.h"
|
||||
|
||||
#define LL_HOST_STR "HOST="
|
||||
#define LL_TTY_STR "TTY="
|
||||
#define LL_CWD_STR "PWD="
|
||||
#define LL_USER_STR "USER="
|
||||
#define LL_GROUP_STR "GROUP="
|
||||
#define LL_ENV_STR "ENV="
|
||||
#define LL_CMND_STR "COMMAND="
|
||||
#define LL_TSID_STR "TSID="
|
||||
|
||||
#define IS_SESSID(s) ( \
|
||||
isalnum((unsigned char)(s)[0]) && isalnum((unsigned char)(s)[1]) && \
|
||||
(s)[2] == '/' && \
|
||||
isalnum((unsigned char)(s)[3]) && isalnum((unsigned char)(s)[4]) && \
|
||||
(s)[5] == '/' && \
|
||||
isalnum((unsigned char)(s)[6]) && isalnum((unsigned char)(s)[7]) && \
|
||||
(s)[8] == '\0')
|
||||
|
||||
/*
|
||||
* Allocate and fill in a new logline.
|
||||
*/
|
||||
static char *
|
||||
new_logline(const char *message, const char *errstr,
|
||||
const struct iolog_details *details)
|
||||
{
|
||||
char *line = NULL, *evstr = NULL;
|
||||
const char *iolog_file = details->iolog_file;
|
||||
char sessid[7];
|
||||
const char *tsid = NULL;
|
||||
size_t len = 0;
|
||||
int i;
|
||||
debug_decl(new_logline, SUDO_DEBUG_UTIL)
|
||||
|
||||
/* A TSID may be a sudoers-style session ID or a free-form string. */
|
||||
if (iolog_file != NULL) {
|
||||
if (IS_SESSID(iolog_file)) {
|
||||
sessid[0] = iolog_file[0];
|
||||
sessid[1] = iolog_file[1];
|
||||
sessid[2] = iolog_file[3];
|
||||
sessid[3] = iolog_file[4];
|
||||
sessid[4] = iolog_file[6];
|
||||
sessid[5] = iolog_file[7];
|
||||
sessid[6] = '\0';
|
||||
tsid = sessid;
|
||||
} else {
|
||||
tsid = iolog_file;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute line length
|
||||
*/
|
||||
if (message != NULL)
|
||||
len += strlen(message) + 3;
|
||||
if (errstr != NULL)
|
||||
len += strlen(errstr) + 3;
|
||||
len += sizeof(LL_HOST_STR) + 2 + strlen(details->submithost);
|
||||
len += sizeof(LL_TTY_STR) + 2 + strlen(details->ttyname);
|
||||
len += sizeof(LL_CWD_STR) + 2 + strlen(details->cwd);
|
||||
if (details->runuser != NULL)
|
||||
len += sizeof(LL_USER_STR) + 2 + strlen(details->runuser);
|
||||
if (details->rungroup != NULL)
|
||||
len += sizeof(LL_GROUP_STR) + 2 + strlen(details->rungroup);
|
||||
if (tsid != NULL)
|
||||
len += sizeof(LL_TSID_STR) + 2 + strlen(tsid);
|
||||
if (details->env_add != NULL) {
|
||||
size_t evlen = 0;
|
||||
char * const *ep;
|
||||
|
||||
for (ep = details->env_add; *ep != NULL; ep++)
|
||||
evlen += strlen(*ep) + 1;
|
||||
if (evlen != 0) {
|
||||
if ((evstr = malloc(evlen)) == NULL)
|
||||
goto oom;
|
||||
ep = details->env_add;
|
||||
if (strlcpy(evstr, *ep, evlen) >= evlen)
|
||||
goto toobig;
|
||||
while (*++ep != NULL) {
|
||||
if (strlcat(evstr, " ", evlen) >= evlen ||
|
||||
strlcat(evstr, *ep, evlen) >= evlen)
|
||||
goto toobig;
|
||||
}
|
||||
len += sizeof(LL_ENV_STR) + 2 + evlen;
|
||||
}
|
||||
}
|
||||
if (details->command != NULL) {
|
||||
len += sizeof(LL_CMND_STR) - 1 + strlen(details->command);
|
||||
if (details->argc > 1) {
|
||||
for (i = 1; i < details->argc; i++)
|
||||
len += strlen(details->argv[i]) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and build up the line.
|
||||
*/
|
||||
if ((line = malloc(++len)) == NULL)
|
||||
goto oom;
|
||||
line[0] = '\0';
|
||||
|
||||
if (message != NULL) {
|
||||
if (strlcat(line, message, len) >= len ||
|
||||
strlcat(line, errstr ? " : " : " ; ", len) >= len)
|
||||
goto toobig;
|
||||
}
|
||||
if (errstr != NULL) {
|
||||
if (strlcat(line, errstr, len) >= len ||
|
||||
strlcat(line, " ; ", len) >= len)
|
||||
goto toobig;
|
||||
}
|
||||
if (strlcat(line, LL_HOST_STR, len) >= len ||
|
||||
strlcat(line, details->submithost, len) >= len ||
|
||||
strlcat(line, " ; ", len) >= len)
|
||||
goto toobig;
|
||||
if (strlcat(line, LL_TTY_STR, len) >= len ||
|
||||
strlcat(line, details->ttyname, len) >= len ||
|
||||
strlcat(line, " ; ", len) >= len)
|
||||
goto toobig;
|
||||
if (strlcat(line, LL_CWD_STR, len) >= len ||
|
||||
strlcat(line, details->cwd, len) >= len ||
|
||||
strlcat(line, " ; ", len) >= len)
|
||||
goto toobig;
|
||||
if (details->runuser != NULL) {
|
||||
if (strlcat(line, LL_USER_STR, len) >= len ||
|
||||
strlcat(line, details->runuser, len) >= len ||
|
||||
strlcat(line, " ; ", len) >= len)
|
||||
goto toobig;
|
||||
}
|
||||
if (details->rungroup != NULL) {
|
||||
if (strlcat(line, LL_GROUP_STR, len) >= len ||
|
||||
strlcat(line, details->rungroup, len) >= len ||
|
||||
strlcat(line, " ; ", len) >= len)
|
||||
goto toobig;
|
||||
}
|
||||
if (tsid != NULL) {
|
||||
if (strlcat(line, LL_TSID_STR, len) >= len ||
|
||||
strlcat(line, tsid, len) >= len ||
|
||||
strlcat(line, " ; ", len) >= len)
|
||||
goto toobig;
|
||||
}
|
||||
if (evstr != NULL) {
|
||||
if (strlcat(line, LL_ENV_STR, len) >= len ||
|
||||
strlcat(line, evstr, len) >= len ||
|
||||
strlcat(line, " ; ", len) >= len)
|
||||
goto toobig;
|
||||
free(evstr);
|
||||
evstr = NULL;
|
||||
}
|
||||
if (details->command != NULL) {
|
||||
if (strlcat(line, LL_CMND_STR, len) >= len)
|
||||
goto toobig;
|
||||
if (strlcat(line, details->command, len) >= len)
|
||||
goto toobig;
|
||||
if (details->argc > 1) {
|
||||
for (i = 1; i < details->argc; i++) {
|
||||
if (strlcat(line, " ", len) >= len ||
|
||||
strlcat(line, details->argv[i], len) >= len)
|
||||
goto toobig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug_return_str(line);
|
||||
oom:
|
||||
free(evstr);
|
||||
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
|
||||
debug_return_str(NULL);
|
||||
toobig:
|
||||
free(evstr);
|
||||
free(line);
|
||||
sudo_warnx(U_("internal error, %s overflow"), __func__);
|
||||
debug_return_str(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* We do an openlog(3)/closelog(3) for each message because some
|
||||
* authentication methods (notably PAM) use syslog(3) for their
|
||||
* own nefarious purposes and may call openlog(3) and closelog(3).
|
||||
* XXX - no longer need openlog/closelog dance, move openlog call
|
||||
*/
|
||||
static void
|
||||
mysyslog(int pri, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
debug_decl(mysyslog, SUDO_DEBUG_UTIL)
|
||||
|
||||
openlog("sudo", 0, logsrvd_conf_syslog_facility());
|
||||
va_start(ap, fmt);
|
||||
vsyslog(pri, fmt, ap);
|
||||
va_end(ap);
|
||||
closelog();
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Log a message to syslog, pre-pending the username and splitting the
|
||||
* message into parts if it is longer than syslog_maxlen.
|
||||
*/
|
||||
static void
|
||||
do_syslog(int pri, const struct iolog_details *details, char *msg)
|
||||
{
|
||||
size_t len, maxlen;
|
||||
char *p, *tmp, save;
|
||||
const char *fmt;
|
||||
debug_decl(do_syslog, SUDO_DEBUG_UTIL)
|
||||
|
||||
/* A priority of -1 corresponds to "none". */
|
||||
if (pri == -1)
|
||||
debug_return;
|
||||
|
||||
/*
|
||||
* Log the full line, breaking into multiple syslog(3) calls if necessary
|
||||
*/
|
||||
fmt = _("%8s : %s");
|
||||
maxlen = logsrvd_conf_syslog_maxlen() -
|
||||
(strlen(fmt) - 5 + strlen(details->submituser));
|
||||
for (p = msg; *p != '\0'; ) {
|
||||
len = strlen(p);
|
||||
if (len > maxlen) {
|
||||
/*
|
||||
* Break up the line into what will fit on one syslog(3) line
|
||||
* Try to avoid breaking words into several lines if possible.
|
||||
*/
|
||||
tmp = memrchr(p, ' ', maxlen);
|
||||
if (tmp == NULL)
|
||||
tmp = p + maxlen;
|
||||
|
||||
/* NULL terminate line, but save the char to restore later */
|
||||
save = *tmp;
|
||||
*tmp = '\0';
|
||||
|
||||
mysyslog(pri, fmt, details->submituser, p);
|
||||
|
||||
*tmp = save; /* restore saved character */
|
||||
|
||||
/* Advance p and eliminate leading whitespace */
|
||||
for (p = tmp; *p == ' '; p++)
|
||||
continue;
|
||||
} else {
|
||||
mysyslog(pri, fmt, details->submituser, p);
|
||||
p += len;
|
||||
}
|
||||
fmt = _("%8s : (command continued) %s");
|
||||
maxlen = logsrvd_conf_syslog_maxlen() -
|
||||
(strlen(fmt) - 5 + strlen(details->submituser));
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
static bool
|
||||
do_logfile(const char *logfile, const struct iolog_details *details,
|
||||
const char *msg)
|
||||
{
|
||||
const char *timefmt = logsrvd_conf_logfile_time_format();
|
||||
char timebuf[8192], *timestr = NULL;
|
||||
struct tm *timeptr;
|
||||
bool ret = false;
|
||||
mode_t oldmask;
|
||||
FILE *fp;
|
||||
debug_decl(do_logfile, SUDO_DEBUG_UTIL)
|
||||
|
||||
oldmask = umask(S_IRWXG|S_IRWXO);
|
||||
fp = fopen(logfile, "a");
|
||||
(void) umask(oldmask);
|
||||
if (fp == NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"unable to open log file %s", logfile);
|
||||
goto done;
|
||||
}
|
||||
if (!sudo_lock_file(fileno(fp), SUDO_LOCK)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"unable to lock log file %s", logfile);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((timeptr = localtime(&details->submit_time)) != NULL) {
|
||||
/* strftime() does not guarantee to NUL-terminate so we must check. */
|
||||
timebuf[sizeof(timebuf) - 1] = '\0';
|
||||
if (strftime(timebuf, sizeof(timebuf), timefmt, timeptr) != 0 &&
|
||||
timebuf[sizeof(timebuf) - 1] == '\0') {
|
||||
timestr = timebuf;
|
||||
}
|
||||
}
|
||||
(void)fprintf(fp, "%s : %s : %s", timestr ? timestr : "invalid date",
|
||||
details->submituser, msg);
|
||||
(void)fflush(fp);
|
||||
if (ferror(fp)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"unable to write log file %s", logfile);
|
||||
goto done;
|
||||
}
|
||||
ret = true;
|
||||
|
||||
done:
|
||||
if (fp != NULL)
|
||||
(void) fclose(fp);
|
||||
debug_return_bool(ret);
|
||||
}
|
||||
|
||||
bool
|
||||
log_accept(const struct iolog_details *details)
|
||||
{
|
||||
const enum logsrvd_eventlog_type log_type = logsrvd_conf_eventlog_type();
|
||||
char *logline;
|
||||
bool ret = true;
|
||||
int pri;
|
||||
debug_decl(log_accept, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (log_type == EVLOG_NONE)
|
||||
debug_return_bool(true);
|
||||
|
||||
if ((logline = new_logline(NULL, NULL, details)) == NULL)
|
||||
debug_return_bool(false);
|
||||
|
||||
switch (log_type) {
|
||||
case EVLOG_SYSLOG:
|
||||
pri = logsrvd_conf_syslog_acceptpri();
|
||||
if (pri != -1)
|
||||
do_syslog(pri, details, logline);
|
||||
break;
|
||||
case EVLOG_FILE:
|
||||
ret = do_logfile(logsrvd_conf_logfile_path(), details, logline);
|
||||
break;
|
||||
default:
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"unexpected eventlog type %d", log_type);
|
||||
ret = false;
|
||||
}
|
||||
free(logline);
|
||||
|
||||
debug_return_bool(ret);
|
||||
}
|
||||
|
||||
bool
|
||||
log_reject(const struct iolog_details *details, const char *reason)
|
||||
{
|
||||
const enum logsrvd_eventlog_type log_type = logsrvd_conf_eventlog_type();
|
||||
char *logline;
|
||||
bool ret = true;
|
||||
int pri;
|
||||
debug_decl(log_reject, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (log_type == EVLOG_NONE)
|
||||
debug_return_bool(true);
|
||||
|
||||
if ((logline = new_logline(reason, NULL, details)) == NULL)
|
||||
debug_return_bool(false);
|
||||
|
||||
switch (log_type) {
|
||||
case EVLOG_SYSLOG:
|
||||
pri = logsrvd_conf_syslog_rejectpri();
|
||||
if (pri != -1)
|
||||
do_syslog(pri, details, logline);
|
||||
break;
|
||||
case EVLOG_FILE:
|
||||
ret = do_logfile(logsrvd_conf_logfile_path(), details, logline);
|
||||
break;
|
||||
default:
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"unexpected eventlog type %d", log_type);
|
||||
ret = false;
|
||||
}
|
||||
free(logline);
|
||||
|
||||
debug_return_bool(ret);
|
||||
}
|
||||
|
||||
bool
|
||||
log_alert(const struct iolog_details *details, TimeSpec *alert_time,
|
||||
const char *reason)
|
||||
{
|
||||
const enum logsrvd_eventlog_type log_type = logsrvd_conf_eventlog_type();
|
||||
char *logline;
|
||||
bool ret = true;
|
||||
int pri;
|
||||
debug_decl(log_alert, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (log_type == EVLOG_NONE)
|
||||
debug_return_bool(true);
|
||||
|
||||
if ((logline = new_logline(reason, NULL, details)) == NULL)
|
||||
debug_return_bool(false);
|
||||
|
||||
/* TODO: log alert_time */
|
||||
switch (log_type) {
|
||||
case EVLOG_SYSLOG:
|
||||
pri = logsrvd_conf_syslog_alertpri();
|
||||
if (pri != -1)
|
||||
do_syslog(pri, details, logline);
|
||||
break;
|
||||
case EVLOG_FILE:
|
||||
ret = do_logfile(logsrvd_conf_logfile_path(), details, logline);
|
||||
break;
|
||||
default:
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"unexpected eventlog type %d", log_type);
|
||||
ret = false;
|
||||
}
|
||||
free(logline);
|
||||
|
||||
debug_return_bool(ret);
|
||||
}
|
@@ -63,29 +63,94 @@ has_strlistval(InfoMessage *info)
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in I/O log details from an AcceptMessage
|
||||
* Only makes a shallow copy of strings and string lists.
|
||||
* Copy the specified string list.
|
||||
* The input string list need not be NULL-terminated.
|
||||
* Returns a NULL-terminated string vector.
|
||||
*/
|
||||
static bool
|
||||
iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
static char **
|
||||
strlist_copy(InfoMessage__StringList *strlist)
|
||||
{
|
||||
char **dst, **src = strlist->strings;
|
||||
size_t i, len = strlist->n_strings;
|
||||
debug_decl(strlist_copy, SUDO_DEBUG_UTIL)
|
||||
|
||||
dst = reallocarray(NULL, len + 1, sizeof(char *));
|
||||
if (dst == NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"reallocarray(NULL, %zu, %zu)", len + 1, sizeof(char *));
|
||||
goto bad;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((dst[i] = strdup(src[i])) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO, "strdup");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
dst[i] = NULL;
|
||||
debug_return_ptr(dst);
|
||||
|
||||
bad:
|
||||
if (dst != NULL) {
|
||||
while (i--)
|
||||
free(dst[i]);
|
||||
free(dst);
|
||||
}
|
||||
debug_return_ptr(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the strings in a struct iolog_details.
|
||||
*/
|
||||
void
|
||||
iolog_details_free(struct iolog_details *details)
|
||||
{
|
||||
int i;
|
||||
debug_decl(iolog_details_free, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (details != NULL) {
|
||||
free(details->iolog_path);
|
||||
free(details->command);
|
||||
free(details->cwd);
|
||||
free(details->rungroup);
|
||||
free(details->runuser);
|
||||
free(details->submithost);
|
||||
free(details->submituser);
|
||||
free(details->submitgroup);
|
||||
free(details->ttyname);
|
||||
for (i = 0; i < details->argc; i++)
|
||||
free(details->argv[i]);
|
||||
free(details->argv);
|
||||
}
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in I/O log details from an AcceptMessage
|
||||
* Caller is responsible for freeing strings in struct iolog_details.
|
||||
* Returns true on success and false on failure.
|
||||
*/
|
||||
bool
|
||||
iolog_details_fill(struct iolog_details *details, TimeSpec *submit_time,
|
||||
InfoMessage **info_msgs, size_t infolen)
|
||||
{
|
||||
size_t idx;
|
||||
bool ret = true;
|
||||
bool ret = false;
|
||||
debug_decl(iolog_details_fill, SUDO_DEBUG_UTIL)
|
||||
|
||||
memset(details, 0, sizeof(*details));
|
||||
|
||||
/* Submit time. */
|
||||
details->submit_time = msg->submit_time->tv_sec;
|
||||
details->submit_time = submit_time->tv_sec;
|
||||
|
||||
/* Default values */
|
||||
details->lines = 24;
|
||||
details->columns = 80;
|
||||
details->submitgroup = "unknown";
|
||||
|
||||
/* Pull out values by key from info array. */
|
||||
for (idx = 0; idx < msg->n_info_msgs; idx++) {
|
||||
InfoMessage *info = msg->info_msgs[idx];
|
||||
for (idx = 0; idx < infolen; idx++) {
|
||||
InfoMessage *info = info_msgs[idx];
|
||||
const char *key = info->key;
|
||||
switch (key[0]) {
|
||||
case 'c':
|
||||
@@ -103,7 +168,12 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
}
|
||||
if (strcmp(key, "command") == 0) {
|
||||
if (has_strval(info)) {
|
||||
details->command = info->strval;
|
||||
if ((details->command = strdup(info->strval)) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"command specified but not a string");
|
||||
@@ -112,7 +182,12 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
}
|
||||
if (strcmp(key, "cwd") == 0) {
|
||||
if (has_strval(info)) {
|
||||
details->cwd = info->strval;
|
||||
if ((details->cwd = strdup(info->strval)) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"cwd specified but not a string");
|
||||
@@ -137,7 +212,9 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
case 'r':
|
||||
if (strcmp(key, "runargv") == 0) {
|
||||
if (has_strlistval(info)) {
|
||||
details->argv = info->strlistval->strings;
|
||||
details->argv = strlist_copy(info->strlistval);
|
||||
if (details->argv == NULL)
|
||||
goto done;
|
||||
details->argc = info->strlistval->n_strings;
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
@@ -147,7 +224,12 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
}
|
||||
if (strcmp(key, "rungroup") == 0) {
|
||||
if (has_strval(info)) {
|
||||
details->rungroup = info->strval;
|
||||
if ((details->rungroup = strdup(info->strval)) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"rungroup specified but not a string");
|
||||
@@ -156,7 +238,12 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
}
|
||||
if (strcmp(key, "runuser") == 0) {
|
||||
if (has_strval(info)) {
|
||||
details->runuser = info->strval;
|
||||
if ((details->runuser = strdup(info->strval)) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"runuser specified but not a string");
|
||||
@@ -167,7 +254,12 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
case 's':
|
||||
if (strcmp(key, "submithost") == 0) {
|
||||
if (has_strval(info)) {
|
||||
details->submithost = info->strval;
|
||||
if ((details->submithost = strdup(info->strval)) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"submithost specified but not a string");
|
||||
@@ -176,7 +268,12 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
}
|
||||
if (strcmp(key, "submitgroup") == 0) {
|
||||
if (has_strval(info)) {
|
||||
details->submitgroup = info->strval;
|
||||
if ((details->submitgroup = strdup(info->strval)) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"submitgroup specified but not a string");
|
||||
@@ -185,7 +282,12 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
}
|
||||
if (strcmp(key, "submituser") == 0) {
|
||||
if (has_strval(info)) {
|
||||
details->submituser = info->strval;
|
||||
if ((details->submituser = strdup(info->strval)) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"submituser specified but not a string");
|
||||
@@ -196,7 +298,12 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
case 't':
|
||||
if (strcmp(key, "ttyname") == 0) {
|
||||
if (has_strval(info)) {
|
||||
details->ttyname = info->strval;
|
||||
if ((details->ttyname = strdup(info->strval)) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"ttyname specified but not a string");
|
||||
@@ -207,23 +314,38 @@ iolog_details_fill(struct iolog_details *details, AcceptMessage *msg)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: make submitgroup required */
|
||||
if (details->submitgroup == NULL) {
|
||||
if ((details->submitgroup = strdup("unknown")) == NULL) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for required settings */
|
||||
if (details->submituser == NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"missing user in AcceptMessage");
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
if (details->submithost == NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"missing host in AcceptMessage");
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
if (details->command == NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"missing command in AcceptMessage");
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
done:
|
||||
if (!ret)
|
||||
iolog_details_free(details);
|
||||
debug_return_bool(ret);
|
||||
}
|
||||
|
||||
@@ -351,54 +473,58 @@ static const struct iolog_path_escape path_escapes[] = {
|
||||
|
||||
/*
|
||||
* Create I/O log path
|
||||
* Sets iolog_dir and iolog_dir_fd in the closure
|
||||
* Sets iolog_path, iolog_file and iolog_dir_fd in the closure
|
||||
*/
|
||||
static bool
|
||||
create_iolog_dir(struct iolog_details *details, struct connection_closure *closure)
|
||||
create_iolog_path(struct connection_closure *closure)
|
||||
{
|
||||
struct iolog_details *details = &closure->details;
|
||||
char pathbuf[PATH_MAX];
|
||||
size_t len;
|
||||
debug_decl(create_iolog_dir, SUDO_DEBUG_UTIL)
|
||||
size_t len, pathlen;
|
||||
debug_decl(create_iolog_path, SUDO_DEBUG_UTIL)
|
||||
|
||||
/* XXX - awkward api */
|
||||
closure->iolog_dir = expand_iolog_path(NULL, logsrvd_conf_iolog_dir(),
|
||||
logsrvd_conf_iolog_file(), NULL, &path_escapes[0], details);
|
||||
if (closure->iolog_dir == NULL) {
|
||||
details->iolog_path = expand_iolog_path(NULL, logsrvd_conf_iolog_dir(),
|
||||
logsrvd_conf_iolog_file(), &details->iolog_file, &path_escapes[0],
|
||||
details);
|
||||
if (details->iolog_path == NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"unable to expand iolog path %s/%s",
|
||||
logsrvd_conf_iolog_dir(), logsrvd_conf_iolog_file());
|
||||
goto bad;
|
||||
}
|
||||
pathlen = details->iolog_file - details->iolog_path;
|
||||
|
||||
/*
|
||||
* Make local copy of I/O log path and create it, along with any
|
||||
* intermediate subdirs. Calls mkdtemp() if iolog_path ends in XXXXXX.
|
||||
*/
|
||||
len = mkdir_iopath(closure->iolog_dir, pathbuf, sizeof(pathbuf));
|
||||
len = mkdir_iopath(details->iolog_path, pathbuf, sizeof(pathbuf));
|
||||
if (len >= sizeof(pathbuf)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"unable to mkdir iolog path %s", closure->iolog_dir);
|
||||
"unable to mkdir iolog path %s", details->iolog_path);
|
||||
goto bad;
|
||||
}
|
||||
free(closure->iolog_dir);
|
||||
if ((closure->iolog_dir = strdup(pathbuf)) == NULL) {
|
||||
free(details->iolog_path);
|
||||
if ((details->iolog_path = strdup(pathbuf)) == NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto bad;
|
||||
}
|
||||
details->iolog_file = details->iolog_path + pathlen + 1;
|
||||
|
||||
/* We use iolog_dir_fd in calls to openat(2) */
|
||||
closure->iolog_dir_fd =
|
||||
iolog_openat(AT_FDCWD, closure->iolog_dir, O_RDONLY);
|
||||
iolog_openat(AT_FDCWD, details->iolog_path, O_RDONLY);
|
||||
if (closure->iolog_dir_fd == -1) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"%s", closure->iolog_dir);
|
||||
"%s", details->iolog_path);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
debug_return_bool(true);
|
||||
bad:
|
||||
free(closure->iolog_dir);
|
||||
free(details->iolog_path);
|
||||
details->iolog_path = NULL;
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
@@ -424,7 +550,7 @@ iolog_details_write(struct iolog_details *details,
|
||||
log_info.cols = details->columns;
|
||||
|
||||
debug_return_bool(iolog_write_info_file(closure->iolog_dir_fd,
|
||||
closure->iolog_dir, &log_info, details->argv));
|
||||
details->iolog_path, &log_info, details->argv));
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -467,19 +593,14 @@ iolog_close_all(struct connection_closure *closure)
|
||||
bool
|
||||
iolog_init(AcceptMessage *msg, struct connection_closure *closure)
|
||||
{
|
||||
struct iolog_details details;
|
||||
debug_decl(iolog_init, SUDO_DEBUG_UTIL)
|
||||
|
||||
/* Fill in iolog_details */
|
||||
if (!iolog_details_fill(&details, msg))
|
||||
debug_return_bool(false);
|
||||
|
||||
/* Create I/O log dir */
|
||||
if (!create_iolog_dir(&details, closure))
|
||||
/* Create I/O log path */
|
||||
if (!create_iolog_path(closure))
|
||||
debug_return_bool(false);
|
||||
|
||||
/* Write sudo I/O log info file */
|
||||
if (!iolog_details_write(&details, closure))
|
||||
if (!iolog_details_write(&closure->details, closure))
|
||||
debug_return_bool(false);
|
||||
|
||||
/*
|
||||
@@ -541,7 +662,7 @@ iolog_restart(RestartMessage *msg, struct connection_closure *closure)
|
||||
target.tv_sec = msg->resume_point->tv_sec;
|
||||
target.tv_nsec = msg->resume_point->tv_nsec;
|
||||
|
||||
if ((closure->iolog_dir = strdup(msg->log_id)) == NULL) {
|
||||
if ((closure->details.iolog_path = strdup(msg->log_id)) == NULL) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"strdup");
|
||||
goto bad;
|
||||
@@ -555,7 +676,7 @@ iolog_restart(RestartMessage *msg, struct connection_closure *closure)
|
||||
if (errno != ENOENT) {
|
||||
sudo_debug_printf(
|
||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||
"unable to open %s/%s", closure->iolog_dir,
|
||||
"unable to open %s/%s", closure->details.iolog_path,
|
||||
iolog_fd_to_name(iofd));
|
||||
goto bad;
|
||||
}
|
||||
@@ -563,7 +684,7 @@ iolog_restart(RestartMessage *msg, struct connection_closure *closure)
|
||||
}
|
||||
if (!closure->iolog_files[IOFD_TIMING].enabled) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"missing timing file in %s", closure->iolog_dir);
|
||||
"missing timing file in %s", closure->details.iolog_path);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@@ -666,7 +787,7 @@ store_iobuf(int iofd, IoBuffer *msg, struct connection_closure *closure)
|
||||
if (!iolog_write(&closure->iolog_files[iofd], msg->data.data,
|
||||
msg->data.len, &errstr)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"unable to write to %s/%s: %s", closure->iolog_dir,
|
||||
"unable to write to %s/%s: %s", closure->details.iolog_path,
|
||||
iolog_fd_to_name(iofd), errstr);
|
||||
debug_return_int(-1);
|
||||
}
|
||||
@@ -675,7 +796,7 @@ store_iobuf(int iofd, IoBuffer *msg, struct connection_closure *closure)
|
||||
if (!iolog_write(&closure->iolog_files[IOFD_TIMING], tbuf,
|
||||
len, &errstr)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"unable to write to %s/%s: %s", closure->iolog_dir,
|
||||
"unable to write to %s/%s: %s", closure->details.iolog_path,
|
||||
iolog_fd_to_name(IOFD_TIMING), errstr);
|
||||
debug_return_int(-1);
|
||||
}
|
||||
@@ -707,7 +828,7 @@ store_suspend(CommandSuspend *msg, struct connection_closure *closure)
|
||||
if (!iolog_write(&closure->iolog_files[IOFD_TIMING], tbuf,
|
||||
len, &errstr)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"unable to write to %s/%s: %s", closure->iolog_dir,
|
||||
"unable to write to %s/%s: %s", closure->details.iolog_path,
|
||||
iolog_fd_to_name(IOFD_TIMING), errstr);
|
||||
debug_return_int(-1);
|
||||
}
|
||||
@@ -739,7 +860,7 @@ store_winsize(ChangeWindowSize *msg, struct connection_closure *closure)
|
||||
if (!iolog_write(&closure->iolog_files[IOFD_TIMING], tbuf,
|
||||
len, &errstr)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"unable to write to %s/%s: %s", closure->iolog_dir,
|
||||
"unable to write to %s/%s: %s", closure->details.iolog_path,
|
||||
iolog_fd_to_name(IOFD_TIMING), errstr);
|
||||
debug_return_int(-1);
|
||||
}
|
||||
|
@@ -87,9 +87,9 @@ connection_closure_free(struct connection_closure *closure)
|
||||
sudo_ev_free(closure->commit_ev);
|
||||
sudo_ev_free(closure->read_ev);
|
||||
sudo_ev_free(closure->write_ev);
|
||||
iolog_details_free(&closure->details);
|
||||
free(closure->read_buf.data);
|
||||
free(closure->write_buf.data);
|
||||
free(closure->iolog_dir);
|
||||
free(closure);
|
||||
|
||||
if (shutting_down && TAILQ_EMPTY(&connections))
|
||||
@@ -206,20 +206,32 @@ handle_accept(AcceptMessage *msg, struct connection_closure *closure)
|
||||
closure->submit_time.tv_sec = msg->submit_time->tv_sec;
|
||||
closure->submit_time.tv_nsec = msg->submit_time->tv_nsec;
|
||||
|
||||
/* TODO: handle event logging via syslog */
|
||||
if (!iolog_details_fill(&closure->details, msg->submit_time, msg->info_msgs,
|
||||
msg->n_info_msgs)) {
|
||||
closure->errstr = _("error parsing AcceptMessage");
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
/* Create I/O log info file and parent directories. */
|
||||
if (msg->expect_iobufs) {
|
||||
if (!iolog_init(msg, closure)) {
|
||||
closure->errstr = _("error creating I/O log");
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!log_accept(&closure->details)) {
|
||||
closure->errstr = _("error logging accept event");
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
if (!msg->expect_iobufs) {
|
||||
closure->state = FLUSHED;
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
/* Create I/O log info file and parent directories. */
|
||||
if (!iolog_init(msg, closure)) {
|
||||
closure->errstr = _("error creating I/O log");
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
/* Send log ID to client for restarting connectoins. */
|
||||
if (!fmt_log_id_message(closure->iolog_dir, &closure->write_buf))
|
||||
if (!fmt_log_id_message(closure->details.iolog_path, &closure->write_buf))
|
||||
debug_return_bool(false);
|
||||
if (sudo_ev_add(NULL, closure->write_ev, NULL, false) == -1) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
@@ -260,7 +272,16 @@ handle_reject(RejectMessage *msg, struct connection_closure *closure)
|
||||
closure->submit_time.tv_sec = msg->submit_time->tv_sec;
|
||||
closure->submit_time.tv_nsec = msg->submit_time->tv_nsec;
|
||||
|
||||
/* TODO: handle event logging via syslog */
|
||||
if (!iolog_details_fill(&closure->details, msg->submit_time, msg->info_msgs,
|
||||
msg->n_info_msgs)) {
|
||||
closure->errstr = _("error parsing RejectMessage");
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
if (!log_reject(&closure->details, msg->reason)) {
|
||||
closure->errstr = _("error logging reject event");
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
closure->state = FLUSHED;
|
||||
debug_return_bool(true);
|
||||
@@ -346,8 +367,12 @@ handle_alert(AlertMessage *msg, struct connection_closure *closure)
|
||||
{
|
||||
debug_decl(handle_alert, SUDO_DEBUG_UTIL)
|
||||
|
||||
/* TODO */
|
||||
debug_return_bool(false);
|
||||
if (!log_alert(&closure->details, msg->alert_time, msg->reason)) {
|
||||
closure->errstr = _("error logging alert event");
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@@ -35,9 +35,10 @@
|
||||
* I/O log details from the AcceptMessage + iolog path and sessid.
|
||||
*/
|
||||
struct iolog_details {
|
||||
char *iolog_path;
|
||||
char *iolog_file; /* substring of iolog_path, do not free */
|
||||
char *command;
|
||||
char *cwd;
|
||||
char *iolog_dir;
|
||||
char *rungroup;
|
||||
char *runuser;
|
||||
char *submithost;
|
||||
@@ -45,6 +46,7 @@ struct iolog_details {
|
||||
char *submitgroup;
|
||||
char *ttyname;
|
||||
char **argv;
|
||||
char **env_add;
|
||||
time_t submit_time;
|
||||
int argc;
|
||||
int lines;
|
||||
@@ -78,6 +80,7 @@ struct connection_buffer {
|
||||
*/
|
||||
struct connection_closure {
|
||||
TAILQ_ENTRY(connection_closure) entries;
|
||||
struct iolog_details details;
|
||||
struct timespec submit_time;
|
||||
struct timespec elapsed_time;
|
||||
struct connection_buffer read_buf;
|
||||
@@ -85,7 +88,6 @@ struct connection_closure {
|
||||
struct sudo_event *commit_ev;
|
||||
struct sudo_event *read_ev;
|
||||
struct sudo_event *write_ev;
|
||||
char *iolog_dir;
|
||||
const char *errstr;
|
||||
struct iolog_file iolog_files[IOFD_MAX];
|
||||
int iolog_dir_fd;
|
||||
@@ -111,18 +113,46 @@ struct listen_address {
|
||||
};
|
||||
TAILQ_HEAD(listen_address_list, listen_address);
|
||||
|
||||
/* Supported eventlog types */
|
||||
enum logsrvd_eventlog_type {
|
||||
EVLOG_NONE,
|
||||
EVLOG_SYSLOG,
|
||||
EVLOG_FILE,
|
||||
};
|
||||
|
||||
/* Supported eventlog formats (currently just sudo) */
|
||||
enum logsrvd_eventlog_format {
|
||||
EVLOG_SUDO
|
||||
};
|
||||
|
||||
/* eventlog.c */
|
||||
bool log_accept(const struct iolog_details *details);
|
||||
bool log_reject(const struct iolog_details *details, const char *reason);
|
||||
bool log_alert(const struct iolog_details *details, TimeSpec *alert_time, const char *reason);
|
||||
|
||||
/* iolog_writer.c */
|
||||
bool iolog_details_fill(struct iolog_details *details, TimeSpec *submit_time, InfoMessage **info_msgs, size_t infolen);
|
||||
bool iolog_init(AcceptMessage *msg, struct connection_closure *closure);
|
||||
bool iolog_restart(RestartMessage *msg, struct connection_closure *closure);
|
||||
int store_iobuf(int iofd, IoBuffer *msg, struct connection_closure *closure);
|
||||
int store_suspend(CommandSuspend *msg, struct connection_closure *closure);
|
||||
int store_winsize(ChangeWindowSize *msg, struct connection_closure *closure);
|
||||
void iolog_close_all(struct connection_closure *closure);
|
||||
void iolog_details_free(struct iolog_details *details);
|
||||
|
||||
/* logsrvd_conf.c */
|
||||
bool logsrvd_conf_read(const char *path);
|
||||
const char *logsrvd_conf_iolog_dir(void);
|
||||
const char *logsrvd_conf_iolog_file(void);
|
||||
struct listen_address_list *logsrvd_conf_listen_address(void);
|
||||
enum logsrvd_eventlog_type logsrvd_conf_eventlog_type(void);
|
||||
enum logsrvd_eventlog_format logsrvd_conf_eventlog_format(void);
|
||||
unsigned int logsrvd_conf_syslog_maxlen(void);
|
||||
int logsrvd_conf_syslog_facility(void);
|
||||
int logsrvd_conf_syslog_acceptpri(void);
|
||||
int logsrvd_conf_syslog_rejectpri(void);
|
||||
int logsrvd_conf_syslog_alertpri(void);
|
||||
const char *logsrvd_conf_logfile_path(void);
|
||||
const char *logsrvd_conf_logfile_time_format(void);
|
||||
|
||||
#endif /* SUDO_LOGSRVD_H */
|
||||
|
@@ -64,30 +64,114 @@ struct logsrvd_config_section {
|
||||
struct logsrvd_config_entry *entries;
|
||||
};
|
||||
|
||||
static char *logsrvd_iolog_dir;
|
||||
static struct logsrvd_config {
|
||||
struct logsrvd_config_server {
|
||||
struct listen_address_list addresses;
|
||||
} server;
|
||||
struct logsrvd_config_iolog {
|
||||
/* XXX - others private to iolog */
|
||||
char *iolog_dir;
|
||||
char *iolog_file;
|
||||
} iolog;
|
||||
struct logsrvd_config_eventlog {
|
||||
enum logsrvd_eventlog_type log_type;
|
||||
enum logsrvd_eventlog_format log_format;
|
||||
} eventlog;
|
||||
struct logsrvd_config_syslog {
|
||||
unsigned int maxlen;
|
||||
int facility;
|
||||
int acceptpri;
|
||||
int rejectpri;
|
||||
int alertpri;
|
||||
} syslog;
|
||||
struct logsrvd_config_logfile {
|
||||
char *path;
|
||||
char *time_format;
|
||||
} logfile;
|
||||
} logsrvd_config = {
|
||||
{ TAILQ_HEAD_INITIALIZER(logsrvd_config.server.addresses) }
|
||||
};
|
||||
|
||||
/* iolog getters */
|
||||
const char *
|
||||
logsrvd_conf_iolog_dir(void)
|
||||
{
|
||||
return logsrvd_iolog_dir;
|
||||
return logsrvd_config.iolog.iolog_dir;
|
||||
}
|
||||
|
||||
static char *logsrvd_iolog_file;
|
||||
|
||||
const char *
|
||||
logsrvd_conf_iolog_file(void)
|
||||
{
|
||||
return logsrvd_iolog_file;
|
||||
return logsrvd_config.iolog.iolog_file;
|
||||
}
|
||||
|
||||
static struct listen_address_list addresses = TAILQ_HEAD_INITIALIZER(addresses);
|
||||
|
||||
/* server getters */
|
||||
struct listen_address_list *
|
||||
logsrvd_conf_listen_address(void)
|
||||
{
|
||||
return &addresses;
|
||||
return &logsrvd_config.server.addresses;
|
||||
}
|
||||
|
||||
/* eventlog getters */
|
||||
enum logsrvd_eventlog_type
|
||||
logsrvd_conf_eventlog_type(void)
|
||||
{
|
||||
return logsrvd_config.eventlog.log_type;
|
||||
}
|
||||
|
||||
enum logsrvd_eventlog_format
|
||||
logsrvd_conf_eventlog_format(void)
|
||||
{
|
||||
return logsrvd_config.eventlog.log_format;
|
||||
}
|
||||
|
||||
/* syslog getters */
|
||||
unsigned int
|
||||
logsrvd_conf_syslog_maxlen(void)
|
||||
{
|
||||
return logsrvd_config.syslog.maxlen;
|
||||
}
|
||||
|
||||
int
|
||||
logsrvd_conf_syslog_facility(void)
|
||||
{
|
||||
return logsrvd_config.syslog.facility;
|
||||
}
|
||||
|
||||
int
|
||||
logsrvd_conf_syslog_acceptpri(void)
|
||||
{
|
||||
return logsrvd_config.syslog.acceptpri;
|
||||
}
|
||||
|
||||
int
|
||||
logsrvd_conf_syslog_rejectpri(void)
|
||||
{
|
||||
return logsrvd_config.syslog.rejectpri;
|
||||
}
|
||||
|
||||
int
|
||||
logsrvd_conf_syslog_alertpri(void)
|
||||
{
|
||||
return logsrvd_config.syslog.alertpri;
|
||||
}
|
||||
|
||||
/* logfile getters */
|
||||
const char *
|
||||
logsrvd_conf_logfile_path(void)
|
||||
{
|
||||
return logsrvd_config.logfile.path;
|
||||
}
|
||||
|
||||
const char *
|
||||
logsrvd_conf_logfile_time_format(void)
|
||||
{
|
||||
return logsrvd_config.logfile.time_format;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset logsrvd_config to default values and reset I/O log values.
|
||||
*/
|
||||
static void
|
||||
logsrvd_conf_reset(void)
|
||||
{
|
||||
@@ -95,26 +179,30 @@ logsrvd_conf_reset(void)
|
||||
debug_decl(logsrvd_conf_reset, SUDO_DEBUG_UTIL)
|
||||
|
||||
iolog_set_defaults();
|
||||
free(logsrvd_iolog_dir);
|
||||
logsrvd_iolog_dir = NULL;
|
||||
free(logsrvd_iolog_file);
|
||||
logsrvd_iolog_file = NULL;
|
||||
free(logsrvd_config.iolog.iolog_dir);
|
||||
logsrvd_config.iolog.iolog_dir = NULL;
|
||||
free(logsrvd_config.iolog.iolog_file);
|
||||
logsrvd_config.iolog.iolog_file = NULL;
|
||||
|
||||
while ((addr = TAILQ_FIRST(&addresses))) {
|
||||
TAILQ_REMOVE(&addresses, addr, entries);
|
||||
while ((addr = TAILQ_FIRST(&logsrvd_config.server.addresses))) {
|
||||
TAILQ_REMOVE(&logsrvd_config.server.addresses, addr, entries);
|
||||
free(addr);
|
||||
}
|
||||
|
||||
free(logsrvd_config.logfile.path);
|
||||
free(logsrvd_config.logfile.time_format);
|
||||
|
||||
debug_return;
|
||||
}
|
||||
|
||||
/* I/O log callbacks */
|
||||
static bool
|
||||
cb_iolog_dir(const char *path)
|
||||
{
|
||||
debug_decl(cb_iolog_dir, SUDO_DEBUG_UTIL)
|
||||
|
||||
free(logsrvd_iolog_dir);
|
||||
if ((logsrvd_iolog_dir = strdup(path)) == NULL) {
|
||||
free(logsrvd_config.iolog.iolog_dir);
|
||||
if ((logsrvd_config.iolog.iolog_dir = strdup(path)) == NULL) {
|
||||
sudo_warn(NULL);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
@@ -126,8 +214,8 @@ cb_iolog_file(const char *path)
|
||||
{
|
||||
debug_decl(cb_iolog_file, SUDO_DEBUG_UTIL)
|
||||
|
||||
free(logsrvd_iolog_file);
|
||||
if ((logsrvd_iolog_file = strdup(path)) == NULL) {
|
||||
free(logsrvd_config.iolog.iolog_file);
|
||||
if ((logsrvd_config.iolog.iolog_file = strdup(path)) == NULL) {
|
||||
sudo_warn(NULL);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
@@ -192,6 +280,13 @@ cb_iolog_mode(const char *str)
|
||||
debug_return_bool(iolog_set_mode(mode));
|
||||
}
|
||||
|
||||
static bool
|
||||
cb_iolog_maxseq(const char *str)
|
||||
{
|
||||
return iolog_set_maxseq(str);
|
||||
}
|
||||
|
||||
/* Server callbacks */
|
||||
/* TODO: unit test */
|
||||
static bool
|
||||
cb_listen_address(const char *str)
|
||||
@@ -256,7 +351,7 @@ cb_listen_address(const char *str)
|
||||
}
|
||||
memcpy(&addr->sa_un, res->ai_addr, res->ai_addrlen);
|
||||
addr->sa_len = res->ai_addrlen;
|
||||
TAILQ_INSERT_TAIL(&addresses, addr, entries);
|
||||
TAILQ_INSERT_TAIL(&logsrvd_config.server.addresses, addr, entries);
|
||||
}
|
||||
|
||||
ret = true;
|
||||
@@ -267,10 +362,157 @@ done:
|
||||
debug_return_bool(ret);
|
||||
}
|
||||
|
||||
/* eventlog callbacks */
|
||||
static bool
|
||||
cb_maxseq(const char *str)
|
||||
cb_eventlog_type(const char *str)
|
||||
{
|
||||
return iolog_set_maxseq(str);
|
||||
debug_decl(cb_eventlog_type, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (strcmp(str, "none") == 0)
|
||||
logsrvd_config.eventlog.log_type = EVLOG_NONE;
|
||||
else if (strcmp(str, "syslog") == 0)
|
||||
logsrvd_config.eventlog.log_type = EVLOG_SYSLOG;
|
||||
else if (strcmp(str, "logfile") == 0)
|
||||
logsrvd_config.eventlog.log_type = EVLOG_FILE;
|
||||
else
|
||||
debug_return_bool(false);
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
cb_eventlog_format(const char *str)
|
||||
{
|
||||
debug_decl(cb_eventlog_format, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (strcmp(str, "sudo") == 0)
|
||||
logsrvd_config.eventlog.log_format = EVLOG_SUDO;
|
||||
else
|
||||
debug_return_bool(false);
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
/* syslog callbacks */
|
||||
static bool
|
||||
cb_syslog_maxlen(const char *str)
|
||||
{
|
||||
unsigned int maxlen;
|
||||
const char *errstr;
|
||||
debug_decl(cb_syslog_maxlen, SUDO_DEBUG_UTIL)
|
||||
|
||||
maxlen = sudo_strtonum(str, 1, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
debug_return_bool(false);
|
||||
|
||||
logsrvd_config.syslog.maxlen = maxlen;
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
cb_syslog_facility(const char *str)
|
||||
{
|
||||
int logfac;
|
||||
debug_decl(cb_syslog_facility, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (!sudo_str2logfac(str, &logfac)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"invalid syslog priority %s", str);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
logsrvd_config.syslog.facility = logfac;
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
cb_syslog_acceptpri(const char *str)
|
||||
{
|
||||
int logpri;
|
||||
debug_decl(cb_syslog_acceptpri, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (!sudo_str2logpri(str, &logpri)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"invalid syslog priority %s", str);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
logsrvd_config.syslog.acceptpri = logpri;
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
cb_syslog_rejectpri(const char *str)
|
||||
{
|
||||
int logpri;
|
||||
debug_decl(cb_syslog_rejectpri, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (!sudo_str2logpri(str, &logpri))
|
||||
debug_return_bool(false);
|
||||
|
||||
logsrvd_config.syslog.rejectpri = logpri;
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
cb_syslog_alertpri(const char *str)
|
||||
{
|
||||
int logpri;
|
||||
debug_decl(cb_syslog_alertpri, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (!sudo_str2logpri(str, &logpri)) {
|
||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||
"invalid syslog priority %s", str);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
logsrvd_config.syslog.alertpri = logpri;
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
/* logfile callbacks */
|
||||
static bool
|
||||
cb_logfile_path(const char *str)
|
||||
{
|
||||
char *copy = NULL;
|
||||
debug_decl(cb_logfile_path, SUDO_DEBUG_UTIL)
|
||||
|
||||
if (*str != '/') {
|
||||
debug_return_bool(false);
|
||||
sudo_warnx(U_("%s: not a fully qualified path"), str);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
if ((copy = strdup(str)) == NULL) {
|
||||
sudo_warn(NULL);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
free(logsrvd_config.logfile.path);
|
||||
logsrvd_config.logfile.path = copy;
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
static bool
|
||||
cb_logfile_time_format(const char *str)
|
||||
{
|
||||
char *copy = NULL;
|
||||
debug_decl(cb_logfile_time_format, SUDO_DEBUG_UTIL)
|
||||
|
||||
if ((copy = strdup(str)) == NULL) {
|
||||
sudo_warn(NULL);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
free(logsrvd_config.logfile.time_format);
|
||||
logsrvd_config.logfile.time_format = copy;
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
||||
static struct logsrvd_config_entry server_conf_entries[] = {
|
||||
@@ -286,13 +528,37 @@ static struct logsrvd_config_entry iolog_conf_entries[] = {
|
||||
{ "iolog_user", cb_iolog_user },
|
||||
{ "iolog_group", cb_iolog_group },
|
||||
{ "iolog_mode", cb_iolog_mode },
|
||||
{ "maxseq", cb_maxseq },
|
||||
{ "maxseq", cb_iolog_maxseq },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static struct logsrvd_config_entry eventlog_conf_entries[] = {
|
||||
{ "log_type", cb_eventlog_type },
|
||||
{ "log_format", cb_eventlog_format },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static struct logsrvd_config_entry syslog_conf_entries[] = {
|
||||
{ "maxlen", cb_syslog_maxlen },
|
||||
{ "facility", cb_syslog_facility },
|
||||
{ "reject_priority", cb_syslog_rejectpri },
|
||||
{ "accept_priority", cb_syslog_acceptpri },
|
||||
{ "alert_priority", cb_syslog_alertpri },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static struct logsrvd_config_entry logfile_conf_entries[] = {
|
||||
{ "path", cb_logfile_path },
|
||||
{ "time_format", cb_logfile_time_format },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static struct logsrvd_config_section logsrvd_config_sections[] = {
|
||||
{ "server", server_conf_entries },
|
||||
{ "iolog", iolog_conf_entries },
|
||||
{ "eventlog", eventlog_conf_entries },
|
||||
{ "syslog", syslog_conf_entries },
|
||||
{ "logfile", logfile_conf_entries },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -300,7 +566,7 @@ static struct logsrvd_config_section logsrvd_config_sections[] = {
|
||||
* Read .ini style logsrvd.conf file.
|
||||
* Note that we use '#' not ';' for the comment character.
|
||||
*/
|
||||
/* XXX - on reload we should preserve old config if there is an error */
|
||||
/* XXX - split into read and apply so we don't overwrite good config with bad */
|
||||
bool
|
||||
logsrvd_conf_read(const char *path)
|
||||
{
|
||||
@@ -318,7 +584,27 @@ logsrvd_conf_read(const char *path)
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
/* Initialize default values for settings that take int values. */
|
||||
logsrvd_conf_reset();
|
||||
logsrvd_config.eventlog.log_type = EVLOG_SYSLOG;
|
||||
logsrvd_config.eventlog.log_format = EVLOG_SUDO;
|
||||
logsrvd_config.syslog.maxlen = 960;
|
||||
if (!cb_syslog_facility(LOGFAC)) {
|
||||
sudo_warnx(U_("unknown syslog facility %s"), LOGFAC);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
if (!cb_syslog_acceptpri(PRI_SUCCESS)) {
|
||||
sudo_warnx(U_("unknown syslog priority %s"), PRI_SUCCESS);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
if (!cb_syslog_rejectpri(PRI_FAILURE)) {
|
||||
sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
if (!cb_syslog_alertpri(PRI_FAILURE)) {
|
||||
sudo_warnx(U_("unknown syslog priority %s"), PRI_FAILURE);
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
while (sudo_parseln(&line, &linesize, &lineno, fp, 0) != -1) {
|
||||
struct logsrvd_config_entry *entry;
|
||||
@@ -386,23 +672,27 @@ logsrvd_conf_read(const char *path)
|
||||
}
|
||||
}
|
||||
|
||||
/* All the others have default values. */
|
||||
if (logsrvd_iolog_dir == NULL) {
|
||||
if ((logsrvd_iolog_dir = strdup(_PATH_SUDO_IO_LOGDIR)) == NULL) {
|
||||
sudo_warn(NULL);
|
||||
/* For settings with pointer values we can tell what is unset. */
|
||||
if (logsrvd_config.iolog.iolog_dir == NULL) {
|
||||
if (!cb_iolog_dir(_PATH_SUDO_IO_LOGDIR))
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (logsrvd_iolog_file == NULL) {
|
||||
if ((logsrvd_iolog_file = strdup("%{seq}")) == NULL) {
|
||||
sudo_warn(NULL);
|
||||
if (logsrvd_config.iolog.iolog_file == NULL) {
|
||||
if (!cb_iolog_file("%{seq}"))
|
||||
debug_return_bool(false);
|
||||
}
|
||||
}
|
||||
if (TAILQ_EMPTY(&addresses)) {
|
||||
if (TAILQ_EMPTY(&logsrvd_config.server.addresses)) {
|
||||
if (!cb_listen_address("*:30344"))
|
||||
debug_return_bool(false);
|
||||
}
|
||||
if (logsrvd_config.logfile.time_format == NULL) {
|
||||
if (!cb_logfile_time_format("%h %e %T"))
|
||||
debug_return_bool(false);
|
||||
}
|
||||
if (logsrvd_config.logfile.path == NULL) {
|
||||
if (!cb_logfile_path(_PATH_SUDO_LOGFILE))
|
||||
debug_return_bool(false);
|
||||
}
|
||||
|
||||
debug_return_bool(true);
|
||||
}
|
||||
|
@@ -46,45 +46,6 @@
|
||||
#include "sudoers.h"
|
||||
#include <gram.h>
|
||||
|
||||
/*
|
||||
* For converting between syslog numbers and strings.
|
||||
*/
|
||||
struct strmap {
|
||||
char *name;
|
||||
int num;
|
||||
};
|
||||
|
||||
static struct strmap facilities[] = {
|
||||
#ifdef LOG_AUTHPRIV
|
||||
{ "authpriv", LOG_AUTHPRIV },
|
||||
#endif
|
||||
{ "auth", LOG_AUTH },
|
||||
{ "daemon", LOG_DAEMON },
|
||||
{ "user", LOG_USER },
|
||||
{ "local0", LOG_LOCAL0 },
|
||||
{ "local1", LOG_LOCAL1 },
|
||||
{ "local2", LOG_LOCAL2 },
|
||||
{ "local3", LOG_LOCAL3 },
|
||||
{ "local4", LOG_LOCAL4 },
|
||||
{ "local5", LOG_LOCAL5 },
|
||||
{ "local6", LOG_LOCAL6 },
|
||||
{ "local7", LOG_LOCAL7 },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
static struct strmap priorities[] = {
|
||||
{ "alert", LOG_ALERT },
|
||||
{ "crit", LOG_CRIT },
|
||||
{ "debug", LOG_DEBUG },
|
||||
{ "emerg", LOG_EMERG },
|
||||
{ "err", LOG_ERR },
|
||||
{ "info", LOG_INFO },
|
||||
{ "notice", LOG_NOTICE },
|
||||
{ "warning", LOG_WARNING },
|
||||
{ "none", -1 },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
static struct early_default early_defaults[] = {
|
||||
{ I_IGNORE_UNKNOWN_DEFAULTS },
|
||||
#ifdef FQDN
|
||||
@@ -113,8 +74,6 @@ static bool store_tuple(const char *str, union sudo_defs_val *sd_un, struct def_
|
||||
static bool store_uint(const char *str, union sudo_defs_val *sd_un);
|
||||
static bool store_timespec(const char *str, union sudo_defs_val *sd_un);
|
||||
static bool list_op(const char *str, size_t, union sudo_defs_val *sd_un, enum list_ops op);
|
||||
static const char *logfac2str(int);
|
||||
static const char *logpri2str(int);
|
||||
|
||||
/*
|
||||
* Table describing compile-time and run-time options.
|
||||
@@ -150,14 +109,14 @@ dump_defaults(void)
|
||||
case T_LOGFAC:
|
||||
if (cur->sd_un.ival) {
|
||||
sudo_printf(SUDO_CONV_INFO_MSG, desc,
|
||||
logfac2str(cur->sd_un.ival));
|
||||
sudo_logfac2str(cur->sd_un.ival));
|
||||
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
|
||||
}
|
||||
break;
|
||||
case T_LOGPRI:
|
||||
if (cur->sd_un.ival) {
|
||||
sudo_printf(SUDO_CONV_INFO_MSG, desc,
|
||||
logpri2str(cur->sd_un.ival));
|
||||
sudo_logpri2str(cur->sd_un.ival));
|
||||
sudo_printf(SUDO_CONV_INFO_MSG, "\n");
|
||||
}
|
||||
break;
|
||||
@@ -990,63 +949,25 @@ store_list(const char *str, union sudo_defs_val *sd_un, int op)
|
||||
static bool
|
||||
store_syslogfac(const char *str, union sudo_defs_val *sd_un)
|
||||
{
|
||||
struct strmap *fac;
|
||||
debug_decl(store_syslogfac, SUDOERS_DEBUG_DEFAULTS)
|
||||
|
||||
if (str == NULL) {
|
||||
sd_un->ival = false;
|
||||
debug_return_bool(true);
|
||||
}
|
||||
for (fac = facilities; fac->name != NULL; fac++) {
|
||||
if (strcmp(str, fac->name) == 0) {
|
||||
sd_un->ival = fac->num;
|
||||
debug_return_bool(true);
|
||||
}
|
||||
}
|
||||
debug_return_bool(false); /* not found */
|
||||
}
|
||||
|
||||
static const char *
|
||||
logfac2str(int n)
|
||||
{
|
||||
struct strmap *fac;
|
||||
debug_decl(logfac2str, SUDOERS_DEBUG_DEFAULTS)
|
||||
|
||||
for (fac = facilities; fac->name && fac->num != n; fac++)
|
||||
continue;
|
||||
debug_return_const_str(fac->name);
|
||||
debug_return_bool(sudo_str2logfac(str, &sd_un->ival));
|
||||
}
|
||||
|
||||
static bool
|
||||
store_syslogpri(const char *str, union sudo_defs_val *sd_un)
|
||||
{
|
||||
struct strmap *pri;
|
||||
debug_decl(store_syslogpri, SUDOERS_DEBUG_DEFAULTS)
|
||||
|
||||
if (str == NULL) {
|
||||
sd_un->ival = -1;
|
||||
debug_return_bool(true);
|
||||
}
|
||||
for (pri = priorities; pri->name != NULL; pri++) {
|
||||
if (strcmp(str, pri->name) == 0) {
|
||||
sd_un->ival = pri->num;
|
||||
debug_return_bool(true);
|
||||
}
|
||||
}
|
||||
debug_return_bool(false); /* not found */
|
||||
}
|
||||
|
||||
static const char *
|
||||
logpri2str(int n)
|
||||
{
|
||||
struct strmap *pri;
|
||||
debug_decl(logpri2str, SUDOERS_DEBUG_DEFAULTS)
|
||||
|
||||
for (pri = priorities; pri->name != NULL; pri++) {
|
||||
if (pri->num == n)
|
||||
debug_return_const_str(pri->name);
|
||||
}
|
||||
debug_return_const_str("unknown");
|
||||
debug_return_bool(sudo_str2logpri(str, &sd_un->ival));
|
||||
}
|
||||
|
||||
static bool
|
||||
|
Reference in New Issue
Block a user