Skip to content

Commit 3708689

Browse files
libzfs: add keylocation=https://, backed by fetch(3) or libcurl
Add support for http and https to the keylocation properly to allow encryption keys to be fetched from the specified URL. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Ahelenia Ziemiańska <[email protected]> Issue #9543 Closes #9947 Closes #11956
1 parent 7d07d1b commit 3708689

31 files changed

+6977
-4282
lines changed

.github/workflows/zfs-tests-functional.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
2727
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
2828
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
29-
python3 python3-dev python3-setuptools python3-cffi
29+
python3 python3-dev python3-setuptools python3-cffi libcurl4-openssl-dev
3030
- name: Autogen.sh
3131
run: |
3232
sh autogen.sh

.github/workflows/zfs-tests-sanity.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
xfslibs-dev libattr1-dev libacl1-dev libudev-dev libdevmapper-dev \
2323
libssl-dev libffi-dev libaio-dev libelf-dev libmount-dev \
2424
libpam0g-dev pamtester python-dev python-setuptools python-cffi \
25-
python3 python3-dev python3-setuptools python3-cffi
25+
python3 python3-dev python3-setuptools python3-cffi libcurl4-openssl-dev
2626
- name: Autogen.sh
2727
run: |
2828
sh autogen.sh

config/Substfiles.am

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ subst_sed_cmd = \
1515
-e 's|@PYTHON[@]|$(PYTHON)|g' \
1616
-e 's|@PYTHON_SHEBANG[@]|$(PYTHON_SHEBANG)|g' \
1717
-e 's|@DEFAULT_INIT_NFS_SERVER[@]|$(DEFAULT_INIT_NFS_SERVER)|g' \
18-
-e 's|@DEFAULT_INIT_SHELL[@]|$(DEFAULT_INIT_SHELL)|g'
18+
-e 's|@DEFAULT_INIT_SHELL[@]|$(DEFAULT_INIT_SHELL)|g' \
19+
-e 's|@LIBFETCH_DYNAMIC[@]|$(LIBFETCH_DYNAMIC)|g' \
20+
-e 's|@LIBFETCH_SONAME[@]|$(LIBFETCH_SONAME)|g'
1921

2022
SUBSTFILES =
2123
CLEANFILES = $(SUBSTFILES)

config/user-libfetch.m4

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
dnl #
2+
dnl # Check for a libfetch - either fetch(3) or libcurl.
3+
dnl #
4+
dnl # There are two configuration dimensions:
5+
dnl # * fetch(3) vs libcurl
6+
dnl # * static vs dynamic
7+
dnl #
8+
dnl # fetch(3) is only dynamic.
9+
dnl # We use sover 6, which first appeared in FreeBSD 8.0-RELEASE.
10+
dnl #
11+
dnl # libcurl development packages include curl-config(1) – we want:
12+
dnl # * HTTPS support
13+
dnl # * version at least 7.16 (October 2006), for sover 4
14+
dnl # * to decide if it's static or not
15+
dnl #
16+
AC_DEFUN([ZFS_AC_CONFIG_USER_LIBFETCH], [
17+
AC_MSG_CHECKING([for libfetch])
18+
LIBFETCH_LIBS=
19+
LIBFETCH_IS_FETCH=0
20+
LIBFETCH_IS_LIBCURL=0
21+
LIBFETCH_DYNAMIC=0
22+
LIBFETCH_SONAME=
23+
have_libfetch=
24+
25+
saved_libs="$LIBS"
26+
LIBS="$LIBS -lfetch"
27+
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
28+
#include <sys/param.h>
29+
#include <stdio.h>
30+
#include <fetch.h>
31+
]], [fetchGetURL("", "");])], [
32+
have_libfetch=1
33+
LIBFETCH_IS_FETCH=1
34+
LIBFETCH_DYNAMIC=1
35+
LIBFETCH_SONAME='"libfetch.so.6"'
36+
LIBFETCH_LIBS="-ldl"
37+
AC_MSG_RESULT([fetch(3)])
38+
], [])
39+
LIBS="$saved_libs"
40+
41+
if test -z "$have_libfetch"; then
42+
if curl-config --protocols 2>/dev/null | grep -q HTTPS &&
43+
test "$(printf "%u" "0x$(curl-config --vernum)")" -ge "$(printf "%u" "0x071000")"; then
44+
have_libfetch=1
45+
LIBFETCH_IS_LIBCURL=1
46+
if test "$(curl-config --built-shared)" = "yes"; then
47+
LIBFETCH_DYNAMIC=1
48+
LIBFETCH_SONAME='"libcurl.so.4"'
49+
LIBFETCH_LIBS="-ldl"
50+
AC_MSG_RESULT([libcurl])
51+
else
52+
LIBFETCH_LIBS="$(curl-config --libs)"
53+
AC_MSG_RESULT([libcurl (static)])
54+
fi
55+
56+
CCFLAGS="$CCFLAGS $(curl-config --cflags)"
57+
fi
58+
fi
59+
60+
if test -z "$have_libfetch"; then
61+
AC_MSG_RESULT([none])
62+
fi
63+
64+
AC_SUBST([LIBFETCH_LIBS])
65+
AC_SUBST([LIBFETCH_DYNAMIC])
66+
AC_SUBST([LIBFETCH_SONAME])
67+
AC_DEFINE_UNQUOTED([LIBFETCH_IS_FETCH], [$LIBFETCH_IS_FETCH], [libfetch is fetch(3)])
68+
AC_DEFINE_UNQUOTED([LIBFETCH_IS_LIBCURL], [$LIBFETCH_IS_LIBCURL], [libfetch is libcurl])
69+
AC_DEFINE_UNQUOTED([LIBFETCH_DYNAMIC], [$LIBFETCH_DYNAMIC], [whether the chosen libfetch is to be loaded at run-time])
70+
AC_DEFINE_UNQUOTED([LIBFETCH_SONAME], [$LIBFETCH_SONAME], [soname of chosen libfetch])
71+
])

