16ccda740Sloli#!/bin/ksh -p
26ccda740Sloli#
36ccda740Sloli# CDDL HEADER START
46ccda740Sloli#
56ccda740Sloli# This file and its contents are supplied under the terms of the
66ccda740Sloli# Common Development and Distribution License ("CDDL"), version 1.0.
76ccda740Sloli# You may only use this file in accordance with the terms of version
86ccda740Sloli# 1.0 of the CDDL.
96ccda740Sloli#
106ccda740Sloli# A full copy of the text of the CDDL should have accompanied this
116ccda740Sloli# source.  A copy of the CDDL is also available via the Internet at
126ccda740Sloli# http://www.illumos.org/license/CDDL.
136ccda740Sloli#
146ccda740Sloli# CDDL HEADER END
156ccda740Sloli#
166ccda740Sloli
176ccda740Sloli#
186ccda740Sloli# Copyright (c) 2018 by Datto Inc. All rights reserved.
19*e3bf7d5aSKody Kantor# Copyright 2020 Joyent, Inc.
206ccda740Sloli#
216ccda740Sloli
226ccda740Sloli. $STF_SUITE/tests/functional/rsend/rsend.kshlib
236ccda740Sloli
246ccda740Sloli#
256ccda740Sloli# DESCRIPTION:
266ccda740Sloli# Verify that zfs properly handles encryption properties when receiving
276ccda740Sloli# send streams.
286ccda740Sloli#
296ccda740Sloli# STRATEGY:
306ccda740Sloli# 1. Create a few unencrypted and encrypted test datasets with some data
316ccda740Sloli# 2. Take snapshots of these datasets in preparation for sending
326ccda740Sloli# 3. Verify that 'zfs recv -o keylocation=prompt' fails
336ccda740Sloli# 4. Verify that 'zfs recv -x <encryption prop>' fails on a raw send stream
346ccda740Sloli# 5. Verify that encryption properties cannot be changed on incrementals
356ccda740Sloli# 6. Verify that a simple send can be received as an encryption root
366ccda740Sloli# 7. Verify that an unencrypted props send can be received as an
376ccda740Sloli#    encryption root
386ccda740Sloli# 8. Verify that an unencrypted recursive send can be received as an
396ccda740Sloli#    encryption root
406ccda740Sloli# 9. Verify that an unencrypted props send can be received as an
416ccda740Sloli#    encryption child
426ccda740Sloli# 10. Verify that an unencrypted recursive send can be received as an
436ccda740Sloli#     encryption child
446ccda740Sloli#
456ccda740Sloli
466ccda740Sloliverify_runnable "both"
476ccda740Sloli
486ccda740Slolifunction cleanup
496ccda740Sloli{
506ccda740Sloli	destroy_dataset $TESTPOOL/recv "-r"
516ccda740Sloli	destroy_dataset $TESTPOOL/crypt "-r"
526ccda740Sloli	destroy_dataset $TESTPOOL/ds "-r"
536ccda740Sloli	[[ -f $sendfile ]] && log_must rm $sendfile
546ccda740Sloli	[[ -f $keyfile ]] && log_must rm $keyfile
556ccda740Sloli}
566ccda740Slolilog_onexit cleanup
576ccda740Sloli
586ccda740Slolilog_assert "'zfs recv' must properly handle encryption properties"
596ccda740Sloli
606ccda740Slolitypeset keyfile=/$TESTPOOL/pkey
616ccda740Slolitypeset sendfile=/$TESTPOOL/sendfile
628675de3aSTom Caputitypeset snap=$TESTPOOL/ds@snap1
638675de3aSTom Caputitypeset snap2=$TESTPOOL/ds@snap2
646ccda740Slolitypeset esnap=$TESTPOOL/crypt@snap1
656ccda740Slolitypeset esnap2=$TESTPOOL/crypt@snap2
666ccda740Sloli
676ccda740Slolilog_must eval "echo 'password' > $keyfile"
686ccda740Sloli
696ccda740Slolilog_must zfs create $TESTPOOL/ds
706ccda740Slolilog_must zfs create $TESTPOOL/ds/ds1
716ccda740Sloli
726ccda740Slolilog_must zfs create -o encryption=on -o keyformat=passphrase \
736ccda740Sloli	-o keylocation=file://$keyfile $TESTPOOL/crypt
746ccda740Slolilog_must zfs create $TESTPOOL/crypt/ds1
756ccda740Slolilog_must zfs create -o keyformat=passphrase -o keylocation=file://$keyfile \
766ccda740Sloli	$TESTPOOL/crypt/ds2
776ccda740Sloli
786ccda740Slolilog_must mkfile 1M /$TESTPOOL/ds/$TESTFILE0
796ccda740Slolilog_must cp /$TESTPOOL/ds/$TESTFILE0 /$TESTPOOL/crypt/$TESTFILE0
80*e3bf7d5aSKody Kantortypeset cksum=$(digest -a md5 /$TESTPOOL/ds/$TESTFILE0)
816ccda740Sloli
826ccda740Slolilog_must zfs snap -r $snap
838675de3aSTom Caputilog_must zfs snap -r $snap2
846ccda740Slolilog_must zfs snap -r $esnap
856ccda740Slolilog_must zfs snap -r $esnap2
866ccda740Sloli
876ccda740Sloli# Embedded data is incompatible with encrypted datasets, so we cannot
886ccda740Sloli# allow embedded streams to be received.
896ccda740Slolilog_note "Must not be able to receive an embedded stream as encrypted"
906ccda740Slolilog_mustnot eval "zfs send -e $TESTPOOL/crypt/ds1 | zfs recv $TESTPOOL/recv"
916ccda740Sloli
926ccda740Sloli# We currently don't have an elegant and secure way to pass the passphrase
936ccda740Sloli# in via prompt because the send stream itself is using stdin.
946ccda740Slolilog_note "Must not be able to use 'keylocation=prompt' on receive"
956ccda740Slolilog_must eval "zfs send $snap > $sendfile"
966ccda740Slolilog_mustnot eval "zfs recv -o encryption=on -o keyformat=passphrase" \
976ccda740Sloli	"$TESTPOOL/recv < $sendfile"
986ccda740Slolilog_mustnot eval "zfs recv -o encryption=on -o keyformat=passphrase" \
996ccda740Sloli	"-o keylocation=prompt $TESTPOOL/recv < $sendfile"
1006ccda740Sloli
1016ccda740Sloli# Raw sends do not have access to the decrypted data so we cannot override
1026ccda740Sloli# the encryption settings without losing the data.
1036ccda740Slolilog_note "Must not be able to disable encryption properties on raw send"
1046ccda740Slolilog_must eval "zfs send -w $esnap > $sendfile"
1056ccda740Slolilog_mustnot eval "zfs recv -x encryption $TESTPOOL/recv < $sendfile"
1066ccda740Slolilog_mustnot eval "zfs recv -x keyformat $TESTPOOL/recv < $sendfile"
1076ccda740Slolilog_mustnot eval "zfs recv -x pbkdf2iters $TESTPOOL/recv < $sendfile"
1086ccda740Sloli
1096ccda740Sloli# Encryption properties are set upon creating the dataset. Changing them
1106ccda740Sloli# afterwards requires using 'zfs change-key' or an update from a raw send.
1116ccda740Slolilog_note "Must not be able to change encryption properties on incrementals"
1126ccda740Slolilog_must eval "zfs send $esnap | zfs recv -o encryption=on" \
1136ccda740Sloli	"-o keyformat=passphrase -o keylocation=file://$keyfile $TESTPOOL/recv"
1146ccda740Slolilog_mustnot eval "zfs send -i $esnap $esnap2 |" \
1156ccda740Sloli	"zfs recv -o encryption=aes-128-ccm $TESTPOOL/recv"
1166ccda740Slolilog_mustnot eval "zfs send -i $esnap $esnap2 |" \
1176ccda740Sloli	"zfs recv -o keyformat=hex $TESTPOOL/recv"
1186ccda740Slolilog_mustnot eval "zfs send -i $esnap $esnap2 |" \
1196ccda740Sloli	"zfs recv -o pbkdf2iters=100k $TESTPOOL/recv"
1206ccda740Slolilog_must zfs destroy -r $TESTPOOL/recv
1216ccda740Sloli
1226ccda740Sloli# Test that we can receive a simple stream as an encryption root.
1236ccda740Slolilog_note "Must be able to receive stream as encryption root"
1246ccda740Slolids=$TESTPOOL/recv
1256ccda740Slolilog_must eval "zfs send $snap > $sendfile"
1266ccda740Slolilog_must eval "zfs recv -o encryption=on -o keyformat=passphrase" \
1276ccda740Sloli	"-o keylocation=file://$keyfile $ds < $sendfile"
1286ccda740Slolilog_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
1296ccda740Slolilog_must test "$(get_prop 'encryptionroot' $ds)" == "$ds"
1306ccda740Slolilog_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
1316ccda740Slolilog_must test "$(get_prop 'keylocation' $ds)" == "file://$keyfile"
1326ccda740Slolilog_must test "$(get_prop 'mounted' $ds)" == "yes"
133*e3bf7d5aSKody Kantorrecv_cksum=$(digest -a md5 /$ds/$TESTFILE0)
1346ccda740Slolilog_must test "$recv_cksum" == "$cksum"
1356ccda740Slolilog_must zfs destroy -r $ds
1366ccda740Sloli
1376ccda740Sloli# Test that we can override encryption properties on a properties stream
1386ccda740Sloli# of an unencrypted dataset, turning it into an encryption root.
1396ccda740Slolilog_note "Must be able to receive stream with props as encryption root"
1406ccda740Slolids=$TESTPOOL/recv
1416ccda740Slolilog_must eval "zfs send -p $snap > $sendfile"
1426ccda740Slolilog_must eval "zfs recv -o encryption=on -o keyformat=passphrase" \
1436ccda740Sloli	"-o keylocation=file://$keyfile $ds < $sendfile"
1446ccda740Slolilog_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
1456ccda740Slolilog_must test "$(get_prop 'encryptionroot' $ds)" == "$ds"
1466ccda740Slolilog_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
1476ccda740Slolilog_must test "$(get_prop 'keylocation' $ds)" == "file://$keyfile"
1486ccda740Slolilog_must test "$(get_prop 'mounted' $ds)" == "yes"
149*e3bf7d5aSKody Kantorrecv_cksum=$(digest -a md5 /$ds/$TESTFILE0)
1506ccda740Slolilog_must test "$recv_cksum" == "$cksum"
1516ccda740Slolilog_must zfs destroy -r $ds
1526ccda740Sloli
1536ccda740Sloli# Test that we can override encryption properties on a recursive stream
1546ccda740Sloli# of an unencrypted dataset, turning it into an encryption root. The root
1556ccda740Sloli# dataset of the stream should become an encryption root with all children
1566ccda740Sloli# inheriting from it.
1576ccda740Slolilog_note "Must be able to receive recursive stream as encryption root"
1586ccda740Slolids=$TESTPOOL/recv
1596ccda740Slolilog_must eval "zfs send -R $snap > $sendfile"
1606ccda740Slolilog_must eval "zfs recv -o encryption=on -o keyformat=passphrase" \
1616ccda740Sloli	"-o keylocation=file://$keyfile $ds < $sendfile"
1626ccda740Slolilog_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
1636ccda740Slolilog_must test "$(get_prop 'encryptionroot' $ds)" == "$ds"
1646ccda740Slolilog_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
1656ccda740Slolilog_must test "$(get_prop 'keylocation' $ds)" == "file://$keyfile"
1666ccda740Slolilog_must test "$(get_prop 'mounted' $ds)" == "yes"
167*e3bf7d5aSKody Kantorrecv_cksum=$(digest -a md5 /$ds/$TESTFILE0)
1686ccda740Slolilog_must test "$recv_cksum" == "$cksum"
1696ccda740Slolilog_must zfs destroy -r $ds
1706ccda740Sloli
1716ccda740Sloli# Test that we can override an unencrypted properties stream's encryption
1726ccda740Sloli# settings, receiving it as an encrypted child.
1736ccda740Slolilog_note "Must be able to receive stream with props to encrypted child"
1746ccda740Slolids=$TESTPOOL/crypt/recv
1756ccda740Slolilog_must eval "zfs send -p $snap > $sendfile"
1766ccda740Slolilog_must eval "zfs recv -x encryption $ds < $sendfile"
1776ccda740Slolilog_must test "$(get_prop 'encryptionroot' $ds)" == "$TESTPOOL/crypt"
1786ccda740Slolilog_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
1796ccda740Slolilog_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
1806ccda740Slolilog_must test "$(get_prop 'mounted' $ds)" == "yes"
181*e3bf7d5aSKody Kantorrecv_cksum=$(digest -a md5 /$ds/$TESTFILE0)
1826ccda740Slolilog_must test "$recv_cksum" == "$cksum"
1836ccda740Slolilog_must zfs destroy -r $ds
1846ccda740Sloli
1858675de3aSTom Caputi# Test that we can override an unencrypted, incremental, properties stream's
1868675de3aSTom Caputi# encryption settings, receiving it as an unencrypted child.
1878675de3aSTom Caputilog_note "Must be able to receive incremental stream with props to encrypted"
1888675de3aSTom Caputids=$TESTPOOL/crypt/recv
1898675de3aSTom Caputilog_must eval "zfs send -p $snap > $sendfile"
1908675de3aSTom Caputilog_must eval "zfs recv -x encryption $ds < $sendfile"
1918675de3aSTom Caputilog_must test "$(get_prop 'encryptionroot' $ds)" == "$TESTPOOL/crypt"
1928675de3aSTom Caputilog_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
1938675de3aSTom Caputilog_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
1948675de3aSTom Caputilog_must test "$(get_prop 'mounted' $ds)" == "yes"
195*e3bf7d5aSKody Kantorrecv_cksum=$(digest -a md5 /$ds/$TESTFILE0)
1968675de3aSTom Caputilog_must test "$recv_cksum" == "$cksum"
1978675de3aSTom Caputilog_must zfs destroy -r $ds
1988675de3aSTom Caputi
1996ccda740Sloli# Test that we can override an unencrypted recursive stream's encryption
2006ccda740Sloli# settings, receiving all datasets as encrypted children.
2016ccda740Slolilog_note "Must be able to receive recursive stream to encrypted child"
2026ccda740Slolids=$TESTPOOL/crypt/recv
2038675de3aSTom Caputilog_must eval "zfs send -R $snap2 > $sendfile"
2046ccda740Slolilog_must eval "zfs recv -x encryption $ds < $sendfile"
2056ccda740Slolilog_must test "$(get_prop 'encryptionroot' $ds)" == "$TESTPOOL/crypt"
2066ccda740Slolilog_must test "$(get_prop 'encryption' $ds)" == "aes-256-ccm"
2076ccda740Slolilog_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
2086ccda740Slolilog_must test "$(get_prop 'mounted' $ds)" == "yes"
209*e3bf7d5aSKody Kantorrecv_cksum=$(digest -a md5 /$ds/$TESTFILE0)
2106ccda740Slolilog_must test "$recv_cksum" == "$cksum"
2116ccda740Slolilog_must zfs destroy -r $ds
2126ccda740Sloli
2136ccda740Sloli# Check that we haven't printed the key to the zpool history log
2146ccda740Slolilog_mustnot eval "zpool history -i | grep -q 'wkeydata'"
2156ccda740Sloli
2166ccda740Slolilog_pass "'zfs recv' properly handles encryption properties"
217