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