Print this page

        

@@ -78,10 +78,12 @@
 static int zpool_do_history(int, char **);
 
 static int zpool_do_get(int, char **);
 static int zpool_do_set(int, char **);
 
+static int zpool_do_key(int, char **);
+
 /*
  * These libumem hooks provide a reasonable set of defaults for the allocator's
  * debugging facilities.
  */
 

@@ -117,11 +119,12 @@
         HELP_REMOVE,
         HELP_SCRUB,
         HELP_STATUS,
         HELP_UPGRADE,
         HELP_GET,
-        HELP_SET
+        HELP_SET,
+        HELP_KEY
 } zpool_help_t;
 
 
 typedef struct zpool_command {
         const char      *name;

@@ -164,10 +167,12 @@
         { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
         { NULL },
         { "history",    zpool_do_history,       HELP_HISTORY            },
         { "get",        zpool_do_get,           HELP_GET                },
         { "set",        zpool_do_set,           HELP_SET                },
+        { NULL },
+        { "key",        zpool_do_key,           HELP_KEY                },
 };
 
 #define NCOMMAND        (sizeof (command_table) / sizeof (command_table[0]))
 
 zpool_command_t *current_command;

@@ -228,10 +233,13 @@
         case HELP_GET:
                 return (gettext("\tget <\"all\" | property[,...]> "
                     "<pool> ...\n"));
         case HELP_SET:
                 return (gettext("\tset <property=value> <pool> \n"));
+        case HELP_KEY:
+                return (gettext("\tkey <-l | -u | -c [ -o <property=value>]> "
+                    "<-a | pool>\n"));
         }
 
         abort();
         /* NOTREACHED */
 }

@@ -805,10 +813,11 @@
  */
 int
 zpool_do_destroy(int argc, char **argv)
 {
         boolean_t force = B_FALSE;
+        boolean_t encrypted_only = B_FALSE;
         int c;
         char *pool;
         zpool_handle_t *zhp;
         int ret;
 

@@ -849,11 +858,11 @@
                         (void) fprintf(stderr, gettext("use 'zfs destroy' to "
                             "destroy a dataset\n"));
                 return (1);
         }
 
-        if (zpool_disable_datasets(zhp, force) != 0) {
+        if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
                 (void) fprintf(stderr, gettext("could not destroy '%s': "
                     "could not unmount datasets\n"), zpool_get_name(zhp));
                 return (1);
         }
 

@@ -876,10 +885,11 @@
 int
 zpool_do_export(int argc, char **argv)
 {
         boolean_t force = B_FALSE;
         boolean_t hardforce = B_FALSE;
+        boolean_t encrypted_only = B_FALSE;
         int c;
         zpool_handle_t *zhp;
         int ret;
         int i;
 

@@ -913,11 +923,11 @@
                 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
                         ret = 1;
                         continue;
                 }
 
-                if (zpool_disable_datasets(zhp, force) != 0) {
+                if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) {
                         ret = 1;
                         zpool_close(zhp);
                         continue;
                 }
 

@@ -1261,10 +1271,11 @@
  */
 static int
 do_import(nvlist_t *config, const char *newname, const char *mntopts,
     int force, nvlist_t *props, boolean_t allowfaulted)
 {
+        boolean_t encrypted_only = B_FALSE;
         zpool_handle_t *zhp;
         char *name;
         uint64_t state;
         uint64_t version;
         int error = 0;

@@ -1321,18 +1332,40 @@
         if (newname != NULL)
                 name = (char *)newname;
 
         verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL);
 
+        /*
+         * Attempt to load the crypto keys before mounting up the datasets
+         * Note that depending on the value of the keysource property
+         * this could cause us to go interactive.
+         * We don't mind if this falls though and continue to enable what
+         * datasets we can if it does.
+         *
+         * Use zpool_load_key() and tell it we are doing an import rather than
+         * zpool_cmd_key_load().
+         *
+         * We then attempt enable all datasets not just the encrypted ones.
+         */
+
+        error = zpool_load_key(zhp, B_TRUE);
+        if (error != 0 && error != ENOTSUP) {
+                libzfs_handle_t *zpool_hdl = zpool_get_handle(zhp);
+                (void) fprintf(stderr, gettext(
+                    "%s.\nEncrypted datasets with keyscope=pool "
+                    "will not be mounted.\n"),
+                    libzfs_error_description(zpool_hdl));
+        }
+
         if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
