From 70236c47675257dd83df25f05ee1739260873153 Mon Sep 17 00:00:00 2001 From: Sergio Correia Date: Oct 04 2021 12:22:29 +0000 Subject: Keys are created with 0440 mode Resolves rhbz#2008204 --- diff --git a/0003-keys-make-sure-keys-are-created-with-0440-mode.patch b/0003-keys-make-sure-keys-are-created-with-0440-mode.patch new file mode 100644 index 0000000..795af3e --- /dev/null +++ b/0003-keys-make-sure-keys-are-created-with-0440-mode.patch @@ -0,0 +1,207 @@ +From b3d12b6a8f0ad7d56a584c1962e92f69b289a2a2 Mon Sep 17 00:00:00 2001 +From: Sergio Correia +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 . + */ + ++#include + #include + #include + #include +@@ -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 + diff --git a/0004-Specify-user-and-group-for-tang.patch b/0004-Specify-user-and-group-for-tang.patch new file mode 100644 index 0000000..ebeed45 --- /dev/null +++ b/0004-Specify-user-and-group-for-tang.patch @@ -0,0 +1,147 @@ +From ab3b913cc74666dffe56d1f87f6f90653d8f4e70 Mon Sep 17 00:00:00 2001 +From: Sergio Correia +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 + diff --git a/tang.spec b/tang.spec index 19bf466..5ab33fe 100644 --- a/tang.spec +++ b/tang.spec @@ -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 - 10-4 +- Keys are created with 0440 mode + Resolves rhbz#2008204 + * Fri Jul 23 2021 Fedora Release Engineering - 10-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild