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