diff options
Diffstat (limited to 'usr/src/cmd/cmd-crypto/kmfcfg/install.c')
-rw-r--r-- | usr/src/cmd/cmd-crypto/kmfcfg/install.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/install.c b/usr/src/cmd/cmd-crypto/kmfcfg/install.c new file mode 100644 index 0000000000..6147638c43 --- /dev/null +++ b/usr/src/cmd/cmd-crypto/kmfcfg/install.c @@ -0,0 +1,311 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 + * + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <strings.h> +#include <ctype.h> +#include <libgen.h> +#include <libintl.h> +#include <errno.h> +#include <kmfapiP.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <cryptoutil.h> +#include "util.h" + +static int err; /* To store errno which may be overwritten by gettext() */ + +int +kc_install(int argc, char *argv[]) +{ + int rv = KC_OK; + int opt; + extern int optind_av; + extern char *optarg_av; + char *keystore_name = NULL; + char *modulepath = NULL; + char *option_str = NULL; + conf_entry_t *entry = NULL; + char realpath[MAXPATHLEN]; + struct stat statbuf; + FILE *pfile = NULL; + FILE *pfile_tmp = NULL; + char tmpfile_name[MAXPATHLEN]; + int found_count = 0; + char buffer[BUFSIZ]; + char *ptr; + boolean_t found; + + while ((opt = getopt_av(argc, argv, "k:(keystore)m:(modulepath)" + "o:(option)")) != EOF) { + switch (opt) { + case 'k': + if (keystore_name != NULL) + rv = KC_ERR_USAGE; + else { + keystore_name = get_string(optarg_av, &rv); + if (keystore_name == NULL) { + (void) fprintf(stderr, gettext( + "Error keystore input.\n")); + } + } + break; + case 'm': + if (modulepath != NULL) + rv = KC_ERR_USAGE; + else { + modulepath = get_string(optarg_av, &rv); + if (modulepath == NULL) { + (void) fprintf(stderr, + gettext("Error modulepath.\n")); + } + } + break; + case 'o': + if (option_str != NULL) { + rv = KC_ERR_USAGE; + } else { + option_str = get_string(optarg_av, &rv); + if (option_str == NULL) { + (void) fprintf(stderr, + gettext("Error option input.\n")); + } + } + break; + default: + (void) fprintf(stderr, + gettext("Error input option.\n")); + rv = KC_ERR_USAGE; + break; + } + if (rv != KC_OK) + goto out; + } + + /* No additional args allowed. */ + argc -= optind_av; + if (argc) { + (void) fprintf(stderr, + gettext("Error input option\n")); + rv = KC_ERR_USAGE; + goto out; + } + + if (keystore_name == NULL || modulepath == NULL) { + (void) fprintf(stderr, gettext("Error input option\n")); + rv = KC_ERR_USAGE; + goto out; + } + + if (strcasecmp(keystore_name, "nss") == 0 || + strcasecmp(keystore_name, "pkcs11") == 0 || + strcasecmp(keystore_name, "file") == 0) { + (void) fprintf(stderr, + gettext("Can not use the built-in keystore name %s\n"), + keystore_name); + rv = KC_ERR_USAGE; + goto out; + } + + entry = get_keystore_entry(keystore_name); + if (entry != NULL) { + (void) fprintf(stderr, gettext("%s exists already.\n"), + keystore_name); + rv = KC_ERR_USAGE; + goto out; + } + + /* + * Find the absolute path of the module and check if it exists in + * the system. If $ISA is in the path, will check the 32bit version + * only. + */ + if (strncmp(modulepath, "/", 1) != 0) { + /* + * Only contain the base name; prepand it with + * KMF_PLUGIN_PATH + */ + (void) snprintf(realpath, MAXPATHLEN, "%s%s", + KMF_PLUGIN_PATH, modulepath); + } else { + char *buf = modulepath; + char *isa; + + if ((isa = strstr(buf, PKCS11_ISA)) != NULL) { + (void) strncpy(realpath, buf, isa - buf); + isa += strlen(PKCS11_ISA) - 1; + (void) strlcat(realpath, isa, MAXPATHLEN); + } else { + (void) strlcpy(realpath, modulepath, MAXPATHLEN); + } + } + + if (stat(realpath, &statbuf) != 0) { + (void) fprintf(stderr, gettext("%s not found.\n"), + realpath); + rv = KC_ERR_ACCESS; + goto out; + } + + if ((pfile = fopen(_PATH_KMF_CONF, "r+")) == NULL) { + err = errno; + (void) fprintf(stderr, + gettext("failed to update the configuration - %s\n"), + strerror(err)); + rv = KC_ERR_ACCESS; + goto out; + } + + if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { + err = errno; + (void) fprintf(stderr, + gettext("failed to lock the configuration - %s\n"), + strerror(err)); + rv = KC_ERR_INSTALL; + goto out; + } + + /* + * Create a temporary file in the /etc/crypto directory. + */ + (void) strlcpy(tmpfile_name, CONF_TEMPFILE, sizeof (tmpfile_name)); + if (mkstemp(tmpfile_name) == -1) { + err = errno; + (void) fprintf(stderr, + gettext("failed to create a temporary file - %s\n"), + strerror(err)); + rv = KC_ERR_INSTALL; + goto out; + } + + if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { + err = errno; + (void) fprintf(stderr, + gettext("failed to open %s - %s\n"), + tmpfile_name, strerror(err)); + rv = KC_ERR_INSTALL; + goto out; + } + + /* + * Loop thru the config file. If the file was reserved within a + * package bracket, just uncomment it. Other wise, append it at + * the end. The resulting file will be saved in the temp file first. + */ + while (fgets(buffer, BUFSIZ, pfile) != NULL) { + found = B_FALSE; + if (buffer[0] == '#') { + ptr = buffer; + ptr++; + while (*ptr == '#' || *ptr == ' ') + ptr++; + if (strncmp(keystore_name, ptr, strlen(keystore_name)) + == 0) { + found = B_TRUE; + found_count++; + } + } + + if (found == B_FALSE) { + if (fputs(buffer, pfile_tmp) == EOF) { + rv = KC_ERR_INSTALL; + goto out; + } + } else { + if (found_count == 1) { + if (fputs(ptr, pfile_tmp) == EOF) { + rv = KC_ERR_INSTALL; + goto out; + } + } else { + /* + * Found a second entry with #keystore_name. + * This should not happen. The kmf.conf file + * is corrupted. Give a warning and skip + * this entry. + */ + (void) fprintf(stderr, gettext( + "(Warning) Found an additional reserved " + "entry for %s.\n"), keystore_name); + } + } + } + + if (found_count == 0) { + char buf[MAXPATHLEN]; + /* + * This entry was not in package before, append it to the + * end of the temp file. + */ + if (option_str == NULL) + (void) snprintf(buf, MAXPATHLEN, "%s:%s%s\n", + keystore_name, CONF_MODULEPATH, modulepath); + else + (void) snprintf(buf, MAXPATHLEN, "%s:%s%s;%s%s\n", + keystore_name, CONF_MODULEPATH, modulepath, + CONF_OPTION, option_str); + + if (fputs(buf, pfile_tmp) == EOF) { + err = errno; + (void) fprintf(stderr, gettext( + "failed to write to %s: %s\n"), tmpfile_name, + strerror(err)); + rv = KC_ERR_INSTALL; + goto out; + } + } + +out: + if (pfile != NULL) + (void) fclose(pfile); + + if (rv != KC_OK && pfile_tmp != NULL) + (void) unlink(tmpfile_name); + + if (pfile_tmp != NULL) + (void) fclose(pfile_tmp); + + if (rv == KC_OK) { + if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) { + err = errno; + (void) fprintf(stderr, gettext( + "failed to update the configuration - %s"), + strerror(err)); + return (KC_ERR_INSTALL); + } + + if (chmod(_PATH_KMF_CONF, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { + err = errno; + (void) fprintf(stderr, gettext( + "failed to update the configuration - %s\n"), + strerror(err)); + return (KC_ERR_INSTALL); + } + } + + return (rv); +} |