/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <locale.h>
#include <libgen.h>
#include <zone.h>
#include <cryptoutil.h>
#include "cryptoadm.h"
/* subcommand index */
enum subcommand_index {
CRYPTO_HELP };
/*
* TRANSLATION_NOTE
* Command keywords are not to be translated.
*/
static char *cmd_table[] = {
"list",
"disable",
"enable",
"install",
"uninstall",
"unload",
"refresh",
"start",
"stop",
"--help" };
/* provider type */
enum provider_type_index {
PROV_BADNAME };
typedef struct {
/*
* TRANSLATION_NOTE
* Operand keywords are not to be translated.
*/
/* static variables */
/* static functions */
static void usage(void);
static int get_provider_type(char *);
static int process_mech_operands(int, char **, boolean_t);
static int do_list(int, char **);
static int do_disable(int, char **);
static int do_enable(int, char **);
static int do_install(int, char **);
static int do_uninstall(int, char **);
static int do_unload(int, char **);
static int do_refresh(int);
static int do_start(int);
static int do_stop(int);
static int list_simple_for_all(boolean_t);
static int list_mechlist_for_all(boolean_t);
static int list_policy_for_all(void);
int
{
char *subcmd;
int cmdnum;
int cmd_index = 0;
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
if (argc < REQ_ARG_CNT) {
usage();
return (ERROR_USAGE);
}
/* get the subcommand index */
cmd_index = 0;
cmd_index++;
}
usage();
return (ERROR_USAGE);
}
/* do the subcommand */
switch (cmd_index) {
case CRYPTO_LIST:
break;
case CRYPTO_DISABLE:
break;
case CRYPTO_ENABLE:
break;
case CRYPTO_INSTALL:
break;
case CRYPTO_UNINSTALL:
break;
case CRYPTO_UNLOAD:
break;
case CRYPTO_REFRESH:
break;
case CRYPTO_START:
break;
case CRYPTO_STOP:
break;
case CRYPTO_HELP:
usage();
break;
default: /* should not come here */
usage();
rc = ERROR_USAGE;
break;
}
return (rc);
}
static void
usage(void)
{
/*
* TRANSLATION_NOTE
* Command usage is not to be translated. Only the word "Usage:"
* along with localized expressions indicating what kind of value
* is expected for arguments.
*/
" cryptoadm list [-mpv] [provider=<%s> | metaslot]"
" [mechanism=<%s>]\n",
" cryptoadm disable provider=<%s>"
" mechanism=<%s> | random | all\n",
" cryptoadm disable metaslot"
" [auto-key-migrate] [mechanism=<%s>]\n",
gettext("mechanism-list"));
" cryptoadm enable provider=<%s>"
" mechanism=<%s> | random | all\n",
" cryptoadm enable metaslot [mechanism=<%s>]"
" [[token=<%s>] [slot=<%s>]"
" | [default-keystore]] | [auto-key-migrate]\n",
gettext("slot-description"));
" cryptoadm install provider=<%s>\n",
gettext("provider-name"));
" cryptoadm install provider=<%s> [mechanism=<%s>]\n",
" cryptoadm uninstall provider=<%s>\n",
gettext("provider-name"));
" cryptoadm unload provider=<%s>\n",
gettext("provider-name"));
" cryptoadm refresh\n"
" cryptoadm start\n"
" cryptoadm stop\n"
" cryptoadm --help\n");
}
/*
* Get the provider type. This function returns
* - PROV_UEF_LIB if provname contains an absolute path name
* - PROV_KEF_SOFT if provname is a base name only (e.g., "aes").
* - PROV_KEF_HARD if provname contains one slash only and the slash is not
* the 1st character (e.g., "mca/0").
* - PROV_BADNAME otherwise.
*/
static int
{
char *pslash1;
char *pslash2;
return (FAILURE);
}
if (provname[0] == '/') {
return (PROV_UEF_LIB);
/* no slash */
return (PROV_KEF_SOFT);
} else {
return (PROV_KEF_HARD);
} else {
return (PROV_BADNAME);
}
}
}
/*
* Get the provider structure. This function returns NULL if no valid
* provider= is found in argv[], otherwise a cryptoadm_provider_t is returned.
* If provider= is found but has no argument, then a cryptoadm_provider_t
* with cp_type = PROV_BADNAME is returned.
*/
static cryptoadm_provider_t *
{
int c = 0;
strlen(METASLOT_KEYWORD)) == 0) {
strlen(KN_PROVIDER)) == 0 &&
/*
* TRANSLATION_NOTE
* "get_provider" is a function name and should
* not be translated.
*/
return (NULL);
}
}
}
if (!found)
return (NULL);
if (provstr) {
}
return (NULL);
}
if (is_metaslot) {
} else {
return (provider);
}
}
return (provider);
}
/*
* Process the "feature" operands.
*
* "argc" and "argv" contain values specified on the command line.
* All other arguments are used for returning parsing results.
* If any of these arguments are NULL, that keyword is not expected,
* and FAILURE will be returned.
*/
static int
{
int c = 2;
while (++c < argc) {
/* process mechanism operands */
!= SUCCESS) {
goto finish;
}
char *tmp;
} else {
return (FAILURE);
}
} else {
return (FAILURE);
}
char *tmp;
} else {
return (FAILURE);
}
} else {
return (FAILURE);
}
strlen(KN_DEFAULT_KS)) == 0) {
if (use_default) {
*use_default = B_TRUE;
} else {
return (FAILURE);
}
strlen(KN_AUTO_KEY_MIGRATE)) == 0) {
if (auto_key_migrate_flag) {
} else {
return (FAILURE);
}
} else {
return (FAILURE);
}
}
return (rc);
}
/*
* Process the "feature" operands.
*/
static int
{
int c = 2;
while (++c < argc) {
}
}
return (SUCCESS);
}
/*
* Process the mechanism operands for the disable, enable and install
* subcommands. This function sets the static variable allflag to be B_TRUE
* if the keyword "all" is specified, otherwise builds a link list of the
* mechanism operands and save it in the static variable mecharglist.
*
* This function returns
* ERROR_USAGE: mechanism operand is missing.
* FAILURE: out of memory.
* SUCCESS: otherwise.
*/
static int
{
int c = -1;
}
}
if (!found) {
if (!quiet)
/*
* TRANSLATION_NOTE
* "mechanism" could be either a literal keyword
* and hence not to be translated, or a descriptive
* word and translatable. A choice was made to
* view it as a literal keyword.
*/
gettext("the %s operand is missing.\n"),
"mechanism");
return (ERROR_USAGE);
}
mecharglist = NULL;
return (SUCCESS);
}
do {
break;
} else {
} else {
}
}
} else {
mecharglist = phead;
}
return (rc);
}
/*
* The top level function for the "cryptoadm list" subcommand and options.
*/
static int
{
char ch;
argc -= 1;
argv += 1;
if (argc == 1) {
goto out;
}
/*
* cryptoadm list [-v] [-m] [-p] [provider=<>] [mechanism=<>]
*/
if (argc > 5) {
usage();
return (rc);
}
switch (ch) {
case 'm':
if (pflag) {
rc = ERROR_USAGE;
}
break;
case 'p':
rc = ERROR_USAGE;
}
break;
case 'v':
if (pflag)
rc = ERROR_USAGE;
break;
default:
rc = ERROR_USAGE;
break;
}
}
if (rc == ERROR_USAGE) {
usage();
return (rc);
}
goto out;
}
if (argc > 0) {
goto out;
/* "-m" is implied when a mechanism list is given */
}
}
if (mflag) {
} else if (pflag) {
rc = list_policy_for_all();
} else if (vflag) {
}
/* no flag is specified, just list metaslot status */
} else if (pflag) {
rc = list_metaslot_policy();
} else {
/* error message */
usage();
rc = ERROR_USAGE;
}
usage();
rc = ERROR_USAGE;
goto out;
} else { /* do the listing for a provider only */
if (vflag)
provname);
case PROV_UEF_LIB:
break;
case PROV_KEF_SOFT:
break;
case PROV_KEF_HARD:
break;
default: /* should not come here */
break;
}
} else if (pflag) {
case PROV_UEF_LIB:
break;
case PROV_KEF_SOFT:
if (getzoneid() == GLOBAL_ZONEID) {
} else {
/*
* TRANSLATION_NOTE
* "global" is keyword and not to
* be translated.
*/
"policy information for kernel "
"providers is available "
"in the %s zone only"), "global");
}
break;
case PROV_KEF_HARD:
if (getzoneid() == GLOBAL_ZONEID) {
} else {
/*
* TRANSLATION_NOTE
* "global" is keyword and not to
* be translated.
*/
"policy information for kernel "
"providers is available "
"in the %s zone only"), "global");
}
break;
default: /* should not come here */
break;
}
} else {
/* error message */
usage();
rc = ERROR_USAGE;
}
}
out:
if (mecharglist != NULL)
return (rc);
}
/*
* The top level function for the "cryptoadm disable" subcommand.
*/
static int
{
usage();
return (ERROR_USAGE);
}
usage();
return (ERROR_USAGE);
}
return (FAILURE);
}
goto out;
}
/*
* If allflag or rndflag has already been set there is no reason to
* process mech=
*/
if ((argc > 3) &&
usage();
return (rc);
}
return (rc);
}
case METASLOT:
break;
case PROV_UEF_LIB:
break;
case PROV_KEF_SOFT:
break;
}
}
if (getzoneid() == GLOBAL_ZONEID) {
} else {
/*
* TRANSLATION_NOTE
* "disable" could be either a literal keyword
* and hence not to be translated, or a verb and
* translatable. A choice was made to view it as
* a literal keyword. "global" is keyword and not
* to be translated.
*/
"providers is supported in the %2$s zone only"),
"disable", "global");
}
break;
case PROV_KEF_HARD:
break;
}
}
if (getzoneid() == GLOBAL_ZONEID) {
} else {
/*
* TRANSLATION_NOTE
* "disable" could be either a literal keyword
* and hence not to be translated, or a verb and
* translatable. A choice was made to view it as
* a literal keyword. "global" is keyword and not
* to be translated.
*/
"providers is supported in the %2$s zone only"),
"disable", "global");
}
break;
default: /* should not come here */
break;
}
out:
if (mecharglist != NULL) {
}
return (rc);
}
/*
* The top level function for the "cryptoadm enable" subcommand.
*/
static int
{
usage();
return (ERROR_USAGE);
}
usage();
return (ERROR_USAGE);
}
usage();
return (ERROR_USAGE);
}
goto out;
}
!= SUCCESS) {
usage();
goto out;
}
usage();
goto out;
}
} else {
goto out;
}
/*
* If allflag or rndflag has already been set there is
* no reason to process mech=
*/
!= SUCCESS) {
goto out;
}
}
case METASLOT:
break;
case PROV_UEF_LIB:
break;
case PROV_KEF_SOFT:
case PROV_KEF_HARD:
break;
}
}
if (getzoneid() == GLOBAL_ZONEID) {
} else {
/*
* TRANSLATION_NOTE
* "enable" could be either a literal keyword
* and hence not to be translated, or a verb and
* translatable. A choice was made to view it as
* a literal keyword. "global" is keyword and not
* to be translated.
*/
"providers is supported in the %2$s zone only"),
"enable", "global");
}
break;
default: /* should not come here */
break;
}
out:
if (mecharglist != NULL) {
}
}
}
return (rc);
}
/*
* The top level function for the "cryptoadm install" subcommand.
*/
static int
{
int rc;
if (argc < 3) {
usage();
return (ERROR_USAGE);
}
/*
* TRANSLATION_NOTE
* "install" could be either a literal keyword and hence
* not to be translated, or a verb and translatable. A
* choice was made to view it as a literal keyword.
*/
goto out;
}
goto out;
}
/* It is the PROV_KEF_SOFT type now */
/* check if there are mechanism operands */
if (argc < 4) {
/*
* TRANSLATION_NOTE
* "mechanism" could be either a literal keyword and hence
* not to be translated, or a descriptive word and
* translatable. A choice was made to view it as a literal
* keyword.
*/
gettext("need %s operands for installing a"
" kernel software provider."), "mechanism");
rc = ERROR_USAGE;
goto out;
}
goto out;
}
/*
* TRANSLATION_NOTE
* "all", "mechanism", and "install" are all keywords and
* not to be translated.
*/
gettext("can not use the %1$s keyword for %2$s "
"in the %3$s subcommand."), "all", "mechanism", "install");
rc = ERROR_USAGE;
goto out;
}
if (getzoneid() == GLOBAL_ZONEID) {
} else {
/*
* TRANSLATION_NOTE
* "install" could be either a literal keyword and hence
* not to be translated, or a verb and translatable. A
* choice was made to view it as a literal keyword.
* "global" is keyword and not to be translated.
*/
"is supported in the %2$s zone only"), "install", "global");
}
out:
return (rc);
}
/*
* The top level function for the "cryptoadm uninstall" subcommand.
*/
static int
{
if (argc != 3) {
usage();
return (ERROR_USAGE);
}
/*
* TRANSLATION_NOTE
* "uninstall" could be either a literal keyword and hence
* not to be translated, or a verb and translatable. A
* choice was made to view it as a literal keyword.
*/
return (FAILURE);
}
if (getzoneid() == GLOBAL_ZONEID) {
/* unload and remove from kcf.conf */
} else {
/*
* TRANSLATION_NOTE
* "uninstall" could be either a literal keyword and
* hence not to be translated, or a verb and
* translatable. A choice was made to view it as a
* literal keyword. "global" is keyword and not to
* be translated.
*/
"providers is supported in the %2$s zone only"),
"uninstall", "global");
}
}
return (rc);
}
/*
* The top level function for the "cryptoadm unload" subcommand.
*/
static int
{
if (argc != 3) {
usage();
return (ERROR_USAGE);
}
/* check if it is a kernel software provider */
gettext("unable to determine provider name."));
goto out;
}
gettext("%s is not a valid kernel software provider."),
provname);
goto out;
}
if (getzoneid() != GLOBAL_ZONEID) {
/*
* TRANSLATION_NOTE
* "unload" could be either a literal keyword and hence
* not to be translated, or a verb and translatable.
* A choice was made to view it as a literal keyword.
* "global" is keyword and not to be translated.
*/
"is supported in the %2$s zone only"), "unload", "global");
goto out;
}
cryptodebug("internal error");
goto out;
gettext("provider %s is not loaded or does not exist."),
provname);
goto out;
}
/* Get kcf.conf entry. If none, build a new entry */
goto out;
}
}
/* If it is unloaded already, return */
goto out;
/* Mark as unloaded in kcf.conf */
} else {
}
out:
return (rc);
}
/*
* The top level function for the "cryptoadm refresh" subcommand.
*/
static int
{
if (argc != 2) {
usage();
return (ERROR_USAGE);
}
if (getzoneid() == GLOBAL_ZONEID) {
return (refresh());
} else { /* non-global zone */
/*
* Note: in non-global zone, this must silently return SUCCESS
* due to integration with SMF, for "svcadm refresh cryptosvc"
*/
return (SUCCESS);
}
}
/*
* The top level function for the "cryptoadm start" subcommand.
* This used to start up kcfd, but now all it does is load up the
* initial providers.
*/
static int
{
if (argc != 2) {
usage();
return (ERROR_USAGE);
}
return (do_refresh(argc));
}
/*
* The top level function for the "cryptoadm stop" subcommand.
* This no longer does anything useful, but we leave it here
* for compatibility.
*/
static int
{
if (argc != 2) {
usage();
return (ERROR_USAGE);
}
return (SUCCESS);
}
/*
* Print a list all the the providers.
* Called for "cryptoadm list" or "cryptoadm list -v" (no -m or -p).
*/
static int
{
int i;
/* get user-level providers */
"failed to retrieve the list of user-level providers."));
}
/* skip metaslot and fips-140 entry */
if (verbose) {
(void) list_mechlist_for_lib(
(void) printf("\n");
}
}
}
/* get kernel software providers */
if (getzoneid() == GLOBAL_ZONEID) {
/* get kernel software providers from kernel ioctl */
char *psoftname;
"software provider list from kernel."));
} else {
== FAILURE) {
"failed to retrieve the providers' "
"information from file kcf.conf - %s.",
} else {
for (i = 0,
i < sl_soft_count;
}
}
}
} else {
SUCCESS) {
gettext("failed to retrieve the "
"list of kernel software providers.\n"));
}
}
}
/* get kernel hardware providers */
"the list of kernel hardware providers.\n"));
} else {
for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
(void) printf("\t%s/%d\n",
}
}
return (rc);
}
/*
* List all the providers. And for each provider, list the mechanism list.
* Called for "cryptoadm list -m" or "cryptoadm list -mv" .
*/
static int
{
int inst_num;
int count;
int i;
int rv;
/* get user-level providers */
/*
* TRANSLATION_NOTE
* Strictly for appearance's sake, this line should be as long as
* the length of the translated text above.
*/
"the list of user-level providers.\n"));
}
/* skip metaslot and fips-140 entry */
}
}
}
/* get kernel software providers */
/*
* TRANSLATION_NOTE
* Strictly for appearance's sake, this line should be as long as
* the length of the translated text above.
*/
if (getzoneid() == GLOBAL_ZONEID) {
/* get kernel software providers from kernel ioctl */
char *psoftname;
int i;
"software provider list from kernel."));
return (FAILURE);
}
== FAILURE) {
"failed to retrieve the providers' "
"information from file kcf.conf - %s.",
return (FAILURE);
}
i < sl_soft_count;
}
} else {
}
}
} else {
SUCCESS) {
"the list of kernel software providers.\n"));
}
"%s: failed to get the mechanism list.\n"),
}
}
}
/* Get kernel hardware providers and their mechanism lists */
/*
* TRANSLATION_NOTE
* Strictly for appearance's sake, this line should be as long as
* the length of the translated text above.
*/
"the list of hardware providers.\n"));
return (FAILURE);
}
for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
inst_num);
SUCCESS) {
} else {
" list.\n"), provname);
}
}
return (rc);
}
/*
* List all the providers. And for each provider, list the policy information.
* Called for "cryptoadm list -p".
*/
static int
list_policy_for_all(void)
{
int i;
/* Get user-level providers */
/*
* TRANSLATION_NOTE
* Strictly for appearance's sake, this line should be as long as
* the length of the translated text above.
*/
"the list of user-level providers.\n"));
} else {
/* skip metaslot and fips-140 entry */
METASLOT_KEYWORD) != 0) &&
FIPS_KEYWORD) != 0)) {
== FAILURE) {
}
}
}
}
/* kernel software providers */
/*
* TRANSLATION_NOTE
* Strictly for appearance's sake, this line should be as long as
* the length of the translated text above.
*/
/* Get all entries from the kernel */
if (getzoneid() == GLOBAL_ZONEID) {
/* get kernel software providers from kernel ioctl */
char *psoftname;
int i;
"software provider list from kernel."));
} else {
i < sl_soft_count;
(void) list_policy_for_soft(psoftname,
}
}
} else {
/* kcf.conf not there in non-global zone, no policy info */
/*
* TRANSLATION_NOTE
* "global" is keyword and not to be translated.
*/
"policy information for kernel software providers is "
"available in the %s zone only"), "global");
}
/* Kernel hardware providers */
/*
* TRANSLATION_NOTE
* Strictly for appearance's sake, this line should be as long as
* the length of the translated text above.
*/
if (getzoneid() != GLOBAL_ZONEID) {
/*
* TRANSLATION_NOTE
* "global" is keyword and not to be translated.
*/
"policy information for kernel hardware providers is "
"available in the %s zone only"), "global");
return (FAILURE);
}
/* Get the hardware provider list from kernel */
"failed to retrieve the list of hardware providers.\n"));
return (FAILURE);
}
"information from file kcf.conf - %s.",
return (FAILURE);
}
/*
* For each hardware provider from kernel, check if it has an entry
* in the config file. If it has an entry, print out the policy from
* config file and remove the entry from the hardware provider list
* of the config file. If it does not have an entry in the config
* file, no mechanisms of it have been disabled. But, we still call
* list_policy_for_hard() to account for the "random" feature.
*/
for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
} else {
}
}
if (found) {
} else {
}
} else {
}
}
/*
* If there are still entries left in the pdevlist_conf list from
* the config file, these providers must have been detached.
* Should print out their policy information also.
*/
}
return (rc);
}