Refactor code in sudoers that creates I/O log files to share with logsrvd.

This commit is contained in:
Todd C. Miller
2019-10-24 20:04:31 -06:00
parent e0c9a9dfa3
commit 059b55ce72
38 changed files with 2110 additions and 1685 deletions

View File

@@ -71,6 +71,7 @@ include/sudo_dso.h
include/sudo_event.h
include/sudo_fatal.h
include/sudo_gettext.h
include/sudo_iolog.h
include/sudo_lbuf.h
include/sudo_plugin.h
include/sudo_queue.h
@@ -81,6 +82,13 @@ init.d/aix.sh.in
init.d/hpux.sh.in
init.d/sudo.conf.in
install-sh
lib/iolog/Makefile.in
lib/iolog/iolog_fileio.c
lib/iolog/iolog_path.c
lib/iolog/iolog_util.c
lib/iolog/regress/iolog_path/check_iolog_path.c
lib/iolog/regress/iolog_path/data
lib/iolog/regress/iolog_util/check_iolog_util.c
lib/util/Makefile.in
lib/util/aix.c
lib/util/arc4random.c
@@ -331,11 +339,7 @@ plugins/sudoers/insults.h
plugins/sudoers/interfaces.c
plugins/sudoers/interfaces.h
plugins/sudoers/iolog.c
plugins/sudoers/iolog.h
plugins/sudoers/iolog_files.h
plugins/sudoers/iolog_path.c
plugins/sudoers/iolog_util.c
plugins/sudoers/iolog_util.h
plugins/sudoers/iolog_path_escapes.c
plugins/sudoers/ldap.c
plugins/sudoers/ldap_conf.c
plugins/sudoers/ldap_util.c
@@ -503,10 +507,7 @@ plugins/sudoers/regress/cvtsudoers/test9.out.ok
plugins/sudoers/regress/cvtsudoers/test9.sh
plugins/sudoers/regress/env_match/check_env_pattern.c
plugins/sudoers/regress/env_match/data
plugins/sudoers/regress/iolog_path/check_iolog_path.c
plugins/sudoers/regress/iolog_path/data
plugins/sudoers/regress/iolog_plugin/check_iolog_plugin.c
plugins/sudoers/regress/iolog_util/check_iolog_util.c
plugins/sudoers/regress/logging/check_wrap.c
plugins/sudoers/regress/logging/check_wrap.in
plugins/sudoers/regress/logging/check_wrap.out.ok

View File

@@ -49,8 +49,8 @@ sudoers_gid = @SUDOERS_GID@
sudoers_mode = @SUDOERS_MODE@
shlib_mode = @SHLIB_MODE@
SUBDIRS = lib/util @ZLIB_SRC@ logsrvd plugins/group_file plugins/sudoers \
plugins/system_group src include doc examples
SUBDIRS = lib/util lib/iolog @ZLIB_SRC@ logsrvd plugins/group_file \
plugins/sudoers plugins/system_group src include doc examples
SAMPLES = plugins/sample
@@ -188,12 +188,13 @@ siglist.c signame.c:
depend: siglist.c signame.c
$(top_srcdir)/mkdep.pl --builddir=`pwd` --srcdir=$(top_srcdir) \
lib/util/Makefile.in lib/zlib/Makefile.in logsrvd/Makefile.in \
plugins/group_file/Makefile.in plugins/sample/Makefile.in \
plugins/sudoers/Makefile.in plugins/system_group/Makefile.in \
src/Makefile.in && \
lib/util/Makefile.in lib/zlib/Makefile.in lib/iolog/Makefile.in \
logsrvd/Makefile.in plugins/group_file/Makefile.in \
plugins/sample/Makefile.in plugins/sudoers/Makefile.in \
plugins/system_group/Makefile.in src/Makefile.in && \
$(top_builddir)/config.status --file $(top_builddir)/lib/util/Makefile \
--file $(top_builddir)/lib/zlib/Makefile \
--file $(top_builddir)/lib/iolog/Makefile \
--file $(top_builddir)/logsrvd/Makefile \
--file $(top_builddir)/plugins/sample/Makefile \
--file $(top_builddir)/plugins/group_file/Makefile \

3
configure vendored
View File

@@ -27067,7 +27067,7 @@ elif test X"$TMPFILES_D" != X""; then
ac_config_files="$ac_config_files init.d/sudo.conf"
fi
ac_config_files="$ac_config_files Makefile doc/Makefile examples/Makefile include/Makefile lib/util/Makefile lib/util/util.exp logsrvd/Makefile src/sudo_usage.h src/Makefile plugins/sample/Makefile plugins/group_file/Makefile plugins/system_group/Makefile plugins/sudoers/Makefile plugins/sudoers/sudoers"
ac_config_files="$ac_config_files Makefile doc/Makefile examples/Makefile include/Makefile lib/iolog/Makefile lib/util/Makefile lib/util/util.exp logsrvd/Makefile src/sudo_usage.h src/Makefile plugins/sample/Makefile plugins/group_file/Makefile plugins/system_group/Makefile plugins/sudoers/Makefile plugins/sudoers/sudoers"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -28065,6 +28065,7 @@ do
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
"examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
"include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
"lib/iolog/Makefile") CONFIG_FILES="$CONFIG_FILES lib/iolog/Makefile" ;;
"lib/util/Makefile") CONFIG_FILES="$CONFIG_FILES lib/util/Makefile" ;;
"lib/util/util.exp") CONFIG_FILES="$CONFIG_FILES lib/util/util.exp" ;;
"logsrvd/Makefile") CONFIG_FILES="$CONFIG_FILES logsrvd/Makefile" ;;

View File

@@ -4491,7 +4491,7 @@ if test X"$INIT_SCRIPT" != X""; then
elif test X"$TMPFILES_D" != X""; then
AC_CONFIG_FILES([init.d/sudo.conf])
fi
AC_CONFIG_FILES([Makefile doc/Makefile examples/Makefile include/Makefile lib/util/Makefile lib/util/util.exp logsrvd/Makefile src/sudo_usage.h src/Makefile plugins/sample/Makefile plugins/group_file/Makefile plugins/system_group/Makefile plugins/sudoers/Makefile plugins/sudoers/sudoers])
AC_CONFIG_FILES([Makefile doc/Makefile examples/Makefile include/Makefile lib/iolog/Makefile lib/util/Makefile lib/util/util.exp logsrvd/Makefile src/sudo_usage.h src/Makefile plugins/sample/Makefile plugins/group_file/Makefile plugins/system_group/Makefile plugins/sudoers/Makefile plugins/sudoers/sudoers])
AC_OUTPUT
dnl

135
include/sudo_iolog.h Normal file
View File

@@ -0,0 +1,135 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2009-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.
*/
#ifndef SUDO_IOLOG_H
#define SUDO_IOLOG_H
#ifdef HAVE_ZLIB_H
# include <zlib.h> /* for gzFile */
#endif
/* Default maximum session ID */
#define SESSID_MAX 2176782336U
/*
* I/O log event types as stored as the first field in the timing file.
* Changing existing values will result in incompatible I/O log files.
*/
#define IO_EVENT_STDIN 0
#define IO_EVENT_STDOUT 1
#define IO_EVENT_STDERR 2
#define IO_EVENT_TTYIN 3
#define IO_EVENT_TTYOUT 4
#define IO_EVENT_WINSIZE 5
#define IO_EVENT_TTYOUT_1_8_7 6
#define IO_EVENT_SUSPEND 7
#define IO_EVENT_COUNT 8
/*
* Indexes into iolog_files[] array.
* These must match the IO_EVENT_ defines above.
* TODO: eliminate use of IOFD_* and IO_EVENT_* as indexes in favor of
* a struct containing iolog_file *s for each (and names too?).
*/
#define IOFD_STDIN 0
#define IOFD_STDOUT 1
#define IOFD_STDERR 2
#define IOFD_TTYIN 3
#define IOFD_TTYOUT 4
#define IOFD_TIMING 5
#define IOFD_MAX 6
/*
* Info present in the I/O log file
*/
struct iolog_info {
char *cwd;
char *user;
char *runas_user;
char *runas_group;
char *tty;
char *cmd;
time_t tstamp;
int lines;
int cols;
};
struct timing_closure {
struct timespec delay;
const char *decimal;
struct iolog_file *iol;
int event;
union {
struct {
int lines;
int cols;
} winsize;
size_t nbytes;
int signo;
} u;
};
struct iolog_file {
bool enabled;
bool compressed;
union {
FILE *f;
#ifdef HAVE_ZLIB_H
gzFile g;
#endif
void *v;
} fd;
};
struct iolog_path_escape {
const char *name;
size_t (*copy_fn)(char *, size_t, char *);
};
/* iolog_path.c */
char *expand_iolog_path(const char *prefix, const char *dir, const char *file, char **slashp, const struct iolog_path_escape *escapes);
/* iolog_util.c */
bool parse_timing(const char *line, struct timing_closure *timing);
char *parse_delay(const char *cp, struct timespec *delay, const char *decimal_point);
struct iolog_info *parse_logfile(const char *logfile);
void free_iolog_info(struct iolog_info *li);
void adjust_delay(struct timespec *delay, struct timespec *max_delay, double scale_factor);
/* iolog_fileio.c */
struct passwd;
struct group;
bool iolog_close(struct iolog_file *iol, const char **errstr);
bool iolog_eof(struct iolog_file *iol);
bool iolog_nextid(char *iolog_dir, char sessid[7]);
bool iolog_open(struct iolog_file *iol, char *pathbuf, const char *mode);
bool iolog_set_compress(const char *str);
bool iolog_set_flush(const char *str);
bool iolog_set_group(const struct group *gr);
bool iolog_set_maxseq(const char *maxval);
bool iolog_set_mode(mode_t mode);
bool iolog_set_user(const struct passwd *pw);
bool iolog_write_info_file(const char *parent, struct iolog_info *log_info, char * const argv[]);
char *iolog_gets(struct iolog_file *iol, char *buf, size_t nbytes, const char **errsttr);
const char *iolog_fd_to_name(int iofd);
off_t iolog_seek(struct iolog_file *iol, off_t offset, int whence);
size_t mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize);
ssize_t iolog_read(struct iolog_file *iol, void *buf, size_t nbytes, const char **errstr);
ssize_t iolog_write(struct iolog_file *iol, const void *buf, size_t len, const char **errstr);
#endif /* SUDO_IOLOG_H */

View File

@@ -25,6 +25,13 @@
# include "compat/stdbool.h"
#endif /* HAVE_STDBOOL_H */
#ifdef __TANDEM
# define ROOT_UID 65535
#else
# define ROOT_UID 0
#endif
#define ROOT_GID 0
#ifndef TIME_T_MAX
# if SIZEOF_TIME_T == 8
# define TIME_T_MAX LLONG_MAX

256
lib/iolog/Makefile.in Normal file
View File

