diff --git a/configure b/configure index 62fd5aa41..d72141b50 100755 --- a/configure +++ b/configure @@ -19418,7 +19418,15 @@ esac fi done -for ac_func in arc4random_uniform +for ac_func in arc4random +do : + ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random" +if test "x$ac_cv_func_arc4random" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ARC4RANDOM 1 +_ACEOF + + for ac_func in arc4random_uniform do : ac_fn_c_check_func "$LINENO" "arc4random_uniform" "ac_cv_func_arc4random_uniform" if test "x$ac_cv_func_arc4random_uniform" = xyes; then : @@ -19428,6 +19436,37 @@ _ACEOF else + case " $LIBOBJS " in + *" arc4random_uniform.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS arc4random_uniform.$ac_objext" + ;; +esac + + + for _sym in sudo_arc4random_uniform; do + COMPAT_EXP="${COMPAT_EXP}${_sym} +" + done + + +fi +done + + +else + + case " $LIBOBJS " in + *" arc4random.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS arc4random.$ac_objext" + ;; +esac + + + for _sym in sudo_arc4random; do + COMPAT_EXP="${COMPAT_EXP}${_sym} +" + done + case " $LIBOBJS " in *" arc4random_uniform.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS arc4random_uniform.$ac_objext" @@ -19440,30 +19479,8 @@ esac " done - for ac_func in arc4random -do : - ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random" -if test "x$ac_cv_func_arc4random" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_ARC4RANDOM 1 -_ACEOF - -else - - case " $LIBOBJS " in - *" arc4random.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS arc4random.$ac_objext" - ;; -esac - - - for _sym in sudo_arc4random; do - COMPAT_EXP="${COMPAT_EXP}${_sym} -" - done - - # arc4random.c needs getentropy() - for ac_func in getentropy + # arc4random.c needs getentropy() + for ac_func in getentropy do : ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy" if test "x$ac_cv_func_getentropy" = xyes; then : @@ -19471,7 +19488,7 @@ if test "x$ac_cv_func_getentropy" = xyes; then : #define HAVE_GETENTROPY 1 _ACEOF - for ac_header in sys/random.h + for ac_header in sys/random.h do : ac_fn_c_check_header_mongrel "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default" if test "x$ac_cv_header_sys_random_h" = xyes; then : @@ -19486,7 +19503,7 @@ done else - case " $LIBOBJS " in + case " $LIBOBJS " in *" getentropy.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getentropy.$ac_objext" ;; @@ -19502,8 +19519,8 @@ esac fi done - # arc4random.c wants pthread_atfork - for ac_header in pthread.h + # arc4random.c wants pthread_atfork + for ac_header in pthread.h do : ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : @@ -19511,7 +19528,7 @@ if test "x$ac_cv_header_pthread_h" = xyes; then : #define HAVE_PTHREAD_H 1 _ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 $as_echo_n "checking for main in -lpthread... " >&6; } if ${ac_cv_lib_pthread_main+:} false; then : $as_echo_n "(cached) " >&6 @@ -19545,7 +19562,7 @@ if test "x$ac_cv_lib_pthread_main" = xyes; then : LIBPTHREAD="-lpthread" fi - for ac_func in pthread_atfork + for ac_func in pthread_atfork do : ac_fn_c_check_func "$LINENO" "pthread_atfork" "ac_cv_func_pthread_atfork" if test "x$ac_cv_func_pthread_atfork" = xyes; then : @@ -19566,10 +19583,6 @@ fi done -fi -done - - utmp_style=LEGACY for ac_func in getutsid getutxid getutid do : diff --git a/configure.ac b/configure.ac index 1752eb1ca..7480fd20a 100644 --- a/configure.ac +++ b/configure.ac @@ -2566,24 +2566,27 @@ AC_CHECK_FUNCS([reallocarray], [], [ AC_LIBOBJ(reallocarray) SUDO_APPEND_COMPAT_EXP(sudo_reallocarray) ]) -AC_CHECK_FUNCS([arc4random_uniform], [], [ +AC_CHECK_FUNCS([arc4random], [ + AC_CHECK_FUNCS([arc4random_uniform], [], [ + AC_LIBOBJ(arc4random_uniform) + SUDO_APPEND_COMPAT_EXP(sudo_arc4random_uniform) + ]) +], [ + AC_LIBOBJ(arc4random) + SUDO_APPEND_COMPAT_EXP(sudo_arc4random) AC_LIBOBJ(arc4random_uniform) SUDO_APPEND_COMPAT_EXP(sudo_arc4random_uniform) - AC_CHECK_FUNCS([arc4random], [], [ - AC_LIBOBJ(arc4random) - SUDO_APPEND_COMPAT_EXP(sudo_arc4random) - # arc4random.c needs getentropy() - AC_CHECK_FUNCS([getentropy], [ - AC_CHECK_HEADERS([sys/random.h]) - ], [ - AC_LIBOBJ(getentropy) - SUDO_APPEND_COMPAT_EXP(sudo_getentropy) - ]) - # arc4random.c wants pthread_atfork - AC_CHECK_HEADERS([pthread.h], [ - AC_CHECK_LIB(pthread, main, [LIBPTHREAD="-lpthread"]) - AC_CHECK_FUNCS([pthread_atfork]) - ]) + # arc4random.c needs getentropy() + AC_CHECK_FUNCS([getentropy], [ + AC_CHECK_HEADERS([sys/random.h]) + ], [ + AC_LIBOBJ(getentropy) + SUDO_APPEND_COMPAT_EXP(sudo_getentropy) + ]) + # arc4random.c wants pthread_atfork + AC_CHECK_HEADERS([pthread.h], [ + AC_CHECK_LIB(pthread, main, [LIBPTHREAD="-lpthread"]) + AC_CHECK_FUNCS([pthread_atfork]) ]) ]) diff --git a/include/sudo_rand.h b/include/sudo_rand.h index 283ce5f2e..49c75ec0c 100644 --- a/include/sudo_rand.h +++ b/include/sudo_rand.h @@ -30,8 +30,7 @@ */ #ifndef HAVE_ARC4RANDOM -/* Note: not exported by libutil. */ -uint32_t sudo_arc4random(void); +__dso_public uint32_t sudo_arc4random(void); # undef arc4random # define arc4random() sudo_arc4random() #endif /* ARC4RANDOM */ diff --git a/logsrvd/Makefile.in b/logsrvd/Makefile.in index 28aa4a5ee..776079fae 100644 --- a/logsrvd/Makefile.in +++ b/logsrvd/Makefile.in @@ -258,15 +258,17 @@ 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_util.h $(srcdir)/logsrvd.h \ - $(srcdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.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_util.h $(srcdir)/logsrvd.h \ - $(srcdir)/protobuf-c/protobuf-c.h $(top_builddir)/config.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 $@ diff --git a/logsrvd/logsrvd.c b/logsrvd/logsrvd.c index 12e45a80f..4a0931ed4 100644 --- a/logsrvd/logsrvd.c +++ b/logsrvd/logsrvd.c @@ -48,12 +48,15 @@ #include "sudo_event.h" #include "sudo_queue.h" #include "sudo_util.h" +#include "sudo_rand.h" #include "sudo_fatal.h" +#include "pathnames.h" #include "logsrvd.h" TAILQ_HEAD(connection_list, connection_closure); static struct connection_list connections = TAILQ_HEAD_INITIALIZER(connections); static const char server_id[] = "Sudo Audit Server 0.1"; +static double random_drop; /* * Proof of concept audit server. @@ -314,10 +317,15 @@ handle_iobuf(int iofd, IoBuffer *msg, struct connection_closure *closure) debug_return_bool(false); } -#ifdef SERVER_DEBUG - if (rand() % 4 == 3) - kill(getpid(), SIGTERM); -#endif + /* Random drop is a debugging tool to test client restart. */ + if (random_drop > 0.0) { + double randval = arc4random() / (double)UINT32_MAX; + if (randval < random_drop) { + sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO, + "randomly dropping connection (%f < %f)", randval, random_drop); + debug_return_bool(false); + } + } /* Schedule a commit point in 10 sec if one is not already pending. */ if (!ISSET(closure->commit_ev->flags, SUDO_EVQ_INSERTED)) { @@ -855,10 +863,57 @@ logsrvd_cleanup(void) return; } +/* + * Fork and detatch from the terminal. + */ +static void +daemonize(void) +{ + int fd; + debug_decl(daemonize, SUDO_DEBUG_UTIL) + + switch (fork()) { + case -1: + sudo_fatal("fork"); + case 0: + /* child */ + break; + default: + /* parent */ + _exit(0); + } + + /* detach from terminal */ + if (setsid() == -1) + sudo_fatal("setsid"); + + if (chdir("/") == -1) + sudo_warn("chdir(\"/\")"); + if ((fd = open(_PATH_DEVNULL, O_RDWR)) != -1) { + (void) dup2(fd, STDIN_FILENO); + (void) dup2(fd, STDOUT_FILENO); + (void) dup2(fd, STDERR_FILENO); + if (fd > STDERR_FILENO) + (void) close(fd); + } + + debug_return; +} + +static void +usage(void) +{ + fprintf(stderr, "usage: %s [-n] [-R percentage]\n", getprogname()); + exit(1); +} + int main(int argc, char *argv[]) { struct sudo_event_base *evbase; + bool nofork = false; + char *ep; + int ch; debug_decl_vars(main, SUDO_DEBUG_MAIN) initprogname(argc > 0 ? argv[0] : "sudo_logsrvd"); @@ -875,12 +930,32 @@ main(int argc, char *argv[]) sudo_debug_register(getprogname(), NULL, NULL, sudo_conf_debug_files(getprogname())); - /* XXX - getopt_long option handling */ - if (protobuf_c_version_number() < 1003000) sudo_fatalx("Protobuf-C version 1.3 or higher required"); + /* XXX - getopt_long option handling */ + while ((ch = getopt(argc, argv, "nR:")) != -1) { + switch (ch) { + case 'n': + nofork = true; + break; + case 'R': + errno = 0; + random_drop = strtod(optarg, &ep); + if (*ep != '\0' || errno != 0) + sudo_fatalx(U_("invalid random drop value: %s"), optarg); + random_drop /= 100.0; /* convert from percentage */ + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + signal(SIGPIPE, SIG_IGN); + if (!nofork) + daemonize(); if ((evbase = sudo_ev_base_alloc()) == NULL) sudo_fatal(NULL);