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