@@ -0,0 +1,256 @@
#
# SPDX-License-Identifier: ISC
#
# Copyright (c) 2011-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.
#
# @configure_input@
#
#### Start of system configuration section. ####
srcdir = @srcdir@
devdir = @devdir@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
incdir = $(top_srcdir)/include
cross_compiling = @CROSS_COMPILING@
# Where to install things...
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
sysconfdir = @sysconfdir@
libexecdir = @libexecdir@
datarootdir = @datarootdir@
localstatedir = @localstatedir@
# Compiler & tools to use
CC = @CC@
LIBTOOL = @LIBTOOL@
SED = @SED@
AWK = @AWK@
# Libraries
LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
LIBS = @LIBS@ @ZLIB@ $(LT_LIBS)
# C preprocessor flags
CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) -I$(top_srcdir) @CPPFLAGS@
# Usually -O and/or -g
CFLAGS = @CFLAGS@
# Flags to pass to the link stage
LDFLAGS = @LDFLAGS@
# Flags to pass to libtool
LTFLAGS = @LT_STATIC@
# Address sanitizer flags
ASAN_CFLAGS = @ASAN_CFLAGS@
ASAN_LDFLAGS = @ASAN_LDFLAGS@
# PIE flags
PIE_CFLAGS = @PIE_CFLAGS@
PIE_LDFLAGS = @PIE_LDFLAGS@
# Stack smashing protection flags
SSP_CFLAGS = @SSP_CFLAGS@
SSP_LDFLAGS = @SSP_LDFLAGS@
# cppcheck options, usually set in the top-level Makefile
CPPCHECK_OPTS = -q --force --enable=warning,performance,portability --suppress=constStatement --error-exitcode=1 --inline-suppr -Dva_copy=va_copy -U__cplusplus -UQUAD_MAX -UQUAD_MIN -UUQUAD_MAX -U_POSIX_HOST_NAME_MAX -U_POSIX_PATH_MAX -U__NBBY -DNSIG=64
# splint options, usually set in the top-level Makefile
SPLINT_OPTS = -D__restrict= -checks
# PVS-studio options
PVS_CFG = $(top_srcdir)/PVS-Studio.cfg
PVS_IGNORE = 'V707,V011,V002,V536'
PVS_LOG_OPTS = -a 'GA:1,2' -e -t errorfile -d $(PVS_IGNORE)
# Regression tests
TEST_PROGS = check_iolog_path check_iolog_util
TEST_LIBS = @LIBS@
TEST_LDFLAGS = @LDFLAGS@
# Set to non-empty for development mode
DEVEL = @DEVEL@
#### End of system configuration section. ####
SHELL = @SHELL@
LIBIOLOG_OBJS = iolog_fileio.lo iolog_path.lo iolog_util.lo
IOBJS = $(LIBIOLOG_OBJS:.lo=.i)
POBJS = $(IOBJS:.i=.plog)
CHECK_IOLOG_PATH_OBJS = check_iolog_path.lo iolog_path.lo
CHECK_IOLOG_UTIL_OBJS = check_iolog_util.lo iolog_util.lo
all: libsudo_iolog.la
pvs-log-files: $(POBJS)
pvs-studio: $(POBJS)
plog-converter $(PVS_LOG_OPTS) $(POBJS)
Makefile: $(srcdir)/Makefile.in
cd $(top_builddir) && ./config.status --file lib/iolog/Makefile
.SUFFIXES: .c .h .i .lo .plog
.c.lo:
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $<
.c.i:
$(CC) -E -o $@ $(CPPFLAGS) $<
.i.plog:
ifile=$<; rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $${ifile%i}c --i-file $< --output-file $@
libsudo_iolog.la: $(LIBIOLOG_OBJS)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBIOLOG_OBJS) $(LT_LIBS) @ZLIB@
check_iolog_path: $(CHECK_IOLOG_PATH_OBJS) libsudo_iolog.la
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PATH_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
check_iolog_util: $(CHECK_IOLOG_UTIL_OBJS) libsudo_iolog.la
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_UTIL_OBJS) libsudo_iolog.la $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(TEST_LDFLAGS) $(TEST_LIBS)
pre-install:
install:
install-binaries:
install-includes:
install-doc:
install-plugin:
uninstall:
splint:
splint $(SPLINT_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
cppcheck:
cppcheck $(CPPCHECK_OPTS) -I$(incdir) -I$(top_builddir) -I$(top_srcdir) $(srcdir)/*.c
pvs-log-files: $(POBJS)
check: $(TEST_PROGS)
@if test X"$(cross_compiling)" != X"yes"; then \
LC_ALL=C; export LC_ALL; \
unset LANG || LANG=; \
rval=0; \
./check_iolog_path $(srcdir)/regress/iolog_path/data || rval=`expr $$rval + $$?`; \
./check_iolog_util || rval=`expr $$rval + $$?`; \
exit $$rval; \
fi
clean:
-$(LIBTOOL) $(LTFLAGS) --mode=clean rm -f $(TEST_PROGS) *.lo *.o \
*.la *.a *.i *.plog stamp-* core *.core core.* regress/*/*.out \
regress/*/*.err
mostlyclean: clean
distclean: clean
-rm -rf Makefile .libs
clobber: distclean
realclean: distclean
rm -f TAGS tags
cleandir: realclean
# Autogenerated dependencies, do not modify
check_iolog_path.lo: $(srcdir)/regress/iolog_path/check_iolog_path.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.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)/regress/iolog_path/check_iolog_path.c
check_iolog_path.i: $(srcdir)/regress/iolog_path/check_iolog_path.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
check_iolog_path.plog: check_iolog_path.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_path/check_iolog_path.c --i-file $< --output-file $@
check_iolog_util.lo: $(srcdir)/regress/iolog_util/check_iolog_util.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.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)/regress/iolog_util/check_iolog_util.c
check_iolog_util.i: $(srcdir)/regress/iolog_util/check_iolog_util.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_iolog.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
check_iolog_util.plog: check_iolog_util.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_util/check_iolog_util.c --i-file $< --output-file $@
iolog_fileio.lo: $(srcdir)/iolog_fileio.c $(incdir)/compat/stdbool.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_iolog.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h \
$(top_builddir)/pathnames.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_fileio.c
iolog_fileio.i: $(srcdir)/iolog_fileio.c $(incdir)/compat/stdbool.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_iolog.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(top_builddir)/config.h \
$(top_builddir)/pathnames.h
$(CC) -E -o $@ $(CPPFLAGS) $<
iolog_fileio.plog: iolog_fileio.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_fileio.c --i-file $< --output-file $@
iolog_path.lo: $(srcdir)/iolog_path.c $(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 $(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_path.c
iolog_path.i: $(srcdir)/iolog_path.c $(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 $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
iolog_path.plog: iolog_path.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_path.c --i-file $< --output-file $@
iolog_util.lo: $(srcdir)/iolog_util.c $(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 $(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_util.c
iolog_util.i: $(srcdir)/iolog_util.c $(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 $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
iolog_util.plog: iolog_util.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_util.c --i-file $< --output-file $@

897
lib/iolog/iolog_fileio.c Normal file
View File

@@ -0,0 +1,897 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2009-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.
*/
/*
* 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/stat.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# include "compat/stdbool.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
#include <grp.h>
#include "sudo_gettext.h" /* must be included before sudo_compat.h */
#include "sudo_compat.h"
#include "sudo_conf.h"
#include "sudo_debug.h"
#include "sudo_event.h"
#include "sudo_queue.h"
#include "sudo_util.h"
#include "sudo_fatal.h"
#include "sudo_iolog.h"
#include "pathnames.h"
static unsigned char const gzip_magic[2] = {0x1f, 0x8b};
static unsigned int sessid_max = SESSID_MAX;
static mode_t iolog_filemode = S_IRUSR|S_IWUSR;
static mode_t iolog_dirmode = S_IRWXU;
static uid_t iolog_uid = ROOT_UID;
static gid_t iolog_gid = ROOT_GID;
static bool iolog_gid_set;
static bool iolog_compress;
static bool iolog_flush;
/*
* Set effective user and group-IDs to iolog_uid and iolog_gid.
* If restore flag is set, swap them back.
*/
static bool
io_swapids(bool restore)
{
#ifdef HAVE_SETEUID
static uid_t user_euid = (uid_t)-1;
static gid_t user_egid = (gid_t)-1;
debug_decl(io_swapids, SUDO_DEBUG_UTIL)
if (user_euid == (uid_t)-1)
user_euid = geteuid();
if (user_egid == (gid_t)-1)
user_euid = getegid();
if (restore) {
if (seteuid(user_euid) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to restore effective uid to %d", __func__,
(int)user_euid);
sudo_warn("seteuid() %d -> %d", (int)iolog_uid, (int)user_euid);
debug_return_bool(false);
}
if (setegid(user_egid) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to restore effective gid to %d", __func__,
(int)user_egid);
sudo_warn("setegid() %d -> %d", (int)iolog_gid, (int)user_egid);
debug_return_bool(false);
}
} else {
/* Fail silently if the user has insufficient privileges. */
if (setegid(iolog_gid) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to set effective gid to %d", __func__,
(int)iolog_gid);
debug_return_bool(false);
}
if (seteuid(iolog_uid) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to set effective uid to %d", __func__,
(int)iolog_uid);
debug_return_bool(false);
}
}
debug_return_bool(true);
#else
return false;
#endif
}
/*
* Create directory and any parent directories as needed.
*/
static bool
io_mkdirs(char *path)
{
mode_t omask;
struct stat sb;
bool ok, uid_changed = false;
debug_decl(io_mkdirs, SUDO_DEBUG_UTIL)
/* umask must not be more restrictive than the file modes. */
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
ok = stat(path, &sb) == 0;
if (!ok && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
if (io_swapids(false)) {
ok = stat(path, &sb) == 0;
if (!io_swapids(true))
ok = false;
}
}
if (ok) {
if (S_ISDIR(sb.st_mode)) {
if (sb.st_uid != iolog_uid || sb.st_gid != iolog_gid) {
if (chown(path, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to chown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, path);
}
}
if ((sb.st_mode & ALLPERMS) != iolog_dirmode) {
if (chmod(path, iolog_dirmode) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to chmod 0%o %s", __func__,
(int)iolog_dirmode, path);
}
}
} else {
sudo_warnx(U_("%s exists but is not a directory (0%o)"),
path, (unsigned int) sb.st_mode);
ok = false;
}
goto done;
}
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (!ok && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
uid_changed = io_swapids(false);
if (uid_changed)
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
}
if (ok) {
/* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o", path, (unsigned int) iolog_dirmode);
ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST;
if (!ok) {
if (errno == EACCES && !uid_changed) {
/* Try again as the I/O log owner (for NFS). */
uid_changed = io_swapids(false);
if (uid_changed)
ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST;
}
if (!ok)
sudo_warn(U_("unable to mkdir %s"), path);
} else {
if (chown(path, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to chown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, path);
}
}
}
if (uid_changed) {
if (!io_swapids(true))
ok = false;
}
done:
umask(omask);
debug_return_bool(ok);
}
/*
* Create temporary directory and any parent directories as needed.
*/
static bool
io_mkdtemp(char *path)
{
bool ok, uid_changed = false;
debug_decl(io_mkdtemp, SUDO_DEBUG_UTIL)
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (!ok && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
uid_changed = io_swapids(false);
if (uid_changed)
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
}
if (ok) {
/* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdtemp %s", path);
/* We cannot retry mkdtemp() so always open as iolog user */
if (!uid_changed)
uid_changed = io_swapids(false);
if (mkdtemp(path) == NULL) {
sudo_warn(U_("unable to mkdir %s"), path);
ok = false;
} else {
if (chmod(path, iolog_dirmode) != 0) {
sudo_warn(U_("unable to change mode of %s to 0%o"),
path, (unsigned int)iolog_dirmode);
}
}
}
if (uid_changed) {
if (!io_swapids(true))
ok = false;
}
debug_return_bool(ok);
}
/*
* Set max sequence number (aka session ID)
*/
bool
iolog_set_maxseq(const char *maxval)
{
const char *errstr;
unsigned int value;
debug_decl(iolog_set_maxseq, SUDO_DEBUG_UTIL)
value = sudo_strtonum(maxval, 0, SESSID_MAX, &errstr);
if (errstr != NULL) {
if (errno != ERANGE) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"bad maxseq: %s: %s", maxval, errstr);
debug_return_bool(false);
}
/* Out of range, clamp to SESSID_MAX as documented. */
value = SESSID_MAX;
}
sessid_max = value;
debug_return_bool(true);
}
/*
* Set iolog_uid (and iolog_gid if iolog_group not specified).
*/
bool
iolog_set_user(const struct passwd *pw)
{
debug_decl(iolog_set_user, SUDO_DEBUG_UTIL)
if (pw != NULL) {
iolog_uid = pw->pw_uid;
if (!iolog_gid_set)
iolog_gid = pw->pw_gid;
} else {
/* Reset to default. */
iolog_uid = ROOT_UID;
if (!iolog_gid_set)
iolog_gid = ROOT_GID;
}
debug_return_bool(true);
}
/*
* Set iolog_gid.
*/
bool
iolog_set_group(const struct group *gr)
{
debug_decl(iolog_set_group, SUDO_DEBUG_UTIL)
if (gr != NULL) {
iolog_gid = gr->gr_gid;
iolog_gid_set = true;
} else {
/* Reset to default. */
iolog_gid = ROOT_GID;
iolog_gid_set = false;
}
debug_return_bool(true);
}
/*
* Set iolog_filemode and iolog_dirmode.
*/
bool
iolog_set_mode(mode_t mode)
{
debug_decl(iolog_set_mode, SUDO_DEBUG_UTIL)
/* I/O log files must be readable and writable by owner. */
iolog_filemode = S_IRUSR|S_IWUSR;
/* Add in group and other read/write if specified. */
iolog_filemode |= mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
/* For directory mode, add execute bits as needed. */
iolog_dirmode = iolog_filemode | S_IXUSR;
if (iolog_dirmode & (S_IRGRP|S_IWGRP))
iolog_dirmode |= S_IXGRP;
if (iolog_dirmode & (S_IROTH|S_IWOTH))
iolog_dirmode |= S_IXOTH;
debug_return_bool(true);
}
/*
* Set iolog_compress
*/
bool
iolog_set_compress(const char *str)
{
int result;
debug_decl(iolog_set_compress, SUDO_DEBUG_UTIL)
if ((result = sudo_strtobool(str)) == -1)
debug_return_bool(false);
iolog_compress = result;
debug_return_bool(true);
}
/*
* Set iolog_flush
*/
bool
iolog_set_flush(const char *str)
{
int result;
debug_decl(iolog_set_flush, SUDO_DEBUG_UTIL)
if ((result = sudo_strtobool(str)) == -1)
debug_return_bool(false);
iolog_flush = result;
debug_return_bool(true);
}
/*
* Wrapper for open(2) that sets umask and retries as iolog_uid/iolog_gid
* if open(2) returns EACCES.
*/
static int
io_open(const char *path, int flags)
{
int fd;
mode_t omask = S_IRWXG|S_IRWXO;
debug_decl(io_open, SUDO_DEBUG_UTIL)
if (ISSET(flags, O_CREAT)) {
/* umask must not be more restrictive than the file modes. */
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
}
fd = open(path, flags, iolog_filemode);
if (fd == -1 && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
if (io_swapids(false)) {
fd = open(path, flags, iolog_filemode);
if (!io_swapids(true)) {
/* io_swapids() warns on error. */
if (fd != -1) {
close(fd);
fd = -1;
}
}
}
}
if (ISSET(flags, O_CREAT))
umask(omask);
debug_return_int(fd);
}
/*
* Read the on-disk sequence number, set sessid to the next
* number, and update the on-disk copy.
* Uses file locking to avoid sequence number collisions.
*/
bool
iolog_nextid(char *iolog_dir, char sessid[7])
{
char buf[32], *ep;
int i, len, fd = -1;
unsigned long id = 0;
ssize_t nread;
bool ret = false;
char pathbuf[PATH_MAX];
static const char b36char[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
debug_decl(iolog_nextid, SUDO_DEBUG_UTIL)
/*
* Create I/O log directory if it doesn't already exist.
*/
if (!io_mkdirs(iolog_dir))
goto done;
/*
* Open sequence file
*/
len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", iolog_dir);
if (len < 0 || len >= ssizeof(pathbuf)) {
errno = ENAMETOOLONG;
goto done;
}
fd = io_open(pathbuf, O_RDWR|O_CREAT);
if (fd == -1) {
goto done;
}
sudo_lock_file(fd, SUDO_LOCK);
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to fchown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, pathbuf);
}
/* Read current seq number (base 36). */
if (id == 0) {
nread = read(fd, buf, sizeof(buf) - 1);
if (nread != 0) {
if (nread == -1) {
goto done;
}
if (buf[nread - 1] == '\n')
nread--;
buf[nread] = '\0';
id = strtoul(buf, &ep, 36);
if (ep == buf || *ep != '\0' || id >= sessid_max) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: bad sequence number: %s", pathbuf, buf);
id = 0;
}
}
}
id++;
/*
* Convert id to a string and stash in sessid.
* Note that that least significant digits go at the end of the string.
*/
for (i = 5; i >= 0; i--) {
buf[i] = b36char[id % 36];
id /= 36;
}
buf[6] = '\n';
/* Stash id for logging purposes. */
memcpy(sessid, buf, 6);
sessid[6] = '\0';
/* Rewind and overwrite old seq file, including the NUL byte. */
#ifdef HAVE_PWRITE
if (pwrite(fd, buf, 7, 0) != 7) {
#else
if (lseek(fd, 0, SEEK_SET) == -1 || write(fd, buf, 7) != 7) {
#endif
goto done;
}
ret = true;
done:
if (fd != -1)
close(fd);
debug_return_bool(ret);
}
/*
* Copy iolog_path to pathbuf and create the directory and any intermediate
* directories. If iolog_path ends in 'XXXXXX', use mkdtemp().
* Returns SIZE_MAX on error.
*/
size_t
mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize)
{
size_t len;
bool ok;
debug_decl(mkdir_iopath, SUDO_DEBUG_UTIL)
len = strlcpy(pathbuf, iolog_path, pathsize);
if (len >= pathsize) {
errno = ENAMETOOLONG;
debug_return_size_t((size_t)-1);
}
/*
* Create path and intermediate subdirs as needed.
* If path ends in at least 6 Xs (ala POSIX mktemp), use mkdtemp().
* Sets iolog_gid (if it is not already set) as a side effect.
*/
if (len >= 6 && strcmp(&pathbuf[len - 6], "XXXXXX") == 0)
ok = io_mkdtemp(pathbuf);
else
ok = io_mkdirs(pathbuf);
debug_return_size_t(ok ? len : (size_t)-1);
}
/*
* Append suffix to pathbuf after len chars and open the resulting file.
* Note that the size of pathbuf is assumed to be PATH_MAX.
* Stores the open file handle which has the close-on-exec flag set.
* XXX - move enabled logic into caller?
*/
bool
iolog_open(struct iolog_file *iol, char *path, const char *mode)
{
int flags;
unsigned char magic[2];
debug_decl(iolog_open, SUDO_DEBUG_UTIL)
if (mode[0] == 'r') {
flags = mode[1] == '+' ? O_RDWR : O_RDONLY;
} else if (mode[0] == 'w') {
flags = O_CREAT|O_TRUNC;
flags |= mode[1] == '+' ? O_RDWR : O_WRONLY;
} else {
sudo_debug_printf(SUDO_DEBUG_ERROR,
"%s: invalid I/O mode %s", __func__, mode);
debug_return_bool(false);
}
iol->compressed = false;
if (iol->enabled) {
int fd = io_open(path, flags);
if (fd != -1) {
if (*mode == 'w') {
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to fchown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, path);
}
iol->compressed = iolog_compress;
} else {
/* check for gzip magic number */
if (read(fd, magic, sizeof(magic)) == ssizeof(magic)) {
if (magic[0] == gzip_magic[0] && magic[1] == gzip_magic[1])
iol->compressed = true;
}
(void)lseek(fd, 0, SEEK_SET);
}
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
#ifdef HAVE_ZLIB_H
if (iol->compressed)
iol->fd.g = gzdopen(fd, mode);
else
#endif
iol->fd.f = fdopen(fd, mode);
if (iol->fd.v == NULL) {
int save_errno = errno;
close(fd);
errno = save_errno;
fd = -1;
}
}
if (fd == -1) {
iol->enabled = false;
debug_return_bool(false);
}
} else {
if (*mode == 'w') {
/* Remove old log file in case we recycled sequence numbers. */
(void)unlink(path);
}
}
debug_return_bool(true);
}
#ifdef HAVE_ZLIB_H
static const char *
gzstrerror(gzFile file)
{
int errnum;
return gzerror(file, &errnum);
}
#endif /* HAVE_ZLIB_H */
/*
* Close an I/O log.
*/
bool
iolog_close(struct iolog_file *iol, const char **errstr)
{
bool ret = true;
debug_decl(iolog_close, SUDO_DEBUG_UTIL)
#ifdef HAVE_ZLIB_H
if (iol->compressed) {
if (gzclose(iol->fd.g) != Z_OK) {
ret = false;
if (errstr != NULL)
*errstr = gzstrerror(iol->fd.g);
}
} else
#endif
if (fclose(iol->fd.f) != 0) {
ret = false;
if (errstr != NULL)
*errstr = strerror(errno);
}
debug_return_bool(ret);
}
/*
* I/O log wrapper for fseek/gzseek.
*/
off_t
iolog_seek(struct iolog_file *iol, off_t offset, int whence)
{
off_t ret;
//debug_decl(iolog_seek, SUDO_DEBUG_UTIL)
#ifdef HAVE_ZLIB_H
if (iol->compressed)
ret = gzseek(iol->fd.g, offset, whence);
else
#endif
#ifdef HAVE_FSEEKO
ret = fseeko(iol->fd.f, offset, whence);
#else
ret = fseek(iol->fd.f, offset, whence);
#endif
//debug_return_off_t(ret);
return ret;
}
/*
* Read from a (possibly compressed) I/O log file.
*/
ssize_t
iolog_read(struct iolog_file *iol, void *buf, size_t nbytes,
const char **errstr)
{
ssize_t nread;
debug_decl(iolog_read, SUDO_DEBUG_UTIL)
if (nbytes > UINT_MAX) {
errno = EINVAL;
if (errstr != NULL)
*errstr = strerror(errno);
debug_return_ssize_t(-1);
}
#ifdef HAVE_ZLIB_H
if (iol->compressed) {
if ((nread = gzread(iol->fd.g, buf, nbytes)) == -1) {
if (errstr != NULL)
*errstr = gzstrerror(iol->fd.g);
}
} else
#endif
{
nread = (ssize_t)fread(buf, 1, nbytes, iol->fd.f);
if (nread == 0 && ferror(iol->fd.f)) {
nread = -1;
if (errstr != NULL)
*errstr = strerror(errno);
}
}
debug_return_ssize_t(nread);
}
/*
* Write to an I/O log, optionally compressing.
*/
ssize_t
iolog_write(struct iolog_file *iol, const void *buf, size_t len,
const char **errstr)
{
ssize_t ret;
debug_decl(iolog_write, SUDO_DEBUG_UTIL)
if (len > UINT_MAX) {
errno = EINVAL;
if (errstr != NULL)
*errstr = strerror(errno);
debug_return_ssize_t(-1);
}
#ifdef HAVE_ZLIB_H
if (iol->compressed) {
ret = gzwrite(iol->fd.g, (const voidp)buf, len);
if (ret == 0) {
ret = -1;
if (errstr != NULL)
*errstr = gzstrerror(iol->fd.g);
goto done;
}
if (iolog_flush) {
if (gzflush(iol->fd.g, Z_SYNC_FLUSH) != Z_OK) {
ret = -1;
if (errstr != NULL)
*errstr = gzstrerror(iol->fd.g);
goto done;
}
}
} else
#endif
{
ret = fwrite(buf, 1, len, iol->fd.f);
if (ret == 0) {
ret = -1;
if (errstr != NULL)
*errstr = strerror(errno);
goto done;
}
if (iolog_flush) {
if (fflush(iol->fd.f) != 0) {
ret = -1;
if (errstr != NULL)
*errstr = strerror(errno);
goto done;
}
}
}
done:
debug_return_ssize_t(ret);
}
/*
* Returns true if at end of I/O log file, else false.
*/
bool
iolog_eof(struct iolog_file *iol)
{
bool ret;
debug_decl(iolog_eof, SUDO_DEBUG_UTIL)
#ifdef HAVE_ZLIB_H
if (iol->compressed)
ret = gzeof(iol->fd.g) == 1;
else
#endif
ret = feof(iol->fd.f) == 1;
debug_return_int(ret);
}
/*
* Like gets() but for struct iolog_file.
*/
char *
iolog_gets(struct iolog_file *iol, char *buf, size_t nbytes,
const char **errstr)
{
char *str;
debug_decl(iolog_gets, SUDO_DEBUG_UTIL)
if (nbytes > UINT_MAX) {
errno = EINVAL;
if (errstr != NULL)
*errstr = strerror(errno);
debug_return_str(NULL);
}
#ifdef HAVE_ZLIB_H
if (iol->compressed) {
if ((str = gzgets(iol->fd.g, buf, nbytes)) == NULL) {
if (errstr != NULL)
*errstr = gzstrerror(iol->fd.g);
}
} else
#endif
{
if ((str = fgets(buf, nbytes, iol->fd.f)) == NULL) {
if (errstr != NULL)
*errstr = strerror(errno);
}
}
debug_return_str(str);
}
/*
* Write the I/O log file that contains the user and command info.
* This file is not compressed.
*/
bool
iolog_write_info_file(const char *parent, struct iolog_info *log_info,
char * const argv[])
{
char path[PATH_MAX];
char * const *av;
FILE *fp;
int error, len, fd;
debug_decl(iolog_info_write_log, SUDO_DEBUG_UTIL)
len = snprintf(path, sizeof(path), "%s/log", parent);
if (len < 0 || len >= ssizeof(path)) {
errno = ENAMETOOLONG;
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"%s/log", parent);
debug_return_bool(false);
}
fd = io_open(path, O_CREAT|O_TRUNC|O_WRONLY);
if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to open %s", path);
if (fd != -1)
close(fd);
debug_return_bool(false);
}
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to fchown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, path);
}
fprintf(fp, "%lld:%s:%s:%s:%s:%d:%d\n%s\n",
(long long)log_info->tstamp,
log_info->user ? log_info->user : "unknown",
log_info->runas_user ? log_info->runas_user : RUNAS_DEFAULT,
log_info->runas_group ? log_info->runas_group : "",
log_info->tty ? log_info->tty : "unknown",
log_info->lines, log_info->cols,
log_info->cwd ? log_info->cwd : "unknown");
fputs(log_info->cmd ? log_info->cmd : "unknown", fp);
for (av = argv + 1; *av != NULL; av++) {
fputc(' ', fp);
fputs(*av, fp);
}
fputc('\n', fp);
fflush(fp);
if ((error = ferror(fp))) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to write to I/O log file %s", path);
}
fclose(fp);
debug_return_bool(!error);
}
/*
* Map IOFD_* -> name.
*/
const char *
iolog_fd_to_name(int iofd)
{
const char *ret = NULL;
debug_decl(iolog_fd_to_name, SUDO_DEBUG_UTIL)
switch (iofd) {
case IOFD_STDIN:
ret = "stdin";
break;
case IOFD_STDOUT:
ret = "stdout";
break;
case IOFD_STDERR:
ret = "stderr";
break;
case IOFD_TTYIN:
ret = "ttyin";
break;
case IOFD_TTYOUT:
ret = "ttyout";
break;
case IOFD_TIMING:
ret = "timing";
break;
default:
sudo_debug_printf(SUDO_DEBUG_ERROR, "%s: unexpected iofd %d",
__func__, iofd);
break;
}
debug_return_const_str(ret);
}

View File

