Keys are created with 0440 mode

Resolves rhbz#2008204
This commit is contained in:
Sergio Correia 2021-09-29 10:13:42 -03:00
parent 2be74fe6bc
commit 70236c4767
No known key found for this signature in database
GPG Key ID: D0D219ED1F7E762C
3 changed files with 373 additions and 2 deletions

View File

@ -0,0 +1,207 @@
From b3d12b6a8f0ad7d56a584c1962e92f69b289a2a2 Mon Sep 17 00:00:00 2001
From: Sergio Correia <scorreia@redhat.com>
Date: Mon, 27 Sep 2021 15:19:42 -0300
Subject: [PATCH 3/3] keys: make sure keys are created with 0440 mode
There is no need for them to be readable by other than the owner/group.
Helpers (tangd-keygen and tangd-rotate-keys) also updated.
---
src/keys.c | 7 ++++++
src/tangd-keygen | 3 +++
src/tangd-rotate-keys | 1 +
tests/adv | 11 +++++++++
tests/helpers | 5 ++++
tests/rec | 3 +++
tests/test-keys.c.in | 54 +++++++++++++++++++++++++++++++++++++++++++
7 files changed, 84 insertions(+)
diff --git a/src/keys.c b/src/keys.c
index 55d0cff..a433f9c 100644
--- a/src/keys.c
+++ b/src/keys.c
@@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
@@ -337,6 +338,12 @@ create_new_keys(const char* jwkdir)
fprintf(stderr, "Error saving JWK to file (%s)\n", path);
return 0;
}
+
+ /* Set 0440 permission for the new key. */
+ if (chmod(path, S_IRUSR | S_IRGRP) == -1) {
+ fprintf(stderr, "Unable to set permissions for JWK file (%s)\n", path);
+ return 0;
+ }
}
return 1;
}
diff --git a/src/tangd-keygen b/src/tangd-keygen
index f37121f..ed51124 100755
--- a/src/tangd-keygen
+++ b/src/tangd-keygen
@@ -34,7 +34,10 @@ THP_DEFAULT_HASH=S256 # SHA-256.
jwe=$(jose jwk gen -i '{"alg":"ES512"}')
[ -z "$sig" ] && sig=$(echo "$jwe" | jose jwk thp -i- -a "${THP_DEFAULT_HASH}")
echo "$jwe" > "$1/$sig.jwk"
+chmod 0440 "$1/$sig.jwk"
+
jwe=$(jose jwk gen -i '{"alg":"ECMR"}')
[ -z "$exc" ] && exc=$(echo "$jwe" | jose jwk thp -i- -a "${THP_DEFAULT_HASH}")
echo "$jwe" > "$1/$exc.jwk"
+chmod 0440 "$1/$exc.jwk"
diff --git a/src/tangd-rotate-keys b/src/tangd-rotate-keys
index a095a91..8649652 100755
--- a/src/tangd-rotate-keys
+++ b/src/tangd-rotate-keys
@@ -78,6 +78,7 @@ cd "${JWKDIR}" || error "Unable to change to keys directory '${JWKDIR}'"
thp="$(printf '%s' "${jwe}" | jose jwk thp --input=- \
-a "${DEFAULT_THP_HASH}")"
echo "${jwe}" > "${thp}.jwk"
+ chmod 0440 "${thp}.jwk"
log "Created new key ${thp}.jwk" "${VERBOSE}"
done
cd - >/dev/null
diff --git a/tests/adv b/tests/adv
index 4c8bc97..1fde37e 100755
--- a/tests/adv
+++ b/tests/adv
@@ -27,6 +27,10 @@ export TMP=`mktemp -d`
mkdir -p $TMP/db
tangd-keygen $TMP/db sig exc
+# Make sure keys generated by tangd-keygen have proper permissions.
+valid_key_perm "${TMP}/db/sig.jwk"
+valid_key_perm "${TMP}/db/exc.jwk"
+
jose jwk gen -i '{"alg": "ES512"}' -o $TMP/db/.sig.jwk
jose jwk gen -i '{"alg": "ES512"}' -o $TMP/db/.oth.jwk
@@ -96,6 +100,10 @@ for i in 1 2 3 4 5 6 7 8 9; do
# Make sure the requested keys exist and are valid.
validate_sig "${TMP}/db/other-sig-${i}.jwk"
validate_exc "${TMP}/db/other-exc-${i}.jwk"
+
+ # Make sure keys generated by tangd-keygen have proper permissions.
+ valid_key_perm "${TMP}/db/other-sig-${i}.jwk"
+ valid_key_perm "${TMP}/db/other-exc-${i}.jwk"
done
# Verify the advertisement is correct.
@@ -121,6 +129,9 @@ thp=
for jwk in "${TMP}"/db/*.jwk; do
validate_sig "${jwk}" && thp="$(jose jwk thp -a "${THP_DEFAULT_HASH}" \
-i "${jwk}")"
+
+ # Make sure keys generated by tangd-rotate-keys have proper permissions.
+ valid_key_perm "${jwk}"
done
[ -z "${thp}" ] && die "There should be valid keys after rotation"
test "$(tang-show-keys $PORT)" = "${thp}"
diff --git a/tests/helpers b/tests/helpers
index 7ce54d7..8b789fb 100755
--- a/tests/helpers
+++ b/tests/helpers
@@ -75,3 +75,8 @@ die() {
echo "${1}" >&2
exit 1
}
+
+valid_key_perm() {
+ _perm="$(stat -c %a "${1}")"
+ [ "${_perm}" = "440" ]
+}
diff --git a/tests/rec b/tests/rec
index af0d075..7fba6a9 100755
--- a/tests/rec
+++ b/tests/rec
@@ -28,6 +28,9 @@ mkdir -p $TMP/db
# Generate the server keys
tangd-keygen $TMP/db sig exc
+# Make sure keys generated by tangd-keygen have proper permissions.
+valid_key_perm "${TMP}/db/sig.jwk"
+valid_key_perm "${TMP}/db/exc.jwk"
# Generate the client keys
exc_kid=`jose jwk thp -i $TMP/db/exc.jwk`
diff --git a/tests/test-keys.c.in b/tests/test-keys.c.in
index 1f811f3..fca26c4 100644
--- a/tests/test-keys.c.in
+++ b/tests/test-keys.c.in
@@ -32,6 +32,56 @@ struct test_result_int {
int expected;
};
+static void
+verify_keys_permissions(const char* targetdir)
+{
+ struct stat st;
+ struct dirent* d;
+ DIR* dir = opendir(targetdir);
+ ASSERT(dir);
+ char filepath[PATH_MAX];
+ const char* pattern = ".jwk";
+ while ((d = readdir(dir)) != NULL) {
+ if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) {
+ continue;
+ }
+
+ char* dot = strrchr(d->d_name, '.');
+ if (!dot) {
+ continue;
+ }
+
+ if (strcmp(dot, pattern) == 0) {
+ /* Found a file with .jwk extension. */
+ if (snprintf(filepath, PATH_MAX, "%s/%s", targetdir, d->d_name) < 0) {
+ fprintf(stderr, "Unable to prepare variable with file full path (%s); skipping\n", d->d_name);
+ continue;
+ }
+ filepath[sizeof(filepath) - 1] = '\0';
+ ASSERT(stat(filepath, &st) == 0);
+
+ ASSERT_WITH_MSG(st.st_mode & (S_IRUSR | S_IRGRP), "key = %s, missing perm (0%o)", filepath, (S_IRUSR | S_IRGRP));
+ int unexpected_perms[] = {
+ S_ISUID, /* 04000 set-user-ID */
+ S_ISGID, /* 02000 set-group-ID */
+ S_IWUSR, /* 00200 write by owner */
+ S_IXUSR, /* 00100 execute/search by owner */
+ S_IWGRP, /* 00020 write by group */
+ S_IXGRP, /* 00010 execute/search by group */
+ S_IROTH, /* 00004 read by others */
+ S_IWOTH, /* 00002 write by others */
+ S_IXOTH, /* 00001 execute/search by others */
+ 0
+ };
+ for (int i = 0; unexpected_perms[i] != 0; i++) {
+ ASSERT_WITH_MSG((st.st_mode & unexpected_perms[i]) == 0, "key = %s, i = %d, unexpected perm (0%o)", filepath, i, unexpected_perms[i]);
+ }
+
+ }
+ }
+ closedir(dir);
+}
+
static void
test_create_new_keys(void)
{
@@ -40,6 +90,10 @@ test_create_new_keys(void)
__attribute__((cleanup(cleanup_tang_keys_info))) struct tang_keys_info* tki = read_keys(newdir);
ASSERT(tki);
ASSERT(tki->m_keys_count == 2);
+
+ /* Make sure keys have proper permissions. */
+ verify_keys_permissions(newdir);
+
remove_tempdir(newdir);
}
--
2.31.1

