xref: /freebsd/libexec/rc/rc.d/zfskeys (revision 276a3dacdb60b65d65301aced5d8443cc5d27ea2)
1#!/bin/sh
2
3# PROVIDE: zfskeys
4# REQUIRE: zpool
5# BEFORE: zfs zvol
6
7. /etc/rc.subr
8
9name="zfskeys"
10desc="Load dataset keys"
11rcvar="zfskeys_enable"
12extra_commands="status"
13start_cmd="load_zfs_keys"
14stop_cmd="unload_zfs_keys"
15status_cmd="status_zfs_keys"
16required_modules="zfs"
17
18# Note that zfskeys_datasets must have any character found in IFS escaped.
19# Forcibly unmounting/unloading only applies to filesystems; ignored for zvols.
20: ${zfskeys_datasets:=''}
21: ${zfskeys_timeout:=10}
22: ${zfskeys_unload_force:='NO'}
23: ${zfskeys_prompt_enable:='NO'}
24
25encode_args()
26{
27    shift && [ $# -gt 0 ] && printf "%s\0" "$@" | b64encode -r -
28}
29
30list_datasets()
31{
32    if [ "$zfskeys_args" ]; then
33        echo "$zfskeys_args" | b64decode -r |
34            xargs -0 zfs get -H -s local -o value,name keylocation
35    elif [ ! "$zfskeys_datasets" ]; then
36        zfs get -H -t filesystem,volume -s local -o value,name keylocation
37    else
38        echo "$zfskeys_datasets" | xargs -n 1 zfs get -H -s local \
39            -o value,name keylocation
40    fi
41}
42
43unlock_fs()
44{
45    local fs="$1"
46    local kl="$2"
47    local k="${kl##file://}"
48
49    if [ "$kl" == "prompt" ]; then
50        if checkyesno zfskeys_prompt_enable ; then
51            echo "Key prompt for $fs."
52            if zfs load-key -L "$kl" "$fs" < /dev/tty > /dev/tty 2>/dev/tty ; then
53                echo "Key loaded for $fs."
54            else
55                echo "Key failed to load for $fs."
56            fi
57        fi
58    elif [ "$k" ] && [ -f "$k" ] && [ -s "$k" ] && [ -r "$k" ]; then
59        if [ "$(zfs get -Ho value keystatus "$fs")" = 'available' ]; then
60            echo "Key already loaded for $fs."
61        elif keytest=$(zfs load-key -n -L "$kl" "$fs" 2>&1); then
62            echo "Loading key for $fs from $kl.."
63            if ! keyload=$(timeout $zfskeys_timeout zfs load-key -L "$kl" "$fs" 2>&1) ; then
64                if [ $? -eq 124 ]; then
65                    echo "Timed out loading key from $kl for $fs"
66                else
67                    echo "Failed to load key from $kl for $fs:"
68                    echo "$keyload"
69                fi
70            fi
71        else
72            echo "Could not verify key from $kl for $fs:"
73            echo "$keytest"
74        fi
75    else
76        echo "Key file $k not found, empty or unreadable. Skipping $fs.."
77    fi
78}
79
80lock_fs()
81{
82    local fs=$1
83
84    if [ "$(zfs get -Ho value mounted "$fs")" = 'yes' ]; then
85        if checkyesno zfskeys_unload_force ; then
86            zfs unmount -f "$fs" && echo "Forcibly unmounted $fs."
87        else
88            zfs unmount "$fs" && echo "Unmounted $fs."
89        fi
90    fi
91    if [ "$?" -ne 0 ]; then
92        echo "Unmount failed for $fs"
93    elif [ "$(zfs get -Ho value keystatus "$fs")" = 'available' ]; then
94        zfs unload-key "$fs" && echo "Unloaded key for $fs."
95    else
96        echo "No key loaded for $fs."
97    fi
98}
99
100status_zfs_keys()
101{
102    local IFS=$(printf "\t")
103
104    list_datasets | while read kl fs ; do
105        echo "$fs: $(zfs get -Ho value keystatus "$fs")"
106    done
107}
108
109load_zfs_keys()
110{
111    local IFS=$(printf "\t")
112
113    list_datasets | while read kl fs ; do
114        unlock_fs "$fs" "$kl"
115    done
116}
117
118unload_zfs_keys()
119{
120    local IFS=$(printf "\t")
121
122    list_datasets | while read kl fs ; do
123        lock_fs "$fs"
124    done
125}
126
127zfskeys_args=$(encode_args "$@")
128load_rc_config $name
129
130# doesn't make sense to run in a svcj: config setting
131zfskeys_svcj="NO"
132
133run_rc_command "$1"
134