@@ -26,6 +26,11 @@
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# include "compat/stdbool.h"
#endif /* HAVE_STDBOOL_H */
#ifdef HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
@@ -34,137 +39,35 @@
#endif /* HAVE_STRINGS_H */
#include <pwd.h>
#include <grp.h>
#include <limits.h>
#include <time.h>
#include <unistd.h>
#include "sudoers.h"
#include "sudo_gettext.h" /* must be included before sudo_compat.h */
struct path_escape {
const char *name;
size_t (*copy_fn)(char *, size_t, char *);
};
static size_t
fill_seq(char *str, size_t strsize, char *logdir)
{
#ifdef SUDOERS_NO_SEQ
debug_decl(fill_seq, SUDOERS_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, "%{seq}", strsize));
#else
static char sessid[7];
int len;
debug_decl(fill_seq, SUDOERS_DEBUG_UTIL)
if (sessid[0] == '\0') {
if (!io_nextid(logdir, def_iolog_dir, sessid))
debug_return_size_t((size_t)-1);
}
/* Path is of the form /var/log/sudo-io/00/00/01. */
len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0],
sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]);
if (len < 0)
debug_return_size_t(strsize); /* handle non-standard snprintf() */
debug_return_size_t(len);
#endif /* SUDOERS_NO_SEQ */
}
static size_t
fill_user(char *str, size_t strsize, char *unused)
{
debug_decl(fill_user, SUDOERS_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, user_name, strsize));
}
static size_t
fill_group(char *str, size_t strsize, char *unused)
{
struct group *grp;
size_t len;
debug_decl(fill_group, SUDOERS_DEBUG_UTIL)
if ((grp = sudo_getgrgid(user_gid)) != NULL) {
len = strlcpy(str, grp->gr_name, strsize);
sudo_gr_delref(grp);
} else {
len = strlen(str);
len = snprintf(str + len, strsize - len, "#%u",
(unsigned int) user_gid);
}
debug_return_size_t(len);
}
static size_t
fill_runas_user(char *str, size_t strsize, char *unused)
{
debug_decl(fill_runas_user, SUDOERS_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, runas_pw->pw_name, strsize));
}
static size_t
fill_runas_group(char *str, size_t strsize, char *unused)
{
struct group *grp;
size_t len;
debug_decl(fill_runas_group, SUDOERS_DEBUG_UTIL)
if (runas_gr != NULL) {
len = strlcpy(str, runas_gr->gr_name, strsize);
} else {
if ((grp = sudo_getgrgid(runas_pw->pw_gid)) != NULL) {
len = strlcpy(str, grp->gr_name, strsize);
sudo_gr_delref(grp);
} else {
len = strlen(str);
len = snprintf(str + len, strsize - len, "#%u",
(unsigned int) runas_pw->pw_gid);
}
}
debug_return_size_t(len);
}
static size_t
fill_hostname(char *str, size_t strsize, char *unused)
{
debug_decl(fill_hostname, SUDOERS_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, user_shost, strsize));
}
static size_t
fill_command(char *str, size_t strsize, char *unused)
{
debug_decl(fill_command, SUDOERS_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, user_base, strsize));
}
/* Note: "seq" must be first in the list. */
static struct path_escape io_path_escapes[] = {
{ "seq", fill_seq },
{ "user", fill_user },
{ "group", fill_group },
{ "runas_user", fill_runas_user },
{ "runas_group", fill_runas_group },
{ "hostname", fill_hostname },
{ "command", fill_command },
{ NULL, NULL }
};
#include "sudo_compat.h"
#include "sudo_fatal.h"
#include "sudo_debug.h"
#include "sudo_util.h"
#include "sudo_iolog.h"
/*
* Concatenate dir + file, expanding any escape sequences.
* Returns the concatenated path and sets slashp point to
* the path separator between the expanded dir and file.
* XXX - simplify by only expanding one thing and removing prefix
*/
char *
expand_iolog_path(const char *prefix, const char *dir, const char *file,
char **slashp)
char **slashp, const struct iolog_path_escape *escapes)
{
size_t len, prelen = 0;
char *dst, *dst0, *path, *pathend, tmpbuf[PATH_MAX];
char *slash = NULL;
const char *endbrace, *src = dir;
struct path_escape *escapes = NULL;
int pass, oldlocale;
int pass;
bool strfit;
debug_decl(expand_iolog_path, SUDOERS_DEBUG_UTIL)
debug_decl(expand_iolog_path, SUDO_DEBUG_UTIL)
/* Expanded path must be <= PATH_MAX */
if (prefix != NULL)
@@ -194,7 +97,7 @@ expand_iolog_path(const char *prefix, const char *dir, const char *file,
switch (pass) {
case 0:
src = dir;
escapes = io_path_escapes + 1; /* skip "%{seq}" */
escapes++; /* skip "%{seq}" */
break;
case 1:
/* Trim trailing slashes from dir component. */
@@ -207,7 +110,7 @@ expand_iolog_path(const char *prefix, const char *dir, const char *file,
continue;
case 2:
src = file;
escapes = io_path_escapes;
escapes--; /* restore "%{seq}" */
break;
}
dst0 = dst;
@@ -216,7 +119,7 @@ expand_iolog_path(const char *prefix, const char *dir, const char *file,
if (src[1] == '{') {
endbrace = strchr(src + 2, '}');
if (endbrace != NULL) {
struct path_escape *esc;
const struct iolog_path_escape *esc;
len = (size_t)(endbrace - src - 2);
for (esc = escapes; esc->name != NULL; esc++) {
if (strncmp(src + 2, esc->name, len) == 0 &&
@@ -238,7 +141,7 @@ expand_iolog_path(const char *prefix, const char *dir, const char *file,
src++;
} else {
/* May need strftime() */
strfit = 1;
strfit = true;
}
}
/* Need at least 2 chars, including the NUL terminator. */
@@ -257,16 +160,10 @@ expand_iolog_path(const char *prefix, const char *dir, const char *file,
if ((timeptr = localtime(&now)) == NULL)
goto bad;
/* Use sudoers locale for strftime() */
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
/* We only call strftime() on the current part of the buffer. */
tmpbuf[sizeof(tmpbuf) - 1] = '\0';
len = strftime(tmpbuf, sizeof(tmpbuf), dst0, timeptr);
/* Restore old locale. */
sudoers_setlocale(oldlocale, NULL);
if (len == 0 || tmpbuf[sizeof(tmpbuf) - 1] != '\0')
goto bad; /* strftime() failed, buf too small? */

View File

@@ -26,6 +26,11 @@
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# include "compat/stdbool.h"
#endif /* HAVE_STDBOOL_H */
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#elif defined(HAVE_INTTYPES_H)
@@ -44,11 +49,6 @@
#include <limits.h>
#include <fcntl.h>
#include <time.h>
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# include "compat/stdbool.h"
#endif /* HAVE_STDBOOL_H */
#include "sudo_gettext.h" /* must be included before sudo_compat.h */
@@ -56,7 +56,7 @@
#include "sudo_fatal.h"
#include "sudo_debug.h"
#include "sudo_util.h"
#include "iolog_util.h"
#include "sudo_iolog.h"
static int timing_event_adj;
@@ -311,8 +311,8 @@ parse_timing(const char *line, struct timing_closure *timing)
char *cp, *ep;
debug_decl(parse_timing, SUDO_DEBUG_UTIL)
/* Clear fd. */
timing->fd.v = NULL;
/* Clear iolog descriptor. */
timing->iol = NULL;
/* Parse event type. */
ulval = strtoul(line, &ep, 10);

View File

@@ -27,19 +27,25 @@
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <unistd.h>
#define SUDO_ERROR_WRAP 0
#include "sudoers.h"
#include "def_data.c"
#include "sudo_compat.h"
#include "sudo_util.h"
#include "sudo_fatal.h"
#include "sudo_iolog.h"
struct sudo_user sudo_user;
struct passwd *list_pw;
static char sessid[7];
static struct iolog_escape_data {
char sessid[7];
char *user;
char *group;
char *runas_user;
char *runas_group;
char *host;
char *command;
} escape_data;
__dso_public int main(int argc, char *argv[]);
@@ -50,6 +56,80 @@ usage(void)
exit(1);
}
static void
reset_escape_data(struct iolog_escape_data *data)
{
free(data->user);
free(data->group);
free(data->runas_user);
free(data->runas_group);
free(data->host);
free(data->command);
memset(data, 0, sizeof(*data));
}
static size_t
fill_seq(char *str, size_t strsize, char *logdir)
{
int len;
/* Path is of the form /var/log/sudo-io/00/00/01. */
len = snprintf(str, strsize, "%c%c/%c%c/%c%c", escape_data.sessid[0],
escape_data.sessid[1], escape_data.sessid[2], escape_data.sessid[3],
escape_data.sessid[4], escape_data.sessid[5]);
if (len < 0)
return strsize; /* handle non-standard snprintf() */
return len;
}
static size_t
fill_user(char *str, size_t strsize, char *unused)
{
return strlcpy(str, escape_data.user, strsize);
}
static size_t
fill_group(char *str, size_t strsize, char *unused)
{
return strlcpy(str, escape_data.group, strsize);
}
static size_t
fill_runas_user(char *str, size_t strsize, char *unused)
{
return strlcpy(str, escape_data.runas_user, strsize);
}
static size_t
fill_runas_group(char *str, size_t strsize, char *unused)
{
return strlcpy(str, escape_data.runas_group, strsize);
}
static size_t
fill_hostname(char *str, size_t strsize, char *unused)
{
return strlcpy(str, escape_data.host, strsize);
}
static size_t
fill_command(char *str, size_t strsize, char *unused)
{
return strlcpy(str, escape_data.command, strsize);
}
/* Note: "seq" must be first in the list. */
static struct iolog_path_escape path_escapes[] = {
{ "seq", fill_seq },
{ "user", fill_user },
{ "group", fill_group },
{ "runas_user", fill_runas_user },
{ "runas_group", fill_runas_group },
{ "hostname", fill_hostname },
{ "command", fill_command },
{ NULL, NULL }
};
static int
do_check(char *dir_in, char *file_in, char *tdir_out, char *tfile_out)
{
@@ -70,7 +150,7 @@ do_check(char *dir_in, char *file_in, char *tdir_out, char *tfile_out)
strftime(dir_out, sizeof(dir_out), tdir_out, timeptr);
strftime(file_out, sizeof(file_out), tfile_out, timeptr);
path = expand_iolog_path(NULL, dir_in, file_in, &slash);
path = expand_iolog_path(NULL, dir_in, file_in, &slash, path_escapes);
if (path == NULL)
sudo_fatalx("unable to expand I/O log path");
*slash = '\0';
@@ -92,13 +172,11 @@ do_check(char *dir_in, char *file_in, char *tdir_out, char *tfile_out)
int
main(int argc, char *argv[])
{
struct passwd pw, rpw;
size_t len;
FILE *fp;
char line[2048];
char *file_in = NULL, *file_out = NULL;
char *dir_in = NULL, *dir_out = NULL;
const char *errstr;
int state = 0;
int errors = 0;
int tests = 0;
@@ -112,11 +190,6 @@ main(int argc, char *argv[])
if (fp == NULL)
sudo_fatalx("unable to open %s", argv[1]);
memset(&pw, 0, sizeof(pw));
memset(&rpw, 0, sizeof(rpw));
sudo_user.pw = &pw;
sudo_user._runas_pw = &rpw;
/*
* Input consists of 12 lines:
* sequence number
@@ -138,37 +211,31 @@ main(int argc, char *argv[])
switch (state) {
case 0:
strlcpy(sessid, line, sizeof(sessid));
strlcpy(escape_data.sessid, line, sizeof(escape_data.sessid));
break;
case 1:
if (user_name != NULL)
free(user_name);
user_name = strdup(line);
if ((escape_data.user = strdup(line)) == NULL)
sudo_fatal(NULL);
break;
case 2:
user_gid = (gid_t)sudo_strtoid(line, &errstr);
if (errstr != NULL)
sudo_fatalx("group ID %s: %s", line, errstr);
if ((escape_data.group = strdup(line)) == NULL)
sudo_fatal(NULL);
break;
case 3:
if (runas_pw->pw_name != NULL)
free(runas_pw->pw_name);
runas_pw->pw_name = strdup(line);
if ((escape_data.runas_user = strdup(line)) == NULL)
sudo_fatal(NULL);
break;
case 4:
runas_pw->pw_gid = (gid_t)sudo_strtoid(line, &errstr);
if (errstr != NULL)
sudo_fatalx("group ID %s: %s", line, errstr);
if ((escape_data.runas_group = strdup(line)) == NULL)
sudo_fatal(NULL);
break;
case 5:
if (user_shost != NULL)
free(user_shost);
user_shost = strdup(line);
if ((escape_data.host = strdup(line)) == NULL)
sudo_fatal(NULL);
break;
case 6:
if (user_base != NULL)
free(user_base);
user_base = strdup(line);
if ((escape_data.command = strdup(line)) == NULL)
sudo_fatal(NULL);
break;
case 7:
if (dir_in != NULL)
@@ -193,6 +260,7 @@ main(int argc, char *argv[])
case 11:
errors += do_check(dir_in, file_in, dir_out, file_out);
tests++;
reset_escape_data(&escape_data);
break;
default:
sudo_fatalx("internal error, invalid state %d", state);
@@ -208,10 +276,3 @@ main(int argc, char *argv[])
exit(errors);
}
bool
io_nextid(char *iolog_dir, char *fallback, char id[7])
{
memcpy(id, sessid, sizeof(sessid));
return true;
}

View File

@@ -1,8 +1,8 @@
000001
nobody
1
nogroup
root
root
0
somehost
id
/var/log/sudo-io
@@ -12,9 +12,9 @@ id
000001
nobody
1
nogroup
root
0
wheel
somehost
id
/var/log/sudo-io
@@ -24,9 +24,9 @@ id
000001
nobody
1
nogroup
root
0
wheel
somehost
id
/var/log/sudo-io
@@ -36,9 +36,9 @@ id
000001
nobody
1
nogroup
root
0
wheel
somehost
id
/var/log/sudo-io/%{user}
@@ -48,9 +48,9 @@ id
000001
nobody
1
nogroup
root
0
wheel
somehost
su
/var/log/sudo-io/%{user}/%{runas_user}
@@ -60,9 +60,9 @@ su_%Y%m%s_%H%M
000001
nobody
1
nogroup
root
0
wheel
somehost
su
/var/log/sudo-io/
@@ -72,9 +72,9 @@ nobody/root/su_%Y%m%s_%H%M
000001
nobody
1
nogroup
root
0
wheel
somehost
su
/var/log/sudo-io/%d%m%Y
@@ -84,9 +84,9 @@ nobody/root/su
000001
nobody
1
nogroup
root
0
wheel
somehost
su
////////

View File

@@ -35,7 +35,7 @@
#include "sudo_compat.h"
#include "sudo_util.h"
#include "sudo_fatal.h"
#include "iolog_util.h"
#include "sudo_iolog.h"
__dso_public int main(int argc, char *argv[]);
@@ -137,14 +137,14 @@ main(int argc, char *argv[])
{
int tests = 0, errors = 0;
initprogname(argc > 0 ? argv[0] : "check_iolog_reader");
initprogname(argc > 0 ? argv[0] : "check_iolog_util");
test_parse_delay(&tests, &errors);
test_adjust_delay(&tests, &errors);
if (tests != 0) {
printf("check_iolog_reader: %d test%s run, %d errors, %d%% success rate\n",
printf("iolog_util: %d test%s run, %d errors, %d%% success rate\n",
tests, tests == 1 ? "" : "s", errors,
(tests - errors) * 100 / tests);
}

View File

@@ -56,12 +56,6 @@
#include "sudo_debug.h"
#include "sudo_util.h"
#ifdef __TANDEM
# define ROOT_UID 65535
#else
# define ROOT_UID 0
#endif
struct sudo_conf_table {
const char *name;
unsigned int namelen;

View File

@@ -24,7 +24,6 @@ srcdir = @srcdir@
devdir = @devdir@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
sudoers_srcdir = @top_srcdir@/plugins/sudoers
incdir = $(top_srcdir)/include
rundir = @rundir@
cross_compiling = @CROSS_COMPILING@
@@ -40,7 +39,7 @@ INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
INSTALL_BACKUP = @INSTALL_BACKUP@
# Libraries
LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
LT_LIBS = $(top_builddir)/lib/iolog/libsudo_iolog.la
LIBS = $(LT_LIBS)
# C preprocessor defines
@@ -49,7 +48,7 @@ CPPDEFS = -D_PATH_SUDO_LOGSRVD_CONF=\"$(sysconfdir)/sudo_logsrvd.conf\" \
# C preprocessor flags
CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(devdir) -I$(srcdir) \
-I$(sudoers_srcdir) -I$(top_srcdir) $(CPPDEFS) @CPPFLAGS@
-I$(top_srcdir) $(CPPDEFS) @CPPFLAGS@
# Usually -O and/or -g
CFLAGS = @CFLAGS@
@@ -108,10 +107,10 @@ SHELL = @SHELL@
PROGS = logsrvd sendlog
LOGSRVD_OBJS = iolog_util.o iolog_writer.o logsrvd.o logsrvd_conf.o \
log_server.pb-c.o protobuf-c.o
LOGSRVD_OBJS = iolog_writer.o logsrvd.o \
logsrvd_conf.o log_server.pb-c.o protobuf-c.o
SENDLOG_OBJS = sendlog.o iolog_util.o log_server.pb-c.o protobuf-c.o
SENDLOG_OBJS = sendlog.o log_server.pb-c.o protobuf-c.o
IOBJS = $(LOGSRVD_OBJS:.o=.i) $(SENDLOG_OBJS:.o=.i)
@@ -144,7 +143,7 @@ logsrvd: $(LOGSRVD_OBJS) $(LT_LIBS)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LOGSRVD_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
sendlog: $(SENDLOG_OBJS) $(LT_LIBS)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(SENDLOG_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS) -lz
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(SENDLOG_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
GENERATED = log_server.pb-c.h log_server.pb-c.c
@@ -212,37 +211,19 @@ realclean: distclean
cleandir: realclean
# Autogenerated dependencies, do not modify
iolog_util.o: plugins/sudoers/iolog_util.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(sudoers_srcdir)/iolog.h $(sudoers_srcdir)/iolog_util.h \
$(top_builddir)/config.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) plugins/sudoers/iolog_util.c
iolog_util.i: plugins/sudoers/iolog_util.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(sudoers_srcdir)/iolog.h $(sudoers_srcdir)/iolog_util.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
iolog_util.plog: iolog_util.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file plugins/sudoers/iolog_util.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_fatal.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(srcdir)/logsrvd.h $(srcdir)/protobuf-c/protobuf-c.h \
$(sudoers_srcdir)/iolog.h $(sudoers_srcdir)/iolog_util.h \
$(top_builddir)/config.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)/iolog_writer.c
iolog_writer.i: $(srcdir)/iolog_writer.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_queue.h $(incdir)/sudo_util.h \
$(srcdir)/logsrvd.h $(srcdir)/protobuf-c/protobuf-c.h \
$(sudoers_srcdir)/iolog.h $(sudoers_srcdir)/iolog_util.h \
$(top_builddir)/config.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) $<
iolog_writer.plog: iolog_writer.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_writer.c --i-file $< --output-file $@
@@ -258,34 +239,36 @@ logsrvd.o: $(srcdir)/logsrvd.c $(devdir)/log_server.pb-c.h \
$(incdir)/compat/stdbool.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_queue.h $(incdir)/sudo_rand.h $(incdir)/sudo_util.h \
$(srcdir)/logsrvd.h $(srcdir)/protobuf-c/protobuf-c.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h $(incdir)/sudo_rand.h \
$(incdir)/sudo_util.h $(srcdir)/logsrvd.h \
$(srcdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.h \
$(top_builddir)/pathnames.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/logsrvd.c
logsrvd.i: $(srcdir)/logsrvd.c $(devdir)/log_server.pb-c.h \
$(incdir)/compat/stdbool.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_queue.h $(incdir)/sudo_rand.h $(incdir)/sudo_util.h \
$(srcdir)/logsrvd.h $(srcdir)/protobuf-c/protobuf-c.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h $(incdir)/sudo_rand.h \
$(incdir)/sudo_util.h $(srcdir)/logsrvd.h \
$(srcdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.h \
$(top_builddir)/pathnames.h
$(CC) -E -o $@ $(CPPFLAGS) $<
logsrvd.plog: logsrvd.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/logsrvd.c --i-file $< --output-file $@
logsrvd_conf.o: $(srcdir)/logsrvd_conf.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_queue.h \
$(incdir)/sudo_util.h $(srcdir)/logsrvd.h \
$(srcdir)/protobuf-c/protobuf-c.h $(sudoers_srcdir)/iolog.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 $(top_builddir)/pathnames.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/logsrvd_conf.c
logsrvd_conf.i: $(srcdir)/logsrvd_conf.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_queue.h \
$(incdir)/sudo_util.h $(srcdir)/logsrvd.h \
$(srcdir)/protobuf-c/protobuf-c.h $(sudoers_srcdir)/iolog.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 $(top_builddir)/pathnames.h
$(CC) -E -o $@ $(CPPFLAGS) $<
logsrvd_conf.plog: logsrvd_conf.i
@@ -301,9 +284,8 @@ sendlog.o: $(srcdir)/sendlog.c $(devdir)/log_server.pb-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_queue.h $(incdir)/sudo_util.h \
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(srcdir)/protobuf-c/protobuf-c.h $(srcdir)/sendlog.h \
$(sudoers_srcdir)/iolog.h $(sudoers_srcdir)/iolog_util.h \
$(top_builddir)/config.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/sendlog.c
sendlog.i: $(srcdir)/sendlog.c $(devdir)/log_server.pb-c.h \
@@ -311,9 +293,8 @@ sendlog.i: $(srcdir)/sendlog.c $(devdir)/log_server.pb-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_queue.h $(incdir)/sudo_util.h \
$(incdir)/sudo_iolog.h $(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(srcdir)/protobuf-c/protobuf-c.h $(srcdir)/sendlog.h \
$(sudoers_srcdir)/iolog.h $(sudoers_srcdir)/iolog_util.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
sendlog.plog: sendlog.i

View File

@@ -42,20 +42,9 @@
#include "sudo_debug.h"
#include "sudo_util.h"
#include "sudo_fatal.h"
#include "iolog_util.h"
#include "sudo_iolog.h"
#include "logsrvd.h"
/* I/O log file names relative to iolog_dir. */
static const char *iolog_names[] = {
"stdin", /* IOFD_STDIN */
"stdout", /* IOFD_STDOUT */
"stderr", /* IOFD_STDERR */
"ttyin", /* IOFD_TTYIN */
"ttyout", /* IOFD_TTYOUT */
"timing", /* IOFD_TIMING */
NULL /* IOFD_MAX */
};
static inline bool
has_numval(InfoMessage *info)
{
@@ -284,13 +273,13 @@ create_iolog_dir(struct iolog_details *details, struct connection_closure *closu
goto bad;
}
/* Make a copy of iolog_dir for error messages. */
if ((closure->iolog_dir = strdup(path)) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"strdup");
goto bad;
}
#if 0
/* We use iolog_dir_fd in calls to openat(2) */
closure->iolog_dir_fd = open(closure->iolog_dir, O_RDONLY);
if (closure->iolog_dir_fd == -1) {
@@ -298,6 +287,7 @@ create_iolog_dir(struct iolog_details *details, struct connection_closure *closu
"%s", closure->iolog_dir);
goto bad;
}
#endif
debug_return_bool(true);
bad:
@@ -349,9 +339,11 @@ iolog_details_write(struct iolog_details *details, struct connection_closure *cl
}
static bool
iolog_open(int iofd, struct connection_closure *closure)
iolog_create(int iofd, struct connection_closure *closure)
{
debug_decl(iolog_open, SUDO_DEBUG_UTIL)
char path[PATH_MAX];
int len;
debug_decl(iolog_create, SUDO_DEBUG_UTIL)
if (iofd < 0 || iofd >= IOFD_MAX) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
@@ -359,24 +351,34 @@ iolog_open(int iofd, struct connection_closure *closure)
debug_return_bool(false);
}
closure->io_fds[iofd] = openat(closure->iolog_dir_fd,
iolog_names[iofd], O_CREAT|O_EXCL|O_WRONLY, 0600);
debug_return_bool(closure->io_fds[iofd] != -1);
len = snprintf(path, sizeof(path), "%s/%s", closure->iolog_dir,
iolog_fd_to_name(iofd));
if (len < 0 || len >= ssizeof(path)) {
errno = ENAMETOOLONG;
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"%s/%s", closure->iolog_dir, iolog_fd_to_name(iofd));
debug_return_bool(false);
}
closure->iolog_files[iofd].enabled = true;
debug_return_bool(iolog_open(&closure->iolog_files[iofd], path, "w"));
}
void
iolog_close(struct connection_closure *closure)
iolog_close_all(struct connection_closure *closure)
{
const char *errstr;
int i;
debug_decl(iolog_close, SUDO_DEBUG_UTIL)
for (i = 0; i < IOFD_MAX; i++) {
if (closure->io_fds[i] == -1)
if (!closure->iolog_files[i].enabled)
continue;
close(closure->io_fds[i]);
if (!iolog_close(&closure->iolog_files[i], &errstr)) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"error closing iofd %d: %s", i, errstr);
}
}
if (closure->iolog_dir_fd != -1)
close(closure->iolog_dir_fd);
debug_return;
}
@@ -385,13 +387,8 @@ bool
iolog_init(ExecMessage *msg, struct connection_closure *closure)
{
struct iolog_details details;
int i;
debug_decl(iolog_init, SUDO_DEBUG_UTIL)
/* Init io_fds in closure. */
for (i = 0; i < IOFD_MAX; i++)
closure->io_fds[i] = -1;
/* Fill in iolog_details */
if (!iolog_details_fill(&details, msg))
debug_return_bool(false);
@@ -404,11 +401,14 @@ iolog_init(ExecMessage *msg, struct connection_closure *closure)
if (!iolog_details_write(&details, closure))
debug_return_bool(false);
/* Create timing, stdout, stderr and ttyout files for sudoreplay. */
if (!iolog_open(IOFD_TIMING, closure) ||
!iolog_open(IOFD_STDOUT, closure) ||
!iolog_open(IOFD_STDERR, closure) ||
!iolog_open(IOFD_TTYOUT, closure))
/*
* Create timing, stdout, stderr and ttyout files for sudoreplay.
* Others will be created on demand.
*/
if (!iolog_create(IOFD_TIMING, closure) ||
!iolog_create(IOFD_STDOUT, closure) ||
!iolog_create(IOFD_STDERR, closure) ||
!iolog_create(IOFD_TTYOUT, closure))
debug_return_bool(false);
/* Ready to log I/O buffers. */
@@ -420,18 +420,19 @@ iolog_init(ExecMessage *msg, struct connection_closure *closure)
* Return 0 on success, 1 on EOF and -1 on error.
*/
static int
read_timing_record(FILE *fp, struct timing_closure *timing)
read_timing_record(struct iolog_file *iol, struct timing_closure *timing)
{
char line[LINE_MAX];
const char *errstr;
debug_decl(read_timing_record, SUDO_DEBUG_UTIL)
/* Read next record from timing file. */
if (fgets(line, sizeof(line), fp) == NULL) {
if (iolog_gets(iol, line, sizeof(line), &errstr) == NULL) {
/* EOF or error reading timing file, we are done. */
if (feof(fp))
if (iolog_eof(iol))
debug_return_int(1); /* EOF */
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"error reading timing file");
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"error reading timing file: %s", errstr);
debug_return_int(-1);
}
@@ -446,80 +447,65 @@ read_timing_record(FILE *fp, struct timing_closure *timing)
debug_return_int(0);
}
/* XXX - compressed I/O logs cannot be restarted, must re-write them */
bool
iolog_restart(RestartMessage *msg, struct connection_closure *closure)
{
struct timespec target;
struct timing_closure timing;
FILE *fp = NULL;
int i, fd;
off_t length;
off_t pos;
int i;
debug_decl(iolog_init, SUDO_DEBUG_UTIL)
target.tv_sec = msg->resume_point->tv_sec;
target.tv_nsec = msg->resume_point->tv_nsec;
/* We use iolog_dir_fd in calls to openat(2) */
if ((closure->iolog_dir = strdup(msg->log_id)) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"strdup");
goto bad;
}
closure->iolog_dir_fd = open(closure->iolog_dir, O_RDONLY);
if (closure->iolog_dir_fd == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"%s", closure->iolog_dir);
goto bad;
}
/* Open existing I/O log files. */
for (i = 0; i < IOFD_MAX; i++) {
closure->io_fds[i] = openat(closure->iolog_dir_fd, iolog_names[i],
O_RDWR, 0600);
}
/* Dup IOFD_TIMING to a stream for easier processing. */
if (closure->io_fds[IOFD_TIMING] == -1)
goto bad;
if ((fd = dup(closure->io_fds[IOFD_TIMING])) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"dup");
char path[PATH_MAX];
int len = snprintf(path, sizeof(path), "%s/%s", closure->iolog_dir,
iolog_fd_to_name(i));
if (len < 0 || len >= ssizeof(path)) {
errno = ENAMETOOLONG;
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: %s/%s", __func__, closure->iolog_dir, iolog_fd_to_name(i));
goto bad;
}
if ((fp = fdopen(fd, "r")) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"fdopen");
goto bad;
closure->iolog_files[i].enabled = true;
(void)iolog_open(&closure->iolog_files[i], path, "r+");
}
if (!closure->iolog_files[IOFD_TIMING].enabled)
goto bad;
/* Parse timing file until we reach the target point. */
/* XXX - split up */
for (;;) {
if (read_timing_record(fp, &timing) != 0)
if (read_timing_record(&closure->iolog_files[IOFD_TIMING], &timing) != 0)
goto bad;
sudo_timespecadd(&timing.delay, &closure->elapsed_time,
&closure->elapsed_time);
if (timing.event < IOFD_TIMING) {
if (closure->io_fds[timing.event] == -1) {
if (!closure->iolog_files[timing.event].enabled) {
/* Missing log file. */
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"iofd %d referenced but not open", timing.event);
goto bad;
}
length = lseek(closure->io_fds[timing.event], timing.u.nbytes,
SEEK_CUR);
if (length == -1) {
pos = iolog_seek(&closure->iolog_files[timing.event],
timing.u.nbytes, SEEK_CUR);
if (pos == -1) {
sudo_debug_printf(
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"lseek(%d, %lld, SEEK_CUR", closure->io_fds[timing.event],
"seek(%d, %lld, SEEK_CUR", timing.event,
(long long)timing.u.nbytes);
goto bad;
}
if (ftruncate(closure->io_fds[timing.event], length) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"ftruncate(%d, %lld)", closure->io_fds[IOFD_TIMING], length);
goto bad;
}
}
if (sudo_timespeccmp(&closure->elapsed_time, &target, >=)) {
if (sudo_timespeccmp(&closure->elapsed_time, &target, ==))
@@ -534,47 +520,19 @@ iolog_restart(RestartMessage *msg, struct connection_closure *closure)
goto bad;
}
}
/* Update timing file position after determining resume point. */
#ifdef HAVE_FSEEKO
length = ftello(fp);
#else
length = ftell(fp);
#endif
fclose(fp);
if (lseek(closure->io_fds[IOFD_TIMING], length, SEEK_SET) == -1) {
/* Must seek or flush before switching from read -> write. */
if (iolog_seek(&closure->iolog_files[IOFD_TIMING], 0, SEEK_CUR) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"lseek(%d, %lld, SEEK_SET", closure->io_fds[IOFD_TIMING], length);
goto bad;
}
if (ftruncate(closure->io_fds[IOFD_TIMING], length) == -1) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"ftruncate(%d, %lld)", closure->io_fds[IOFD_TIMING], length);
"lseek(IOFD_TIMING, 0, SEEK_CUR)");
goto bad;
}
/* Ready to log I/O buffers. */
debug_return_bool(true);
bad:
if (fp != NULL)
fclose(fp);
debug_return_bool(false);
}
static bool
iolog_write(int iofd, void *buf, size_t len, struct connection_closure *closure)
{
debug_decl(iolog_write, SUDO_DEBUG_UTIL)
size_t nread;
if (iofd < 0 || iofd >= IOFD_MAX) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"invalid iofd %d", iofd);
debug_return_bool(false);
}
nread = write(closure->io_fds[iofd], buf, len);
debug_return_bool(nread == len);
}
/*
* Add given delta to elapsed time.
* We cannot use timespecadd here since delta is not struct timespec.
@@ -598,13 +556,14 @@ update_elapsed_time(TimeSpec *delta, struct timespec *elapsed)
int
store_iobuf(int iofd, IoBuffer *msg, struct connection_closure *closure)
{
const char *errstr;
char tbuf[1024];
int len;
debug_decl(store_iobuf, SUDO_DEBUG_UTIL)
/* Open log file as needed. */
if (closure->io_fds[iofd] == -1) {
if (!iolog_open(iofd, closure))
if (!closure->iolog_files[iofd].enabled) {
if (!iolog_create(iofd, closure))
debug_return_int(-1);
}
@@ -620,12 +579,22 @@ store_iobuf(int iofd, IoBuffer *msg, struct connection_closure *closure)
}
/* Write to specified I/O log file. */
if (!iolog_write(iofd, msg->data.data, msg->data.len, 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,
iolog_fd_to_name(iofd), errstr);
debug_return_int(-1);
}
/* Write timing data. */
if (!iolog_write(IOFD_TIMING, tbuf, len, 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,
iolog_fd_to_name(IOFD_TIMING), errstr);
debug_return_int(-1);
}
update_elapsed_time(msg->delay, &closure->elapsed_time);
@@ -635,6 +604,7 @@ store_iobuf(int iofd, IoBuffer *msg, struct connection_closure *closure)
int
store_suspend(CommandSuspend *msg, struct connection_closure *closure)
{
const char *errstr;
char tbuf[1024];
int len;
debug_decl(store_suspend, SUDO_DEBUG_UTIL)
@@ -650,8 +620,13 @@ store_suspend(CommandSuspend *msg, struct connection_closure *closure)
}
/* Write timing data. */
if (!iolog_write(IOFD_TIMING, tbuf, len, 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,
iolog_fd_to_name(IOFD_TIMING), errstr);
debug_return_int(-1);
}
update_elapsed_time(msg->delay, &closure->elapsed_time);
@@ -661,6 +636,7 @@ store_suspend(CommandSuspend *msg, struct connection_closure *closure)
int
store_winsize(ChangeWindowSize *msg, struct connection_closure *closure)
{
const char *errstr;
char tbuf[1024];
int len;
debug_decl(store_winsize, SUDO_DEBUG_UTIL)
@@ -676,8 +652,13 @@ store_winsize(ChangeWindowSize *msg, struct connection_closure *closure)
}
/* Write timing data. */
if (!iolog_write(IOFD_TIMING, tbuf, len, 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,
iolog_fd_to_name(IOFD_TIMING), errstr);
debug_return_int(-1);
}
update_elapsed_time(msg->delay, &closure->elapsed_time);

