mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 17:45:07 -05:00
client: add support for dropping root privileges
To minimize the impact of potential attacks targeting chronyc started under root (e.g. performed by a local chronyd process running without root privileges, a remote chronyd process, or a MITM attacker on the network), add support for changing the effective UID/GID in chronyc after start. The user can be specified by the -u option, similarly to chronyd. The default chronyc user can be changed by the --with-chronyc-user configure option. The default value of the default chronyc user is "root", i.e. chronyc doesn't try to change the identity by default. The default chronyc user does not follow the default chronyd user set by the configure --with-user option to avoid errors on systems where chronyc is not allowed to change its UID/GID (e.g. by a SELinux policy).
This commit is contained in:
20
client.c
20
client.c
@@ -3590,9 +3590,11 @@ print_help(const char *progname)
|
|||||||
" -m\t\tAccept multiple commands\n"
|
" -m\t\tAccept multiple commands\n"
|
||||||
" -h HOST\tSpecify server (%s)\n"
|
" -h HOST\tSpecify server (%s)\n"
|
||||||
" -p PORT\tSpecify UDP port (%d)\n"
|
" -p PORT\tSpecify UDP port (%d)\n"
|
||||||
|
" -u USER\tSpecify user (%s)\n"
|
||||||
" -v, --version\tPrint version and exit\n"
|
" -v, --version\tPrint version and exit\n"
|
||||||
" --help\tPrint usage 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)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *line;
|
char *line;
|
||||||
|
const char *hostnames = NULL, *user = DEFAULT_CHRONYC_USER;
|
||||||
const char *progname = argv[0];
|
const char *progname = argv[0];
|
||||||
const char *hostnames = NULL;
|
|
||||||
int opt, ret = 1, multi = 0, family = IPADDR_UNSPEC;
|
int opt, ret = 1, multi = 0, family = IPADDR_UNSPEC;
|
||||||
int port = DEFAULT_CANDM_PORT;
|
int port = DEFAULT_CANDM_PORT;
|
||||||
|
struct passwd *pw;
|
||||||
|
|
||||||
/* Parse long command-line options */
|
/* Parse long command-line options */
|
||||||
for (optind = 1; optind < argc; optind++) {
|
for (optind = 1; optind < argc; optind++) {
|
||||||
@@ -3628,7 +3631,7 @@ main(int argc, char **argv)
|
|||||||
optind = 1;
|
optind = 1;
|
||||||
|
|
||||||
/* Parse short command-line options */
|
/* 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) {
|
switch (opt) {
|
||||||
case '4':
|
case '4':
|
||||||
case '6':
|
case '6':
|
||||||
@@ -3664,6 +3667,9 @@ main(int argc, char **argv)
|
|||||||
case 'p':
|
case 'p':
|
||||||
port = atoi(optarg);
|
port = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'u':
|
||||||
|
user = optarg;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
print_version();
|
print_version();
|
||||||
return 0;
|
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)) {
|
if (isatty(0) && isatty(1) && isatty(2)) {
|
||||||
on_terminal = 1;
|
on_terminal = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
7
configure
vendored
7
configure
vendored
@@ -133,6 +133,7 @@ For better control, use the options below.
|
|||||||
--with-ntp-era=SECONDS Specify earliest assumed NTP time in seconds
|
--with-ntp-era=SECONDS Specify earliest assumed NTP time in seconds
|
||||||
since 1970-01-01 [50*365 days ago]
|
since 1970-01-01 [50*365 days ago]
|
||||||
--with-user=USER Specify default chronyd user [root]
|
--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-hwclockfile=PATH Specify default path to hwclock(8) adjtime file
|
||||||
--with-pidfile=PATH Specify default pidfile [/var/run/chrony/chronyd.pid]
|
--with-pidfile=PATH Specify default pidfile [/var/run/chrony/chronyd.pid]
|
||||||
--with-rtcdevice=PATH Specify default path to RTC device [/dev/rtc]
|
--with-rtcdevice=PATH Specify default path to RTC device [/dev/rtc]
|
||||||
@@ -250,6 +251,7 @@ try_timestamping=0
|
|||||||
feat_ntp_signd=0
|
feat_ntp_signd=0
|
||||||
ntp_era_split=""
|
ntp_era_split=""
|
||||||
default_user="root"
|
default_user="root"
|
||||||
|
default_chronyc_user="root"
|
||||||
default_hwclockfile=""
|
default_hwclockfile=""
|
||||||
default_pidfile="/var/run/chrony/chronyd.pid"
|
default_pidfile="/var/run/chrony/chronyd.pid"
|
||||||
default_rtcdevice="/dev/rtc"
|
default_rtcdevice="/dev/rtc"
|
||||||
@@ -354,6 +356,9 @@ do
|
|||||||
--with-user=* )
|
--with-user=* )
|
||||||
default_user=`echo $option | sed -e 's/^.*=//;'`
|
default_user=`echo $option | sed -e 's/^.*=//;'`
|
||||||
;;
|
;;
|
||||||
|
--with-chronyc-user=* )
|
||||||
|
default_chronyc_user=`echo $option | sed -e 's/^.*=//;'`
|
||||||
|
;;
|
||||||
--with-hwclockfile=* )
|
--with-hwclockfile=* )
|
||||||
default_hwclockfile=`echo $option | sed -e 's/^.*=//;'`
|
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_PID_FILE "\"$default_pidfile\""
|
||||||
add_def DEFAULT_RTC_DEVICE "\"$default_rtcdevice\""
|
add_def DEFAULT_RTC_DEVICE "\"$default_rtcdevice\""
|
||||||
add_def DEFAULT_USER "\"$default_user\""
|
add_def DEFAULT_USER "\"$default_user\""
|
||||||
|
add_def DEFAULT_CHRONYC_USER "\"$default_chronyc_user\""
|
||||||
add_def DEFAULT_COMMAND_SOCKET "\"$CHRONYRUNDIR/chronyd.sock\""
|
add_def DEFAULT_COMMAND_SOCKET "\"$CHRONYRUNDIR/chronyd.sock\""
|
||||||
add_def MAIL_PROGRAM "\"$mail_program\""
|
add_def MAIL_PROGRAM "\"$mail_program\""
|
||||||
|
|
||||||
@@ -1123,6 +1129,7 @@ do
|
|||||||
s%@DEFAULT_PID_FILE@%${default_pidfile}%;\
|
s%@DEFAULT_PID_FILE@%${default_pidfile}%;\
|
||||||
s%@DEFAULT_RTC_DEVICE@%${default_rtcdevice}%;\
|
s%@DEFAULT_RTC_DEVICE@%${default_rtcdevice}%;\
|
||||||
s%@DEFAULT_USER@%${default_user}%;\
|
s%@DEFAULT_USER@%${default_user}%;\
|
||||||
|
s%@DEFAULT_CHRONYC_USER@%${default_chronyc_user}%;\
|
||||||
s%@CHRONY_VERSION@%${CHRONY_VERSION}%;" \
|
s%@CHRONY_VERSION@%${CHRONY_VERSION}%;" \
|
||||||
< ${f}.in > $f
|
< ${f}.in > $f
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ CHRONYRUNDIR = @CHRONYRUNDIR@
|
|||||||
CHRONYVARDIR = @CHRONYVARDIR@
|
CHRONYVARDIR = @CHRONYVARDIR@
|
||||||
CHRONY_VERSION = @CHRONY_VERSION@
|
CHRONY_VERSION = @CHRONY_VERSION@
|
||||||
DEFAULT_USER = @DEFAULT_USER@
|
DEFAULT_USER = @DEFAULT_USER@
|
||||||
|
DEFAULT_CHRONYC_USER = @DEFAULT_CHRONYC_USER@
|
||||||
DEFAULT_HWCLOCK_FILE = @DEFAULT_HWCLOCK_FILE@
|
DEFAULT_HWCLOCK_FILE = @DEFAULT_HWCLOCK_FILE@
|
||||||
DEFAULT_PID_FILE = @DEFAULT_PID_FILE@
|
DEFAULT_PID_FILE = @DEFAULT_PID_FILE@
|
||||||
DEFAULT_RTC_DEVICE = @DEFAULT_RTC_DEVICE@
|
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_PID_FILE\@%$(DEFAULT_PID_FILE)%g;\
|
||||||
s%\@DEFAULT_RTC_DEVICE\@%$(DEFAULT_RTC_DEVICE)%g;\
|
s%\@DEFAULT_RTC_DEVICE\@%$(DEFAULT_RTC_DEVICE)%g;\
|
||||||
s%\@DEFAULT_USER\@%$(DEFAULT_USER)%g;\
|
s%\@DEFAULT_USER\@%$(DEFAULT_USER)%g;\
|
||||||
|
s%\@DEFAULT_CHRONYC_USER\@%$(DEFAULT_CHRONYC_USER)%g;\
|
||||||
s%\@CHRONYRUNDIR\@%$(CHRONYRUNDIR)%g;\
|
s%\@CHRONYRUNDIR\@%$(CHRONYRUNDIR)%g;\
|
||||||
s%\@CHRONYVARDIR\@%$(CHRONYVARDIR)%g;"
|
s%\@CHRONYVARDIR\@%$(CHRONYVARDIR)%g;"
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
*chronyd* is using for its monitoring connections. This defaults to 323; there
|
||||||
would rarely be a need to change this.
|
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_::
|
*-f* _file_::
|
||||||
This option is ignored and is provided only for compatibility.
|
This option is ignored and is provided only for compatibility.
|
||||||
|
|
||||||
|
|||||||
@@ -390,7 +390,7 @@ run_chronyc() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
$CHRONYC_WRAPPER $wrapper_options \
|
$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
|
test_ok || test_error
|
||||||
[ $? -ne 0 ] && ret=1
|
[ $? -ne 0 ] && ret=1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user