From 50330beda2c2f548e3eb6fe37b5cb14cb5df293e Mon Sep 17 00:00:00 2001 From: Anatol Pomozov Date: Fri, 5 Nov 2021 11:23:29 -0700 Subject: [PATCH 1/5] Add BSD_SOURCES to use setgroups at CentOS7 Per manpage here is requirement for setgroups(): Since glibc 2.19: _DEFAULT_SOURCE Glibc 2.19 and earlier: _BSD_SOURCE CentOS7 uses glibc-2.17 and thus requires _BSD_SOURCE. Without it we get following compilation error: src/luks/udisks2/clevis-luks-udisks2.c:327:13: error: implicit declaration of function 'setgroups' [-Werror=implicit-function-declaration] if (setgroups(1, &gid) != 0) { ^ --- src/luks/udisks2/clevis-luks-udisks2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/luks/udisks2/clevis-luks-udisks2.c b/src/luks/udisks2/clevis-luks-udisks2.c index 023c098d..d3e9f11d 100644 --- a/src/luks/udisks2/clevis-luks-udisks2.c +++ b/src/luks/udisks2/clevis-luks-udisks2.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#define _BSD_SOURCE + #include #include #include From 944f2869cb280fb9d0291bb6670f75b346f8328a Mon Sep 17 00:00:00 2001 From: Anatol Pomozov Date: Wed, 17 Nov 2021 12:21:20 -0800 Subject: [PATCH 2/5] Revert "systemd: drop hard requirement on networking" This reverts commit ba8fab247cd075e4ef882171774f67f33ce17d76. --- src/luks/systemd/clevis-luks-askpass.path | 8 ++++---- src/luks/systemd/clevis-luks-askpass.service.in | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/luks/systemd/clevis-luks-askpass.path b/src/luks/systemd/clevis-luks-askpass.path index 6c5333e7..61024a48 100644 --- a/src/luks/systemd/clevis-luks-askpass.path +++ b/src/luks/systemd/clevis-luks-askpass.path @@ -1,13 +1,13 @@ [Unit] Description=Forward Password Requests to Clevis Directory Watch Documentation=man:clevis-luks-unlockers(7) -DefaultDependencies=no -Before=cryptsetup-pre.target -Wants=cryptsetup-pre.target +Description=Clevis systemd-ask-password Watcher +Before=remote-fs-pre.target +Wants=remote-fs-pre.target [Path] DirectoryNotEmpty=/run/systemd/ask-password MakeDirectory=yes [Install] -WantedBy=cryptsetup.target +WantedBy=remote-fs.target diff --git a/src/luks/systemd/clevis-luks-askpass.service.in b/src/luks/systemd/clevis-luks-askpass.service.in index 6b4a7e31..a1b260a1 100644 --- a/src/luks/systemd/clevis-luks-askpass.service.in +++ b/src/luks/systemd/clevis-luks-askpass.service.in @@ -1,7 +1,8 @@ [Unit] Description=Forward Password Requests to Clevis Documentation=man:clevis-luks-unlockers(7) -DefaultDependencies=no +Requires=network-online.target +After=network-online.target [Service] Type=simple From add1863b8bdeb9faf9766264a23480e4cbc7772f Mon Sep 17 00:00:00 2001 From: Anatol Pomozov Date: Thu, 18 Nov 2021 13:44:13 -0800 Subject: [PATCH 3/5] work --- src/luks/clevis-luks-common-functions.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/luks/clevis-luks-common-functions.in b/src/luks/clevis-luks-common-functions.in index 743d638b..98d149b3 100644 --- a/src/luks/clevis-luks-common-functions.in +++ b/src/luks/clevis-luks-common-functions.in @@ -173,9 +173,12 @@ clevis_luks_print_pin_config() { local pin= case "${P}" in tang) + echo ${content} local url + local thp url="$(jose fmt -j- -g url -u- <<< "${content}")" - pin=$(printf '{"url":"%s"}' "${url}") + thp="$(jose fmt -j- -g thp -u- <<< "${content}")" + pin=$(printf '{"url":"%s", "thp":"%s"}' "${url}" "${thp}") printf "tang '%s'" "${pin}" ;; tpm2) From 919665328e5cd31628d32ced0ffd26dd2666c7ff Mon Sep 17 00:00:00 2001 From: Anatol Pomozov Date: Fri, 19 Nov 2021 10:54:25 -0800 Subject: [PATCH 4/5] Restore systemd and dracut hook from CentOS7 codebase It turns out that the new (CentOS8) dracut/systemd integration does not work well with CentOS7 environment. Tested: installed new clevis rpms at several hosts, regenerated dracut image with `dracut --force`, reboot the host and observe it unlocked. --- src/luks/systemd/clevis-luks-askpass.in | 64 +++++++++---------- .../systemd/dracut/clevis/module-setup.sh.in | 13 +--- 2 files changed, 33 insertions(+), 44 deletions(-) diff --git a/src/luks/systemd/clevis-luks-askpass.in b/src/luks/systemd/clevis-luks-askpass.in index a6699c9d..deeb2fda 100755 --- a/src/luks/systemd/clevis-luks-askpass.in +++ b/src/luks/systemd/clevis-luks-askpass.in @@ -1,5 +1,4 @@ -#!/bin/bash -set -eu +#!/bin/bash -e # vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: # # Copyright (c) 2016 Red Hat, Inc. @@ -20,60 +19,57 @@ set -eu # along with this program. If not, see . # -. clevis-luks-common-functions +UUID=cb6e8904-81ff-40da-a84a-07ab9ab5715e -# Make sure to exit cleanly if SIGTERM is received. -trap 'echo "Exiting due to SIGTERM" && exit 0' TERM +shopt -s nullglob -loop= -path=/run/systemd/ask-password -while getopts ":lp:" o; do - case "${o}" in +while getopts ":l" o; do + case "$o" in l) loop=true;; - p) path="${OPTARG}";; - *) ;; esac done while true; do - for question in "${path}"/ask.*; do - # question will expand to itself, in case no files match, so we verify - # whether it actually exists, before proceeding. - [ ! -e "${question}" ] && continue + todo=0 + for question in /run/systemd/ask-password/ask.*; do + metadata=false + unlocked=false d= s= - while read -r line; do + + while read line; do case "$line" in Id=cryptsetup:*) d="${line##Id=cryptsetup:}";; Socket=*) s="${line##Socket=}";; esac done < "$question" - [ -b "${d}" ] || continue - [ -S "${s}" ] || continue + [ -z "$d" -o -z "$s" ] && continue - if ! pt="$(clevis_luks_unlock_device "${d}")" || [ -z "${pt}" ]; then - continue - fi + # If the device is not initialized, sliently skip it. + luksmeta test -d "$d" || continue - uuid="$(cryptsetup luksUUID "${d}")" - if ! printf '%s' "${pt}" | @SYSTEMD_REPLY_PASS@ 1 "${s}"; then - echo "Unable to unlock ${d} (UUID=${uuid}) with recovered passphrase" >&2 - continue - fi + while read -r slot state uuid; do + [ "$state" != "active" ] && continue + [ "$uuid" != "$UUID" ] && continue + metadata=true - echo "Unlocked ${d} (UUID=${uuid}) successfully" >&2 - done + if pt="`luksmeta load -d $d -s $slot -u $UUID | clevis decrypt`"; then + echo -n "+$pt" | nc -U -u --send-only "$s" + unlocked=true + break + fi + done < <(luksmeta show -d "$d") - [ "${loop}" != true ] && break + [ $metadata == true ] || continue + [ $unlocked == true ] && continue + todo=$((todo + 1)) + done - # Checking for pending devices to be unlocked. - remaining_crypttab=$(clevis_devices_to_unlock) ||: - remaining_askfiles=$(ls "${path}"/ask.* 2>/dev/null) ||: - if [ -z "${remaining_crypttab}" ] && [ -z "${remaining_askfiles}" ]; then + if [ $todo -eq 0 ] || [ "$loop" != "true" ]; then break; fi sleep 0.5 -done +done \ No newline at end of file diff --git a/src/luks/systemd/dracut/clevis/module-setup.sh.in b/src/luks/systemd/dracut/clevis/module-setup.sh.in index bfe657c1..a38742d4 100755 --- a/src/luks/systemd/dracut/clevis/module-setup.sh.in +++ b/src/luks/systemd/dracut/clevis/module-setup.sh.in @@ -24,22 +24,15 @@ depends() { } install() { - if dracut_module_included "systemd"; then - inst_multiple \ - $systemdsystemunitdir/clevis-luks-askpass.service \ - $systemdsystemunitdir/clevis-luks-askpass.path - systemctl -q --root "$initdir" add-wants cryptsetup.target clevis-luks-askpass.path - else - inst_hook initqueue/online 60 "$moddir/clevis-hook.sh" - inst_hook initqueue/settled 60 "$moddir/clevis-hook.sh" - fi + inst_hook initqueue/online 60 "$moddir/clevis-hook.sh" + inst_hook initqueue/settled 60 "$moddir/clevis-hook.sh" inst_multiple \ /etc/services \ @SYSTEMD_REPLY_PASS@ \ @libexecdir@/clevis-luks-askpass \ clevis-luks-common-functions \ - grep sed cut \ + grep sed cut nc \ clevis-decrypt \ clevis-luks-list \ cryptsetup \ From 8d3a80dfb346827b02bd54a6647e4d72d46e252d Mon Sep 17 00:00:00 2001 From: Anatol Pomozov Date: Wed, 2 Nov 2022 11:34:29 -0700 Subject: [PATCH 5/5] sss: sss-encrypt must read pipe data until EOF is reached With current implementation sss-encrypt opens a pipe to the child pin, then tries to read this pipe *only once*. This might return only partial data or not data at all in case if the child pin response is slow. Fix it by reading the pipe until it is closed, and only then process the data. Also increase the response buffer from 1024 bytes to 4096 bytes to accound for larger subpin responses that can be larger than 1024 bytes. Fixes #389 --- src/pins/sss/clevis-encrypt-sss.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/pins/sss/clevis-encrypt-sss.c b/src/pins/sss/clevis-encrypt-sss.c index 1b2cc314..6eca611a 100644 --- a/src/pins/sss/clevis-encrypt-sss.c +++ b/src/pins/sss/clevis-encrypt-sss.c @@ -115,26 +115,34 @@ encrypt_frag(json_t *sss, const char *pin, const json_t *cfg, int assume_yes) if (!pipe) return NULL; + char buf[4096] = {}; + size_t rd = 0; + json_t *tmp = NULL; while (!feof(pipe)) { - char buf[1024] = {}; - json_t *tmp = NULL; - size_t rd = 0; + char tmp_buf[4096] = {}; + size_t tmp_rd = 0; - rd = fread(buf, 1, sizeof(buf), pipe); + tmp_rd = fread(tmp_buf, 1, sizeof(tmp_buf), pipe); if (ferror(pipe)) { fclose(pipe); return NULL; } - - tmp = json_pack("s+%", json_string_value(jwe), buf, rd); - if (!tmp) { + if (rd + tmp_rd > sizeof(buf)) { fclose(pipe); + fprintf(stderr, "sss: read buffer overflow\n"); return NULL; } - - json_decref(jwe); - jwe = tmp; + memcpy(buf + rd, tmp_buf, tmp_rd); + rd += tmp_rd; } + tmp = json_pack("s+%", json_string_value(jwe), buf, rd); + if (!tmp) { + fclose(pipe); + return NULL; + } + + json_decref(jwe); + jwe = tmp; fclose(pipe); waitpid(pid, &status, 0);