View File

@@ -50,6 +50,7 @@
#include "sudo_util.h"
#include "sudo_rand.h"
#include "sudo_fatal.h"
#include "sudo_iolog.h"
#include "pathnames.h"
#include "logsrvd.h"
@@ -84,7 +85,7 @@ connection_closure_free(struct connection_closure *closure)
TAILQ_REMOVE(&connections, closure, entries);
close(closure->sock);
iolog_close(closure);
iolog_close_all(closure);
sudo_ev_free(closure->commit_ev);
sudo_ev_free(closure->read_ev);
sudo_ev_free(closure->write_ev);

View File

@@ -14,6 +14,9 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SUDO_LOGSRVD_H
#define SUDO_LOGSRVD_H
#if PROTOBUF_C_VERSION_NUMBER < 1003000
# error protobuf-c version 1.30 or higher required
#endif
@@ -28,18 +31,6 @@
/* Shutdown timeout (in seconds) in case client connections time out. */
#define SHUTDOWN_TIMEO 10
/*
* Indexes into io_fds[] and iolog_names[]
* The first five must match the IO_EVENT_ defines in iolog.h.
*/
#define IOFD_STDIN 0
#define IOFD_STDOUT 1
#define IOFD_STDERR 2
#define IOFD_TTYIN 3
#define IOFD_TTYOUT 4
#define IOFD_TIMING 5
#define IOFD_MAX 6
/*
* I/O log details from the ExecMessage
*/
@@ -93,19 +84,19 @@ struct connection_closure {
struct sudo_event *read_ev;
struct sudo_event *write_ev;
char *iolog_dir;
struct iolog_file iolog_files[IOFD_MAX];
int iolog_dir_fd;
int io_fds[IOFD_MAX];
int sock;
enum connection_status state;
};
/* iolog.c */
/* iolog_writer.c */
bool iolog_init(ExecMessage *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(struct connection_closure *closure);
void iolog_close_all(struct connection_closure *closure);
/* logsrvd_conf.c */
bool logsrvd_conf_iolog_compress(void);
@@ -117,3 +108,5 @@ const char *logsrvd_conf_iolog_user(void);
mode_t logsrvd_conf_iolog_mode(void);
unsigned int logsrvd_conf_maxseq(void);
void logsrvd_conf_read(const char *path);
#endif /* SUDO_LOGSRVD_H */

View File

@@ -39,9 +39,9 @@
#include "sudo_debug.h"
#include "sudo_util.h"
#include "sudo_fatal.h"
#include "sudo_iolog.h"
#include "pathnames.h"
#include "logsrvd.h"
#include "iolog.h"
enum config_type {
CONF_BOOL,

View File

@@ -54,22 +54,11 @@
#include "sudo_util.h"
#include "sudo_event.h"
#include "sudo_fatal.h"
#include "iolog_util.h"
#include "sudo_iolog.h"
#include "sendlog.h"
static gzFile io_fds[IOFD_MAX];
/* I/O log file names relative to the iolog dir. */
/* XXX - duplicated with server */
static const char *iolog_names[] = {
"stdin", /* IOFD_STDIN */
"stdout", /* IOFD_STDOUT */
"stderr", /* IOFD_STDERR */
"ttyin", /* IOFD_TTYIN */
"ttyout", /* IOFD_TTYOUT */
"timing", /* IOFD_TIMING */
NULL /* IOFD_MAX */
};
static struct iolog_file iolog_files[IOFD_MAX];
static char *iolog_path;
static void
usage(void)
@@ -151,8 +140,6 @@ client_closure_free(struct client_closure *closure)
free(closure->read_buf.data);
free(closure->write_buf.data);
free(closure->buf);
// XXX - avoid use after free
//free(closure);
}
debug_return;
@@ -165,26 +152,23 @@ client_closure_free(struct client_closure *closure)
int
read_timing_record(struct timing_closure *timing)
{
const char *errstr;
char line[LINE_MAX];
int errnum;
const char *errstr;
debug_decl(read_timing_record, SUDO_DEBUG_UTIL)
/* Read next record from timing file. */
if (gzgets(io_fds[IOFD_TIMING], line, sizeof(line)) == NULL) {
if (iolog_gets(&iolog_files[IOFD_TIMING], line, sizeof(line), &errstr) == NULL) {
/* EOF or error reading timing file, we are done. */
if (gzeof(io_fds[IOFD_TIMING]))
debug_return_int(1); /* EOF */
if ((errstr = gzerror(io_fds[IOFD_TIMING], &errnum)) == NULL)
errstr = strerror(errno);
sudo_warnx("error reading timing file: %s", errstr);
if (iolog_eof(&iolog_files[IOFD_TIMING]))
debug_return_int(1);
sudo_warnx(U_("error reading timing file: %s"), errstr);
debug_return_int(-1);
}
/* Parse timing file record. */
line[strcspn(line, "\n")] = '\0';
if (!parse_timing(line, timing)) {
sudo_warnx("invalid timing file line: %s", line);
sudo_warnx(U_("invalid timing file line: %s"), line);
debug_return_int(-1);
}
@@ -198,11 +182,13 @@ static bool
read_io_buf(struct client_closure *closure)
{
struct timing_closure *timing = &closure->timing;
const char *errstr = NULL;
size_t nread;
debug_decl(read_io_buf, SUDO_DEBUG_UTIL)
if (io_fds[timing->event] == NULL) {
sudo_warnx("%s file not open", iolog_names[timing->event]);
if (!iolog_files[timing->event].enabled) {
errno = ENOENT;
sudo_warn("%s/%s", iolog_path, iolog_fd_to_name(timing->event));
debug_return_bool(false);
}
@@ -219,15 +205,11 @@ read_io_buf(struct client_closure *closure)
}
}
nread = gzread(io_fds[timing->event], closure->buf, timing->u.nbytes);
nread = iolog_read(&iolog_files[timing->event], closure->buf,
timing->u.nbytes, &errstr);
if (nread != timing->u.nbytes) {
int errnum;
const char *errstr;
if ((errstr = gzerror(io_fds[timing->event], &errnum)) == NULL)
errstr = strerror(errno);
sudo_warnx("unable to read %s file: %s", iolog_names[timing->event],
errstr);
sudo_warnx(U_("unable to read %s/%s: %s"), iolog_path,
iolog_fd_to_name(timing->event), errstr);
debug_return_bool(false);
}
debug_return_bool(true);
@@ -742,7 +724,7 @@ handle_server_hello(ServerHello *msg, struct client_closure *closure)
/* Sanity check ServerHello message. */
if (msg->server_id == NULL || msg->server_id[0] == '\0') {
sudo_warnx("invalid ServerHello");
sudo_warnx("%s", U_("invalid ServerHello"));
debug_return_bool(false);
}
@@ -1034,23 +1016,25 @@ bad:
* The timing file must always exist.
*/
bool
iolog_open_all(const char *iolog_path)
iolog_open_all(char *path, size_t dir_len)
{
char fname[PATH_MAX];
int i, len;
size_t file_len;
int i;
debug_decl(iolog_open_all, SUDO_DEBUG_UTIL)
for (i = 0; iolog_names[i] != NULL; i++) {
len = snprintf(fname, sizeof(fname), "%s/%s", iolog_path,
iolog_names[i]);
if (len < 0 || len >= ssizeof(fname)) {
for (i = 0; i < IOFD_MAX; i++) {
path[dir_len] = '\0';
file_len = strlen(iolog_fd_to_name(i));
if (dir_len + 1 + file_len + 1 >= PATH_MAX) {
errno = ENAMETOOLONG;
sudo_warn("%s/%s", iolog_path, iolog_names[i]);
sudo_warn("%s/%s", path, iolog_fd_to_name(i));
debug_return_bool(false);
}
io_fds[i] = gzopen(fname, "r");
if (io_fds[i] == NULL && i == IOFD_TIMING) {
/* The timing file is not optional. */
sudo_warn("unable to open %s/%s", iolog_path, iolog_names[i]);
path[dir_len++] = '/';
memcpy(path + dir_len, iolog_fd_to_name(i), file_len + 1);
iolog_files[i].enabled = true;
if (!iolog_open(&iolog_files[i], path, "r")) {
sudo_warn(U_("unable to open %s"), path);
debug_return_bool(false);
}
}
@@ -1104,9 +1088,9 @@ main(int argc, char *argv[])
const char *host = "localhost";
const char *port = DEFAULT_PORT_STR;
struct timespec restart = { 0, 0 };
char fname[PATH_MAX], *iolog_path;
char pathbuf[PATH_MAX];
const char *iolog_id = NULL;
int ch, sock;
int ch, len, sock;
debug_decl_vars(main, SUDO_DEBUG_MAIN)
initprogname(argc > 0 ? argv[0] : "sendlog");
@@ -1158,12 +1142,18 @@ main(int argc, char *argv[])
signal(SIGPIPE, SIG_IGN);
/* Parse I/O info log file. */
snprintf(fname, sizeof(fname), "%s/log", iolog_path);
if ((log_info = parse_logfile(fname)) == NULL)
len = snprintf(pathbuf, sizeof(pathbuf), "%s/log", iolog_path);
if (len < 0 || len >= ssizeof(pathbuf)) {
errno = ENAMETOOLONG;
sudo_warn("%s/log", iolog_path);
goto bad;
}
len -= 4;
if ((log_info = parse_logfile(pathbuf)) == NULL)
goto bad;
/* Open the I/O log files. */
if (!iolog_open_all(iolog_path))
if (!iolog_open_all(pathbuf, len))
goto bad;
/* Connect to server, setup events. */

View File

@@ -14,25 +14,15 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SUDO_SENDLOG_H
#define SUDO_SENDLOG_H
#if PROTOBUF_C_VERSION_NUMBER < 1003000
# error protobuf-c version 1.30 or higher required
#endif
#define DEFAULT_PORT_STR "30344"
/*
* Indexes into io_fds[] and iolog_names[]
* The first five must match the IO_EVENT_ defines in iolog.h.
* XXX - needed?
*/
#define IOFD_STDIN 0
#define IOFD_STDOUT 1
#define IOFD_STDERR 2
#define IOFD_TTYIN 3
#define IOFD_TTYOUT 4
#define IOFD_TIMING 5
#define IOFD_MAX 6
enum client_state {
ERROR,
RECV_HELLO,
@@ -67,3 +57,5 @@ struct client_closure {
size_t bufsize; /* XXX */
enum client_state state;
};
#endif /* SUDO_SENDLOG_H */

View File

@@ -59,12 +59,6 @@
* caching the validate and invalidate functions are NULL.
*/
#ifdef __TANDEM
# define ROOT_UID 65535
#else
# define ROOT_UID 0
#endif
static struct plugin_state {
char **envp;
char * const *settings;

View File

@@ -52,11 +52,12 @@ INSTALL_OWNER = -o $(install_uid) -g $(install_gid)
INSTALL_BACKUP = @INSTALL_BACKUP@
# Libraries
LT_LIBS = $(top_builddir)/lib/util/libsudo_util.la
LIBS = $(LT_LIBS)
LIBUTIL = $(top_builddir)/lib/util/libsudo_util.la
LIBIOLOG = $(top_builddir)/lib/iolog/libsudo_iolog.la
LIBS = $(LIBUTIL)
NET_LIBS = @NET_LIBS@
SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(LIBS) $(NET_LIBS) @ZLIB@
REPLAY_LIBS = @REPLAY_LIBS@ @ZLIB@
SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(NET_LIBS) $(LIBIOLOG)
REPLAY_LIBS = @REPLAY_LIBS@ $(LIBIOLOG)
VISUDO_LIBS = $(NET_LIBS)
CVTSUDOERS_LIBS = $(NET_LIBS)
TESTSUDOERS_LIBS = $(NET_LIBS)
@@ -148,8 +149,8 @@ SHELL = @SHELL@
PROGS = sudoers.la visudo sudoreplay cvtsudoers testsudoers
TEST_PROGS = check_addr check_base64 check_digest check_env_pattern check_fill \
check_gentime check_hexchar check_iolog_path check_iolog_plugin \
check_iolog_util check_wrap check_starttime @SUDOERS_TEST_PROGS@
check_gentime check_hexchar check_iolog_plugin check_wrap \
check_starttime @SUDOERS_TEST_PROGS@
AUTH_OBJS = sudo_auth.lo @AUTH_OBJS@
@@ -165,7 +166,7 @@ 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.lo locale.lo logging.lo logwrap.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@
@@ -183,7 +184,7 @@ CVTSUDOERS_OBJS = cvtsudoers.o cvtsudoers_json.o cvtsudoers_ldif.o \
CVTSUDOERS_IOBJS = cvtsudoers.i cvtsudoers_json.i cvtsudoers_ldif.i \
cvtsudoers_pwutil.i strlist.i
REPLAY_OBJS = getdate.o sudoreplay.o iolog_util.o
REPLAY_OBJS = getdate.o sudoreplay.o
REPLAY_IOBJS = $(REPLAY_OBJS:.o=.i)
@@ -213,16 +214,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_PATH_OBJS = check_iolog_path.o iolog_path.lo locale.lo \
pwutil.lo pwutil_impl.lo redblack.lo sudoers_debug.lo
CHECK_IOLOG_PLUGIN_OBJS = check_iolog_plugin.o iolog.lo iolog_path.lo \
iolog_util.o locale.lo pwutil.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_UTIL_OBJS = check_iolog_util.o iolog_util.o locale.lo \
sudoers_debug.lo
CHECK_SYMBOLS_OBJS = check_symbols.o
CHECK_STARTTIME_OBJS = check_starttime.o starttime.lo sudoers_debug.lo
@@ -272,7 +266,7 @@ Makefile: $(srcdir)/Makefile.in
libparsesudoers.la: $(LIBPARSESUDOERS_OBJS)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(LIBPARSESUDOERS_OBJS) -no-install
sudoers.la: $(SUDOERS_OBJS) $(LT_LIBS) libparsesudoers.la @LT_LDDEP@
sudoers.la: $(SUDOERS_OBJS) $(LIBUTIL) $(LIBIOLOG) 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;; \
@@ -280,59 +274,53 @@ sudoers.la: $(SUDOERS_OBJS) $(LT_LIBS) libparsesudoers.la @LT_LDDEP@
$(LIBTOOL) $(LTFLAGS) @LT_STATIC@ --mode=link $(CC) $(LDFLAGS) $(ASAN_LDFLAGS) $(SSP_LDFLAGS) $(LT_LDFLAGS) -o $@ $(SUDOERS_OBJS) libparsesudoers.la $(SUDOERS_LIBS) -module -avoid-version -rpath $(plugindir) -shrext .so;; \
esac
visudo: libparsesudoers.la $(VISUDO_OBJS) $(LT_LIBS)
visudo: libparsesudoers.la $(VISUDO_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(VISUDO_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) libparsesudoers.la $(LIBS) $(VISUDO_LIBS)
cvtsudoers: libparsesudoers.la $(CVTSUDOERS_OBJS) $(LT_LIBS)
cvtsudoers: libparsesudoers.la $(CVTSUDOERS_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CVTSUDOERS_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) libparsesudoers.la $(LIBS) $(CVTSUDOERS_LIBS)
sudoreplay: timestr.lo $(REPLAY_OBJS) $(LT_LIBS)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(REPLAY_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) timestr.lo $(LIBS) $(REPLAY_LIBS)
sudoreplay: timestr.lo $(REPLAY_OBJS) $(LIBUTIL) $(LIBIOLOG)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(REPLAY_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) timestr.lo $(REPLAY_LIBS)
testsudoers: libparsesudoers.la $(TEST_OBJS) $(LT_LIBS)
testsudoers: libparsesudoers.la $(TEST_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(TEST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) libparsesudoers.la $(LIBS) $(TESTSUDOERS_LIBS)
tsdump: $(TSDUMP_OBJS) $(LT_LIBS)
tsdump: $(TSDUMP_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(TSDUMP_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
check_addr: $(CHECK_ADDR_OBJS) $(LT_LIBS)
check_addr: $(CHECK_ADDR_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_ADDR_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS) $(NET_LIBS)
check_base64: $(CHECK_BASE64_OBJS) $(LT_LIBS)
check_base64: $(CHECK_BASE64_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_BASE64_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
check_digest: $(CHECK_DIGEST_OBJS) $(LT_LIBS)
check_digest: $(CHECK_DIGEST_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_DIGEST_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
check_env_pattern: $(CHECK_ENV_MATCH_OBJS) $(LT_LIBS)
check_env_pattern: $(CHECK_ENV_MATCH_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_ENV_MATCH_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
check_fill: $(CHECK_FILL_OBJS) $(LT_LIBS)
check_fill: $(CHECK_FILL_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_FILL_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
check_gentime: $(CHECK_GENTIME_OBJS) $(LT_LIBS)
check_gentime: $(CHECK_GENTIME_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_GENTIME_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
check_hexchar: $(CHECK_HEXCHAR_OBJS) $(LT_LIBS)
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_path: $(CHECK_IOLOG_PATH_OBJS) $(LT_LIBS)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PATH_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) $(LT_LIBS)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PLUGIN_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS) @ZLIB@
check_iolog_util: $(CHECK_IOLOG_UTIL_OBJS) $(LT_LIBS)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_IOLOG_UTIL_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS) @ZLIB@
check_starttime: $(CHECK_STARTTIME_OBJS) $(LT_LIBS)
check_starttime: $(CHECK_STARTTIME_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_STARTTIME_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
# We need to link check_symbols with -lpthread on HP-UX since LDAP uses threads
check_symbols: $(CHECK_SYMBOLS_OBJS) $(LT_LIBS)
check_symbols: $(CHECK_SYMBOLS_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_SYMBOLS_OBJS) $(CHECK_SYMBOLS_LDFLAGS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS) @SUDO_LIBS@
check_wrap: $(CHECK_WRAP_OBJS) $(LT_LIBS)
check_wrap: $(CHECK_WRAP_OBJS) $(LIBUTIL)
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -o $@ $(CHECK_WRAP_OBJS) $(LDFLAGS) $(ASAN_LDFLAGS) $(PIE_LDFLAGS) $(SSP_LDFLAGS) $(LIBS)
GENERATED = gram.h gram.c toke.c def_data.c def_data.h getdate.c
@@ -472,9 +460,7 @@ check: $(TEST_PROGS) visudo testsudoers cvtsudoers
./check_fill || rval=`expr $$rval + $$?`; \
./check_gentime || rval=`expr $$rval + $$?`; \
./check_hexchar || rval=`expr $$rval + $$?`; \
./check_iolog_path $(srcdir)/regress/iolog_path/data || rval=`expr $$rval + $$?`; \
./check_iolog_plugin $(srcdir)/regress/iolog_plugin/iolog || rval=`expr $$rval + $$?`; \
./check_iolog_util || rval=`expr $$rval + $$?`; \
./check_starttime || rval=`expr $$rval + $$?`; \
if test -f check_symbols; then \
./check_symbols .libs/sudoers.so $(shlib_exp) || rval=`expr $$rval + $$?`; \
@@ -933,72 +919,32 @@ check_hexchar.i: $(srcdir)/regress/parser/check_hexchar.c \
$(CC) -E -o $@ $(CPPFLAGS) $<
check_hexchar.plog: check_hexchar.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/parser/check_hexchar.c --i-file $< --output-file $@
check_iolog_path.o: $(srcdir)/regress/iolog_path/check_iolog_path.c \
$(devdir)/def_data.c $(devdir)/def_data.h \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.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)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/iolog_path/check_iolog_path.c
check_iolog_path.i: $(srcdir)/regress/iolog_path/check_iolog_path.c \
$(devdir)/def_data.c $(devdir)/def_data.h \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.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)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(CC) -E -o $@ $(CPPFLAGS) $<
check_iolog_path.plog: check_iolog_path.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_path/check_iolog_path.c --i-file $< --output-file $@
check_iolog_plugin.o: $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c \
$(devdir)/def_data.c $(devdir)/def_data.h \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.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.h $(srcdir)/iolog_util.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
$(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
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c
check_iolog_plugin.i: $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c \
$(devdir)/def_data.c $(devdir)/def_data.h \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.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.h $(srcdir)/iolog_util.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
$(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
$(CC) -E -o $@ $(CPPFLAGS) $<
check_iolog_plugin.plog: check_iolog_plugin.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_plugin/check_iolog_plugin.c --i-file $< --output-file $@
check_iolog_util.o: $(srcdir)/regress/iolog_util/check_iolog_util.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_util.h \
$(srcdir)/iolog.h $(srcdir)/iolog_util.h \
$(top_builddir)/config.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/regress/iolog_util/check_iolog_util.c
check_iolog_util.i: $(srcdir)/regress/iolog_util/check_iolog_util.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_util.h \
$(srcdir)/iolog.h $(srcdir)/iolog_util.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
check_iolog_util.plog: check_iolog_util.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/regress/iolog_util/check_iolog_util.c --i-file $< --output-file $@
check_starttime.o: $(srcdir)/regress/starttime/check_starttime.c \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_util.h \
@@ -1550,8 +1496,8 @@ interfaces.plog: interfaces.i
iolog.lo: $(srcdir)/iolog.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.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.h $(srcdir)/iolog_files.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
@@ -1559,50 +1505,38 @@ iolog.lo: $(srcdir)/iolog.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
iolog.i: $(srcdir)/iolog.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.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.h $(srcdir)/iolog_files.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
$(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_path.lo: $(srcdir)/iolog_path.c $(devdir)/def_data.h \
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 \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_path.c
iolog_path.i: $(srcdir)/iolog_path.c $(devdir)/def_data.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
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_path_escapes.c
iolog_path_escapes.i: $(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 \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.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
$(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
$(CC) -E -o $@ $(CPPFLAGS) $<
iolog_path.plog: iolog_path.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_path.c --i-file $< --output-file $@
iolog_util.o: $(srcdir)/iolog_util.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/iolog.h \
$(srcdir)/iolog_util.h $(top_builddir)/config.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/iolog_util.c
iolog_util.i: $(srcdir)/iolog_util.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h $(srcdir)/iolog.h \
$(srcdir)/iolog_util.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
iolog_util.plog: iolog_util.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_util.c --i-file $< --output-file $@
iolog_path_escapes.plog: iolog_path_escapes.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/iolog_path_escapes.c --i-file $< --output-file $@
kerb5.lo: $(authdir)/kerb5.c $(devdir)/def_data.h $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
@@ -2365,22 +2299,22 @@ sudoers.lo: $(srcdir)/sudoers.c $(devdir)/def_data.h \
$(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
$(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
$(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(srcdir)/auth/sudo_auth.h $(srcdir)/defaults.h \
$(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
$(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(srcdir)/auth/sudo_auth.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
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/sudoers.c
sudoers.i: $(srcdir)/sudoers.c $(devdir)/def_data.h \
$(incdir)/compat/getaddrinfo.h $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
$(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \
$(incdir)/sudo_gettext.h $(incdir)/sudo_plugin.h \
$(incdir)/sudo_queue.h $(incdir)/sudo_util.h \
$(srcdir)/auth/sudo_auth.h $(srcdir)/defaults.h \
$(srcdir)/logging.h $(srcdir)/parse.h $(srcdir)/sudo_nss.h \
$(srcdir)/sudoers.h $(srcdir)/sudoers_debug.h \
$(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(srcdir)/auth/sudo_auth.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
$(CC) -E -o $@ $(CPPFLAGS) $<
sudoers.plog: sudoers.i
@@ -2411,21 +2345,19 @@ sudoreplay.o: $(srcdir)/sudoreplay.c $(incdir)/compat/getopt.h \
$(incdir)/compat/stdbool.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)/iolog.h \
$(srcdir)/iolog_files.h $(srcdir)/iolog_util.h \
$(srcdir)/logging.h $(top_builddir)/config.h \
$(top_builddir)/pathnames.h
$(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(srcdir)/logging.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/sudoreplay.c
sudoreplay.i: $(srcdir)/sudoreplay.c $(incdir)/compat/getopt.h \
$(incdir)/compat/stdbool.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)/iolog.h \
$(srcdir)/iolog_files.h $(srcdir)/iolog_util.h \
$(srcdir)/logging.h $(top_builddir)/config.h \
$(top_builddir)/pathnames.h
$(incdir)/sudo_gettext.h $(incdir)/sudo_iolog.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(srcdir)/logging.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(CC) -E -o $@ $(CPPFLAGS) $<
sudoreplay.plog: sudoreplay.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/sudoreplay.c --i-file $< --output-file $@

View File

@@ -402,8 +402,8 @@ struct sudo_defs_types sudo_defs_table[] = {
N_("Perform PAM account validation management"),
NULL,
}, {
"maxseq", T_UINT,
N_("Maximum I/O log sequence number: %u"),
"maxseq", T_STR,
N_("Maximum I/O log sequence number: %s"),
NULL,
}, {
"use_netgroups", T_FLAG,

View File

@@ -181,7 +181,7 @@
#define I_PAM_ACCT_MGMT 90
#define def_pam_acct_mgmt (sudo_defs_table[I_PAM_ACCT_MGMT].sd_un.flag)
#define I_MAXSEQ 91
#define def_maxseq (sudo_defs_table[I_MAXSEQ].sd_un.uival)
#define def_maxseq (sudo_defs_table[I_MAXSEQ].sd_un.str)
#define I_USE_NETGROUPS 92
#define def_use_netgroups (sudo_defs_table[I_USE_NETGROUPS].sd_un.flag)
#define I_SUDOEDIT_CHECKDIR 93

View File

@@ -287,8 +287,8 @@ pam_acct_mgmt
T_FLAG
"Perform PAM account validation management"
maxseq
T_UINT
"Maximum I/O log sequence number: %u"
T_STR
"Maximum I/O log sequence number: %s"
use_netgroups
T_FLAG
"Enable sudoers netgroup support"

View File

@@ -42,8 +42,7 @@
#include <grp.h>
#include "sudoers.h"
#include "iolog.h"
#include "iolog_files.h"
#include "sudo_iolog.h"
/* XXX - separate sudoers.h and iolog.h? */
#undef runas_pw
@@ -62,206 +61,29 @@ struct iolog_details {
bool ignore_iolog_errors;
};
static struct iolog_file iolog_files[] = {
{ false }, /* IOFD_STDIN */
{ false }, /* IOFD_STDOUT */
{ false }, /* IOFD_STDERR */
{ false }, /* IOFD_TTYIN */
{ false }, /* IOFD_TTYOUT */
{ true, }, /* IOFD_TIMING */
};
static struct iolog_details iolog_details;
static bool iolog_compress = false;
static bool warned = false;
static struct timespec last_time;
static unsigned int sessid_max = SESSID_MAX;
static mode_t iolog_filemode = S_IRUSR|S_IWUSR;
static mode_t iolog_dirmode = S_IRWXU;
static bool iolog_gid_set;
/* shared with set_perms.c */
uid_t iolog_uid = ROOT_UID;
gid_t iolog_gid = ROOT_GID;
/* sudoers_io is declared at the end of this file. */
extern __dso_public struct io_plugin sudoers_io;
/*
* Create directory and any parent directories as needed.
*/
static bool
io_mkdirs(char *path)
{
struct stat sb;
bool ok, uid_changed = false;
debug_decl(io_mkdirs, SUDOERS_DEBUG_UTIL)
ok = stat(path, &sb) == 0;
if (!ok && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
if (set_perms(PERM_IOLOG)) {
ok = stat(path, &sb) == 0;
if (!restore_perms())
ok = false;
}
}
if (ok) {
if (S_ISDIR(sb.st_mode)) {
if (sb.st_uid != iolog_uid || sb.st_gid != iolog_gid) {
if (chown(path, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to chown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, path);
}
}
if ((sb.st_mode & ALLPERMS) != iolog_dirmode) {
if (chmod(path, iolog_dirmode) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to chmod 0%o %s", __func__,
(int)iolog_dirmode, path);
}
}
} else {
sudo_warnx(U_("%s exists but is not a directory (0%o)"),
path, (unsigned int) sb.st_mode);
ok = false;
}
goto done;
}
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (!ok && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
uid_changed = set_perms(PERM_IOLOG);
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
}
if (ok) {
/* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o", path, (unsigned int) iolog_dirmode);
ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST;
if (!ok) {
if (errno == EACCES && !uid_changed) {
/* Try again as the I/O log owner (for NFS). */
uid_changed = set_perms(PERM_IOLOG);
ok = mkdir(path, iolog_dirmode) == 0 || errno == EEXIST;
}
if (!ok)
sudo_warn(U_("unable to mkdir %s"), path);
} else {
if (chown(path, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to chown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, path);
}
}
}
if (uid_changed) {
if (!restore_perms())
ok = false;
}
done:
debug_return_bool(ok);
}
/*
* Create temporary directory and any parent directories as needed.
*/
static bool
io_mkdtemp(char *path)
{
bool ok, uid_changed = false;
debug_decl(io_mkdtemp, SUDOERS_DEBUG_UTIL)
ok = sudo_mkdir_parents(path, iolog_uid, iolog_gid, iolog_dirmode, true);
if (!ok && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
uid_changed = set_perms(PERM_IOLOG);
ok = sudo_mkdir_parents(path, -1, -1, iolog_dirmode, false);
}
if (ok) {
/* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdtemp %s", path);
/* We cannot retry mkdtemp() so always use PERM_IOLOG */
if (!uid_changed)
uid_changed = set_perms(PERM_IOLOG);
if (mkdtemp(path) == NULL) {
sudo_warn(U_("unable to mkdir %s"), path);
ok = false;
} else {
if (chmod(path, iolog_dirmode) != 0) {
sudo_warn(U_("unable to change mode of %s to 0%o"),
path, (unsigned int)iolog_dirmode);
}
}
}
if (uid_changed) {
if (!restore_perms())
ok = false;
}
debug_return_bool(ok);
}
/*
* Set max session ID (aka sequence number)
*/
static bool
io_set_max_sessid(const char *maxval)
{
const char *errstr;
unsigned int value;
debug_decl(io_set_max_sessid, SUDOERS_DEBUG_UTIL)
value = sudo_strtonum(maxval, 0, SESSID_MAX, &errstr);
if (errstr != NULL) {
if (errno != ERANGE) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"bad maxseq: %s: %s", maxval, errstr);
debug_return_bool(false);
}
/* Out of range, clamp to SESSID_MAX as documented. */
value = SESSID_MAX;
}
sessid_max = value;
debug_return_bool(true);
}
/*
* Sudoers callback for maxseq Defaults setting.
*/
bool
cb_maxseq(const union sudo_defs_val *sd_un)
{
debug_decl(cb_maxseq, SUDOERS_DEBUG_UTIL)
/* Clamp value to SESSID_MAX as documented. */
sessid_max = sd_un->uival < SESSID_MAX ? sd_un->uival : SESSID_MAX;
debug_return_bool(true);
}
/*
* Look up I/O log user-ID from user name. Sets iolog_uid.
* Also sets iolog_gid if iolog_group not specified.
*/
static bool
iolog_set_user(const char *name)
{
struct passwd *pw;
debug_decl(iolog_set_user, SUDOERS_DEBUG_UTIL)
if (name != NULL) {
pw = sudo_getpwnam(name);
if (pw != NULL) {
iolog_uid = pw->pw_uid;
if (!iolog_gid_set)
iolog_gid = pw->pw_gid;
sudo_pw_delref(pw);
} else {
log_warningx(SLOG_SEND_MAIL,
N_("unknown user: %s"), name);
}
} else {
/* Reset to default. */
iolog_uid = ROOT_UID;
if (!iolog_gid_set)
iolog_gid = ROOT_GID;
}
debug_return_bool(true);
return iolog_set_maxseq(sd_un->str);
}
/*
@@ -270,36 +92,23 @@ iolog_set_user(const char *name)
bool
cb_iolog_user(const union sudo_defs_val *sd_un)
{
return iolog_set_user(sd_un->str);
}
/*
* Look up I/O log group-ID from group name.
* Sets iolog_gid.
*/
static bool
iolog_set_group(const char *name)
{
struct group *gr;
debug_decl(iolog_set_group, SUDOERS_DEBUG_UTIL)
const char *name = sd_un->str;
struct passwd *pw = NULL;
bool ret;
debug_decl(cb_iolog_user, SUDOERS_DEBUG_UTIL)
/* NULL name means reset to default. */
if (name != NULL) {
gr = sudo_getgrnam(name);
if (gr != NULL) {
iolog_gid = gr->gr_gid;
iolog_gid_set = true;
sudo_gr_delref(gr);
} else {
log_warningx(SLOG_SEND_MAIL,
N_("unknown group: %s"), name);
if ((pw = sudo_getpwnam(name)) == NULL) {
log_warningx(SLOG_SEND_MAIL, N_("unknown user: %s"), name);
debug_return_bool(false);
}
} else {
/* Reset to default. */
iolog_gid = ROOT_GID;
iolog_gid_set = false;
}
ret = iolog_set_user(pw);
if (pw != NULL)
sudo_pw_delref(pw);
debug_return_bool(true);
debug_return_bool(ret);
}
/*
@@ -308,31 +117,23 @@ iolog_set_group(const char *name)
bool
cb_iolog_group(const union sudo_defs_val *sd_un)
{
return iolog_set_group(sd_un->str);
}
const char *name = sd_un->str;
struct group *gr = NULL;
bool ret;
debug_decl(cb_iolog_group, SUDOERS_DEBUG_UTIL)
/*
* Set iolog_filemode and iolog_dirmode.
*/
static bool
iolog_set_mode(mode_t mode)
{
debug_decl(iolog_set_mode, SUDOERS_DEBUG_UTIL)
/* NULL name means reset to default. */
if (name != NULL) {
if ((gr = sudo_getgrnam(name)) == NULL) {
log_warningx(SLOG_SEND_MAIL, N_("unknown group: %s"), name);
debug_return_bool(false);
}
}
ret = iolog_set_group(gr);
if (gr != NULL)
sudo_gr_delref(gr);
/* I/O log files must be readable and writable by owner. */
iolog_filemode = S_IRUSR|S_IWUSR;
/* Add in group and other read/write if specified. */
iolog_filemode |= mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
/* For directory mode, add execute bits as needed. */
iolog_dirmode = iolog_filemode | S_IXUSR;
if (iolog_dirmode & (S_IRGRP|S_IWGRP))
iolog_dirmode |= S_IXGRP;
if (iolog_dirmode & (S_IROTH|S_IWOTH))
iolog_dirmode |= S_IXOTH;
debug_return_bool(true);
debug_return_bool(ret);
}
/*
@@ -344,248 +145,6 @@ cb_iolog_mode(const union sudo_defs_val *sd_un)
return iolog_set_mode(sd_un->mode);
}
/*
* Wrapper for open(2) that retries with PERM_IOLOG if open(2)
* returns EACCES.
*/
static int
io_open(const char *path, int flags, mode_t perm)
{
int fd;
debug_decl(io_open, SUDOERS_DEBUG_UTIL)
fd = open(path, flags, perm);
if (fd == -1 && errno == EACCES) {
/* Try again as the I/O log owner (for NFS). */
if (set_perms(PERM_IOLOG)) {
fd = open(path, flags, perm);
if (!restore_perms()) {
/* restore_perms() warns on error. */
if (fd != -1) {
close(fd);
fd = -1;
}
}
}
}
debug_return_int(fd);
}
/*
* Read the on-disk sequence number, set sessid to the next
* number, and update the on-disk copy.
* Uses file locking to avoid sequence number collisions.
*/
bool
io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7])
{
struct stat sb;
char buf[32], *ep;
int i, len, fd = -1;
unsigned long id = 0;
mode_t omask;
ssize_t nread;
bool ret = false;
char pathbuf[PATH_MAX];
static const char b36char[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
debug_decl(io_nextid, SUDOERS_DEBUG_UTIL)
/* umask must not be more restrictive than the file modes. */
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
/*
* Create I/O log directory if it doesn't already exist.
*/
if (!io_mkdirs(iolog_dir))
goto done;
/*
* Open sequence file
*/
len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", iolog_dir);
if (len < 0 || len >= ssizeof(pathbuf)) {
errno = ENAMETOOLONG;
log_warning(SLOG_SEND_MAIL, "%s/seq", pathbuf);
goto done;
}
fd = io_open(pathbuf, O_RDWR|O_CREAT, iolog_filemode);
if (fd == -1) {
log_warning(SLOG_SEND_MAIL, N_("unable to open %s"), pathbuf);
goto done;
}
sudo_lock_file(fd, SUDO_LOCK);
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to fchown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, pathbuf);
}
/*
* If there is no seq file in iolog_dir and a fallback dir was
* specified, look for seq in the fallback dir. This is to work
* around a bug in sudo 1.8.5 and older where iolog_dir was not
* expanded before the sequence number was updated.
*/
if (iolog_dir_fallback != NULL && fstat(fd, &sb) == 0 && sb.st_size == 0) {
char fallback[PATH_MAX];
len = snprintf(fallback, sizeof(fallback), "%s/seq",
iolog_dir_fallback);
if (len > 0 && len < ssizeof(fallback)) {
int fd2 = io_open(fallback, O_RDWR|O_CREAT, iolog_filemode);
if (fd2 != -1) {
if (fchown(fd2, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to fchown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, fallback);
}
nread = read(fd2, buf, sizeof(buf) - 1);
if (nread > 0) {
if (buf[nread - 1] == '\n')
nread--;
buf[nread] = '\0';
id = strtoul(buf, &ep, 36);
if (ep == buf || *ep != '\0' || id >= sessid_max) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: bad sequence number: %s", fallback, buf);
id = 0;
}
}
close(fd2);
}
}
}
/* Read current seq number (base 36). */
if (id == 0) {
nread = read(fd, buf, sizeof(buf) - 1);
if (nread != 0) {
if (nread == -1) {
log_warning(SLOG_SEND_MAIL, N_("unable to read %s"), pathbuf);
goto done;
}
if (buf[nread - 1] == '\n')
nread--;
buf[nread] = '\0';
id = strtoul(buf, &ep, 36);
if (ep == buf || *ep != '\0' || id >= sessid_max) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: bad sequence number: %s", pathbuf, buf);
id = 0;
}
}
}
id++;
/*
* Convert id to a string and stash in sessid.
* Note that that least significant digits go at the end of the string.
*/
for (i = 5; i >= 0; i--) {
buf[i] = b36char[id % 36];
id /= 36;
}
buf[6] = '\n';
/* Stash id for logging purposes. */
memcpy(sessid, buf, 6);
sessid[6] = '\0';
/* Rewind and overwrite old seq file, including the NUL byte. */
#ifdef HAVE_PWRITE
if (pwrite(fd, buf, 7, 0) != 7) {
#else
if (lseek(fd, 0, SEEK_SET) == -1 || write(fd, buf, 7) != 7) {
#endif
log_warning(SLOG_SEND_MAIL, N_("unable to write to %s"), pathbuf);
warned = true;
goto done;
}
ret = true;
done:
umask(omask);
if (fd != -1)
close(fd);
debug_return_bool(ret);
}
/*
* Copy iolog_path to pathbuf and create the directory and any intermediate
* directories. If iolog_path ends in 'XXXXXX', use mkdtemp().
* Returns SIZE_MAX on error.
*/
static size_t
mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize)
{
size_t len;
bool ok;
debug_decl(mkdir_iopath, SUDOERS_DEBUG_UTIL)
len = strlcpy(pathbuf, iolog_path, pathsize);
if (len >= pathsize) {
errno = ENAMETOOLONG;
log_warning(SLOG_SEND_MAIL, "%s", iolog_path);
debug_return_size_t((size_t)-1);
}
/*
* Create path and intermediate subdirs as needed.
* If path ends in at least 6 Xs (ala POSIX mktemp), use mkdtemp().
* Sets iolog_gid (if it is not already set) as a side effect.
*/
if (len >= 6 && strcmp(&pathbuf[len - 6], "XXXXXX") == 0)
ok = io_mkdtemp(pathbuf);
else
ok = io_mkdirs(pathbuf);
debug_return_size_t(ok ? len : (size_t)-1);
}
/*
* Append suffix to pathbuf after len chars and open the resulting file.
* Note that the size of pathbuf is assumed to be PATH_MAX.
* Uses zlib if docompress is true.
* Stores the open file handle which has the close-on-exec flag set.
*/
static bool
open_io_fd(char *pathbuf, size_t len, struct io_log_file *iol, bool docompress)
{
debug_decl(open_io_fd, SUDOERS_DEBUG_UTIL)
pathbuf[len] = '\0';
strlcat(pathbuf, iol->suffix, PATH_MAX);
if (iol->enabled) {
int fd = io_open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, iolog_filemode);
if (fd != -1) {
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to fchown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, pathbuf);
}
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
#ifdef HAVE_ZLIB_H
if (docompress)
iol->fd.g = gzdopen(fd, "w");
else
#endif
iol->fd.f = fdopen(fd, "w");
if (iol->fd.v == NULL) {
close(fd);
fd = -1;
}
}
if (fd == -1) {
log_warning(SLOG_SEND_MAIL, N_("unable to create %s"), pathbuf);
debug_return_bool(false);
}
} else {
/* Remove old log file if we recycled sequence numbers. */
unlink(pathbuf);
}
debug_return_bool(true);
}
/*
* Pull out I/O log related data from user_info and command_info arrays.
* Returns true if I/O logging is enabled, else false.
@@ -666,52 +225,81 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
}
if (strncmp(*cur, "iolog_stdin=", sizeof("iolog_stdin=") - 1) == 0) {
if (sudo_strtobool(*cur + sizeof("iolog_stdin=") - 1) == true)
io_log_files[IOFD_STDIN].enabled = true;
iolog_files[IOFD_STDIN].enabled = true;
continue;
}
if (strncmp(*cur, "iolog_stdout=", sizeof("iolog_stdout=") - 1) == 0) {
if (sudo_strtobool(*cur + sizeof("iolog_stdout=") - 1) == true)
io_log_files[IOFD_STDOUT].enabled = true;
iolog_files[IOFD_STDOUT].enabled = true;
continue;
}
if (strncmp(*cur, "iolog_stderr=", sizeof("iolog_stderr=") - 1) == 0) {
if (sudo_strtobool(*cur + sizeof("iolog_stderr=") - 1) == true)
io_log_files[IOFD_STDERR].enabled = true;
iolog_files[IOFD_STDERR].enabled = true;
continue;
}
if (strncmp(*cur, "iolog_ttyin=", sizeof("iolog_ttyin=") - 1) == 0) {
if (sudo_strtobool(*cur + sizeof("iolog_ttyin=") - 1) == true)
io_log_files[IOFD_TTYIN].enabled = true;
iolog_files[IOFD_TTYIN].enabled = true;
continue;
}
if (strncmp(*cur, "iolog_ttyout=", sizeof("iolog_ttyout=") - 1) == 0) {
if (sudo_strtobool(*cur + sizeof("iolog_ttyout=") - 1) == true)
io_log_files[IOFD_TTYOUT].enabled = true;
iolog_files[IOFD_TTYOUT].enabled = true;
continue;
}
if (strncmp(*cur, "iolog_compress=", sizeof("iolog_compress=") - 1) == 0) {
if (sudo_strtobool(*cur + sizeof("iolog_compress=") - 1) == true)
iolog_compress = true; /* must be global */
if (!iolog_set_compress(*cur + sizeof("iolog_compress=") - 1)) {
sudo_debug_printf(SUDO_DEBUG_WARN,
"%s: unable to parse %s", __func__, *cur);
}
continue;
}
if (strncmp(*cur, "iolog_flush=", sizeof("iolog_flush=") - 1) == 0) {
if (!iolog_set_flush(*cur + sizeof("iolog_flush=") - 1)) {
sudo_debug_printf(SUDO_DEBUG_WARN,
"%s: unable to parse %s", __func__, *cur);
}
continue;
}
if (strncmp(*cur, "iolog_mode=", sizeof("iolog_mode=") - 1) == 0) {
mode_t mode = sudo_strtomode(*cur + sizeof("iolog_mode=") - 1, &errstr);
if (errstr == NULL)
if (errstr == NULL) {
iolog_set_mode(mode);
} else {
sudo_debug_printf(SUDO_DEBUG_WARN,
"%s: unable to parse %s", __func__, *cur);
}
continue;
}
if (strncmp(*cur, "iolog_group=", sizeof("iolog_group=") - 1) == 0) {
iolog_set_group(*cur + sizeof("iolog_group=") - 1);
struct group *gr =
sudo_getgrnam(*cur + sizeof("iolog_group=") - 1);
if (gr == NULL) {
sudo_debug_printf(SUDO_DEBUG_WARN, "%s: unknown group %s",
__func__, *cur + sizeof("iolog_group=") - 1);
} else {
iolog_set_group(gr);
sudo_gr_delref(gr);
}
continue;
}
if (strncmp(*cur, "iolog_user=", sizeof("iolog_user=") - 1) == 0) {
iolog_set_user(*cur + sizeof("iolog_user=") - 1);
struct passwd *pw =
sudo_getpwnam(*cur + sizeof("iolog_user=") - 1);
if (pw == NULL) {
sudo_debug_printf(SUDO_DEBUG_WARN, "%s: unknown user %s",
__func__, *cur + sizeof("iolog_user=") - 1);
} else {
iolog_set_user(pw);
sudo_pw_delref(pw);
}
continue;
}
break;
case 'm':
if (strncmp(*cur, "maxseq=", sizeof("maxseq=") - 1) == 0) {
io_set_max_sessid(*cur + sizeof("maxseq=") - 1);
iolog_set_maxseq(*cur + sizeof("maxseq=") - 1);
continue;
}
break;
@@ -774,9 +362,9 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[],
}
}
debug_return_bool(
io_log_files[IOFD_STDIN].enabled || io_log_files[IOFD_STDOUT].enabled ||
io_log_files[IOFD_STDERR].enabled || io_log_files[IOFD_TTYIN].enabled ||
io_log_files[IOFD_TTYOUT].enabled);
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);
}
/*
@@ -787,97 +375,28 @@ static bool
write_info_log(char *pathbuf, size_t len, struct iolog_details *details,
char * const argv[])
{
time_t now;
char * const *av;
FILE *fp;
int fd;
bool ret = true;
struct iolog_info iolog_info;
debug_decl(write_info_log, SUDOERS_DEBUG_UTIL)
/* XXX - just use iolog_info in the first place? */
time(&iolog_info.tstamp);
iolog_info.user = (char *)details->user;
iolog_info.runas_user = details->runas_pw->pw_name;
iolog_info.runas_group = details->runas_gr ? details->runas_gr->gr_name: NULL;
iolog_info.tty = (char *)details->tty;
iolog_info.cwd = (char *)details->cwd;
iolog_info.cmd = (char *)details->command;
iolog_info.lines = details->lines;
iolog_info.cols = details->cols;
pathbuf[len] = '\0';
strlcat(pathbuf, "/log", PATH_MAX);
fd = io_open(pathbuf, O_CREAT|O_TRUNC|O_WRONLY, iolog_filemode);
if (fd == -1 || (fp = fdopen(fd, "w")) == NULL) {
log_warning(SLOG_SEND_MAIL, N_("unable to create %s"), pathbuf);
debug_return_bool(false);
}
if (fchown(fd, iolog_uid, iolog_gid) != 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
"%s: unable to fchown %d:%d %s", __func__,
(int)iolog_uid, (int)iolog_gid, pathbuf);
}
fprintf(fp, "%lld:%s:%s:%s:%s:%d:%d\n%s\n%s", (long long)time(&now),
details->user ? details->user : "unknown", details->runas_pw->pw_name,
details->runas_gr ? details->runas_gr->gr_name : "",
details->tty ? details->tty : "unknown", details->lines, details->cols,
details->cwd ? details->cwd : "unknown",
details->command ? details->command : "unknown");
for (av = argv + 1; *av != NULL; av++) {
fputc(' ', fp);
fputs(*av, fp);
}
fputc('\n', fp);
fflush(fp);
if (ferror(fp)) {
if (!iolog_write_info_file(pathbuf, &iolog_info, argv)) {
log_warning(SLOG_SEND_MAIL,
N_("unable to write to I/O log file: %s"), strerror(errno));
warned = true;
ret = false;
debug_return_bool(false);
}
fclose(fp);
debug_return_bool(ret);
}
#ifdef HAVE_ZLIB_H
static const char *
gzstrerror(gzFile file)
{
int errnum;
return gzerror(file, &errnum);
}
#endif /* HAVE_ZLIB_H */
/*
* Write to an I/O log, compressing if iolog_compress is enabled.
* If def_iolog_flush is true, flush the buffer immediately.
*/
static const char *
iolog_write(union io_fd ifd, const void *buf, unsigned int len)
{
const char *errstr = NULL;
debug_decl(iolog_write, SUDOERS_DEBUG_PLUGIN)
#ifdef HAVE_ZLIB_H
if (iolog_compress) {
if (gzwrite(ifd.g, (const voidp)buf, len) != (int)len) {
errstr = gzstrerror(ifd.g);
goto done;
}
if (def_iolog_flush) {
if (gzflush(ifd.g, Z_SYNC_FLUSH) != Z_OK) {
errstr = gzstrerror(ifd.g);
goto done;
}
}
} else
#endif
{
if (fwrite(buf, 1, len, ifd.f) != len) {
errstr = strerror(errno);
goto done;
}
if (def_iolog_flush) {
if (fflush(ifd.f) != 0) {
errstr = strerror(errno);
goto done;
}
}
}
done:
debug_return_const_str(errstr);
debug_return_bool(true);
}
static int
@@ -892,7 +411,6 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
char * const *cur;
const char *cp, *plugin_path = NULL;
size_t len;
mode_t omask;
int i, ret = -1;
debug_decl(sudoers_io_open, SUDOERS_DEBUG_PLUGIN)
@@ -919,9 +437,6 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
}
}
/* umask must not be more restrictive than the file modes. */
omask = umask(ACCESSPERMS & ~(iolog_filemode|iolog_dirmode));
if (!sudoers_debug_register(plugin_path, &debug_files)) {
ret = -1;
goto done;
@@ -944,7 +459,8 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
goto done;
}
memcpy(tofree, _PATH_SUDO_IO_LOGDIR, sizeof(_PATH_SUDO_IO_LOGDIR));
if (!io_nextid(tofree, NULL, sessid)) {
if (!iolog_nextid(tofree, sessid)) {
log_warning(SLOG_SEND_MAIL, N_("unable to update sequence file"));
ret = false;
goto done;
}
@@ -959,8 +475,10 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
* intermediate subdirs. Calls mkdtemp() if iolog_path ends in XXXXXX.
*/
len = mkdir_iopath(iolog_details.iolog_path, pathbuf, sizeof(pathbuf));
if (len >= sizeof(pathbuf))
if (len >= sizeof(pathbuf)) {
log_warning(SLOG_SEND_MAIL, "%s", iolog_details.iolog_path);
goto done;
}
/* Write log file with user and command details. */
if (!write_info_log(pathbuf, len, &iolog_details, argv))
@@ -968,22 +486,31 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
/* Create the timing and I/O log files. */
for (i = 0; i < IOFD_MAX; i++) {
if (!open_io_fd(pathbuf, len, &io_log_files[i], iolog_compress))
pathbuf[len] = '/';
pathbuf[len + 1] = '\0';
if (strlcat(pathbuf, iolog_fd_to_name(i), sizeof(pathbuf)) >= sizeof(pathbuf)) {
errno = ENAMETOOLONG;
log_warning(SLOG_SEND_MAIL, N_("unable to create %s"), pathbuf);
goto done;
}
if (!iolog_open(&iolog_files[i], pathbuf, "w")) {
log_warning(SLOG_SEND_MAIL, N_("unable to create %s"), pathbuf);
goto done;
}
}
/*
* Clear I/O log function pointers for disabled log functions.
*/
if (!io_log_files[IOFD_STDIN].enabled)
if (!iolog_files[IOFD_STDIN].enabled)
sudoers_io.log_stdin = NULL;
if (!io_log_files[IOFD_STDOUT].enabled)
if (!iolog_files[IOFD_STDOUT].enabled)
sudoers_io.log_stdout = NULL;
if (!io_log_files[IOFD_STDERR].enabled)
if (!iolog_files[IOFD_STDERR].enabled)
sudoers_io.log_stderr = NULL;
if (!io_log_files[IOFD_TTYIN].enabled)
if (!iolog_files[IOFD_TTYIN].enabled)
sudoers_io.log_ttyin = NULL;
if (!io_log_files[IOFD_TTYOUT].enabled)
if (!iolog_files[IOFD_TTYOUT].enabled)
sudoers_io.log_ttyout = NULL;
if (sudo_gettime_awake(&last_time) == -1) {
@@ -995,7 +522,6 @@ sudoers_io_open(unsigned int version, sudo_conv_t conversation,
ret = true;
done:
umask(omask);
free(tofree);
if (iolog_details.runas_pw)
sudo_pw_delref(iolog_details.runas_pw);
@@ -1019,18 +545,9 @@ sudoers_io_close(int exit_status, int error)
debug_decl(sudoers_io_close, SUDOERS_DEBUG_PLUGIN)
for (i = 0; i < IOFD_MAX; i++) {
if (io_log_files[i].fd.v == NULL)
if (iolog_files[i].fd.v == NULL)
continue;
#ifdef HAVE_ZLIB_H
if (iolog_compress) {
int errnum;
if (gzclose(io_log_files[i].fd.g) != Z_OK)
errstr = gzerror(io_log_files[i].fd.g, &errnum);
} else
#endif
if (fclose(io_log_files[i].fd.f) != 0)
errstr = strerror(errno);
iolog_close(&iolog_files[i], &errstr);
}
if (errstr != NULL && !warned) {
@@ -1061,7 +578,8 @@ sudoers_io_version(int verbose)
* Returns 1 on success and -1 on error.
*/
static int
sudoers_io_log(union io_fd ifd, const char *buf, unsigned int len, int event)
sudoers_io_log(struct iolog_file *iol, const char *buf, unsigned int len,
int event)
{
struct timespec now, delay;
char tbuf[1024];
@@ -1069,7 +587,7 @@ sudoers_io_log(union io_fd ifd, const char *buf, unsigned int len, int event)
int ret = -1;
debug_decl(sudoers_io_log, SUDOERS_DEBUG_PLUGIN)
if (ifd.v == NULL) {
if (!iol->enabled) {
sudo_warnx(U_("%s: internal error, I/O log file for event %d not open"),
__func__, event);
debug_return_int(-1);
@@ -1083,8 +601,7 @@ sudoers_io_log(union io_fd ifd, const char *buf, unsigned int len, int event)
}
/* Write I/O log file entry. */
errstr = iolog_write(ifd, buf, len);
if (errstr != NULL)
if (iolog_write(iol, buf, len, &errstr) == -1)
goto done;
/* Write timing file entry. */
@@ -1096,8 +613,7 @@ sudoers_io_log(union io_fd ifd, const char *buf, unsigned int len, int event)
errstr = strerror(EOVERFLOW);
goto done;
}
errstr = iolog_write(io_log_files[IOFD_TIMING].fd, tbuf, len);
if (errstr != NULL)
if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, &errstr) == -1)
goto done;
/* Success. */
@@ -1127,41 +643,31 @@ bad:
static int
sudoers_io_log_stdin(const char *buf, unsigned int len)
{
const union io_fd ifd = io_log_files[IOFD_STDIN].fd;
return sudoers_io_log(ifd, buf, len, IO_EVENT_STDIN);
return sudoers_io_log(&iolog_files[IOFD_STDIN], buf, len, IO_EVENT_STDIN);
}
static int
sudoers_io_log_stdout(const char *buf, unsigned int len)
{
const union io_fd ifd = io_log_files[IOFD_STDOUT].fd;
return sudoers_io_log(ifd, buf, len, IO_EVENT_STDOUT);
return sudoers_io_log(&iolog_files[IOFD_STDOUT], buf, len, IO_EVENT_STDOUT);
}
static int
sudoers_io_log_stderr(const char *buf, unsigned int len)
{
const union io_fd ifd = io_log_files[IOFD_STDERR].fd;
return sudoers_io_log(ifd, buf, len, IO_EVENT_STDERR);
return sudoers_io_log(&iolog_files[IOFD_STDERR], buf, len, IO_EVENT_STDERR);
}
static int
sudoers_io_log_ttyin(const char *buf, unsigned int len)
{
const union io_fd ifd = io_log_files[IOFD_TTYIN].fd;
return sudoers_io_log(ifd, buf, len, IO_EVENT_TTYIN);
return sudoers_io_log(&iolog_files[IOFD_TTYIN], buf, len, IO_EVENT_TTYIN);
}
static int
sudoers_io_log_ttyout(const char *buf, unsigned int len)
{
const union io_fd ifd = io_log_files[IOFD_TTYOUT].fd;
return sudoers_io_log(ifd, buf, len, IO_EVENT_TTYOUT);
return sudoers_io_log(&iolog_files[IOFD_TTYOUT], buf, len, IO_EVENT_TTYOUT);
}
static int
@@ -1190,8 +696,7 @@ sudoers_io_change_winsize(unsigned int lines, unsigned int cols)
errstr = strerror(EOVERFLOW);
goto done;
}
errstr = iolog_write(io_log_files[IOFD_TIMING].fd, tbuf, len);
if (errstr != NULL)
if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, &errstr) == -1)
goto done;
/* Success. */
@@ -1251,8 +756,7 @@ sudoers_io_suspend(int signo)
errstr = strerror(EOVERFLOW);
goto done;
}
errstr = iolog_write(io_log_files[IOFD_TIMING].fd, tbuf, len);
if (errstr != NULL)
if (iolog_write(&iolog_files[IOFD_TIMING], tbuf, len, &errstr) == -1)
goto done;
/* Success. */

View File

@@ -1,51 +0,0 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2009-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.
*/
#ifndef SUDOERS_IOLOG_H
#define SUDOERS_IOLOG_H
#ifdef HAVE_ZLIB_H
# include <zlib.h> /* for gzFile */
#endif
/*
* I/O log event types as stored as the first field in the timing file.
* Changing existing values will result in incompatible I/O log files.
*/
#define IO_EVENT_STDIN 0
#define IO_EVENT_STDOUT 1
#define IO_EVENT_STDERR 2
#define IO_EVENT_TTYIN 3
#define IO_EVENT_TTYOUT 4
#define IO_EVENT_WINSIZE 5
#define IO_EVENT_TTYOUT_1_8_7 6
#define IO_EVENT_SUSPEND 7
#define IO_EVENT_COUNT 8
/* Default maximum session ID */
#define SESSID_MAX 2176782336U
union io_fd {
FILE *f;
#ifdef HAVE_ZLIB_H
gzFile g;
#endif
void *v;
};
#endif /* SUDOERS_IOLOG_H */

View File

@@ -1,49 +0,0 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2013 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.
*/
#ifndef SUDOERS_IOLOG_FILES_H
#define SUDOERS_IOLOG_FILES_H
/*
* Indexes into io_log_files[]
*/
#define IOFD_STDIN 0
#define IOFD_STDOUT 1
#define IOFD_STDERR 2
#define IOFD_TTYIN 3
#define IOFD_TTYOUT 4
#define IOFD_TIMING 5
#define IOFD_MAX 6
struct io_log_file {
bool enabled;
const char *suffix;
union io_fd fd;
};
static struct io_log_file io_log_files[] = {
{ false, "/stdin" }, /* IOFD_STDIN */
{ false, "/stdout" }, /* IOFD_STDOUT */
{ false, "/stderr" }, /* IOFD_STDERR */
{ false, "/ttyin" }, /* IOFD_TTYIN */
{ false, "/ttyout" }, /* IOFD_TTYOUT */
{ true, "/timing" }, /* IOFD_TIMING */
{ false, NULL } /* IOFD_MAX */
};
#endif /* SUDOERS_IOLOG_H */

View File

@@ -0,0 +1,148 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2011-2015 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.
*/
/*
* 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>
#ifdef HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include <pwd.h>
#include <grp.h>
#include <limits.h>
#include <time.h>
#include <unistd.h>
#include "sudoers.h"
#include "sudo_iolog.h"
static size_t
fill_seq(char *str, size_t strsize, char *logdir)
{
#ifdef SUDOERS_NO_SEQ
debug_decl(fill_seq, SUDO_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, "%{seq}", strsize));
#else
static char sessid[7];
int len;
debug_decl(fill_seq, SUDO_DEBUG_UTIL)
if (sessid[0] == '\0') {
if (!iolog_nextid(logdir, sessid))
debug_return_size_t((size_t)-1);
}
/* Path is of the form /var/log/sudo-io/00/00/01. */
len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0],
sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]);
if (len < 0)
debug_return_size_t(strsize); /* handle non-standard snprintf() */
debug_return_size_t(len);
#endif /* SUDOERS_NO_SEQ */
}
static size_t
fill_user(char *str, size_t strsize, char *unused)
{
debug_decl(fill_user, SUDO_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, user_name, strsize));
}
static size_t
fill_group(char *str, size_t strsize, char *unused)
{
struct group *grp;
size_t len;
debug_decl(fill_group, SUDO_DEBUG_UTIL)
if ((grp = sudo_getgrgid(user_gid)) != NULL) {
len = strlcpy(str, grp->gr_name, strsize);
sudo_gr_delref(grp);
} else {
len = strlen(str);
len = snprintf(str + len, strsize - len, "#%u",
(unsigned int) user_gid);
}
debug_return_size_t(len);
}
static size_t
fill_runas_user(char *str, size_t strsize, char *unused)
{
debug_decl(fill_runas_user, SUDO_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, runas_pw->pw_name, strsize));
}
static size_t
fill_runas_group(char *str, size_t strsize, char *unused)
{
struct group *grp;
size_t len;
debug_decl(fill_runas_group, SUDO_DEBUG_UTIL)
if (runas_gr != NULL) {
len = strlcpy(str, runas_gr->gr_name, strsize);
} else {
if ((grp = sudo_getgrgid(runas_pw->pw_gid)) != NULL) {
len = strlcpy(str, grp->gr_name, strsize);
sudo_gr_delref(grp);
} else {
len = strlen(str);
len = snprintf(str + len, strsize - len, "#%u",
(unsigned int) runas_pw->pw_gid);
}
}
debug_return_size_t(len);
}
static size_t
fill_hostname(char *str, size_t strsize, char *unused)
{
debug_decl(fill_hostname, SUDO_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, user_shost, strsize));
}
static size_t
fill_command(char *str, size_t strsize, char *unused)
{
debug_decl(fill_command, SUDO_DEBUG_UTIL)
debug_return_size_t(strlcpy(str, user_base, strsize));
}
/* Note: "seq" must be first in the list. */
static const struct iolog_path_escape path_escapes[] = {
{ "seq", fill_seq },
{ "user", fill_user },
{ "group", fill_group },
{ "runas_user", fill_runas_user },
{ "runas_group", fill_runas_group },
{ "hostname", fill_hostname },
{ "command", fill_command },
{ NULL, NULL }
};
const struct iolog_path_escape *sudoers_iolog_path_escapes = path_escapes;

View File

@@ -1,61 +0,0 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2009-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.
*/
#ifndef SUDOERS_IOLOG_READER_H
#define SUDOERS_IOLOG_READER_H
#include "iolog.h"
/*
* Info present in the I/O log file
*/
struct iolog_info {
char *cwd;
char *user;
char *runas_user;
char *runas_group;
char *tty;
char *cmd;
time_t tstamp;
int lines;
int cols;
};
struct timing_closure {
struct timespec delay;
const char *decimal;
union io_fd fd;
int event;
union {
struct {
int lines;
int cols;
} winsize;
size_t nbytes; // XXX
int signo;
} u;
};
/* iolog_reader.c */
bool parse_timing(const char *line, struct timing_closure *timing);
char *parse_delay(const char *cp, struct timespec *delay, const char *decimal_point);
struct iolog_info *parse_logfile(const char *logfile);
void free_iolog_info(struct iolog_info *li);
void adjust_delay(struct timespec *delay, struct timespec *max_delay, double scale_factor);
#endif /* SUDOERS_IOLOG_READER_H */

View File

@@ -550,8 +550,12 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask,
if ((command_info[info_len++] = strdup("iolog_compress=true")) == NULL)
goto oom;
}
if (def_maxseq) {
if (asprintf(&command_info[info_len++], "maxseq=%u", def_maxseq) == -1)
if (def_iolog_flush) {
if ((command_info[info_len++] = strdup("iolog_flush=true")) == NULL)
goto oom;
}
if (def_maxseq != NULL) {
if (asprintf(&command_info[info_len++], "maxseq=%s", def_maxseq) == -1)
goto oom;
}
}