-            zpool_enable_datasets(zhp, mntopts, 0) != 0) {
+            zpool_enable_datasets(zhp, mntopts, 0, encrypted_only) != 0) {
                 zpool_close(zhp);
                 return (1);
         }
 
         zpool_close(zhp);
-        return (error);
+        return (0);
 }
 
 /*
  * zpool import [-d dir] [-D]
  *       import [-o mntopts] [-o prop=value] ... [-R root] [-D]

@@ -2988,10 +3021,12 @@
         char *msgid;
         int reason;
         const char *health;
         uint_t c;
         vdev_stat_t *vs;
+        char keystatus[MAXNAMELEN];
+        zprop_source_t srctype;
 
         config = zpool_get_config(zhp, NULL);
         reason = zpool_get_status(zhp, &msgid);
 
         cbp->cb_count++;

@@ -3022,10 +3057,15 @@
         health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
 
         (void) printf(gettext("  pool: %s\n"), zpool_get_name(zhp));
         (void) printf(gettext(" state: %s\n"), health);
 
+        (void) zpool_get_prop(zhp, ZPOOL_PROP_KEYSTATUS, keystatus,
+            sizeof (keystatus), &srctype);
+
+        (void) printf(gettext("   key: %s\n"), keystatus);
+
         switch (reason) {
         case ZPOOL_STATUS_MISSING_DEV_R:
                 (void) printf(gettext("status: One or more devices could not "
                     "be opened.  Sufficient replicas exist for\n\tthe pool to "
                     "continue functioning in a degraded state.\n"));

@@ -3495,10 +3535,11 @@
                 (void) printf(gettext(" 11  Improved scrub performance\n"));
                 (void) printf(gettext(" 12  Snapshot properties\n"));
                 (void) printf(gettext(" 13  snapused property\n"));
                 (void) printf(gettext(" 14  passthrough-x aclinherit "
                     "support\n"));
+                (void) printf(gettext(" 15  Cryptographic support.\n"));
                 (void) printf(gettext("For more information on a particular "
                     "version, including supported releases, see:\n\n"));
                 (void) printf("http://www.opensolaris.org/os/community/zfs/"
                     "version/N\n\n");
                 (void) printf(gettext("Where 'N' is the version number.\n"));

@@ -3580,10 +3621,11 @@
         "snapshot",
         "filesystem version upgrade",
         "refquota set",
         "refreservation set",
         "pool scrub done",
+        "crypto key create",
 };
 
 /*
  * Print out the command history for a specific pool.
  */

@@ -3809,11 +3851,10 @@
 {
         int error;
         set_cbdata_t *cb = (set_cbdata_t *)data;
 
         error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
-
         if (!error)
                 cb->cb_any_successful = B_TRUE;
 
         return (error);
 }

@@ -3861,10 +3902,167 @@
             set_callback, &cb);
 
         return (error);
 }
 
+
+static int
+/* LINTED E_FUNC_ARG_UNUSED */
+key_callback_load(zpool_handle_t *zhp, void *data)
+{
+        int ret;
+        if (zpool_keysource_prompt(zhp)) {
+                char *smf_fmri = getenv("SMF_FMRI");
+
+                if (smf_fmri != NULL &&
+                    strcmp(smf_fmri, "svc:/system/device/local") == 0) {
+                        return (0);
+                }
+        }
+        ret = zpool_cmd_key_load(zhp);
+        if (ret != 0 && !(ret == EEXIST || ret == ENOTSUP)) {
+                return (1);
+        }
+
+        return (0);
+}
+
+static int
+/* LINTED E_FUNC_ARG_UNUSED */
+key_callback_unload(zpool_handle_t *zhp, void *data)
+{
+        int ret;
+
+        ret = zpool_cmd_key_unload(zhp);
+        if (ret != 0 && !(ret == ENOENT || ret == ENOTSUP)) {
+                return (1);
+        }
+
+        return (0);
+}
+
+
+static int
+zpool_do_key(int argc, char **argv)
+{
+        int error = 1, options = 0;
+        nvlist_t *props = NULL;
+        char c, *propval = NULL;
+        boolean_t load = B_FALSE, unload = B_FALSE, change = B_FALSE;
+        boolean_t do_all = B_FALSE;
+        zpool_handle_t *zhp = NULL;
+
+        while ((c = getopt(argc, argv, "aluco:")) != -1) {
+                switch (c) {
+                case 'a':
+                        do_all = B_TRUE;
+                        break;
+
+                case 'l':
+                        load = B_TRUE;
+                        break;
+
+                case 'u':
+                        unload = B_TRUE;
+                        break;
+
+                case 'c':
+                        change = B_TRUE;
+                        break;
+
+                case 'o':
+                        if ((propval = strchr(optarg, '=')) == NULL) {
+                                (void) fprintf(stderr, gettext("missing "
+                                    "'=' for -o option\n"));
+                                return (error);
+                        }
+
+                        *propval = '\0';
+                        propval++;
+                        if (strcmp(optarg, "keysource") != 0) {
+                                (void) fprintf(stderr, gettext(
+                                    "Invalid property for key change: "
+                                    "\"%s\"\n"),
+                                    optarg);
+                                return (error);
+                        }
+                        if (add_prop_list(optarg, propval, &props, B_TRUE))
+                                return (error);
+
+                        options += 2;
+                        break;
+
+                }
+        }
+
+        if (!change && props != NULL) {
+                (void) fprintf(stderr, gettext("Properties are not allowed to "
+                    "be used in this command.\n"));
+                goto error;
+        }
+
+        if (((load || unload) && (argc > 3)) ||
+            (change && ((argc - options) > 3))) {
+                        (void) fprintf(stderr,
+                            gettext("too many arguments\n"));
+                        usage(B_FALSE);
+                        goto error;
+        } else if ((load || unload) && (argc < 3)) {
+                        (void) fprintf(stderr, gettext("missing dataset "
+                            "argument (specify -a for all)\n"));
+                        usage(B_FALSE);
+                        goto error;
+        } else if (change && ((argc - options) < 3)) {
+                        (void) fprintf(stderr, gettext("missing dataset "
+                            "argument\n"));
+                        usage(B_FALSE);
+                        goto error;
+        }
+
+        if (do_all == B_FALSE) {
+                zhp = zpool_open(g_zfs, argv[argc - 1]);
+                if (zhp == NULL)
+                        goto error;
+        }
+
+        if (load) {
+                if (do_all)
+                        error = for_each_pool(0, NULL, B_TRUE, NULL,
+                            key_callback_load, NULL);
+                else
+                        error = zpool_cmd_key_load(zhp);
+
+        } else if (unload) {
+                if (do_all)
+                        error = for_each_pool(0, NULL, B_TRUE, NULL,
+                            key_callback_unload, NULL);
+                else
+                        error = zpool_cmd_key_unload(zhp);
+
+        } else if (change) {
+                if (do_all) {
+                        (void) fprintf(stderr, gettext("cannot use '-a' with "
+                            "change operation.\n"));
+                        usage(B_FALSE);
+                        goto error;
+                }
+
+                error = zpool_cmd_key_change(zhp, props);
+
+        } else
+                usage(B_FALSE);
+
+        if (zhp != NULL && !do_all)
+                zpool_close(zhp);
+
+error:
+        nvlist_free(props);
+        if (error != 0)
+                return (1);
+        return (0);
+}
+
 static int
 find_command_idx(char *command, int *idx)
 {
         int i;