merge zfs-crypto-gate
authorDarren Moffat <Darren.Moffat@Sun.COM>
Thu, 18 Sep 2008 16:15:30 +0100
changeset 13383 2c9985a43a60
parent 13382 0804093b7482 (current diff)
parent 13381 79026c62a4bd (diff)
child 13384 541442f51ed9
merge zfs-crypto-gate
usr/src/lib/libzfs/common/libzfs.h
usr/src/lib/libzfs/common/libzfs_dataset.c
--- a/usr/src/lib/libzfs/common/libzfs.h	Thu Sep 18 16:14:35 2008 +0100
+++ b/usr/src/lib/libzfs/common/libzfs.h	Thu Sep 18 16:15:30 2008 +0100
@@ -357,6 +357,10 @@
 extern int zfs_ioctl(libzfs_handle_t *, int, struct zfs_cmd *);
 extern int zfs_crypto_create(libzfs_handle_t *, nvlist_t *, const char *path,
     struct zfs_cmd *);
+extern int zfs_crypto_clone(libzfs_handle_t *, const char *target,
+    const char *parent);
+extern int zfs_crypto_rename(libzfs_handle_t *, const char *target,
+    const char *parent);
 extern int zpool_crypto_create(libzfs_handle_t *, nvlist_t *, struct zfs_cmd *);
 extern int valid_keysource(char *);
 extern int valid_set_keysource_change(zfs_crypt_t *, char *, char *);
--- a/usr/src/lib/libzfs/common/libzfs_crypto.c	Thu Sep 18 16:14:35 2008 +0100
+++ b/usr/src/lib/libzfs/common/libzfs_crypto.c	Thu Sep 18 16:15:30 2008 +0100
@@ -1387,6 +1387,79 @@
 	return (keysource_prop_parser(src, &format, &locator, &uri));
 }
 
+/*
+ * zfs_crypto_clone/zfs_crypto_rename
+ *
+ * Validate that the clone/rename is okay to place in the tree at that
+ * location. 
+ *
+ * Just like we don't allow an encryption=off dataset to be created below
+ * and encrypted one we shouldn't allow a clone of an encryption=off dataset
+ * to be placed below an encrypted dataset either.
+ *
+ * If in the future we allow clones to have different keys from their
+ * parents some key setup may be required in here and zfs_crypto_rename
+ * will likely need split off.
+ */
+#pragma weak zfs_crypto_rename = zfs_crypto_clone
+int
+zfs_crypto_clone(libzfs_handle_t *hdl, const char *snapshot, const char *parent)
+{
+	int ret = 0;
+	zfs_handle_t *pzhp = NULL, *szhp = NULL;
+	uint64_t pcrypt = ZIO_CRYPT_INHERIT, scrypt = ZIO_CRYPT_INHERIT;
+
+	ASSERT(snapshot != NULL);
+	ASSERT(parent != NULL);
+
+	do {
+	    	pzhp = make_dataset_handle(hdl, parent);
+		if (pzhp == NULL) {
+			break;
+		}
+		pcrypt = zfs_prop_get_int(pzhp, ZFS_PROP_ENCRYPTION);
+	} while (pcrypt == ZIO_CRYPT_INHERIT);
+
+	if (pcrypt == ZIO_CRYPT_INHERIT) {
+		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+		    "failed to obtain parent encryption value."));
+		ret = -1;
+		goto out;
+	}
+
+	do {
+	    	szhp = make_dataset_handle(hdl, snapshot);
+		if (szhp == NULL) {
+			break;
+		}
+		scrypt = zfs_prop_get_int(szhp, ZFS_PROP_ENCRYPTION);
+	} while (scrypt == ZIO_CRYPT_INHERIT);
+
+	if (scrypt == ZIO_CRYPT_INHERIT) {
+		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+		    "failed to obtain source encryption value."));
+		ret = -1;
+		goto out;
+	}
+
+	ASSERT(scrypt != ZIO_CRYPT_INHERIT);
+	ASSERT(pcrypt != ZIO_CRYPT_INHERIT);
+
+	if (pcrypt != ZIO_CRYPT_OFF && scrypt == ZIO_CRYPT_OFF) {
+		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+		    "source must be encrypted."));
+		ret = -1;
+	}
+out:
+	if (pzhp != NULL) {
+		zfs_close(pzhp);
+	}
+	if (szhp != NULL) {
+		zfs_close(szhp);
+	}
+
+	return (ret);
+}
 
 /*
  * zfs_crypto_create
@@ -1520,7 +1593,7 @@
 
 		keysource = malloc(ZFS_MAXNAMELEN);
 		if (keysource == NULL) {
-			(void) fprintf(stderr, "Error in keysource malloc.");
+			no_memory(hdl);
 			return (-1);
 		}
 
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c	Thu Sep 18 16:14:35 2008 +0100
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c	Thu Sep 18 16:15:30 2008 +0100
@@ -1984,7 +1984,8 @@
 			break;
 
 		case ERANGE:
-			if (prop == ZFS_PROP_COMPRESSION) {
+			if (prop == ZFS_PROP_COMPRESSION ||
+			    prop == ZFS_PROP_ENCRYPTION) {
 				(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 				    "property setting is not allowed on "
 				    "bootable datasets"));
@@ -3368,6 +3369,8 @@
 
 		nvlist_free(props);
 	}
+	if (zfs_crypto_clone(hdl, zhp->zfs_name, parent) != 0)
+		return (zfs_error(hdl, EZFS_KEYERR, errbuf));
 
 	(void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name));
 	(void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value));
@@ -4013,6 +4016,9 @@
 	else
 		zc.zc_objset_type = DMU_OST_ZFS;
 
+	if (zfs_crypto_rename(hdl, zhp->zfs_name, parent) != 0)
+		return (zfs_error(hdl, EZFS_KEYERR, errbuf));
+	
 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
 	(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));