diff --git a/client.c b/client.c index c5898d1..1701dfd 100644 --- a/client.c +++ b/client.c @@ -3590,9 +3590,11 @@ print_help(const char *progname) " -m\t\tAccept multiple commands\n" " -h HOST\tSpecify server (%s)\n" " -p PORT\tSpecify UDP port (%d)\n" + " -u USER\tSpecify user (%s)\n" " -v, --version\tPrint version and exit\n" " --help\tPrint usage and exit\n", - progname, DEFAULT_COMMAND_SOCKET",127.0.0.1,::1", DEFAULT_CANDM_PORT); + progname, DEFAULT_COMMAND_SOCKET",127.0.0.1,::1", + DEFAULT_CANDM_PORT, DEFAULT_CHRONYC_USER); } /* ================================================== */ @@ -3609,10 +3611,11 @@ int main(int argc, char **argv) { char *line; + const char *hostnames = NULL, *user = DEFAULT_CHRONYC_USER; const char *progname = argv[0]; - const char *hostnames = NULL; int opt, ret = 1, multi = 0, family = IPADDR_UNSPEC; int port = DEFAULT_CANDM_PORT; + struct passwd *pw; /* Parse long command-line options */ for (optind = 1; optind < argc; optind++) { @@ -3628,7 +3631,7 @@ main(int argc, char **argv) optind = 1; /* Parse short command-line options */ - while ((opt = getopt(argc, argv, "+46acdef:h:mnNp:v")) != -1) { + while ((opt = getopt(argc, argv, "+46acdef:h:mnNp:u:v")) != -1) { switch (opt) { case '4': case '6': @@ -3664,6 +3667,9 @@ main(int argc, char **argv) case 'p': port = atoi(optarg); break; + case 'u': + user = optarg; + break; case 'v': print_version(); return 0; @@ -3673,6 +3679,14 @@ main(int argc, char **argv) } } + /* Drop root privileges if configured to do so */ + if (strcmp(user, "root") != 0 && geteuid() == 0) { + pw = getpwnam(user); + if (!pw) + LOG_FATAL("Could not get user/group ID of %s", user); + UTI_DropRoot(pw->pw_uid, pw->pw_gid); + } + if (isatty(0) && isatty(1) && isatty(2)) { on_terminal = 1; } diff --git a/configure b/configure index 7f978c6..58159de 100755 --- a/configure +++ b/configure @@ -133,6 +133,7 @@ For better control, use the options below. --with-ntp-era=SECONDS Specify earliest assumed NTP time in seconds since 1970-01-01 [50*365 days ago] --with-user=USER Specify default chronyd user [root] + --with-chronyc-user=USER Specify default chronyc user [root] --with-hwclockfile=PATH Specify default path to hwclock(8) adjtime file --with-pidfile=PATH Specify default pidfile [/var/run/chrony/chronyd.pid] --with-rtcdevice=PATH Specify default path to RTC device [/dev/rtc] @@ -250,6 +251,7 @@ try_timestamping=0 feat_ntp_signd=0 ntp_era_split="" default_user="root" +default_chronyc_user="root" default_hwclockfile="" default_pidfile="/var/run/chrony/chronyd.pid" default_rtcdevice="/dev/rtc" @@ -354,6 +356,9 @@ do --with-user=* ) default_user=`echo $option | sed -e 's/^.*=//;'` ;; + --with-chronyc-user=* ) + default_chronyc_user=`echo $option | sed -e 's/^.*=//;'` + ;; --with-hwclockfile=* ) default_hwclockfile=`echo $option | sed -e 's/^.*=//;'` ;; @@ -1080,6 +1085,7 @@ add_def DEFAULT_HWCLOCK_FILE "\"$default_hwclockfile\"" add_def DEFAULT_PID_FILE "\"$default_pidfile\"" add_def DEFAULT_RTC_DEVICE "\"$default_rtcdevice\"" add_def DEFAULT_USER "\"$default_user\"" +add_def DEFAULT_CHRONYC_USER "\"$default_chronyc_user\"" add_def DEFAULT_COMMAND_SOCKET "\"$CHRONYRUNDIR/chronyd.sock\"" add_def MAIL_PROGRAM "\"$mail_program\"" @@ -1123,6 +1129,7 @@ do s%@DEFAULT_PID_FILE@%${default_pidfile}%;\ s%@DEFAULT_RTC_DEVICE@%${default_rtcdevice}%;\ s%@DEFAULT_USER@%${default_user}%;\ + s%@DEFAULT_CHRONYC_USER@%${default_chronyc_user}%;\ s%@CHRONY_VERSION@%${CHRONY_VERSION}%;" \ < ${f}.in > $f done diff --git a/doc/Makefile.in b/doc/Makefile.in index 1777da5..a8ce3c7 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -17,6 +17,7 @@ CHRONYRUNDIR = @CHRONYRUNDIR@ CHRONYVARDIR = @CHRONYVARDIR@ CHRONY_VERSION = @CHRONY_VERSION@ DEFAULT_USER = @DEFAULT_USER@ +DEFAULT_CHRONYC_USER = @DEFAULT_CHRONYC_USER@ DEFAULT_HWCLOCK_FILE = @DEFAULT_HWCLOCK_FILE@ DEFAULT_PID_FILE = @DEFAULT_PID_FILE@ DEFAULT_RTC_DEVICE = @DEFAULT_RTC_DEVICE@ @@ -29,6 +30,7 @@ SED_COMMANDS = "s%\@SYSCONFDIR\@%$(SYSCONFDIR)%g;\ s%\@DEFAULT_PID_FILE\@%$(DEFAULT_PID_FILE)%g;\ s%\@DEFAULT_RTC_DEVICE\@%$(DEFAULT_RTC_DEVICE)%g;\ s%\@DEFAULT_USER\@%$(DEFAULT_USER)%g;\ + s%\@DEFAULT_CHRONYC_USER\@%$(DEFAULT_CHRONYC_USER)%g;\ s%\@CHRONYRUNDIR\@%$(CHRONYRUNDIR)%g;\ s%\@CHRONYVARDIR\@%$(CHRONYVARDIR)%g;" diff --git a/doc/chronyc.adoc b/doc/chronyc.adoc index 65040ef..36790da 100644 --- a/doc/chronyc.adoc +++ b/doc/chronyc.adoc @@ -121,6 +121,13 @@ This option allows the user to specify the UDP port number which the target *chronyd* is using for its monitoring connections. This defaults to 323; there would rarely be a need to change this. +*-u* _user_:: +This option sets the name of the user to which *chronyc* will switch when it is +started under the root user in order to drop its privileges. *chronyc* will not +try to change its identity if the option is set to _root_, or the effective +user ID of the started process is not 0. The compiled-in default value is +_@DEFAULT_CHRONYC_USER@_. + *-f* _file_:: This option is ignored and is provided only for compatibility. diff --git a/test/system/test.common b/test/system/test.common index e4d9fb6..07f259d 100644 --- a/test/system/test.common +++ b/test/system/test.common @@ -390,7 +390,7 @@ run_chronyc() { fi $CHRONYC_WRAPPER $wrapper_options \ - "$chronyc" -h "$host" $options "$@" > "$TEST_DIR/chronyc.out" && \ + "$chronyc" -h "$host" -u "$(get_user)" $options "$@" > "$TEST_DIR/chronyc.out" && \ test_ok || test_error [ $? -ne 0 ] && ret=1