View File

@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2018 Todd C. Miller <Todd.Miller@sudo.ws>
* Copyright (c) 2018-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
@@ -37,7 +37,7 @@
#include "sudoers.h"
#include "def_data.c" /* for iolog_path.c */
#include "sudo_plugin.h"
#include "iolog_util.h"
#include "sudo_iolog.h"
extern struct io_plugin sudoers_io;
@@ -337,7 +337,7 @@ test_endpoints(int *ntests, int *nerrors, const char *iolog_dir, char *envp[])
int
main(int argc, char *argv[], char *envp[])
{
struct passwd pw, rpw, *tpw;
struct passwd *tpw;
int tests = 0, errors = 0;
const char *iolog_dir;
@@ -347,21 +347,20 @@ main(int argc, char *argv[], char *envp[])
usage();
iolog_dir = argv[1];
/* Bare minimum to link. */
memset(&pw, 0, sizeof(pw));
memset(&rpw, 0, sizeof(rpw));
/* Set runas user. */
if ((tpw = getpwuid(0)) == NULL) {
if ((tpw = getpwnam("root")) == NULL)
sudo_fatalx("unable to look up uid 0 or root");
}
rpw.pw_uid = tpw->pw_uid;
rpw.pw_gid = tpw->pw_gid;
sudo_user.pw = &pw;
sudo_user._runas_pw = &rpw;
sudo_user._runas_pw = pw_dup(tpw);
/* Set invoking user. */
if ((tpw = getpwuid(geteuid())) == NULL)
sudo_fatalx("unable to look up invoking user's uid");
sudo_user.pw = pw_dup(tpw);
/* Set iolog uid/gid to invoking user. */
iolog_uid = geteuid();
iolog_gid = getegid();
iolog_set_user(sudo_user.pw);
test_endpoints(&tests, &errors, iolog_dir, envp);

View File

@@ -356,37 +356,6 @@ set_perms(int perm)
goto bad;
}
break;
case PERM_IOLOG:
state->gidlist = ostate->gidlist;
sudo_gidlist_addref(state->gidlist);
state->rgid = ostate->rgid;
state->egid = iolog_gid;
state->sgid = ostate->sgid;
state->ruid = ROOT_UID;
state->euid = iolog_uid;
state->suid = ROOT_UID;
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: gid: "
"[%d, %d, %d] -> [%d, %d, %d]", __func__,
(int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
(int)state->rgid, (int)state->egid, (int)state->sgid);
if (GID_CHANGED && setresgid(ID(rgid), ID(egid), ID(sgid))) {
(void)snprintf(errbuf, sizeof(errbuf),
"PERM_IOLOG: setresgid(%d, %d, %d)",
(int)ID(rgid), (int)ID(egid), (int)ID(sgid));
goto bad;
}
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: uid: "
"[%d, %d, %d] -> [%d, %d, %d]", __func__,
(int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
(int)state->ruid, (int)state->euid, (int)state->suid);
if (UID_CHANGED && setresuid(ID(ruid), ID(euid), ID(suid))) {
(void)snprintf(errbuf, sizeof(errbuf),
"PERM_IOLOG: setresuid(%d, %d, %d)",
(int)ID(ruid), (int)ID(euid), (int)ID(suid));
goto bad;
}
break;
}
perm_stack_depth++;
@@ -726,46 +695,6 @@ set_perms(int perm)
}
}
break;
case PERM_IOLOG:
state->gidlist = ostate->gidlist;
sudo_gidlist_addref(state->gidlist);
state->rgid = ostate->rgid;
state->egid = iolog_gid;
state->sgid = ostate->sgid;
state->ruid = ROOT_UID;
state->euid = iolog_uid;
state->suid = ROOT_UID;
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: gid: "
"[%d, %d, %d] -> [%d, %d, %d]", __func__,
(int)ostate->rgid, (int)ostate->egid, (int)ostate->sgid,
(int)state->rgid, (int)state->egid, (int)state->sgid);
if (GID_CHANGED && setgidx(ID_EFFECTIVE, iolog_gid)) {
(void)snprintf(errbuf, sizeof(errbuf),
"PERM_IOLOG: setgidx(ID_EFFECTIVE, %d)", (int)iolog_gid);
goto bad;
}
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: uid: "
"[%d, %d, %d] -> [%d, %d, %d]", __func__,
(int)ostate->ruid, (int)ostate->euid, (int)ostate->suid,
(int)state->ruid, (int)state->euid, (int)state->suid);
if (UID_CHANGED) {
if (ostate->ruid != ROOT_UID || ostate->suid != ROOT_UID) {
if (setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, ROOT_UID)) {
(void)snprintf(errbuf, sizeof(errbuf),
"PERM_IOLOG: setuidx(ID_EFFECTIVE|ID_REAL|ID_SAVED, %d)",
ROOT_UID);
goto bad;
}
}
if (setuidx(ID_EFFECTIVE, timestamp_uid)) {
(void)snprintf(errbuf, sizeof(errbuf),
"PERM_IOLOG: setuidx(ID_EFFECTIVE, %d)",
(int)timestamp_uid);
goto bad;
}
}
break;
}
perm_stack_depth++;
@@ -1129,33 +1058,6 @@ set_perms(int perm)
goto bad;
}
break;
case PERM_IOLOG:
state->gidlist = ostate->gidlist;
sudo_gidlist_addref(state->gidlist);
state->rgid = ostate->rgid;
state->egid = iolog_gid;
state->ruid = ROOT_UID;
state->euid = iolog_uid;
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: gid: "
"[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
(int)ostate->egid, (int)state->rgid, (int)state->egid);
if (GID_CHANGED && setregid(ID(rgid), ID(egid))) {
(void)snprintf(errbuf, sizeof(errbuf),
"PERM_IOLOG: setregid(%d, %d)",
(int)ID(rgid), (int)ID(egid));
goto bad;
}
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: uid: "
"[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
(int)ostate->euid, (int)state->ruid, (int)state->euid);
if (UID_CHANGED && setreuid(ID(ruid), ID(euid))) {
(void)snprintf(errbuf, sizeof(errbuf),
"PERM_IOLOG: setreuid(%d, %d)",
(int)ID(ruid), (int)ID(euid));
goto bad;
}
break;
}
perm_stack_depth++;
@@ -1459,31 +1361,6 @@ set_perms(int perm)
goto bad;
}
break;
case PERM_IOLOG:
state->gidlist = ostate->gidlist;
sudo_gidlist_addref(state->gidlist);
state->rgid = ostate->rgid;
state->egid = iolog_gid;
state->ruid = ROOT_UID;
state->euid = iolog_uid;
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: gid: "
"[%d, %d] -> [%d, %d]", __func__, (int)ostate->rgid,
(int)ostate->egid, (int)state->rgid, (int)state->egid);
if (GID_CHANGED && setegid(iolog_gid)) {
(void)snprintf(errbuf, sizeof(errbuf),
"PERM_IOLOG: setegid(%d)", (int)iolog_gid);
goto bad;
}
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_IOLOG: uid: "
"[%d, %d] -> [%d, %d]", __func__, (int)ostate->ruid,
(int)ostate->euid, (int)state->ruid, (int)state->euid);
if (seteuid(timestamp_uid)) {
(void)snprintf(errbuf, sizeof(errbuf),
"PERM_IOLOG: seteuid(%d)", (int)timestamp_uid);
goto bad;
}
break;
}
perm_stack_depth++;
@@ -1524,11 +1401,11 @@ restore_perms(void)
* real and effective uids to ROOT_UID initially to be safe.
*/
if (seteuid(ROOT_UID)) {
sudo_warnx("seteuid() [%d] -> [%d]", (int)state->euid, ROOT_UID);
sudo_warn("seteuid() [%d] -> [%d]", (int)state->euid, ROOT_UID);
goto bad;
}
if (setuid(ROOT_UID)) {
sudo_warnx("setuid() [%d, %d] -> [%d, %d]", (int)state->ruid, ROOT_UID,
sudo_warn("setuid() [%d, %d] -> [%d, %d]", (int)state->ruid, ROOT_UID,
ROOT_UID, ROOT_UID);
goto bad;
}
@@ -1643,7 +1520,6 @@ set_perms(int perm)
case PERM_SUDOERS:
case PERM_RUNAS:
case PERM_TIMESTAMP:
case PERM_IOLOG:
/* Unsupported since we can't set euid. */
state->ruid = ostate->ruid;
state->rgid = ostate->rgid;

View File

@@ -68,6 +68,7 @@
#include "sudoers.h"
#include "parse.h"
#include "auth/sudo_auth.h"
#include "sudo_iolog.h"
#ifndef HAVE_GETADDRINFO
# include "compat/getaddrinfo.h"
@@ -472,8 +473,12 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT))) {
if ((def_log_input || def_log_output) && def_iolog_file && def_iolog_dir) {
const char prefix[] = "iolog_path=";
/* Use sudoers locale for strftime() */
sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
iolog_path = expand_iolog_path(prefix, def_iolog_dir,
def_iolog_file, &sudo_user.iolog_file);
def_iolog_file, &sudo_user.iolog_file,
sudoers_iolog_path_escapes);
sudoers_setlocale(oldlocale, NULL);
if (iolog_path == NULL) {
if (!def_ignore_iolog_errors)
goto done;

View File

@@ -237,13 +237,6 @@ struct sudo_user {
# define SUDOERS_MODE 0600
#endif
#ifdef __TANDEM
# define ROOT_UID 65535
#else
# define ROOT_UID 0
#endif
#define ROOT_GID 0
struct sudo_lbuf;
struct passwd;
struct stat;
@@ -350,17 +343,14 @@ char *get_timestr(time_t, int);
bool get_boottime(struct timespec *);
/* iolog.c */
bool io_nextid(char *iolog_dir, char *iolog_dir_fallback, char sessid[7]);
bool cb_maxseq(const union sudo_defs_val *sd_un);
bool cb_iolog_user(const union sudo_defs_val *sd_un);
bool cb_iolog_group(const union sudo_defs_val *sd_un);
bool cb_iolog_mode(const union sudo_defs_val *sd_un);
extern uid_t iolog_uid;
extern gid_t iolog_gid;
/* iolog_path.c */
char *expand_iolog_path(const char *prefix, const char *dir, const char *file,
char **slashp);
/* iolog_path_escapes.c */
struct iolog_path_escape;
extern const struct iolog_path_escape *sudoers_iolog_path_escapes;
/* env.c */
char **env_get(void);

View File

@@ -64,8 +64,7 @@
#include "sudo_compat.h"
#include "sudo_fatal.h"
#include "logging.h"
#include "iolog_util.h"
#include "iolog_files.h"
#include "sudo_iolog.h"
#include "sudo_queue.h"
#include "sudo_plugin.h"
#include "sudo_conf.h"
@@ -80,6 +79,7 @@
#endif /* HAVE_GETOPT_LONG */
struct replay_closure {
const char *iolog_dir;
struct sudo_event_base *evbase;
struct sudo_event *delay_ev;
struct sudo_event *keyboard_ev;
@@ -146,6 +146,15 @@ static int terminal_lines, terminal_cols;
static int ttyfd = -1;
static struct iolog_file iolog_files[] = {
{ false }, /* IOFD_STDIN */
{ false }, /* IOFD_STDOUT */
{ false }, /* IOFD_STDERR */
{ false }, /* IOFD_TTYIN */
{ false }, /* IOFD_TTYOUT */
{ true, }, /* IOFD_TIMING */
};
static const char short_opts[] = "d:f:hlm:nRSs:V";
static struct option long_opts[] = {
{ "directory", required_argument, NULL, 'd' },
@@ -166,11 +175,11 @@ extern char *get_timestr(time_t, int);
extern time_t get_date(char *);
static int list_sessions(int, char **, const char *, const char *, const char *);
static int open_io_fd(char *path, int len, struct io_log_file *iol);
static int parse_expr(struct search_node_list *, char **, bool);
static void read_keyboard(int fd, int what, void *v);
static void help(void) __attribute__((__noreturn__));
static int replay_session(struct timespec *max_wait, const char *decimal, bool interactive, bool suspend_wait);
static int replay_session(const char *iolog_dir, struct timespec *max_wait,
const char *decimal, bool interactive, bool suspend_wait);
static void sudoreplay_cleanup(void);
static void usage(int);
static void write_output(int fd, int what, void *v);
@@ -238,15 +247,15 @@ main(int argc, char *argv[])
def_filter = false;
for (cp = strtok_r(optarg, ",", &ep); cp; cp = strtok_r(NULL, ",", &ep)) {
if (strcmp(cp, "stdin") == 0)
io_log_files[IOFD_STDIN].enabled = true;
iolog_files[IOFD_STDIN].enabled = true;
else if (strcmp(cp, "stdout") == 0)
io_log_files[IOFD_STDOUT].enabled = true;
iolog_files[IOFD_STDOUT].enabled = true;
else if (strcmp(cp, "stderr") == 0)
io_log_files[IOFD_STDERR].enabled = true;
iolog_files[IOFD_STDERR].enabled = true;
else if (strcmp(cp, "ttyin") == 0)
io_log_files[IOFD_TTYIN].enabled = true;
iolog_files[IOFD_TTYIN].enabled = true;
else if (strcmp(cp, "ttyout") == 0)
io_log_files[IOFD_TTYOUT].enabled = true;
iolog_files[IOFD_TTYOUT].enabled = true;
else
sudo_fatalx(U_("invalid filter option: %s"), optarg);
}
@@ -308,9 +317,9 @@ main(int argc, char *argv[])
/* By default we replay stdout, stderr and ttyout. */
if (def_filter) {
io_log_files[IOFD_STDOUT].enabled = true;
io_log_files[IOFD_STDERR].enabled = true;
io_log_files[IOFD_TTYOUT].enabled = true;
iolog_files[IOFD_STDOUT].enabled = true;
iolog_files[IOFD_STDERR].enabled = true;
iolog_files[IOFD_TTYOUT].enabled = true;
}
/* 6 digit ID in base 36, e.g. 01G712AB or free-form name */
@@ -327,15 +336,22 @@ main(int argc, char *argv[])
sudo_fatalx(U_("%s/timing: %s"), id, strerror(ENAMETOOLONG));
} else {
plen = snprintf(path, sizeof(path), "%s/%s/timing", session_dir, id);
if (plen < 0 || plen >= ssizeof(path))
if (plen < 0 || plen >= ssizeof(path)) {
sudo_fatalx(U_("%s/%s/timing: %s"), session_dir, id,
strerror(ENAMETOOLONG));
}
}
plen -= 7;
/* Open files for replay, applying replay filter for the -f flag. */
for (i = 0; i < IOFD_MAX; i++) {
if (open_io_fd(path, plen, &io_log_files[i]) == -1)
path[plen] = '/';
path[plen + 1] = '\0';
if (strlcat(path, iolog_fd_to_name(i), sizeof(path)) >= sizeof(path)) {
errno = ENAMETOOLONG;
sudo_fatal("%s%s", path, iolog_fd_to_name(i));
}
if (!iolog_open(&iolog_files[i], path, "r"))
sudo_fatal(U_("unable to open %s"), path);
}
@@ -357,8 +373,10 @@ main(int argc, char *argv[])
free_iolog_info(li);
li = NULL;
/* Replay session corresponding to io_log_files[]. */
exitcode = replay_session(max_delay, decimal, interactive, suspend_wait);
/* Replay session corresponding to iolog_files[]. */
path[plen] = '\0';
exitcode = replay_session(path, max_delay, decimal, interactive,
suspend_wait);
restore_terminal_size();
sudo_term_restore(ttyfd, true);
@@ -367,58 +385,6 @@ done:
exit(exitcode);
}
/*
* Call gzread() or fread() for the I/O log file in question.
* Return 0 for EOF or -1 on error.
*/
static ssize_t
io_log_read(union io_fd ifd, char *buf, size_t nbytes)
{
ssize_t nread;
debug_decl(io_log_read, SUDO_DEBUG_UTIL)
if (nbytes > INT_MAX) {
errno = EINVAL;
debug_return_ssize_t(-1);
}
#ifdef HAVE_ZLIB_H
nread = gzread(ifd.g, buf, nbytes);
#else
nread = (ssize_t)fread(buf, 1, nbytes, ifd.f);
if (nread == 0 && ferror(ifd.f))
nread = -1;
#endif
debug_return_ssize_t(nread);
}
static int
io_log_eof(union io_fd ifd)
{
int ret;
debug_decl(io_log_eof, SUDO_DEBUG_UTIL)
#ifdef HAVE_ZLIB_H
ret = gzeof(ifd.g);
#else
ret = feof(ifd.f);
#endif
debug_return_int(ret);
}
static char *
io_log_gets(union io_fd ifd, char *buf, size_t nbytes)
{
char *str;
debug_decl(io_log_gets, SUDO_DEBUG_UTIL)
#ifdef HAVE_ZLIB_H
str = gzgets(ifd.g, buf, nbytes);
#else
str = fgets(buf, nbytes, ifd.f);
#endif
debug_return_str(str);
}
/*
* List of terminals that support xterm-like resizing.
* This is not an exhaustive list.
@@ -753,18 +719,23 @@ restore_terminal_size(void)
* Read the next record from the timing file and schedule a delay
* event with the specified timeout.
* Return 0 on success, 1 on EOF and -1 on error.
* XXX - duplicated in sendlog
*/
static int
read_timing_record(struct replay_closure *closure)
{
struct timing_closure *timing = &closure->timing;
char line[LINE_MAX];
const char *errstr;
debug_decl(read_timing_record, SUDO_DEBUG_UTIL)
/* Read next record from timing file. */
if (io_log_gets(io_log_files[IOFD_TIMING].fd, line, sizeof(line)) == NULL) {
if (iolog_gets(&iolog_files[IOFD_TIMING], line, sizeof(line), &errstr) == NULL) {
/* EOF or error reading timing file, we are done. */
debug_return_int(io_log_eof(io_log_files[IOFD_TIMING].fd) ? 1 : -1);
if (iolog_eof(&iolog_files[IOFD_TIMING]))
debug_return_int(1);
sudo_fatalx(U_("error reading timing file: %s"), errstr);
debug_return_int(-1);
}
/* Parse timing file record. */
@@ -773,7 +744,6 @@ read_timing_record(struct replay_closure *closure)
sudo_fatalx(U_("invalid timing file line: %s"), line);
/* Record number bytes to read. */
/* XXX - remove timing->nbytes? */
if (timing->event != IO_EVENT_WINSIZE &&
timing->event != IO_EVENT_SUSPEND) {
closure->iobuf.len = 0;
@@ -828,24 +798,27 @@ fill_iobuf(struct replay_closure *closure)
{
const size_t space = sizeof(closure->iobuf.buf) - closure->iobuf.len;
const struct timing_closure *timing = &closure->timing;
const char *errstr;
debug_decl(fill_iobuf, SUDO_DEBUG_UTIL)
if (closure->iobuf.toread != 0 && space != 0) {
const size_t len =
closure->iobuf.toread < space ? closure->iobuf.toread : space;
ssize_t nread = io_log_read(timing->fd,
closure->iobuf.buf + closure->iobuf.off, len);
ssize_t nread = iolog_read(timing->iol,
closure->iobuf.buf + closure->iobuf.off, len, &errstr);
if (nread <= 0) {
if (nread == 0) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s: premature EOF, expected %u bytes",
io_log_files[timing->event].suffix, closure->iobuf.toread);
"%s/%s: premature EOF, expected %u bytes",
closure->iolog_dir, iolog_fd_to_name(timing->event),
closure->iobuf.toread);
} else {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO|SUDO_DEBUG_LINENO,
"%s: read error", io_log_files[timing->event].suffix);
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s/%s: read error: %s", closure->iolog_dir,
iolog_fd_to_name(timing->event), errstr);
}
sudo_warnx(U_("unable to read %s"),
io_log_files[timing->event].suffix);
sudo_warnx(U_("unable to read %s/%s: %s"),
closure->iolog_dir, iolog_fd_to_name(timing->event), errstr);
debug_return_bool(false);
}
closure->iobuf.toread -= nread;
@@ -872,28 +845,28 @@ delay_cb(int fd, int what, void *v)
resize_terminal(timing->u.winsize.lines, timing->u.winsize.cols);
break;
case IO_EVENT_STDIN:
if (io_log_files[IOFD_STDIN].enabled)
timing->fd = io_log_files[IOFD_STDIN].fd;
if (iolog_files[IOFD_STDIN].enabled)
timing->iol = &iolog_files[IOFD_STDIN];
break;
case IO_EVENT_STDOUT:
if (io_log_files[IOFD_STDOUT].enabled)
timing->fd = io_log_files[IOFD_STDOUT].fd;
if (iolog_files[IOFD_STDOUT].enabled)
timing->iol = &iolog_files[IOFD_STDOUT];
break;
case IO_EVENT_STDERR:
if (io_log_files[IOFD_STDERR].enabled)
timing->fd = io_log_files[IOFD_STDERR].fd;
if (iolog_files[IOFD_STDERR].enabled)
timing->iol = &iolog_files[IOFD_STDERR];
break;
case IO_EVENT_TTYIN:
if (io_log_files[IOFD_TTYIN].enabled)
timing->fd = io_log_files[IOFD_TTYIN].fd;
if (iolog_files[IOFD_TTYIN].enabled)
timing->iol = &iolog_files[IOFD_TTYIN];
break;
case IO_EVENT_TTYOUT:
if (io_log_files[IOFD_TTYOUT].enabled)
timing->fd = io_log_files[IOFD_TTYOUT].fd;
if (iolog_files[IOFD_TTYOUT].enabled)
timing->iol = &iolog_files[IOFD_TTYOUT];
break;
}
if (timing->fd.v != NULL) {
if (timing->iol != NULL) {
/* If the stream is open, enable the write event. */
if (sudo_ev_add(closure->evbase, closure->output_ev, NULL, false) == -1)
sudo_fatal(U_("unable to add event to queue"));
@@ -950,8 +923,8 @@ signal_cb(int signo, int what, void *v)
}
static struct replay_closure *
replay_closure_alloc(struct timespec *max_delay, const char *decimal,
bool interactive, bool suspend_wait)
replay_closure_alloc(const char *iolog_dir, struct timespec *max_delay,
const char *decimal, bool interactive, bool suspend_wait)
{
struct replay_closure *closure;
debug_decl(replay_closure_alloc, SUDO_DEBUG_UTIL)
@@ -959,6 +932,7 @@ replay_closure_alloc(struct timespec *max_delay, const char *decimal,
if ((closure = calloc(1, sizeof(*closure))) == NULL)
debug_return_ptr(NULL);
closure->iolog_dir = iolog_dir;
closure->interactive = interactive;
closure->suspend_wait = suspend_wait;
closure->max_delay = max_delay;
@@ -1033,15 +1007,15 @@ bad:
}
static int
replay_session(struct timespec *max_delay, const char *decimal,
bool interactive, bool suspend_wait)
replay_session(const char *iolog_dir, struct timespec *max_delay,
const char *decimal, bool interactive, bool suspend_wait)
{
struct replay_closure *closure;
int ret = 0;
debug_decl(replay_session, SUDO_DEBUG_UTIL)
/* Allocate the delay closure and read the first timing record. */
closure = replay_closure_alloc(max_delay, decimal, interactive,
closure = replay_closure_alloc(iolog_dir, max_delay, decimal, interactive,
suspend_wait);
if (read_timing_record(closure) != 0) {
ret = 1;
@@ -1059,28 +1033,6 @@ done:
debug_return_int(ret);
}
static int
open_io_fd(char *path, int len, struct io_log_file *iol)
{
debug_decl(open_io_fd, SUDO_DEBUG_UTIL)
if (!iol->enabled)
debug_return_int(0);
path[len] = '\0';
strlcat(path, iol->suffix, PATH_MAX);
#ifdef HAVE_ZLIB_H
iol->fd.g = gzopen(path, "r");
#else
iol->fd.f = fopen(path, "r");
#endif
if (iol->fd.v == NULL) {
iol->enabled = false;
debug_return_int(-1);
}
debug_return_int(0);
}
/*
* Write the I/O buffer.
*/

View File

@@ -50,12 +50,6 @@
# define NDEBUG
#endif
#ifdef __TANDEM
# define ROOT_UID 65535
#else
# define ROOT_UID 0
#endif
/*
* Various modes sudo can be in (based on arguments) in hex
*/