Print this page
6414175 kcf.conf's supportedlist not providing much usefulness
@@ -35,27 +35,31 @@
#include <sys/crypto/ioctladmin.h>
#include <signal.h>
#include <sys/crypto/elfsign.h>
#include "cryptoadm.h"
-static int err; /* to store the value of errno in case being overwritten */
static int check_hardware_provider(char *, char *, int *, int *);
/*
* Display the mechanism list for a kernel software provider.
+ * This implements part of the "cryptoadm list -m" command.
+ *
+ * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
+ * If NULL, this function obtains it by calling get_kcfconf_info() internally.
*/
int
-list_mechlist_for_soft(char *provname)
+list_mechlist_for_soft(char *provname,
+ entrylist_t *phardlist, entrylist_t *psoftlist)
{
- mechlist_t *pmechlist;
+ mechlist_t *pmechlist = NULL;
int rc;
if (provname == NULL) {
return (FAILURE);
}
- rc = get_soft_info(provname, &pmechlist);
+ rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
if (rc == SUCCESS) {
(void) filter_mechlist(&pmechlist, RANDOM);
print_mechlist(provname, pmechlist);
free_mechlist(pmechlist);
} else {
@@ -63,20 +67,20 @@
"failed to retrieve the mechanism list for %s."),
provname);
}
return (rc);
-
}
/*
* Display the mechanism list for a kernel hardware provider.
+ * This implements part of the "cryptoadm list -m" command.
*/
int
list_mechlist_for_hard(char *provname)
{
- mechlist_t *pmechlist;
+ mechlist_t *pmechlist = NULL;
char devname[MAXNAMELEN];
int inst_num;
int count;
int rc = SUCCESS;
@@ -105,31 +109,40 @@
}
/*
* Display the policy information for a kernel software provider.
+ * This implements part of the "cryptoadm list -p" command.
+ *
+ * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
+ * If NULL, this function obtains it by calling get_kcfconf_info() internally.
*/
int
-list_policy_for_soft(char *provname)
+list_policy_for_soft(char *provname,
+ entrylist_t *phardlist, entrylist_t *psoftlist)
{
int rc;
entry_t *pent = NULL;
- mechlist_t *pmechlist;
+ mechlist_t *pmechlist = NULL;
boolean_t has_random = B_FALSE;
boolean_t has_mechs = B_FALSE;
+ boolean_t in_kernel = B_FALSE;
if (provname == NULL) {
return (FAILURE);
}
- if ((pent = getent_kef(provname)) == NULL) {
+ if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
+ return (FAILURE);
+ } else if (in_kernel == B_FALSE) {
cryptoerror(LOG_STDERR, gettext("%s does not exist."),
provname);
return (FAILURE);
}
+ pent = getent_kef(provname, phardlist, psoftlist);
- rc = get_soft_info(provname, &pmechlist);
+ rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
if (rc == SUCCESS) {
has_random = filter_mechlist(&pmechlist, RANDOM);
if (pmechlist != NULL) {
has_mechs = B_TRUE;
free_mechlist(pmechlist);
@@ -139,26 +152,34 @@
"failed to retrieve the mechanism list for %s."),
provname);
return (rc);
}
- print_kef_policy(pent, has_random, has_mechs);
+ print_kef_policy(provname, pent, has_random, has_mechs);
free_entry(pent);
return (SUCCESS);
}
/*
* Display the policy information for a kernel hardware provider.
+ * This implements part of the "cryptoadm list -p" command.
+ *
+ * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
+ * If NULL, this function obtains it by calling get_kcfconf_info() internally.
+ * Parameter pdevlist is supplied by get_dev_list().
+ * If NULL, this function obtains it by calling get_dev_list() internally.
*/
int
-list_policy_for_hard(char *provname)
+list_policy_for_hard(char *provname,
+ entrylist_t *phardlist, entrylist_t *psoftlist,
+ crypto_get_dev_list_t *pdevlist)
{
- entry_t *pent;
- boolean_t is_active;
- mechlist_t *pmechlist;
+ entry_t *pent = NULL;
+ boolean_t in_kernel;
+ mechlist_t *pmechlist = NULL;
char devname[MAXNAMELEN];
int inst_num;
int count;
int rc = SUCCESS;
boolean_t has_random = B_FALSE;
@@ -197,19 +218,19 @@
* If the hardware provider has an entry in the kcf.conf file,
* some of its mechanisms must have been disabled. Print out
* the disabled list from the config file entry. Otherwise,
* if it is active, then all the mechanisms for it are enabled.
*/
- if ((pent = getent_kef(provname)) != NULL) {
- print_kef_policy(pent, has_random, has_mechs);
+ if ((pent = getent_kef(provname, phardlist, psoftlist)) != NULL) {
+ print_kef_policy(provname, pent, has_random, has_mechs);
free_entry(pent);
return (SUCCESS);
} else {
- if (check_active_for_hard(provname, &is_active) ==
- FAILURE) {
+ if (check_kernel_for_hard(provname, pdevlist,
+ &in_kernel) == FAILURE) {
return (FAILURE);
- } else if (is_active == B_TRUE) {
+ } else if (in_kernel == B_TRUE) {
(void) printf(gettext(
"%s: all mechanisms are enabled."), provname);
if (has_random)
/*
* TRANSLATION_NOTE
@@ -228,23 +249,27 @@
}
}
}
-
+/*
+ * Disable a kernel hardware provider.
+ * This implements the "cryptoadm disable" command for
+ * kernel hardware providers.
+ */
int
disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag,
mechlist_t *dislist)
{
- crypto_load_dev_disabled_t *pload_dev_dis;
- mechlist_t *infolist;
- entry_t *pent;
+ crypto_load_dev_disabled_t *pload_dev_dis = NULL;
+ mechlist_t *infolist = NULL;
+ entry_t *pent = NULL;
boolean_t new_dev_entry = B_FALSE;
char devname[MAXNAMELEN];
int inst_num;
int count;
- int fd;
+ int fd = -1;
int rc = SUCCESS;
if (provname == NULL) {
return (FAILURE);
}
@@ -265,22 +290,17 @@
/*
* Get the entry of this hardware provider from the config file.
* If there is no entry yet, create one for it.
*/
- if ((pent = getent_kef(provname)) == NULL) {
- if ((pent = malloc(sizeof (entry_t))) == NULL) {
+ if ((pent = getent_kef(provname, NULL, NULL)) == NULL) {
+ if ((pent = create_entry(provname)) == NULL) {
cryptoerror(LOG_STDERR, gettext("out of memory."));
free_mechlist(infolist);
return (FAILURE);
}
new_dev_entry = B_TRUE;
- (void) strlcpy(pent->name, provname, MAXNAMELEN);
- pent->suplist = NULL;
- pent->sup_count = 0;
- pent->dislist = NULL;
- pent->dis_count = 0;
}
/*
* kCF treats random as an internal mechanism. So, we need to
* filter it from the mechanism list here, if we are NOT disabling
@@ -351,132 +371,168 @@
(void) close(fd);
return (SUCCESS);
}
-
+/*
+ * Disable a kernel software provider.
+ * This implements the "cryptoadm disable" command for
+ * kernel software providers.
+ */
int
disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
mechlist_t *dislist)
{
crypto_load_soft_disabled_t *pload_soft_dis = NULL;
- mechlist_t *infolist;
- entry_t *pent;
- boolean_t is_active;
- int fd;
+ mechlist_t *infolist = NULL;
+ entry_t *pent = NULL;
+ entrylist_t *phardlist = NULL;
+ entrylist_t *psoftlist = NULL;
+ boolean_t in_kernel = B_FALSE;
+ int fd = -1;
+ int rc = SUCCESS;
if (provname == NULL) {
return (FAILURE);
}
- /* Get the entry of this provider from the config file. */
- if ((pent = getent_kef(provname)) == NULL) {
- cryptoerror(LOG_STDERR,
- gettext("%s does not exist."), provname);
- return (FAILURE);
- }
-
/*
* Check if the kernel software provider is currently unloaded.
* If it is unloaded, return FAILURE, because the disable subcommand
* can not perform on inactive (unloaded) providers.
*/
- if (check_active_for_soft(provname, &is_active) == FAILURE) {
- free_entry(pent);
+ if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
return (FAILURE);
- } else if (is_active == B_FALSE) {
- /*
- * TRANSLATION_NOTE
- * "disable" is a keyword and not to be translated.
- */
+ } else if (in_kernel == B_FALSE) {
cryptoerror(LOG_STDERR,
- gettext("can not do %1$s on an unloaded "
- "kernel software provider -- %2$s."), "disable", provname);
- free_entry(pent);
+ gettext("%s is not loaded or does not exist."),
+ provname);
return (FAILURE);
}
- /* Get the mechanism list for the software provider */
- if (get_soft_info(provname, &infolist) == FAILURE) {
- free(pent);
+ if (get_kcfconf_info(&phardlist, &psoftlist) == FAILURE) {
+ cryptoerror(LOG_ERR,
+ "failed to retrieve the providers' "
+ "information from the configuration file - %s.",
+ _PATH_KCF_CONF);
return (FAILURE);
}
- /* See comments in disable_kef_hardware() */
+ /*
+ * Get the entry of this provider from the kcf.conf file, if any.
+ * Otherwise, create a new kcf.conf entry for writing back to the file.
+ */
+ pent = getent_kef(provname, phardlist, psoftlist);
+ if (pent == NULL) { /* create a new entry */
+ pent = create_entry(provname);
+ if (pent == NULL) {
+ cryptodebug("out of memory.");
+ rc = FAILURE;
+ goto out;
+ }
+ }
+
+ /* Get the mechanism list for the software provider from the kernel */
+ if (get_soft_info(provname, &infolist, phardlist, psoftlist) ==
+ FAILURE) {
+ rc = FAILURE;
+ goto out;
+ }
+
+ if ((infolist != NULL) && (infolist->name[0] != '\0')) {
+ /*
+ * Replace the supportedlist from kcf.conf with possibly
+ * more-up-to-date list from the kernel. This is the case
+ * for default software providers that had more mechanisms
+ * added in the current version of the kernel.
+ */
+ free_mechlist(pent->suplist);
+ pent->suplist = infolist;
+ }
+
+ /*
+ * kCF treats random as an internal mechanism. So, we need to
+ * filter it from the mechanism list here, if we are NOT disabling
+ * or enabling the random feature. Note that we map random feature at
+ * cryptoadm(1M) level to the "random" mechanism in kCF.
+ */
if (!rndflag) {
(void) filter_mechlist(&infolist, RANDOM);
}
/* Calculate the new disabled list */
if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
- free_entry(pent);
- free_mechlist(infolist);
- return (FAILURE);
+ rc = FAILURE;
+ goto out;
}
- /* infolist is no longer needed; free it */
- free_mechlist(infolist);
-
/* Update the kcf.conf file with the updated entry */
if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) {
- free_entry(pent);
- return (FAILURE);
+ rc = FAILURE;
+ goto out;
}
- /* Inform kernel about the new disabled list. */
+ /* Setup argument to inform kernel about the new disabled list. */
if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
- free_entry(pent);
- return (FAILURE);
+ rc = FAILURE;
+ goto out;
}
- /* pent is no longer needed; free it. */
- free_entry(pent);
-
if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
cryptoerror(LOG_STDERR,
gettext("failed to open %s for RW: %s"),
ADMIN_IOCTL_DEVICE, strerror(errno));
- free(pload_soft_dis);
- return (FAILURE);
+ rc = FAILURE;
+ goto out;
}
+ /* Inform kernel about the new disabled list. */
if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
strerror(errno));
- free(pload_soft_dis);
- (void) close(fd);
- return (FAILURE);
+ rc = FAILURE;
+ goto out;
}
if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
"%d", pload_soft_dis->sd_return_value);
- free(pload_soft_dis);
- (void) close(fd);
- return (FAILURE);
+ rc = FAILURE;
+ goto out;
}
+out:
+ free_entrylist(phardlist);
+ free_entrylist(psoftlist);
+ free_mechlist(infolist);
+ free_entry(pent);
free(pload_soft_dis);
+ if (fd != -1)
(void) close(fd);
- return (SUCCESS);
+ return (rc);
}
+/*
+ * Enable a kernel software or hardware provider.
+ * This implements the "cryptoadm enable" command for kernel providers.
+ */
int
enable_kef(char *provname, boolean_t rndflag, boolean_t allflag,
mechlist_t *mlist)
{
crypto_load_soft_disabled_t *pload_soft_dis = NULL;
crypto_load_dev_disabled_t *pload_dev_dis = NULL;
- entry_t *pent;
+ entry_t *pent = NULL;
boolean_t redo_flag = B_FALSE;
- int fd;
+ boolean_t in_kernel = B_FALSE;
+ int fd = -1;
int rc = SUCCESS;
- /* Get the entry with the provider name from the kcf.conf file */
- pent = getent_kef(provname);
+ /* Get the entry of this provider from the kcf.conf file, if any. */
+ pent = getent_kef(provname, NULL, NULL);
if (is_device(provname)) {
if (pent == NULL) {
/*
* This device doesn't have an entry in the config
@@ -483,29 +539,40 @@
* file, therefore nothing is disabled.
*/
cryptoerror(LOG_STDERR, gettext(
"all mechanisms are enabled already for %s."),
provname);
+ free_entry(pent);
return (SUCCESS);
}
} else { /* a software module */
- if (pent == NULL) {
- cryptoerror(LOG_STDERR,
- gettext("%s does not exist."), provname);
+ if (check_kernel_for_soft(provname, NULL, &in_kernel) ==
+ FAILURE) {
+ free_entry(pent);
return (FAILURE);
- } else if (pent->dis_count == 0) {
+ } else if (in_kernel == B_FALSE) {
+ cryptoerror(LOG_STDERR, gettext("%s does not exist."),
+ provname);
+ free_entry(pent);
+ return (FAILURE);
+ } else if ((pent == NULL) || (pent->dis_count == 0)) {
/* nothing to be enabled. */
cryptoerror(LOG_STDERR, gettext(
"all mechanisms are enabled already for %s."),
provname);
free_entry(pent);
return (SUCCESS);
}
}
+ /*
+ * kCF treats random as an internal mechanism. So, we need to
+ * filter it from the mechanism list here, if we are NOT disabling
+ * or enabling the random feature. Note that we map random feature at
+ * cryptoadm(1M) level to the "random" mechanism in kCF.
+ */
if (!rndflag) {
- /* See comments in disable_kef_hardware() */
redo_flag = filter_mechlist(&pent->dislist, RANDOM);
if (redo_flag)
pent->dis_count--;
}
@@ -528,11 +595,11 @@
}
/*
* Update the kcf.conf file with the updated entry.
* For a hardware provider, if there is no more disabled mechanism,
- * the entire entry in the config file should be removed.
+ * remove the entire kcf.conf entry.
*/
if (is_device(pent->name) && (pent->dis_count == 0)) {
rc = update_kcfconf(pent, DELETE_MODE);
} else {
rc = update_kcfconf(pent, MODIFY_MODE);
@@ -547,61 +614,70 @@
/* Inform Kernel about the policy change */
if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
ADMIN_IOCTL_DEVICE, strerror(errno));
+ free_entry(pent);
return (FAILURE);
}
if (is_device(provname)) {
/* LOAD_DEV_DISABLED */
if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
+ free_entry(pent);
return (FAILURE);
}
if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: "
"%s", strerror(errno));
+ free_entry(pent);
free(pload_dev_dis);
(void) close(fd);
return (FAILURE);
}
if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
"return_value = %d",
pload_dev_dis->dd_return_value);
+ free_entry(pent);
free(pload_dev_dis);
(void) close(fd);
return (FAILURE);
}
- } else {
+ } else { /* a software module */
/* LOAD_SOFT_DISABLED */
if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
+ free_entry(pent);
return (FAILURE);
}
if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis)
== -1) {
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: "
"%s", strerror(errno));
+ free_entry(pent);
free(pload_soft_dis);
(void) close(fd);
return (FAILURE);
}
if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
"return_value = %d",
pload_soft_dis->sd_return_value);
+ free_entry(pent);
free(pload_soft_dis);
(void) close(fd);
return (FAILURE);
}
}
+ free_entry(pent);
+ free(pload_soft_dis);
(void) close(fd);
return (SUCCESS);
}
@@ -614,46 +690,43 @@
int
install_kef(char *provname, mechlist_t *mlist)
{
crypto_load_soft_config_t *pload_soft_conf = NULL;
boolean_t found;
- entry_t *pent;
- FILE *pfile;
- FILE *pfile_tmp;
+ entry_t *pent = NULL;
+ FILE *pfile = NULL;
+ FILE *pfile_tmp = NULL;
char tmpfile_name[MAXPATHLEN];
char *ptr;
char *str;
char *name;
char buffer[BUFSIZ];
char buffer2[BUFSIZ];
int found_count;
- int fd;
+ int fd = -1;
int rc = SUCCESS;
+ int err;
if ((provname == NULL) || (mlist == NULL)) {
return (FAILURE);
}
/* Check if the provider already exists */
- if ((pent = getent_kef(provname)) != NULL) {
+ if ((pent = getent_kef(provname, NULL, NULL)) != NULL) {
cryptoerror(LOG_STDERR, gettext("%s exists already."),
provname);
free_entry(pent);
return (FAILURE);
}
/* Create an entry with provname and mlist. */
- if ((pent = malloc(sizeof (entry_t))) == NULL) {
+ if ((pent = create_entry(provname)) == NULL) {
cryptoerror(LOG_STDERR, gettext("out of memory."));
return (FAILURE);
}
-
- (void) strlcpy(pent->name, provname, MAXNAMELEN);
pent->sup_count = get_mech_count(mlist);
pent->suplist = mlist;
- pent->dis_count = 0;
- pent->dislist = NULL;
/* Append an entry for this software module to the kcf.conf file. */
if ((str = ent2str(pent)) == NULL) {
free_entry(pent);
return (FAILURE);
@@ -735,11 +808,11 @@
rc = FAILURE;
}
} else {
/*
* Found a second entry with #libname.
- * Should not happen. The kcf.conf ffile
+ * Should not happen. The kcf.conf file
* is corrupted. Give a warning and skip
* this entry.
*/
cryptoerror(LOG_STDERR, gettext(
"(Warning) Found an additional reserved "
@@ -790,10 +863,11 @@
if (fclose(pfile_tmp) != 0) {
err = errno;
cryptoerror(LOG_STDERR,
gettext("failed to close %s: %s"), tmpfile_name,
strerror(err));
+ free_entry(pent);
return (FAILURE);
}
if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
err = errno;
@@ -821,10 +895,11 @@
err = errno;
cryptoerror(LOG_STDERR, gettext(
"(Warning) failed to remove %s: %s"),
tmpfile_name, strerror(err));
}
+ free_entry(pent);
return (FAILURE);
}
/* Inform kernel of this new software module. */
@@ -873,277 +948,125 @@
* that there is still an entry if the earlier unload failed for any reason.
*/
int
uninstall_kef(char *provname)
{
- entry_t *pent;
- boolean_t is_active;
- boolean_t in_package;
- boolean_t found;
- FILE *pfile;
- FILE *pfile_tmp;
- char tmpfile_name[MAXPATHLEN];
- char *name;
- char strbuf[BUFSIZ];
- char buffer[BUFSIZ];
- char buffer2[BUFSIZ];
- char *str;
- int len;
+ entry_t *pent = NULL;
int rc = SUCCESS;
+ boolean_t in_kernel = B_FALSE;
+ boolean_t in_kcfconf = B_FALSE;
+ int fd = -1;
+ crypto_load_soft_config_t *pload_soft_conf = NULL;
-
- /* Check if it is in the kcf.conf file first. */
- if ((pent = getent_kef(provname)) == NULL) {
- cryptoerror(LOG_STDERR,
- gettext("%s does not exist."), provname);
+ /* Check to see if the provider exists first. */
+ if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
return (FAILURE);
+ } else if (in_kernel == B_FALSE) {
+ cryptoerror(LOG_STDERR, gettext("%s does not exist."),
+ provname);
+ return (FAILURE);
}
-
/*
- * Get rid of the disabled list for the provider and get the converted
- * string for the entry. This is to prepare the string for a provider
- * that is in a package.
+ * If it is loaded, unload it first. This does 2 ioctl calls:
+ * CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED.
*/
- free_mechlist(pent->dislist);
- pent->dis_count = 0;
- pent->dislist = NULL;
- str = ent2str(pent);
- free_entry(pent);
- if (str == NULL) {
- cryptoerror(LOG_STDERR, gettext("internal error."));
- return (FAILURE);
- }
- (void) snprintf(strbuf, sizeof (strbuf), "%s%s", "#", str);
- free(str);
-
- /* If it is not loaded, unload it first */
- if (check_active_for_soft(provname, &is_active) == FAILURE) {
- return (FAILURE);
- } else if ((is_active == B_TRUE) &&
- (unload_kef_soft(provname, B_TRUE) == FAILURE)) {
+ if (unload_kef_soft(provname) == FAILURE) {
cryptoerror(LOG_STDERR,
- gettext("failed to uninstall %s.\n"), provname);
+ gettext("failed to unload %s during uninstall.\n"),
+ provname);
return (FAILURE);
}
/*
- * Remove the entry from the config file. If the provider to be
- * uninstalled is in a package, just comment it off.
+ * Inform kernel to remove the configuration of this software module.
*/
- if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to update the configuration - %s"),
- strerror(err));
- cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
- return (FAILURE);
- }
- if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to lock the configuration - %s"),
- strerror(err));
- (void) fclose(pfile);
+ /* Setup ioctl() parameter */
+ pent = getent_kef(provname, NULL, NULL);
+ if (pent != NULL) { /* in kcf.conf */
+ in_kcfconf = B_TRUE;
+ free_mechlist(pent->suplist);
+ pent->suplist = NULL;
+ pent->sup_count = 0;
+ } else if ((pent = create_entry(provname)) == NULL) {
+ cryptoerror(LOG_STDERR, gettext("out of memory."));
return (FAILURE);
}
-
- /*
- * Create a temporary file in the /etc/crypto directory to save
- * the new configuration file first.
- */
- (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
- if (mkstemp(tmpfile_name) == -1) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to create a temporary file - %s"),
- strerror(err));
- (void) fclose(pfile);
+ if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
+ free_entry(pent);
return (FAILURE);
}
- if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
- err = errno;
- cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
- tmpfile_name, strerror(err));
- if (unlink(tmpfile_name) != 0) {
- err = errno;
- cryptoerror(LOG_STDERR, gettext(
- "(Warning) failed to remove %s: %s"), tmpfile_name,
- strerror(err));
- }
- (void) fclose(pfile);
+ /* Open the /dev/cryptoadm device */
+ if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
+ int err = errno;
+ cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
+ ADMIN_IOCTL_DEVICE, strerror(err));
+ free_entry(pent);
+ free(pload_soft_conf);
return (FAILURE);
}
- /*
- * Loop thru the config file. If the kernel software provider
- * to be uninstalled is in a package, just comment it off.
- */
- in_package = B_FALSE;
- while (fgets(buffer, BUFSIZ, pfile) != NULL) {
- found = B_FALSE;
- if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
- buffer[0] == '\t')) {
- if (strstr(buffer, " Start ") != NULL) {
- in_package = B_TRUE;
- } else if (strstr(buffer, " End ") != NULL) {
- in_package = B_FALSE;
- } else if (buffer[0] != '#') {
- (void) strlcpy(buffer2, buffer, BUFSIZ);
-
- /* get rid of trailing '\n' */
- len = strlen(buffer2);
- if (buffer2[len-1] == '\n') {
- len--;
- }
- buffer2[len] = '\0';
-
- if ((name = strtok(buffer2, SEP_COLON))
- == NULL) {
- rc = FAILURE;
- break;
- } else if (strcmp(provname, name) == 0) {
- found = B_TRUE;
- }
- }
- }
-
- if (found) {
- if (in_package) {
- if (fputs(strbuf, pfile_tmp) == EOF) {
- rc = FAILURE;
- }
- }
- } else {
- if (fputs(buffer, pfile_tmp) == EOF) {
- rc = FAILURE;
- }
- }
-
- if (rc == FAILURE) {
- break;
- }
- }
-
- if (rc == FAILURE) {
- cryptoerror(LOG_STDERR, gettext("write error."));
- (void) fclose(pfile);
- (void) fclose(pfile_tmp);
- if (unlink(tmpfile_name) != 0) {
- err = errno;
- cryptoerror(LOG_STDERR, gettext(
- "(Warning) failed to remove %s: %s"), tmpfile_name,
- strerror(err));
- }
+ if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG,
+ pload_soft_conf) == -1) {
+ cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
+ strerror(errno));
+ free_entry(pent);
+ free(pload_soft_conf);
+ (void) close(fd);
return (FAILURE);
}
- (void) fclose(pfile);
- if (fclose(pfile_tmp) != 0) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to close %s: %s"), tmpfile_name,
- strerror(err));
+ if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
+ cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d",
+ pload_soft_conf->sc_return_value);
+ free_entry(pent);
+ free(pload_soft_conf);
+ (void) close(fd);
return (FAILURE);
}
- /* Now update the real config file */
- if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to update the configuration - %s"),
- strerror(err));
- cryptodebug("failed to rename %1$s to %2$s: %3$s", tmpfile,
- _PATH_KCF_CONF, strerror(err));
- rc = FAILURE;
- } else if (chmod(_PATH_KCF_CONF,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
- err = errno;
- cryptoerror(LOG_STDERR,
- gettext("failed to update the configuration - %s"),
- strerror(err));
- cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
- strerror(err));
- rc = FAILURE;
- } else {
- rc = SUCCESS;
- }
+ /* ioctl cleanup */
+ free(pload_soft_conf);
+ (void) close(fd);
- if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
- err = errno;
- cryptoerror(LOG_STDERR, gettext(
- "(Warning) failed to remove %s: %s"), tmpfile_name,
- strerror(err));
+
+ /* Finally, remove entry from kcf.conf, if present */
+ if (in_kcfconf && (pent != NULL)) {
+ rc = update_kcfconf(pent, DELETE_MODE);
}
+ free_entry(pent);
return (rc);
-
}
+/*
+ * Implement the "cryptoadm refresh" command for global zones.
+ * That is, send the current contents of kcf.conf to the kernel via ioctl().
+ */
int
refresh(void)
{
- crypto_get_soft_list_t *psoftlist_kernel = NULL;
crypto_load_soft_config_t *pload_soft_conf = NULL;
crypto_load_soft_disabled_t *pload_soft_dis = NULL;
crypto_load_dev_disabled_t *pload_dev_dis = NULL;
entrylist_t *pdevlist = NULL;
entrylist_t *psoftlist = NULL;
entrylist_t *ptr;
- boolean_t found;
- char *psoftname;
- int fd;
+ int fd = -1;
int rc = SUCCESS;
- int i;
+ int err;
- if (get_soft_list(&psoftlist_kernel) == FAILURE) {
- cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
- "software provider list from kernel."));
- return (FAILURE);
- }
-
if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) {
cryptoerror(LOG_ERR, "failed to retrieve the providers' "
"information from the configuration file - %s.",
_PATH_KCF_CONF);
return (FAILURE);
}
- /*
- * If a kernel software provider is in kernel, but it is not in the
- * kcf.conf file, it must have been pkgrm'ed and needs to be unloaded
- * now.
- */
- if (psoftlist_kernel->sl_soft_count > 0) {
- psoftname = psoftlist_kernel->sl_soft_names;
- for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
- ptr = psoftlist;
- found = B_FALSE;
- while (ptr != NULL) {
- if (strcmp(psoftname, ptr->pent->name) == 0) {
- found = B_TRUE;
- break;
- }
- ptr = ptr->next;
- }
-
- if (!found) {
- rc = unload_kef_soft(psoftname, B_FALSE);
- if (rc == FAILURE) {
- cryptoerror(LOG_ERR, gettext(
- "WARNING - the provider %s is "
- "still in kernel."), psoftname);
- }
- }
- psoftname = psoftname + strlen(psoftname) + 1;
- }
- }
- free(psoftlist_kernel);
-
if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
err = errno;
cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
ADMIN_IOCTL_DEVICE, strerror(err));
free(psoftlist);
@@ -1150,21 +1073,32 @@
free(pdevlist);
return (FAILURE);
}
/*
- * For each software module, pass two sets of information to kernel
- * - the supported list and the disabled list
+ * For each software provider module, pass two sets of information to
+ * the kernel: the supported list and the disabled list.
*/
- ptr = psoftlist;
- while (ptr != NULL) {
+ for (ptr = psoftlist; ptr != NULL; ptr = ptr->next) {
+ entry_t *pent = ptr->pent;
+
/* load the supported list */
- if ((pload_soft_conf = setup_soft_conf(ptr->pent)) == NULL) {
+ if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
+ cryptodebug("setup_soft_conf() failed");
rc = FAILURE;
break;
}
+ if (!pent->load) { /* unloaded--mark as loaded */
+ pent->load = B_TRUE;
+ rc = update_kcfconf(pent, MODIFY_MODE);
+ if (rc != SUCCESS) {
+ free(pload_soft_conf);
+ break;
+ }
+ }
+
if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf)
== -1) {
cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
strerror(errno));
free(pload_soft_conf);
@@ -1179,14 +1113,18 @@
free(pload_soft_conf);
rc = FAILURE;
break;
}
+ free(pload_soft_conf);
+
/* load the disabled list */
if (ptr->pent->dis_count != 0) {
pload_soft_dis = setup_soft_dis(ptr->pent);
if (pload_soft_dis == NULL) {
+ cryptodebug("setup_soft_dis() failed");
+ free(pload_soft_dis);
rc = FAILURE;
break;
}
if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED,
@@ -1207,24 +1145,23 @@
rc = FAILURE;
break;
}
free(pload_soft_dis);
}
-
- free(pload_soft_conf);
- ptr = ptr->next;
}
if (rc != SUCCESS) {
(void) close(fd);
return (rc);
}
- /* Pass the disabledlist information for Device to kernel */
- ptr = pdevlist;
- while (ptr != NULL) {
+ /*
+ * For each hardware provider module, pass the disabled list
+ * information to the kernel.
+ */
+ for (ptr = pdevlist; ptr != NULL; ptr = ptr->next) {
/* load the disabled list */
if (ptr->pent->dis_count != 0) {
pload_dev_dis = setup_dev_dis(ptr->pent);
if (pload_dev_dis == NULL) {
rc = FAILURE;
@@ -1248,64 +1185,62 @@
rc = FAILURE;
break;
}
free(pload_dev_dis);
}
-
- ptr = ptr->next;
}
(void) close(fd);
return (rc);
}
/*
* Unload the kernel software provider. Before calling this function, the
- * caller should check if the provider is in the config file and if it
- * is kernel. This routine makes 3 ioctl calls to remove it from kernel
- * completely. The argument do_check set to B_FALSE means that the
- * caller knows the provider is not the config file and hence the check
- * is skipped.
+ * caller should check to see if the provider is in the kernel.
+ *
+ * This routine makes 2 ioctl calls to remove it completely from the kernel:
+ * CRYPTO_UNLOAD_SOFT_MODULE - does a modunload of the KCF module
+ * CRYPTO_LOAD_SOFT_DISABLED - updates kernel disabled mechanism list
+ *
+ * This implements part of "cryptoadm unload" and "cryptoadm uninstall".
*/
int
-unload_kef_soft(char *provname, boolean_t do_check)
+unload_kef_soft(char *provname)
{
crypto_unload_soft_module_t *punload_soft = NULL;
- crypto_load_soft_config_t *pload_soft_conf = NULL;
crypto_load_soft_disabled_t *pload_soft_dis = NULL;
entry_t *pent = NULL;
- int fd;
+ int fd = -1;
+ int err;
if (provname == NULL) {
cryptoerror(LOG_STDERR, gettext("internal error."));
return (FAILURE);
}
- if (!do_check) {
+ pent = getent_kef(provname, NULL, NULL);
+ if (pent == NULL) { /* not in kcf.conf */
/* Construct an entry using the provname */
- pent = calloc(1, sizeof (entry_t));
+ pent = create_entry(provname);
if (pent == NULL) {
cryptoerror(LOG_STDERR, gettext("out of memory."));
return (FAILURE);
}
- (void) strlcpy(pent->name, provname, MAXNAMELEN);
- } else if ((pent = getent_kef(provname)) == NULL) {
- cryptoerror(LOG_STDERR, gettext("%s does not exist."),
- provname);
- return (FAILURE);
}
/* Open the admin_ioctl_device */
if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
err = errno;
cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
ADMIN_IOCTL_DEVICE, strerror(err));
+ free_entry(pent);
return (FAILURE);
}
/* Inform kernel to unload this software module */
if ((punload_soft = setup_unload_soft(pent)) == NULL) {
+ free_entry(pent);
(void) close(fd);
return (FAILURE);
}
if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) {
@@ -1333,43 +1268,10 @@
}
}
free(punload_soft);
- /*
- * Inform kernel to remove the configuration of this software
- * module.
- */
- free_mechlist(pent->suplist);
- pent->suplist = NULL;
- pent->sup_count = 0;
- if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
- free_entry(pent);
- (void) close(fd);
- return (FAILURE);
- }
-
- if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
- cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
- strerror(errno));
- free_entry(pent);
- free(pload_soft_conf);
- (void) close(fd);
- return (FAILURE);
- }
-
- if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
- cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl return_value = "
- "%d", pload_soft_conf->sc_return_value);
- free_entry(pent);
- free(pload_soft_conf);
- (void) close(fd);
- return (FAILURE);
- }
-
- free(pload_soft_conf);
-
/* Inform kernel to remove the disabled entries if any */
if (pent->dis_count == 0) {
free_entry(pent);
(void) close(fd);
return (SUCCESS);