config/user.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER], [
2222
ZFS_AC_CONFIG_USER_LIBCRYPTO
2323
ZFS_AC_CONFIG_USER_LIBAIO
2424
ZFS_AC_CONFIG_USER_LIBATOMIC
25+
ZFS_AC_CONFIG_USER_LIBFETCH
2526
ZFS_AC_CONFIG_USER_CLOCK_GETTIME
2627
ZFS_AC_CONFIG_USER_PAM
2728
ZFS_AC_CONFIG_USER_RUNSTATEDIR

contrib/dracut/90zfs/module-setup.sh.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ install() {
5656
# Fallback: Guess the path and include all matches
5757
dracut_install /usr/lib/gcc/*/*/libgcc_s.so*
5858
fi
59+
if [ @LIBFETCH_DYNAMIC@ != 0 ]; then
60+
for d in $libdirs; do
61+
[ -e "$d"/@LIBFETCH_SONAME@ ] && dracut_install "$d"/@LIBFETCH_SONAME@
62+
done
63+
fi
5964
dracut_install @mounthelperdir@/mount.zfs
6065
dracut_install @udevdir@/vdev_id
6166
dracut_install awk

contrib/dracut/90zfs/zfs-env-bootfs.service.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Before=zfs-import.target
88

99
[Service]
1010
Type=oneshot
11-
ExecStart=/bin/sh -c "systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -v '^-$')"
11+
ExecStart=/bin/sh -c "exec systemctl set-environment BOOTFS=$(@sbindir@/zpool list -H -o bootfs | grep -m1 -v '^-$')"
1212

1313
[Install]
1414
WantedBy=zfs-import.target

contrib/dracut/90zfs/zfs-load-key.sh.in

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,14 @@ if [ "$(zpool list -H -o feature@encryption "$(echo "${BOOTFS}" | awk -F/ '{prin
4343
[ "$KEYSTATUS" = "unavailable" ] || exit 0
4444
# if key is stored in a file, do not prompt
4545
if ! [ "${KEYLOCATION}" = "prompt" ]; then
46+
if ! [ "${KEYLOCATION#http}" = "${KEYLOCATION}" ]; then
47+
systemctl start network-online.target
48+
fi
4649
zfs load-key "${ENCRYPTIONROOT}"
4750
else
4851
# decrypt them
49-
TRY_COUNT=5
50-
while [ $TRY_COUNT -gt 0 ]; do
52+
for _ in 1 2 3 4 5; do
5153
systemd-ask-password "Encrypted ZFS password for ${BOOTFS}" --no-tty | zfs load-key "${ENCRYPTIONROOT}" && break
52-
TRY_COUNT=$((TRY_COUNT - 1))
5354
done
5455
fi
5556
fi

contrib/dracut/90zfs/zfs-rollback-bootfs.service.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ ConditionKernelCommandLine=bootfs.rollback
1010
# ${BOOTFS} should have been set by zfs-env-bootfs.service
1111
Type=oneshot
1212
ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"'
13-
ExecStart=/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; @sbindir@/zfs rollback -Rf "${BOOTFS}@${SNAPNAME:-%v}"'
13+
ExecStart=/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; exec @sbindir@/zfs rollback -Rf "${BOOTFS}@${SNAPNAME:-%v}"'
1414
RemainAfterExit=yes

contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ ConditionKernelCommandLine=bootfs.snapshot
1010
# ${BOOTFS} should have been set by zfs-env-bootfs.service
1111
Type=oneshot
1212
ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"'
13-
ExecStart=-/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; @sbindir@/zfs snapshot "${BOOTFS}@${SNAPNAME:-%v}"'
13+
ExecStart=-/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "${BOOTFS}@${SNAPNAME:-%v}"'
1414
RemainAfterExit=yes

contrib/initramfs/hooks/zfs.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ mkdir -p "$DESTDIR/etc/"
6363
# multi-arch installations.
6464
cp --target-directory="$DESTDIR" --parents $(find /lib/ -type f -name libgcc_s.so.1)
6565

66+
if [ @LIBFETCH_DYNAMIC@ != 0 ]
67+
then
68+
for l in $(find /lib/ -name @LIBFETCH_SONAME@)
69+
do
70+
copy_exec "$l"
71+
done
72+
fi
73+
6674
for ii in $COPY_EXEC_LIST
6775
do
6876
copy_exec "$ii"

contrib/initramfs/scripts/zfs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -406,28 +406,25 @@ decrypt_fs()
406406
KEYSTATUS="$(get_fs_value "${ENCRYPTIONROOT}" keystatus)"
407407
# Continue only if the key needs to be loaded
408408
[ "$KEYSTATUS" = "unavailable" ] || return 0
409-
TRY_COUNT=3
410409

411-
# If key is stored in a file, do not prompt
410+
# Do not prompt if key is stored noninteractively,
412411
if ! [ "${KEYLOCATION}" = "prompt" ]; then
413412
$ZFS load-key "${ENCRYPTIONROOT}"
414413

415414
# Prompt with plymouth, if active
416-
elif [ -e /bin/plymouth ] && /bin/plymouth --ping 2>/dev/null; then
415+
elif /bin/plymouth --ping 2>/dev/null; then
417416
echo "plymouth" > /run/zfs_console_askpwd_cmd
418-
while [ $TRY_COUNT -gt 0 ]; do
417+
for _ in 1 2 3; do
419418
plymouth ask-for-password --prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}" | \
420419
$ZFS load-key "${ENCRYPTIONROOT}" && break
421-
TRY_COUNT=$((TRY_COUNT - 1))
422420
done
423421

424422
# Prompt with systemd, if active
425423
elif [ -e /run/systemd/system ]; then
426424
echo "systemd-ask-password" > /run/zfs_console_askpwd_cmd
427-
while [ $TRY_COUNT -gt 0 ]; do
425+
for _ in 1 2 3; do
428426
systemd-ask-password "Encrypted ZFS password for ${ENCRYPTIONROOT}" --no-tty | \
429427
$ZFS load-key "${ENCRYPTIONROOT}" && break
430-
TRY_COUNT=$((TRY_COUNT - 1))
431428
done
432429

433430
# Prompt with ZFS tty, otherwise

include/libzfs_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ struct libzfs_handle {
6969
boolean_t libzfs_prop_debug;
7070
regex_t libzfs_urire;
7171
uint64_t libzfs_max_nvlist;
72+
void *libfetch;
73+
char *libfetch_load_error;
7274
};
7375

7476
struct zfs_handle {

lib/libzfs/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ libzfs_la_LIBADD = \
7575
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
7676
$(abs_top_builddir)/lib/libuutil/libuutil.la
7777

78-
libzfs_la_LIBADD += -lm $(LIBCRYPTO_LIBS) $(ZLIB_LIBS) $(LTLIBINTL)
78+
libzfs_la_LIBADD += -lm $(LIBCRYPTO_LIBS) $(ZLIB_LIBS) $(LIBFETCH_LIBS) $(LTLIBINTL)
7979

8080
libzfs_la_LDFLAGS = -pthread
8181

0 commit comments

Comments
 (0)