xref: /freebsd/libexec/rc/rc.d/zfskeys (revision a90b9d0159070121c221b966469c3e36d912bf82)
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
24encode_args()
25{
26    shift && [ $# -gt 0 ] && printf "%s\0" "$@" | b64encode -r -
27}
28
29list_datasets()
30{
31    if [ "$zfskeys_args" ]; then
32        echo "$zfskeys_args" | b64decode -r |
33            xargs -0 zfs get -H -s local -o value,name keylocation
34    elif [ ! "$zfskeys_datasets" ]; then
35        zfs get -H -t filesystem,volume -s local -o value,name keylocation
36    else
37        echo "$zfskeys_datasets" | xargs -n 1 zfs get -H -s local \
38            -o value,name keylocation
39    fi
40}
41
42unlock_fs()
43{
44    local fs="$1"
45    local kl="$2"
46    local k="${kl##file://}"
47
48    if [ "$k" ] && [ -f "$k" ] && [ -s "$k" ] && [ -r "$k" ]; then
49        if [ "$(zfs get -Ho value keystatus "$fs")" = 'available' ]; then
50            echo "Key already loaded for $fs."
51        elif keytest=$(zfs load-key -n -L "$kl" "$fs" 2>&1); then
52            echo "Loading key for $fs from $kl.."
53            if ! keyload=$(timeout $zfskeys_timeout zfs load-key -L "$kl" "$fs" 2>&1) ; then
54                if [ $? -eq 124 ]; then
55                    echo "Timed out loading key from $kl for $fs"
56                else
57                    echo "Failed to load key from $kl for $fs:"
58                    echo "$keyload"
59                fi
60            fi
61        else
62            echo "Could not verify key from $kl for $fs:"
63            echo "$keytest"
64        fi
65    else
66        echo "Key file $k not found, empty or unreadable. Skipping $fs.."
67    fi
68}
69
70lock_fs()
71{
72    local fs=$1
73
74    if [ "$(zfs get -Ho value mounted "$fs")" = 'yes' ]; then
75        if checkyesno zfskeys_unload_force ; then
76            zfs unmount -f "$fs" && echo "Forcibly unmounted $fs."
77        else
78            zfs unmount "$fs" && echo "Unmounted $fs."
79        fi
80    fi
81    if [ "$?" -ne 0 ]; then
82        echo "Unmount failed for $fs"
83    elif [ "$(zfs get -Ho value keystatus "$fs")" = 'available' ]; then
84        zfs unload-key "$fs" && echo "Unloaded key for $fs."
85    else
86        echo "No key loaded for $fs."
87    fi
88}
89
90status_zfs_keys()
91{
92    local IFS=$(printf "\t")
93
94    list_datasets | while read kl fs ; do
95        echo "$fs: $(zfs get -Ho value keystatus "$fs")"
96    done
97}
98
99load_zfs_keys()
100{
101    local IFS=$(printf "\t")
102
103    list_datasets | while read kl fs ; do
104        unlock_fs "$fs" "$kl"
105    done
106}
107
108unload_zfs_keys()
109{
110    local IFS=$(printf "\t")
111
112    list_datasets | while read kl fs ; do
113        lock_fs "$fs"
114    done
115}
116
117zfskeys_args=$(encode_args "$@")
118load_rc_config $name
119
120# doesn't make sense to run in a svcj: config setting
121zfskeys_svcj="NO"
122
123run_rc_command "$1"
124