--- old/usr/src/cmd/zpool/zpool_main.c Tue Feb 3 13:17:21 2009 +++ new/usr/src/cmd/zpool/zpool_main.c Tue Feb 3 13:17:20 2009 @@ -80,6 +80,8 @@ 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. @@ -119,7 +121,8 @@ HELP_STATUS, HELP_UPGRADE, HELP_GET, - HELP_SET + HELP_SET, + HELP_KEY } zpool_help_t; @@ -166,6 +169,8 @@ { "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])) @@ -230,6 +235,9 @@ " ...\n")); case HELP_SET: return (gettext("\tset \n")); + case HELP_KEY: + return (gettext("\tkey <-l | -u | -c [ -o ]> " + "<-a | pool>\n")); } abort(); @@ -807,6 +815,7 @@ 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; @@ -851,7 +860,7 @@ 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); @@ -878,6 +887,7 @@ { boolean_t force = B_FALSE; boolean_t hardforce = B_FALSE; + boolean_t encrypted_only = B_FALSE; int c; zpool_handle_t *zhp; int ret; @@ -915,7 +925,7 @@ continue; } - if (zpool_disable_datasets(zhp, force) != 0) { + if (zpool_disable_datasets(zhp, force, encrypted_only) != 0) { ret = 1; zpool_close(zhp); continue; @@ -1263,6 +1273,7 @@ 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; @@ -1323,14 +1334,36 @@ 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); } /* @@ -2990,6 +3023,8 @@ 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); @@ -3024,6 +3059,11 @@ (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 " @@ -3497,6 +3537,7 @@ (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/" @@ -3582,6 +3623,7 @@ "refquota set", "refreservation set", "pool scrub done", + "crypto key create", }; /* @@ -3811,7 +3853,6 @@ 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; @@ -3863,6 +3904,163 @@ 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) {