View File

@ -0,0 +1,147 @@
From ab3b913cc74666dffe56d1f87f6f90653d8f4e70 Mon Sep 17 00:00:00 2001
From: Sergio Correia <scorreia@redhat.com>
Date: Sat, 2 Oct 2021 09:14:21 -0300
Subject: [PATCH 4/4] Specify user and group for tang
So that we can run tang itself with a different user.
Systemd unit and helpers for rotating keys updated to use the
new user and group.
---
meson.build | 2 ++
meson_options.txt | 2 ++
src/meson.build | 18 ++++++++++++++++--
src/{tangd-keygen => tangd-keygen.in} | 11 +++++++++--
...{tangd-rotate-keys => tangd-rotate-keys.in} | 9 ++++++++-
units/tangd@.service.in | 1 +
6 files changed, 38 insertions(+), 5 deletions(-)
create mode 100644 meson_options.txt
rename src/{tangd-keygen => tangd-keygen.in} (85%)
rename src/{tangd-rotate-keys => tangd-rotate-keys.in} (92%)
diff --git a/meson.build b/meson.build
index 1733d47..7664e05 100644
--- a/meson.build
+++ b/meson.build
@@ -26,6 +26,8 @@ data.set('libexecdir', libexecdir)
data.set('sysconfdir', sysconfdir)
data.set('systemunitdir', systemunitdir)
data.set('jwkdir', jwkdir)
+data.set('user', get_option('user'))
+data.set('group', get_option('group'))
add_project_arguments(
'-D_POSIX_C_SOURCE=200809L',
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..9b1f7c6
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,2 @@
+option('user', type: 'string', value: 'tang', description: 'Unprivileged user for tang operations')
+option('group', type: 'string', value: 'tang', description: 'Unprivileged group for tang operations')
diff --git a/src/meson.build b/src/meson.build
index e7dc60c..f022775 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -7,8 +7,22 @@ tangd = executable('tangd',
install_dir: libexecdir
)
+tangd_keygen = configure_file(
+ input: 'tangd-keygen.in',
+ output: 'tangd-keygen',
+ configuration: data,
+ install: true,
+ install_dir: libexecdir
+)
+
+tangd_rotate_keys = configure_file(
+ input: 'tangd-rotate-keys.in',
+ output: 'tangd-rotate-keys',
+ configuration: data,
+ install: true,
+ install_dir: libexecdir
+)
+
bins += join_paths(meson.current_source_dir(), 'tang-show-keys')
-libexecbins += join_paths(meson.current_source_dir(), 'tangd-keygen')
-libexecbins += join_paths(meson.current_source_dir(), 'tangd-rotate-keys')
# vim:set ts=2 sw=2 et:
diff --git a/src/tangd-keygen b/src/tangd-keygen.in
similarity index 85%
rename from src/tangd-keygen
rename to src/tangd-keygen.in
index ed51124..f74b86f 100755
--- a/src/tangd-keygen
+++ b/src/tangd-keygen.in
@@ -25,6 +25,13 @@ usage() {
exit 1
}
+set_perms() {
+ chmod 0440 -- "${1}"
+ if ! chown @user@:@group@ -- "${1}" 2>/dev/null; then
+ echo "Unable to change owner/group for ${1} to @user@:@group@" >&2
+ fi
+}
+
[ $# -ne 1 ] && [ $# -ne 3 ] && usage
[ -d "$1" ] || usage
@@ -34,10 +41,10 @@ THP_DEFAULT_HASH=S256 # SHA-256.
jwe=$(jose jwk gen -i '{"alg":"ES512"}')
[ -z "$sig" ] && sig=$(echo "$jwe" | jose jwk thp -i- -a "${THP_DEFAULT_HASH}")
echo "$jwe" > "$1/$sig.jwk"
-chmod 0440 "$1/$sig.jwk"
+set_perms "$1/$sig.jwk"
jwe=$(jose jwk gen -i '{"alg":"ECMR"}')
[ -z "$exc" ] && exc=$(echo "$jwe" | jose jwk thp -i- -a "${THP_DEFAULT_HASH}")
echo "$jwe" > "$1/$exc.jwk"
-chmod 0440 "$1/$exc.jwk"
+set_perms "$1/$exc.jwk"
diff --git a/src/tangd-rotate-keys b/src/tangd-rotate-keys.in
similarity index 92%
rename from src/tangd-rotate-keys
rename to src/tangd-rotate-keys.in
index 8649652..56b94ad 100755
--- a/src/tangd-rotate-keys
+++ b/src/tangd-rotate-keys.in
@@ -48,6 +48,13 @@ error() {
usage 1
}
+set_perms() {
+ chmod 0440 -- "${1}"
+ if ! chown @user@:@group@ -- "${1}" 2>/dev/null; then
+ echo "Unable to change owner/group for ${1} to @user@:@group@" >&2
+ fi
+}
+
JWKDIR=
VERBOSE=
while getopts "hvd:" o; do
@@ -78,7 +85,7 @@ cd "${JWKDIR}" || error "Unable to change to keys directory '${JWKDIR}'"
thp="$(printf '%s' "${jwe}" | jose jwk thp --input=- \
-a "${DEFAULT_THP_HASH}")"
echo "${jwe}" > "${thp}.jwk"
- chmod 0440 "${thp}.jwk"
+ set_perms "${thp}.jwk"
log "Created new key ${thp}.jwk" "${VERBOSE}"
done
cd - >/dev/null
diff --git a/units/tangd@.service.in b/units/tangd@.service.in
index f1db261..aeb2dc1 100644
--- a/units/tangd@.service.in
+++ b/units/tangd@.service.in
@@ -6,3 +6,4 @@ StandardInput=socket
StandardOutput=socket
StandardError=journal
ExecStart=@libexecdir@/tangd @jwkdir@
+User=@user@
--
2.31.1

View File

@ -1,6 +1,6 @@
Name: tang
Version: 10
Release: 3%{?dist}
Release: 4%{?dist}
Summary: Network Presence Binding Daemon
License: GPLv3+
@ -9,6 +9,8 @@ Source0: https://github.com/latchset/%{name}/releases/download/v%{version
Patch0001: 0001-Fix-issues-reported-by-shellcheck.patch
Patch0002: 0002-Fix-possible-NULL-pointer-dereference-in-find_by_thp.patch
Patch0003: 0003-keys-make-sure-keys-are-created-with-0440-mode.patch
Patch0004: 0004-Specify-user-and-group-for-tang.patch
BuildRequires: gcc
BuildRequires: meson
@ -51,7 +53,6 @@ Tang is a small daemon for binding data to the presence of a third party.
%install
%meson_install
echo "User=%{name}" >> $RPM_BUILD_ROOT/%{_unitdir}/%{name}d@.service
%{__mkdir_p} $RPM_BUILD_ROOT/%{_localstatedir}/db/%{name}
%check
@ -67,6 +68,18 @@ exit 0
%post
%systemd_post %{name}d.socket
# Let's make sure any existing keys are readable only
# by the owner/group.
if [ -d /var/db/tang ]; then
for k in /var/db/tang/*.jwk; do
chmod 0440 -- "${k}"
done
for k in /var/db/tang/.*.jwk; do
chmod 0440 -- "${k}"
done
chown tang:tang -R /var/db/tang
fi
%preun
%systemd_preun %{name}d.socket
@ -86,6 +99,10 @@ exit 0
%{_mandir}/man1/tang-show-keys.1*
%changelog
* Mon Oct 04 2021 Sergio Correia <scorreia@redhat.com> - 10-4
- Keys are created with 0440 mode
Resolves rhbz#2008204
* Fri Jul 23 2021 Fedora Release Engineering <releng@fedoraproject.org> - 10-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild