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;