update to 4.4-pre1

This commit is contained in:
Miroslav Lichvar 2023-05-10 15:51:12 +02:00
parent 08a5b8042d
commit e3bd39f52e
5 changed files with 10 additions and 285 deletions

6
.gitignore vendored
View File

@ -1,3 +1,3 @@
/chrony-4.3.tar.gz
/chrony-4.3-tar-gz-asc.txt
/clknetsim-f00531.tar.gz
/chrony-4.4-pre1.tar.gz
/chrony-4.4-pre1-tar-gz-asc.txt
/clknetsim-13b0a5.tar.gz

View File

@ -1,191 +0,0 @@
commit 9cba9c8585bc5ebf19bafece118fb2362090547c
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Thu Jan 19 16:09:40 2023 +0100
keys+nts: warn if loading world-readable/writable key
Log a warning message if the file specified by the keyfile or
ntsserverkey directive is world-readable or writable, which is likely
an insecure misconfiguration. There is no check of directories
containing the file.
diff --git a/keys.c b/keys.c
index 11f8b761..9225e6cd 100644
--- a/keys.c
+++ b/keys.c
@@ -182,6 +182,9 @@ KEY_Reload(void)
if (!key_file)
return;
+ if (!UTI_CheckFilePermissions(key_file, 0771))
+ ;
+
in = UTI_OpenFile(NULL, key_file, NULL, 'r', 0);
if (!in) {
LOG(LOGS_WARN, "Could not open keyfile %s", key_file);
diff --git a/nts_ke_session.c b/nts_ke_session.c
index dfcd18ab..2ae1e915 100644
--- a/nts_ke_session.c
+++ b/nts_ke_session.c
@@ -667,6 +667,8 @@ create_credentials(const char **certs, const char **keys, int n_certs_keys,
assert(0);
for (i = 0; i < n_certs_keys; i++) {
+ if (!UTI_CheckFilePermissions(keys[i], 0771))
+ ;
r = gnutls_certificate_set_x509_key_file(credentials, certs[i], keys[i],
GNUTLS_X509_FMT_PEM);
if (r < 0)
diff --git a/util.c b/util.c
index 064292ce..4b9d30ee 100644
--- a/util.c
+++ b/util.c
@@ -1248,6 +1248,29 @@ UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid)
/* ================================================== */
+int
+UTI_CheckFilePermissions(const char *path, mode_t perm)
+{
+ mode_t extra_perm;
+ struct stat buf;
+
+ if (stat(path, &buf) < 0 || !S_ISREG(buf.st_mode)) {
+ /* Not considered an error */
+ return 1;
+ }
+
+ extra_perm = (buf.st_mode & 0777) & ~perm;
+ if (extra_perm != 0) {
+ LOG(LOGS_WARN, "%s permissions on %s", extra_perm & 0006 ?
+ (extra_perm & 0004 ? "World-readable" : "World-writable") : "Wrong", path);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* ================================================== */
+
static int
join_path(const char *basedir, const char *name, const char *suffix,
char *buffer, size_t length, LOG_Severity severity)
diff --git a/util.h b/util.h
index 4655e537..6844798c 100644
--- a/util.h
+++ b/util.h
@@ -196,6 +196,10 @@ extern int UTI_CreateDirAndParents(const char *path, mode_t mode, uid_t uid, gid
permissions and its uid/gid must match the specified values. */
extern int UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid_t gid);
+/* Check and log a warning message if a file has more permissions than
+ specified. It does not return error if it is not an accessible file. */
+extern int UTI_CheckFilePermissions(const char *path, mode_t perm);
+
/* Open a file. The full path of the file is constructed from the basedir
(may be NULL), '/' (if basedir is not NULL), name, and suffix (may be NULL).
Created files have specified permissions (umasked). Returns NULL on error.
commit 883b0dde946105e0910456a0bebb24d57fecb0fc
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Wed Jan 25 14:29:06 2023 +0100
conf: warn if not having read-only access to keys
After dropping root privileges, log a warning message if chronyd
doesn't have read access or has (unnecessary) write access to the
files containing symmetric and server NTS keys.
diff --git a/conf.c b/conf.c
index 9f42a426..0597836d 100644
--- a/conf.c
+++ b/conf.c
@@ -1774,6 +1774,19 @@ CNF_CreateDirs(uid_t uid, gid_t gid)
/* ================================================== */
+void
+CNF_CheckReadOnlyAccess(void)
+{
+ unsigned int i;
+
+ if (keys_file)
+ UTI_CheckReadOnlyAccess(keys_file);
+ for (i = 0; i < ARR_GetSize(nts_server_key_files); i++)
+ UTI_CheckReadOnlyAccess(*(char **)ARR_GetElement(nts_server_key_files, i));
+}
+
+/* ================================================== */
+
void
CNF_AddInitSources(void)
{
diff --git a/conf.h b/conf.h
index 11fd11df..d7acb4fd 100644
--- a/conf.h
+++ b/conf.h
@@ -44,6 +44,8 @@ extern void CNF_ParseLine(const char *filename, int number, char *line);
extern void CNF_CreateDirs(uid_t uid, gid_t gid);
+extern void CNF_CheckReadOnlyAccess(void);
+
extern void CNF_AddInitSources(void);
extern void CNF_AddSources(void);
extern void CNF_AddBroadcasts(void);
diff --git a/main.c b/main.c
index c40b5e4b..31e3c8f0 100644
--- a/main.c
+++ b/main.c
@@ -637,9 +637,13 @@ int main
}
/* Drop root privileges if the specified user has a non-zero UID */
- if (!geteuid() && (pw->pw_uid || pw->pw_gid))
+ if (!geteuid() && (pw->pw_uid || pw->pw_gid)) {
SYS_DropRoot(pw->pw_uid, pw->pw_gid, SYS_MAIN_PROCESS);
+ /* Warn if missing read access or having write access to keys */
+ CNF_CheckReadOnlyAccess();
+ }
+
if (!geteuid())
LOG(LOGS_WARN, "Running with root privileges");
diff --git a/util.c b/util.c
index 4b9d30ee..0321720e 100644
--- a/util.c
+++ b/util.c
@@ -1271,6 +1271,17 @@ UTI_CheckFilePermissions(const char *path, mode_t perm)
/* ================================================== */
+void
+UTI_CheckReadOnlyAccess(const char *path)
+{
+ if (access(path, R_OK) != 0 && errno != ENOENT)
+ LOG(LOGS_WARN, "Missing read access to %s : %s", path, strerror(errno));
+ if (access(path, W_OK) == 0)
+ LOG(LOGS_WARN, "Having write access to %s", path);
+}
+
+/* ================================================== */
+
static int
join_path(const char *basedir, const char *name, const char *suffix,
char *buffer, size_t length, LOG_Severity severity)
diff --git a/util.h b/util.h
index 6844798c..d8e25dee 100644
--- a/util.h
+++ b/util.h
@@ -200,6 +200,10 @@ extern int UTI_CheckDirPermissions(const char *path, mode_t perm, uid_t uid, gid
specified. It does not return error if it is not an accessible file. */
extern int UTI_CheckFilePermissions(const char *path, mode_t perm);
+/* Log a warning message if not having read access or having write access
+ to a file/directory */
+extern void UTI_CheckReadOnlyAccess(const char *path);
+
/* Open a file. The full path of the file is constructed from the basedir
(may be NULL), '/' (if basedir is not NULL), name, and suffix (may be NULL).
Created files have specified permissions (umasked). Returns NULL on error.

View File

@ -1,79 +0,0 @@
commit 6fba5a4a7fbe785849c0ec759e18bce0b7e234e4
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Tue Jan 10 15:02:49 2023 +0100
examples: add chronyd-restricted.service
This is a more restricted version of the chronyd service intended for
minimal NTP/NTS client configurations. The daemon is started without
root privileges and is allowed to write only to its own runtime, state,
and log directories. It cannot bind to privileged ports in order to
operate as an NTP server, or provide monitoring access over IPv4/IPv6.
It cannot use reference clocks, HW timestamping, RTC tracking, and other
features.
diff --git a/examples/chronyd-restricted.service b/examples/chronyd-restricted.service
new file mode 100644
index 00000000..50998338
--- /dev/null
+++ b/examples/chronyd-restricted.service
@@ -0,0 +1,59 @@
+# This is a more restricted version of the chronyd service intended for
+# minimal NTP/NTS client configurations. The daemon is started without root
+# privileges and is allowed to write only to its own runtime, state, and log
+# directories. It cannot bind to privileged ports in order to operate as an
+# NTP server, or provide monitoring access over IPv4/IPv6. It cannot use
+# reference clocks, HW timestamping, RTC tracking, and other features.
+[Unit]
+Description=NTP client (restricted)
+Documentation=man:chronyd(8) man:chrony.conf(5)
+After=chronyd.service ntpdate.service sntp.service ntpd.service
+Conflicts=chronyd.service ntpd.service systemd-timesyncd.service
+ConditionCapability=CAP_SYS_TIME
+
+[Service]
+Type=forking
+PIDFile=/run/chrony/chronyd.pid
+EnvironmentFile=-/etc/sysconfig/chronyd
+ExecStart=/usr/sbin/chronyd -U $OPTIONS
+
+User=chrony
+LogsDirectory=chrony
+LogsDirectoryMode=0750
+RuntimeDirectory=chrony
+RuntimeDirectoryMode=0750
+RuntimeDirectoryPreserve=restart
+StateDirectory=chrony
+StateDirectoryMode=0750
+
+AmbientCapabilities=CAP_SYS_TIME
+CapabilityBoundingSet=CAP_SYS_TIME
+DevicePolicy=closed
+LockPersonality=yes
+MemoryDenyWriteExecute=yes
+NoNewPrivileges=yes
+PrivateDevices=yes
+PrivateTmp=yes
+# This breaks adjtimex()
+#PrivateUsers=yes
+ProcSubset=pid
+ProtectControlGroups=yes
+ProtectHome=yes
+ProtectHostname=yes
+ProtectKernelLogs=yes
+ProtectKernelModules=yes
+ProtectKernelTunables=yes
+ProtectProc=invisible
+ProtectSystem=strict
+RemoveIPC=yes
+RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
+RestrictNamespaces=yes
+RestrictRealtime=yes
+RestrictSUIDSGID=yes
+SystemCallArchitectures=native
+SystemCallFilter=~@cpu-emulation @debug @module @mount @obsolete @raw-io
+SystemCallFilter=~@reboot @resources @swap
+UMask=0077
+
+[Install]
+WantedBy=multi-user.target

View File

@ -1,5 +1,6 @@
%global _hardened_build 1
%global clknetsim_ver f00531
%global clknetsim_ver 13b0a5
%global prerelease -pre1
%bcond_without debug
%bcond_without nts
@ -8,7 +9,7 @@
%endif
Name: chrony
Version: 4.3
Version: 4.4
Release: 3%{?dist}
Summary: An NTP client/server
@ -25,10 +26,6 @@ Source10: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/c
# add distribution-specific bits to DHCP dispatcher
Patch1: chrony-nm-dispatcher-dhcp.patch
# add chronyd-restricted service
Patch2: chrony-restricted.patch
# warn if keys are world-accessible or chronyd doesn't have read-only access
Patch3: chrony-keyaccess.patch
BuildRequires: libcap-devel libedit-devel nettle-devel pps-tools-devel
BuildRequires: gcc gcc-c++ make bison systemd gnupg2
@ -60,8 +57,6 @@ service to other computers in the network.
%setup -q -n %{name}-%{version}%{?prerelease} -a 10
%{?gitpatch:%patch0 -p1}
%patch1 -p1 -b .nm-dispatcher-dhcp
%patch2 -p1 -b .restricted
%patch3 -p1 -b .keyaccess
%{?gitpatch: echo %{version}-%{gitpatch} > version.txt}
@ -71,7 +66,7 @@ md5sum -c <<-EOF | (! grep -v 'OK$')
2d01b94bc1a7b7fb70cbee831488d121 examples/chrony.conf.example2
6a3178c4670de7de393d9365e2793740 examples/chrony.logrotate
c3992e2f985550739cd1cd95f98c9548 examples/chrony.nm-dispatcher.dhcp
2b81c60c020626165ac655b2633608eb examples/chrony.nm-dispatcher.onoffline
4e85d36595727318535af3387411070c examples/chrony.nm-dispatcher.onoffline
677ad16d6439daa369da44a1b75d1772 examples/chronyd.service
f092f965dc61f691ca838958eeeb3377 examples/chronyd-restricted.service
EOF

View File

@ -1,3 +1,3 @@
SHA512 (chrony-4.3.tar.gz) = 1394bac3ed684352fe89b7fef7da50e61f9f522abee807627ae1fc4c2dde891017bc8e5b13759fced028f3a1e875d5e4e5a4f85de65c63b5f83d0ca03bb4c5df
SHA512 (chrony-4.3-tar-gz-asc.txt) = 300b06f253ac3727edb86a1b7c337f9529ee752bbb471b266217b6a8ac5183e827264177a3210d436425d746673bf11fbdc41da145673213e28165197c6c76b7
SHA512 (clknetsim-f00531.tar.gz) = a44f543574519d1d5b5778f91b88fc73a976de511b97011c8ff3bc61a7ebff868fe9c6b46947ff4b58b29bd45520ffa68147934b1d289b1ffada4a329c048df5
SHA512 (chrony-4.4-pre1.tar.gz) = d251f822ff49be0ff691c41e08b2c68ca86c3c3b1896c11d8f72cb72c5d3fde38ec4609ffab2a737faf0824f603b6c36d56a827aacde3b296cadddca59ad7812
SHA512 (chrony-4.4-pre1-tar-gz-asc.txt) = b03592f26603403eaff2140f640f88408a1bd5be3468cf91fdd221fc9579611bdd475017a5803d7a5b1db08b11e20f260a4af91ee0a4d3b33ae6232b81a109fe
SHA512 (clknetsim-13b0a5.tar.gz) = e23b90bd0650502856ce472489d9ea0274aab7c1bd8945cac460f3a12338a509cad76133c60ccc2c7c31375496ec55b42c62008250109453f237ceb750bee03a