diff options
author | hylee <none@none> | 2007-12-06 15:56:13 -0800 |
---|---|---|
committer | hylee <none@none> | 2007-12-06 15:56:13 -0800 |
commit | 431deaa01ac039d796fdfaf86b909a75e7d9ac48 (patch) | |
tree | 0d4bb232b811d43a31fcb0d6149d0624c643e3f4 /usr/src/cmd/cmd-crypto | |
parent | c73e9863820a560b7fbb4fb258aa450a88315a39 (diff) | |
download | illumos-joyent-431deaa01ac039d796fdfaf86b909a75e7d9ac48.tar.gz |
PSARC 2007/604 KMF Pluggability Enhancements
6621224 KMF Dynamic Plugin Support
6621231 pktool list keystore=file dir=/tmp/test prints out incorrect output
Diffstat (limited to 'usr/src/cmd/cmd-crypto')
-rw-r--r-- | usr/src/cmd/cmd-crypto/etc/Makefile | 1 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/etc/kmf.conf | 43 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/kmfcfg/Makefile | 6 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/kmfcfg/install.c | 311 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c | 21 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/kmfcfg/list.c | 83 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/kmfcfg/modify.c | 262 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/kmfcfg/uninstall.c | 248 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/kmfcfg/util.c | 30 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/kmfcfg/util.h | 9 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/pktool/list.c | 2 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/scripts/Makefile | 6 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/scripts/i.kmfconf | 116 | ||||
-rw-r--r-- | usr/src/cmd/cmd-crypto/scripts/r.kmfconf | 81 |
14 files changed, 1196 insertions, 23 deletions
diff --git a/usr/src/cmd/cmd-crypto/etc/Makefile b/usr/src/cmd/cmd-crypto/etc/Makefile index 7b600f0489..14f4b1e541 100644 --- a/usr/src/cmd/cmd-crypto/etc/Makefile +++ b/usr/src/cmd/cmd-crypto/etc/Makefile @@ -32,6 +32,7 @@ RELEASECRYPTO = SUNW_SunOS_5.10 \ ETCCRYPTOFILES = \ kcf.conf \ pkcs11.conf \ + kmf.conf \ $(RELEASECRYPTO:%=certs/%) \ certs/CA \ certs/SUNWObjectCA diff --git a/usr/src/cmd/cmd-crypto/etc/kmf.conf b/usr/src/cmd/cmd-crypto/etc/kmf.conf new file mode 100644 index 0000000000..e98dea72be --- /dev/null +++ b/usr/src/cmd/cmd-crypto/etc/kmf.conf @@ -0,0 +1,43 @@ +# +# 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. +# +# ident "%Z%%M% %I% %E% SMI" +# +# /etc/crypto/kmf.conf +# +# This file contains non-default plugin entries to the Solaris Key Management +# Framework (KMF). Do NOT edit this file by hand. An administrator should use +# kmfcfg(1m) to install or uninstall a non-default plugin. A developer for a +# KMF plugin package should provide an input file and use the {i,r}.kmfconf +# class action scripts to update this file during the installation and removal +# of the package. +# +# This document does not constitute an API. The /etc/crypto/kmf.conf file +# may not exist or may have a different content or interpretation in a future +# release. The existence of this notice does not imply that any other +# documentation that lacks this notice constitutes an API. +# +# The format for each entry is: +# keystore:modulepath=path[;option=option_str] +# diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/Makefile b/usr/src/cmd/cmd-crypto/kmfcfg/Makefile index 57e1b6d72e..f476df768f 100644 --- a/usr/src/cmd/cmd-crypto/kmfcfg/Makefile +++ b/usr/src/cmd/cmd-crypto/kmfcfg/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -36,7 +36,9 @@ OBJS = kmfcfg.o \ create.o \ modify.o \ export.o \ - import.o + import.o \ + install.o \ + uninstall.o include ../../Makefile.cmd 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); +} diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c b/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c index e58368284f..997fbc131d 100644 --- a/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c +++ b/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -53,11 +53,15 @@ int kc_create(int argc, char *argv[]); int kc_modify(int argc, char *argv[]); int kc_export(int argc, char *argv[]); int kc_import(int argc, char *argv[]); +int kc_install(int argc, char *argv[]); +int kc_uninstall(int argc, char *argv[]); + static int kc_help(); static verbcmd cmds[] = { - { "list", kc_list, "list [dbfile=dbfile] " - "[policy=policyname]" }, + { "list", kc_list, + "list [dbfile=dbfile] [policy=policyname]\n" + "\tlist plugin" }, { "delete", kc_delete, "delete [dbfile=dbfile] " "policy=policyname" }, { "create", kc_create, @@ -125,11 +129,16 @@ static verbcmd cmds[] = { "\t\tipsecUser | timeStamping |\n\t" "\t\tOCSPSigning],[...]\n" "\t\t[ekuoids=OID,OID,OID...]\n" - "\t\t[eku-none=true|false]\n" }, + "\t\t[eku-none=true|false]\n\n" + "\tmodify plugin keystore=keystorename option=optionstring\n"}, + { "import", kc_import, "import [dbfile=dbfile] policy=policyname " "infile=inputdbfile\n" }, { "export", kc_export, "export [dbfile=dbfile] policy=policyname " "outfile=newdbfile\n" }, + { "install", kc_install, "install keystore=keystorename " + "modulepath=path [option=optionstring]\n"}, + { "uninstall", kc_uninstall, "uninstall keystore=keystorename\n"}, { "-?", kc_help, "help"}, { "help", kc_help, ""} }; @@ -235,6 +244,10 @@ main(int argc, char *argv[]) break; case KC_ERR_ACCESS: break; + case KC_ERR_INSTALL: + break; + case KC_ERR_UNINSTALL: + break; default: (void) fprintf(stderr, gettext("%s operation failed. " "error 0x%02x\n"), cmds[found].verb, ret); diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/list.c b/usr/src/cmd/cmd-crypto/kmfcfg/list.c index b05400a2fd..ff2f83a8d5 100644 --- a/usr/src/cmd/cmd-crypto/kmfcfg/list.c +++ b/usr/src/cmd/cmd-crypto/kmfcfg/list.c @@ -30,10 +30,13 @@ #include <libgen.h> #include <libintl.h> #include <errno.h> +#include <sys/stat.h> #include <kmfapiP.h> - #include "util.h" +#define LIB_NSS_PATH "/usr/lib/mps/libnss3.so" +#define LIB_NSPR_PATH "/usr/lib/mps/libnspr4.so" + static void show_policy(KMF_POLICY_RECORD *plc) { @@ -162,6 +165,46 @@ show_policy(KMF_POLICY_RECORD *plc) (void) printf("\n"); } +void +show_plugin(void) +{ + conf_entrylist_t *phead = NULL; + struct stat statbuf; + + (void) printf(gettext("KMF plugin information:\n")); + (void) printf(gettext("-----------------------\n")); + + /* List the built-in plugins */ + (void) printf("pkcs11:kmf_pkcs11.so.1 (built-in)\n"); + (void) printf("file:kmf_openssl.so.1 (built-in)\n"); + + /* + * If the NSS libraries are not installed in the system, + * then we will not show the nss plugin either. + */ + if (stat(LIB_NSS_PATH, &statbuf) == 0 && + stat(LIB_NSPR_PATH, &statbuf) == 0) { + (void) printf("nss:kmf_nss.so.1 (built-in)\n"); + } + + /* List non-default plugins, if there is any. */ + if (get_entrylist(&phead) == KMF_OK) { + while (phead != NULL) { + (void) printf("%s:%s", phead->entry->keystore, + phead->entry->modulepath); + + if (phead->entry->option == NULL) + (void) printf("\n"); + else + (void) printf(";option=%s\n", + phead->entry->option); + phead = phead->next; + } + free_entrylist(phead); + } +} + + int kc_list(int argc, char *argv[]) { @@ -173,28 +216,41 @@ kc_list(int argc, char *argv[]) char *policyname = NULL; POLICY_LIST *plclist = NULL, *pnode; int sanity_err = 0; + boolean_t list_plugin = B_FALSE; - while ((opt = getopt_av(argc, argv, "i:(dbfile)p:(policy)")) != EOF) { + while ((opt = getopt_av(argc, argv, "i:(dbfile)p:(policy)m(plugin)")) + != EOF) { switch (opt) { - case 'i': + case 'i': + if (list_plugin) + rv = KC_ERR_USAGE; + else { filename = get_string(optarg_av, &rv); if (filename == NULL) { (void) fprintf(stderr, gettext("Error dbfile input.\n")); } - break; - case 'p': + } + break; + case 'p': + if (list_plugin) + rv = KC_ERR_USAGE; + else { policyname = get_string(optarg_av, &rv); if (policyname == NULL) { (void) fprintf(stderr, gettext("Error policy name.\n")); } - break; - default: - (void) fprintf(stderr, - gettext("Error input option.\n")); - rv = KC_ERR_USAGE; - break; + } + break; + case 'm': + list_plugin = B_TRUE; + break; + default: + (void) fprintf(stderr, + gettext("Error input option.\n")); + rv = KC_ERR_USAGE; + break; } if (rv != KC_OK) goto out; @@ -209,6 +265,11 @@ kc_list(int argc, char *argv[]) goto out; } + if (list_plugin) { + show_plugin(); + goto out; + } + if (filename == NULL) { filename = strdup(KMF_DEFAULT_POLICY_FILE); if (filename == NULL) { diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/modify.c b/usr/src/cmd/cmd-crypto/kmfcfg/modify.c index de9f7539ee..462a35f705 100644 --- a/usr/src/cmd/cmd-crypto/kmfcfg/modify.c +++ b/usr/src/cmd/cmd-crypto/kmfcfg/modify.c @@ -32,6 +32,8 @@ #include <errno.h> #include <kmfapiP.h> #include <cryptoutil.h> +#include <sys/stat.h> +#include <sys/param.h> #include "util.h" #define KC_IGNORE_DATE 0x0000001 @@ -60,8 +62,11 @@ #define KC_EKUS 0x0800000 #define KC_EKUS_NONE 0x1000000 +static int err; /* To store errno which may be overwritten by gettext() */ + + int -kc_modify(int argc, char *argv[]) +kc_modify_policy(int argc, char *argv[]) { KMF_RETURN ret; int rv = KC_OK; @@ -843,3 +848,258 @@ out: return (rv); } + + +static int +kc_modify_plugin(int argc, char *argv[]) +{ + int rv = KC_OK; + int opt; + extern int optind_av; + extern char *optarg_av; + char *keystore_name = NULL; + char *option = NULL; + boolean_t modify_plugin = B_FALSE; + boolean_t has_option_arg = B_FALSE; + conf_entry_t *entry = NULL; + FILE *pfile = NULL; + FILE *pfile_tmp = NULL; + char tmpfile_name[MAXPATHLEN]; + char buffer[MAXPATHLEN]; + char buffer2[MAXPATHLEN]; + + while ((opt = getopt_av(argc, argv, "p(plugin)k:(keystore)o:(option)")) + != EOF) { + switch (opt) { + case 'p': + if (modify_plugin) { + (void) fprintf(stderr, + gettext("duplicate plugin input.\n")); + rv = KC_ERR_USAGE; + } else { + modify_plugin = B_TRUE; + } + break; + 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")); + rv = KC_ERR_USAGE; + } + } + break; + case 'o': + if (has_option_arg) { + (void) fprintf(stderr, + gettext("duplicate option input.\n")); + rv = KC_ERR_USAGE; + } else { + has_option_arg = B_TRUE; + option = get_string(optarg_av, NULL); + } + 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 || has_option_arg == B_FALSE) { + (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 modify the built-in keystore %s\n"), + keystore_name); + rv = KC_ERR_USAGE; + goto out; + } + + entry = get_keystore_entry(keystore_name); + if (entry == NULL) { + (void) fprintf(stderr, gettext("%s does not exist.\n"), + keystore_name); + rv = KC_ERR_USAGE; + goto out; + } + + if ((entry->option == NULL && option == NULL) || + (entry->option != NULL && option != NULL && + strcmp(entry->option, option) == 0)) { + (void) fprintf(stderr, gettext("No change - " + "the new option is same as the old option.\n")); + rv = KC_OK; + 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_MODIFY_PLUGIN; + 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_MODIFY_PLUGIN; + 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_MODIFY_PLUGIN; + goto out; + } + + /* + * Loop thru the config file and update the entry. + */ + while (fgets(buffer, MAXPATHLEN, pfile) != NULL) { + char *name; + int len; + + if (buffer[0] == '#') { + if (fputs(buffer, pfile_tmp) == EOF) { + rv = KC_ERR_MODIFY_PLUGIN; + goto out; + } else { + continue; + } + } + + /* + * make a copy of the original buffer to buffer2. Also get + * rid of the trailing '\n' from buffer2. + */ + (void) strlcpy(buffer2, buffer, MAXPATHLEN); + len = strlen(buffer2); + if (buffer2[len-1] == '\n') { + len--; + } + buffer2[len] = '\0'; + + if ((name = strtok(buffer2, SEP_COLON)) == NULL) { + rv = KC_ERR_UNINSTALL; + goto out; + } + + if (strcmp(name, keystore_name) == 0) { + /* found the entry */ + if (option == NULL) + (void) snprintf(buffer, MAXPATHLEN, + "%s:%s%s\n", keystore_name, + CONF_MODULEPATH, entry->modulepath); + else + (void) snprintf(buffer, MAXPATHLEN, + "%s:%s%s;%s%s\n", keystore_name, + CONF_MODULEPATH, entry->modulepath, + CONF_OPTION, option); + + if (fputs(buffer, pfile_tmp) == EOF) { + err = errno; + (void) fprintf(stderr, gettext( + "failed to write to %s: %s\n"), + tmpfile_name, strerror(err)); + rv = KC_ERR_MODIFY_PLUGIN; + goto out; + } + } else { + + if (fputs(buffer, pfile_tmp) == EOF) { + rv = KC_ERR_UNINSTALL; + goto out; + } + } + } + + if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) { + err = errno; + (void) fprintf(stderr, gettext( + "failed to update the configuration - %s"), strerror(err)); + rv = KC_ERR_MODIFY_PLUGIN; + goto out; + } + + 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)); + rv = KC_ERR_MODIFY_PLUGIN; + goto out; + } + +out: + if (entry != NULL) + free_entry(entry); + + 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); + + return (rv); +} + + +int +kc_modify(int argc, char *argv[]) +{ + if (argc > 2 && + strcmp(argv[0], "modify") == 0 && + strcmp(argv[1], "plugin") == 0) { + return (kc_modify_plugin(argc, argv)); + } else { + return (kc_modify_policy(argc, argv)); + } +} diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/uninstall.c b/usr/src/cmd/cmd-crypto/kmfcfg/uninstall.c new file mode 100644 index 0000000000..72de8e627c --- /dev/null +++ b/usr/src/cmd/cmd-crypto/kmfcfg/uninstall.c @@ -0,0 +1,248 @@ +/* + * 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_uninstall(int argc, char *argv[]) +{ + int rv = KC_OK; + int opt; + extern int optind_av; + extern char *optarg_av; + char *keystore_name = NULL; + conf_entry_t *entry = NULL; + FILE *pfile = NULL; + FILE *pfile_tmp = NULL; + char tmpfile_name[MAXPATHLEN]; + char buffer[MAXPATHLEN]; + char buffer2[MAXPATHLEN]; + boolean_t found; + boolean_t in_package; + + while ((opt = getopt_av(argc, argv, "k:(keystore)")) != 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; + 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) { + (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 uninstall the built-in keystore %s\n"), + keystore_name); + rv = KC_ERR_UNINSTALL; + goto out; + } + + entry = get_keystore_entry(keystore_name); + if (entry == NULL) { + (void) fprintf(stderr, gettext("%s does not exist.\n"), + keystore_name); + rv = KC_ERR_USAGE; + 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_UNINSTALL; + 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_UNINSTALL; + goto out; + } + + if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { + err = errno; + (void) fprintf(stderr, + gettext("failed to open a temporary file - %s\n"), + strerror(err)); + rv = KC_ERR_UNINSTALL; + goto out; + } + + /* + * Loop thru the config file. If the plugin to be uninstalled is in + * a package, then just comment it off. + */ + in_package = B_FALSE; + while (fgets(buffer, MAXPATHLEN, 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] != '#') { + char *name; + int len; + + /* + * make a copy of the original buffer to + * buffer2. Also get rid of the trailing + * '\n' from buffer2. + */ + (void) strlcpy(buffer2, buffer, MAXPATHLEN); + /* get rid of trailing '\n' */ + len = strlen(buffer2); + if (buffer2[len-1] == '\n') { + len--; + } + buffer2[len] = '\0'; + + if ((name = strtok(buffer2, SEP_COLON)) == + NULL) { + rv = KC_ERR_UNINSTALL; + goto out; + } + + if (strcmp(keystore_name, name) == 0) + found = B_TRUE; + } + } + + if (found) { + /* + * If found and not in_package, then don't write + * this line to the result file. + */ + if (in_package) { + (void) snprintf(buffer2, sizeof (buffer2), + "%s%s", "#", buffer); + + if (fputs(buffer2, pfile_tmp) == EOF) { + rv = KC_ERR_UNINSTALL; + goto out; + } + } + } else { + if (fputs(buffer, pfile_tmp) == EOF) { + rv = KC_ERR_UNINSTALL; + 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_UNINSTALL); + } + + 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_UNINSTALL); + } + } + + return (rv); +} diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/util.c b/usr/src/cmd/cmd-crypto/kmfcfg/util.c index 3fce0c839d..f151e454ce 100644 --- a/usr/src/cmd/cmd-crypto/kmfcfg/util.c +++ b/usr/src/cmd/cmd-crypto/kmfcfg/util.c @@ -34,9 +34,9 @@ #include <libxml/parser.h> #include <kmfapiP.h> - #include "util.h" + /* Supporting structures and global variables for getopt_av(). */ typedef struct av_opts_s { int shortnm; /* short name character */ @@ -490,3 +490,31 @@ print_sanity_error(KMF_RETURN ret) break; } } + + +conf_entry_t * +get_keystore_entry(char *kstore_name) +{ + conf_entrylist_t *phead = NULL; + conf_entrylist_t *ptr; + conf_entry_t *rtn_entry = NULL; + + if (kstore_name == NULL) + return (NULL); + + if (get_entrylist(&phead) != KMF_OK) + return (NULL); + + ptr = phead; + while (ptr != NULL) { + if (strcmp(ptr->entry->keystore, kstore_name) == 0) + break; + ptr = ptr->next; + } + + if (ptr != NULL) /* found the entry */ + rtn_entry = dup_entry(ptr->entry); + + free_entrylist(phead); + return (rtn_entry); +} diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/util.h b/usr/src/cmd/cmd-crypto/kmfcfg/util.h index 74f4b0be9b..db1af092e4 100644 --- a/usr/src/cmd/cmd-crypto/kmfcfg/util.h +++ b/usr/src/cmd/cmd-crypto/kmfcfg/util.h @@ -18,7 +18,7 @@ * * CDDL HEADER END * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _UTIL_H @@ -49,6 +49,8 @@ int parseEKUNames(char *, KMF_POLICY_RECORD *); uint16_t parseKUlist(char *); void print_sanity_error(KMF_RETURN); +conf_entry_t *get_keystore_entry(char *); + #define KC_OK 0 #define KC_ERR_USAGE 1 #define KC_ERR_LOADDB 2 @@ -59,6 +61,11 @@ void print_sanity_error(KMF_RETURN); #define KC_ERR_INCOMPLETE_POLICY 7 #define KC_ERR_MEMORY 8 #define KC_ERR_ACCESS 9 +#define KC_ERR_INSTALL 10 +#define KC_ERR_UNINSTALL 11 +#define KC_ERR_MODIFY_PLUGIN 12 + +#define CONF_TEMPFILE "/etc/crypto/kmfXXXXXX" #ifdef __cplusplus } diff --git a/usr/src/cmd/cmd-crypto/pktool/list.c b/usr/src/cmd/cmd-crypto/pktool/list.c index 0cc686ebc2..934d3f4df1 100644 --- a/usr/src/cmd/cmd-crypto/pktool/list.c +++ b/usr/src/cmd/cmd-crypto/pktool/list.c @@ -514,7 +514,7 @@ list_file_objects(KMF_HANDLE_T kmfhandle, int oclass, char *issuer, char *subject, KMF_CERT_VALIDITY find_criteria_flag) { - int rv; + KMF_RETURN rv = KMF_OK; KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; int numattr = 0; KMF_ATTRIBUTE attrlist[16]; diff --git a/usr/src/cmd/cmd-crypto/scripts/Makefile b/usr/src/cmd/cmd-crypto/scripts/Makefile index 9aa297ad53..44b8c971c6 100644 --- a/usr/src/cmd/cmd-crypto/scripts/Makefile +++ b/usr/src/cmd/cmd-crypto/scripts/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -29,7 +29,9 @@ CLASS_ACTION_SCRIPTS = \ i.kcfconf \ r.kcfconf \ i.pkcs11conf \ - r.pkcs11conf + r.pkcs11conf \ + i.kmfconf \ + r.kmfconf MANIFEST = cryptosvc.xml diff --git a/usr/src/cmd/cmd-crypto/scripts/i.kmfconf b/usr/src/cmd/cmd-crypto/scripts/i.kmfconf new file mode 100644 index 0000000000..52b06b088c --- /dev/null +++ b/usr/src/cmd/cmd-crypto/scripts/i.kmfconf @@ -0,0 +1,116 @@ +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# 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 +# +# ident "%Z%%M% %I% %E% SMI" +# +# Class action script for "kmfconf" class files. +# +# This script appends the input file from the package to the +# /etc/crypto/kmf.conf file. +# +# The syntax of the input file is +# keystore:modulepath=path[;option=option_str] +# +# +pkg_start="# Start $PKGINST" +pkg_end="# End $PKGINST" +tmpfile=/tmp/$$kmfconf +error=no + +while read src dest +do + [ "$src" = /dev/null ] && continue + + if [ -f "$dest" ] + then + # For multiple input files; exit if error occurred in previous + # input file. + if [ "$error" = yes ] + then + echo "$0: failed to update $lastdest for $PKGINST." + exit 2 + fi + lastdest=$dest + + # + # If the package has been already installed, remove old entries + # + start=0; + end=0; + egrep -s "$pkg_start" $dest && start=1 + egrep -s "$pkg_end" $dest && end=1 + + if [ $start -ne $end ] + then + echo "$0: missing Start or End delimiters for \ + $PKGINST in $dest." + echo "$0: $dest may be corrupted and was not updated." + error=yes + continue + fi + + if [ $start -eq 1 ] + then + sed -e "/$pkg_start/,/$pkg_end/d" $dest > $tmpfile \ + || error=yes + else + cp $dest $tmpfile || error=yes + fi + + # + # Check the input file syntax (should at least contain + # ":module_path="). Then append the input entries with the + #scc package delimiters. + # + line_count=`wc -l $src | awk '{ print $1}'` + file_count=`grep ":modulepath=" $src | wc -l` + if [ $line_count -ne $file_count ] + then + echo "$0: Syntax Error - $src for $PKGINST." + error=yes + continue + else + echo "$pkg_start" >> $tmpfile || error=yes + cat $src >> $tmpfile || error=yes + echo "$pkg_end" >> $tmpfile || error=yes + fi + + # Install the updated config file and clean up the tmp file + if [ "$error" = no ] + then + mv $tmpfile $dest || error=yes + fi + rm -f $tmpfile + else + echo "$0: ERROR - $dest doesn't exist for $PKGINST." + exit 2 + fi +done + +if [ "$error" = yes ] +then + echo "$0: ERROR - failed to update $lastdest for $PKGINST." + exit 2 +fi + +exit 0 diff --git a/usr/src/cmd/cmd-crypto/scripts/r.kmfconf b/usr/src/cmd/cmd-crypto/scripts/r.kmfconf new file mode 100644 index 0000000000..8c35957f76 --- /dev/null +++ b/usr/src/cmd/cmd-crypto/scripts/r.kmfconf @@ -0,0 +1,81 @@ +# +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# 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 +# +# ident "%Z%%M% %I% %E% SMI" +# +# Removal class action script for "kmfconf" class files. +# +# This script removes entries belonging to the package from the +# /etc/crypto/kmf.conf file. +# + +pkg_start="# Start $PKGINST" +pkg_end="# End $PKGINST" +tmpfile=/tmp/$$kmfconf +error=no + +while read dest +do + # For multiple input files; exit if error occurred in preious + # input file. + if [ "$error" = yes ] + then + echo "$0: failed to update $lastdest for $PKGINST." + exit 2 + fi + lastdest=$dest + + # Strip all entries belonging to this package + start=0 + end=0 + egrep -s "$pkg_start" $dest && start=1 + egrep -s "$pkg_end" $dest && end=1 + + if [ $start -ne $end ] ; then + echo "$0: missing Start or End delimiters for $PKGINST in \ + $dest." + echo "$0: $dest may be corrupted and was not updated." + error=yes + continue + fi + + if [ $start -eq 1 ] + then + sed -e "/$pkg_start/,/$pkg_end/d" $dest > $tmpfile || error=yes + if [ "$error" = no ] + then + mv $tmpfile $dest || error=yes + fi + rm -f $tmpfile + else + echo "$0: WARNING - no entries found in $dest for $PKGINST." + exit 0 + fi +done + +if [ "$error" = yes ] +then + echo "$0: ERROR - failed to update $lastdest for $PKGINST." + exit 2 +fi +exit 0 |