summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-crypto/kmfcfg
diff options
context:
space:
mode:
authorwyllys <none@none>2006-11-10 15:34:56 -0800
committerwyllys <none@none>2006-11-10 15:34:56 -0800
commit99ebb4ca412cb0a19d77a3899a87c055b9c30fa8 (patch)
treea972f78468519a4e00234388688f45a506e934ba /usr/src/cmd/cmd-crypto/kmfcfg
parent177fd15c9f814babb60e824f89984cdd8acf7c85 (diff)
downloadillumos-joyent-99ebb4ca412cb0a19d77a3899a87c055b9c30fa8.tar.gz
PSARC 2005/074 Solaris Key Management Framework
6224192 Solaris needs unified key management interfaces --HG-- rename : usr/src/cmd/cmd-crypto/pktool/biginteger.h => deleted_files/usr/src/cmd/cmd-crypto/pktool/biginteger.h rename : usr/src/cmd/cmd-crypto/pktool/derparse.c => deleted_files/usr/src/cmd/cmd-crypto/pktool/derparse.c rename : usr/src/cmd/cmd-crypto/pktool/derparse.h => deleted_files/usr/src/cmd/cmd-crypto/pktool/derparse.h rename : usr/src/cmd/cmd-crypto/pktool/osslcommon.c => deleted_files/usr/src/cmd/cmd-crypto/pktool/osslcommon.c rename : usr/src/cmd/cmd-crypto/pktool/osslcommon.h => deleted_files/usr/src/cmd/cmd-crypto/pktool/osslcommon.h rename : usr/src/cmd/cmd-crypto/pktool/p12common.c => deleted_files/usr/src/cmd/cmd-crypto/pktool/p12common.c rename : usr/src/cmd/cmd-crypto/pktool/p12common.h => deleted_files/usr/src/cmd/cmd-crypto/pktool/p12common.h
Diffstat (limited to 'usr/src/cmd/cmd-crypto/kmfcfg')
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/Makefile91
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/create.c498
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/delete.c132
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/export.c167
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/import.c169
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c245
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd84
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.xml40
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/list.c277
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/modify.c845
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/util.c497
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/util.h66
12 files changed, 3111 insertions, 0 deletions
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/Makefile b/usr/src/cmd/cmd-crypto/kmfcfg/Makefile
new file mode 100644
index 0000000000..86fd4eb30e
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/Makefile
@@ -0,0 +1,91 @@
+#
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Makefile for policy testing code
+#
+
+PROG = kmfcfg
+
+OBJS = kmfcfg.o \
+ list.o \
+ delete.o \
+ util.o \
+ create.o \
+ modify.o \
+ export.o \
+ import.o
+
+include ../../Makefile.cmd
+
+KMFDIR = $(SRC)/lib/libkmf
+SRCS = $(OBJS:%.o=%.c)
+
+POFILES = $(OBJS:%.o=%.po)
+POFILE = $(PROG)_msg.po
+MSGFILES = $(SRCS:%.c=%.i)
+
+CPPFLAGS += -I/usr/include/libxml2 -I$(KMFDIR)/include -I.
+LDLIBS += -L$(ROOT)/usr/lib -lkmf -lcryptoutil
+XMLLIB = -lxml2
+
+.KEEP_STATE:
+
+XMLDIR= $(ROOT)/etc/security
+DTDDIR= $(ROOT)/usr/share/lib/xml/dtd
+ROOTDTDS= $(DTDDIR)/kmfpolicy.dtd
+ROOTXML= $(XMLDIR)/kmfpolicy.xml
+
+$(ROOTDTDS) := FILEMODE = 444
+$(ROOTDTDS) := OWNER = root
+$(ROOTDTDS) := GROUP = bin
+
+$(ROOTXML) := FILEMODE = 644
+$(ROOTXML) := OWNER = root
+$(ROOTXML) := GROUP = bin
+
+all: $(PROG) $(ROOTDTDS)
+
+$(PROG): $(OBJS)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(XMLLIB)
+ $(POST_PROCESS)
+
+$(POFILE): $(POFILES)
+ $(BUILDPO.pofiles)
+
+install: all $(ROOTDTDS) $(ROOTXML) $(ROOTPROG)
+
+$(XMLDIR)/%: %
+ $(INS.file)
+
+$(DTDDIR)/%: %
+ $(INS.file)
+
+clean:
+ $(RM) $(OBJS)
+
+lint : lint_SRCS
+
+include ../../Makefile.targ
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/create.c b/usr/src/cmd/cmd-crypto/kmfcfg/create.c
new file mode 100644
index 0000000000..ceacf5f5d5
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/create.c
@@ -0,0 +1,498 @@
+/*
+ * 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 2006 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 <cryptoutil.h>
+#include "util.h"
+
+int
+kc_create(int argc, char *argv[])
+{
+ KMF_RETURN ret;
+ int rv = KC_OK;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ char *filename = NULL;
+ int ocsp_set_attr = 0;
+ boolean_t crl_set_attr = 0;
+ KMF_POLICY_RECORD plc;
+
+ (void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
+
+ while ((opt = getopt_av(argc, argv,
+ "i:(dbfile)"
+ "p:(policy)"
+ "d:(ignore-date)"
+ "e:(ignore-unknown-eku)"
+ "a:(ignore-trust-anchor)"
+ "v:(validity-adjusttime)"
+ "t:(ta-name)"
+ "s:(ta-serial)"
+ "o:(ocsp-responder)"
+ "P:(ocsp-proxy)"
+ "r:(ocsp-use-cert-responder)"
+ "T:(ocsp-response-lifetime)"
+ "R:(ocsp-ignore-response-sign)"
+ "n:(ocsp-responder-cert-name)"
+ "A:(ocsp-responder-cert-serial)"
+ "c:(crl-basefilename)"
+ "I:(crl-directory)"
+ "g:(crl-get-crl-uri)"
+ "X:(crl-proxy)"
+ "S:(crl-ignore-crl-sign)"
+ "D:(crl-ignore-crl-date)"
+ "u:(keyusage)"
+ "E:(ekunames)"
+ "O:(ekuoids)")) != EOF) {
+ switch (opt) {
+ case 'i':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ plc.name = get_string(optarg_av, &rv);
+ if (plc.name == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ case 'd':
+ plc.ignore_date = get_boolean(optarg_av);
+ if (plc.ignore_date == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'e':
+ plc.ignore_unknown_ekus =
+ get_boolean(optarg_av);
+ if (plc.ignore_unknown_ekus == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'a':
+ plc.ignore_trust_anchor =
+ get_boolean(optarg_av);
+ if (plc.ignore_trust_anchor == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'v':
+ plc.validity_adjusttime =
+ get_string(optarg_av, &rv);
+ if (plc.validity_adjusttime == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error time input.\n"));
+ } else {
+ uint32_t adj;
+ /* for syntax checking */
+ if (str2lifetime(
+ plc.validity_adjusttime,
+ &adj) < 0) {
+ (void) fprintf(stderr,
+ gettext("Error time "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ }
+ break;
+ case 't':
+ plc.ta_name = get_string(optarg_av, &rv);
+ if (plc.ta_name == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error name input.\n"));
+ } else {
+ KMF_X509_NAME taDN;
+ /* for syntax checking */
+ if (KMF_DNParser(plc.ta_name,
+ &taDN) != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error name "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ KMF_FreeDN(&taDN);
+ }
+ }
+ break;
+ case 's':
+ plc.ta_serial = get_string(optarg_av, &rv);
+ if (plc.ta_serial == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error serial input.\n"));
+ } else {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
+
+ ret = KMF_HexString2Bytes(
+ (uchar_t *)plc.ta_serial,
+ &bytes, &bytelen);
+ if (ret != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr,
+ gettext("serial number "
+ "must be specified as a "
+ "hex number "
+ "(ex: 0x0102030405"
+ "ffeeddee)\n"));
+ rv = KC_ERR_USAGE;
+ }
+ if (bytes != NULL)
+ free(bytes);
+ }
+ break;
+ case 'o':
+ plc.VAL_OCSP_RESPONDER_URI =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
+ (void) fprintf(stderr, gettext(
+ "Error responder input.\n"));
+ } else {
+ ocsp_set_attr++;
+ }
+ break;
+ case 'P':
+ plc.VAL_OCSP_PROXY =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_PROXY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error proxy input.\n"));
+ } else {
+ ocsp_set_attr++;
+ }
+ break;
+ case 'r':
+ plc.VAL_OCSP_URI_FROM_CERT =
+ get_boolean(optarg_av);
+ if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ ocsp_set_attr++;
+ }
+ break;
+ case 'T':
+ plc.VAL_OCSP_RESP_LIFETIME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error time input.\n"));
+ } else {
+ uint32_t adj;
+ /* for syntax checking */
+ if (str2lifetime(
+ plc.VAL_OCSP_RESP_LIFETIME,
+ &adj) < 0) {
+ (void) fprintf(stderr,
+ gettext("Error time "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ ocsp_set_attr++;
+ }
+ }
+ break;
+ case 'R':
+ plc.VAL_OCSP_IGNORE_RESP_SIGN =
+ get_boolean(optarg_av);
+ if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ ocsp_set_attr++;
+ }
+ break;
+ case 'n':
+ plc.VAL_OCSP_RESP_CERT_NAME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error name input.\n"));
+ } else {
+ KMF_X509_NAME respDN;
+ /* for syntax checking */
+ if (KMF_DNParser(
+ plc.VAL_OCSP_RESP_CERT_NAME,
+ &respDN) != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error name "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ KMF_FreeDN(&respDN);
+ ocsp_set_attr++;
+ }
+ }
+ break;
+ case 'A':
+ plc.VAL_OCSP_RESP_CERT_SERIAL =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error serial input.\n"));
+ } else {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
+
+ ret = KMF_HexString2Bytes((uchar_t *)
+ plc.VAL_OCSP_RESP_CERT_SERIAL,
+ &bytes, &bytelen);
+ if (ret != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr,
+ gettext("serial number "
+ "must be specified as a "
+ "hex number "
+ "(ex: 0x0102030405"
+ "ffeeddee)\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ if (bytes != NULL)
+ free(bytes);
+ ocsp_set_attr++;
+ }
+ break;
+ case 'c':
+ plc.VAL_CRL_BASEFILENAME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_BASEFILENAME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'I':
+ plc.VAL_CRL_DIRECTORY =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_DIRECTORY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'g':
+ plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
+ if (plc.VAL_CRL_GET_URI == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'X':
+ plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_PROXY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error proxy input.\n"));
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'S':
+ plc.VAL_CRL_IGNORE_SIGN =
+ get_boolean(optarg_av);
+ if (plc.VAL_CRL_IGNORE_SIGN == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'D':
+ plc.VAL_CRL_IGNORE_DATE =
+ get_boolean(optarg_av);
+ if (plc.VAL_CRL_IGNORE_DATE == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'u':
+ plc.ku_bits = parseKUlist(optarg_av);
+ if (plc.ku_bits == 0) {
+ (void) fprintf(stderr, gettext(
+ "Error keyusage input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'E':
+ if (parseEKUNames(optarg_av, &plc) != 0) {
+ (void) fprintf(stderr,
+ gettext("Error EKU input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'O':
+ if (parseEKUOIDs(optarg_av, &plc) != 0) {
+ (void) fprintf(stderr,
+ gettext("Error EKU OID input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ 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 (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ /*
+ * Must have a policy name. The policy name can not be default
+ * if using the default policy file.
+ */
+ if (plc.name == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not create a default policy in the default "
+ "policy file\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /*
+ * If the policy file exists and the policy is in the policy file
+ * already, we will not create it again.
+ */
+ if (access(filename, R_OK) == 0) {
+ POLICY_LIST *plclist = NULL, *pnode;
+ int found = 0;
+
+ rv = load_policies(filename, &plclist);
+ if (rv != KMF_OK)
+ goto out;
+
+ pnode = plclist;
+ while (pnode != NULL && !found) {
+ if (strcmp(plc.name, pnode->plc.name) == 0)
+ found++;
+ pnode = pnode->next;
+ }
+ free_policy_list(plclist);
+
+ if (found) {
+ (void) fprintf(stderr,
+ gettext("Could not create policy \"%s\" - exists "
+ "already\n"), plc.name);
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+ }
+
+ /*
+ * If any OCSP attribute is set, turn on the OCSP checking flag.
+ * Also set "has_resp_cert" to be true, if the responder cert
+ * is provided.
+ */
+ if (ocsp_set_attr > 0)
+ plc.revocation |= KMF_REVOCATION_METHOD_OCSP;
+
+ if (plc.VAL_OCSP_RESP_CERT.name != NULL &&
+ plc.VAL_OCSP_RESP_CERT.serial != NULL) {
+ plc.VAL_OCSP.has_resp_cert = B_TRUE;
+ }
+
+ /*
+ * If any CRL attribute is set, turn on the CRL checking flag.
+ */
+ if (crl_set_attr > 0)
+ plc.revocation |= KMF_REVOCATION_METHOD_CRL;
+
+ /*
+ * Does a sanity check on the new policy.
+ */
+ ret = KMF_VerifyPolicy(&plc);
+ if (ret != KMF_OK) {
+ print_sanity_error(ret);
+ rv = KC_ERR_ADD_POLICY;
+ goto out;
+ }
+
+ /*
+ * Add to the DB.
+ */
+ ret = KMF_AddPolicyToDB(&plc, filename, B_FALSE);
+ if (ret != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error adding policy to database: 0x%04x\n"), ret);
+ rv = KC_ERR_ADD_POLICY;
+ }
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ KMF_FreePolicyRecord(&plc);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/delete.c b/usr/src/cmd/cmd-crypto/kmfcfg/delete.c
new file mode 100644
index 0000000000..7e0a1c7d45
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/delete.c
@@ -0,0 +1,132 @@
+/*
+ * 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 2006 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 "util.h"
+
+int
+kc_delete(int argc, char *argv[])
+{
+ int rv = KC_OK;
+ KMF_RETURN kmfrv = KMF_OK;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ char *filename = NULL;
+ char *policyname = NULL;
+
+ while ((opt = getopt_av(argc, argv, "i:(dbfile)p:(policy)")) != EOF) {
+ switch (opt) {
+ case 'i':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ 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;
+
+ }
+
+ 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 (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ /*
+ * Must have a policy name. The policy name can not be default
+ * if using the default policy file.
+ */
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(policyname, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not delete the default policy in the default "
+ "policy file\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /* Check the access permission of the policy DB */
+ if (access(filename, W_OK) < 0) {
+ int err = errno;
+ (void) fprintf(stderr,
+ gettext("Cannot access \"%s\" for delete - %s\n"),
+ filename, strerror(err));
+ rv = KC_ERR_ACCESS;
+ goto out;
+ }
+
+ kmfrv = KMF_DeletePolicyFromDB(policyname, filename);
+ if (kmfrv != KMF_OK)
+ rv = KC_ERR_DELETE_POLICY;
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ if (policyname != NULL)
+ free(policyname);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/export.c b/usr/src/cmd/cmd-crypto/kmfcfg/export.c
new file mode 100644
index 0000000000..c1ddab153c
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/export.c
@@ -0,0 +1,167 @@
+/*
+ * 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 2006 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 <locale.h>
+#include <errno.h>
+#include <kmfapiP.h>
+
+#include "util.h"
+
+int
+kc_export(int argc, char *argv[])
+{
+ int rv = KC_OK;
+ char *filename = NULL;
+ char *outfile = NULL;
+ char *policyname = NULL;
+ POLICY_LIST *plclist = NULL, *pnode;
+ int opt, found = 0;
+ extern int optind_av;
+ extern char *optarg_av;
+
+ while ((opt = getopt_av(argc, argv,
+ "d:(dbfile)p:(policy)o:(outfile)")) != EOF) {
+ switch (opt) {
+ case 'd':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ policyname = get_string(optarg_av, &rv);
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ case 'o':
+ outfile = get_string(optarg_av, &rv);
+ if (outfile == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error outfile 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 (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (outfile == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a output DB file\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (strcmp(outfile, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(policyname, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not export the default policy record to "
+ "the system default policy database\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ rv = load_policies(filename, &plclist);
+ if (rv != KMF_OK)
+ goto out;
+
+ pnode = plclist;
+ while (pnode != NULL && !found) {
+ if (strcmp(policyname, pnode->plc.name) == 0) {
+ KMF_RETURN ret;
+
+ found++;
+ ret = KMF_VerifyPolicy(&pnode->plc);
+ if (ret != KMF_OK) {
+ print_sanity_error(ret);
+ rv = KC_ERR_VERIFY_POLICY;
+ break;
+ }
+ rv = KMF_AddPolicyToDB(&pnode->plc, outfile, B_FALSE);
+ }
+ pnode = pnode->next;
+ }
+
+ if (!found) {
+ (void) fprintf(stderr,
+ gettext("Could not find policy \"%s\" in %s\n"),
+ policyname, filename);
+ rv = KC_ERR_FIND_POLICY;
+ }
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ if (policyname != NULL)
+ free(policyname);
+
+ if (outfile != NULL)
+ free(outfile);
+
+ free_policy_list(plclist);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/import.c b/usr/src/cmd/cmd-crypto/kmfcfg/import.c
new file mode 100644
index 0000000000..b55caac068
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/import.c
@@ -0,0 +1,169 @@
+/*
+ * 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 2006 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 <locale.h>
+#include <errno.h>
+
+#include <kmfapiP.h>
+
+#include "util.h"
+
+int
+kc_import(int argc, char *argv[])
+{
+ int rv = KC_OK;
+ char *filename = NULL;
+ char *infile = NULL;
+ char *policyname = NULL;
+ POLICY_LIST *plclist = NULL, *pnode;
+ int opt, found = 0;
+ extern int optind_av;
+ extern char *optarg_av;
+
+ while ((opt = getopt_av(argc, argv,
+ "d:(dbfile)p:(policy)i:(infile)")) != EOF) {
+ switch (opt) {
+ case 'd':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ policyname = get_string(optarg_av, &rv);
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ case 'i':
+ infile = get_string(optarg_av, &rv);
+ if (infile == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error infile 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 (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (infile == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a input DB file\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(policyname, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not import the default policy record to "
+ "the system default policy database\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ rv = load_policies(infile, &plclist);
+ if (rv != KMF_OK)
+ goto out;
+
+ pnode = plclist;
+ while (pnode != NULL && !found) {
+ if (strcmp(policyname, pnode->plc.name) == 0) {
+ KMF_RETURN ret;
+
+ found++;
+ ret = KMF_VerifyPolicy(&pnode->plc);
+ if (ret != KMF_OK) {
+ print_sanity_error(ret);
+ rv = KC_ERR_VERIFY_POLICY;
+ break;
+ }
+ rv = KMF_AddPolicyToDB(&pnode->plc, filename, B_FALSE);
+ }
+ pnode = pnode->next;
+ }
+
+ if (!found) {
+ (void) fprintf(stderr,
+ gettext("Could not find policy \"%s\" in %s\n"),
+ policyname, infile);
+ rv = KC_ERR_FIND_POLICY;
+ }
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ if (policyname != NULL)
+ free(policyname);
+
+ if (infile != NULL)
+ free(infile);
+
+ free_policy_list(plclist);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c b/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c
new file mode 100644
index 0000000000..e58368284f
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c
@@ -0,0 +1,245 @@
+/*
+ * 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 2006 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 <locale.h>
+
+#include <kmfapiP.h>
+
+#include "util.h"
+
+/*
+ * The verbcmd construct allows genericizing information about a verb so
+ * that it is easier to manipulate. Makes parsing code easier to read,
+ * fix, and extend with new verbs.
+ */
+typedef struct verbcmd_s {
+ char *verb;
+ int (*action)(int, char *[]);
+ char *synopsis;
+} verbcmd;
+
+int kc_list(int argc, char *argv[]);
+int kc_delete(int argc, char *argv[]);
+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[]);
+static int kc_help();
+
+static verbcmd cmds[] = {
+ { "list", kc_list, "list [dbfile=dbfile] "
+ "[policy=policyname]" },
+ { "delete", kc_delete, "delete [dbfile=dbfile] "
+ "policy=policyname" },
+ { "create", kc_create,
+ "create [dbfile=dbfile] policy=policyname\n"
+ "\t\t[ignore-date=true|false]\n"
+ "\t\t[ignore-unknown-eku=true|false]\n"
+ "\t\t[ignore-trust-anchor=true|false]\n"
+ "\t\t[validity-adjusttime=adjusttime]\n"
+ "\t\t[ta-name=trust anchor subject DN]\n"
+ "\t\t[ta-serial=trust anchor serial number]\n"
+ "\t\t[ocsp-responder=URL]\n"
+ "\t\t[ocsp-proxy=URL]\n"
+ "\t\t[ocsp-use-cert-responder=true|false]\n"
+ "\t\t[ocsp-response-lifetime=timelimit]\n"
+ "\t\t[ocsp-ignore-response-sign=true|false]\n"
+ "\t\t[ocsp-responder-cert-name=Issuer DN]\n"
+ "\t\t[ocsp-responder-cert-serial=serial number]\n"
+ "\t\t[crl-basefilename=basefilename]\n"
+ "\t\t[crl-directory=directory]\n"
+ "\t\t[crl-get-crl-uri=true|false]\n"
+ "\t\t[crl-proxy=URL]\n"
+ "\t\t[crl-ignore-crl-sign=true|false]\n"
+ "\t\t[crl-ignore-crl-date=true|false]\n"
+ "\t\t[keyusage=digitalSignature|nonRepudiation\n\t"
+ "\t\t|keyEncipherment | dataEncipherment |\n\t"
+ "\t\tkeyAgreement |keyCertSign |\n\t"
+ "\t\tcRLSign | encipherOnly | decipherOnly],[...]\n"
+ "\t\t[ekunames=serverAuth | clientAuth |\n\t"
+ "\t\tcodeSigning | emailProtection |\n\t"
+ "\t\tipsecEndSystem | ipsecTunnel |\n\t"
+ "\t\tipsecUser | timeStamping |\n\t"
+ "\t\tOCSPSigning],[...]\n"
+ "\t\t[ekuoids=OID,OID,OID...]\n" },
+ { "modify", kc_modify,
+ "modify [dbfile=dbfile] policy=policyname\n"
+ "\t\t[ignore-date=true|false]\n"
+ "\t\t[ignore-unknown-eku=true|false]\n"
+ "\t\t[ignore-trust-anchor=true|false]\n"
+ "\t\t[validity-adjusttime=adjusttime]\n"
+ "\t\t[ta-name=trust anchor subject DN]\n"
+ "\t\t[ta-serial=trust anchor serial number]\n"
+ "\t\t[ocsp-responder=URL]\n"
+ "\t\t[ocsp-proxy=URL]\n"
+ "\t\t[ocsp-use-cert-responder=true|false]\n"
+ "\t\t[ocsp-response-lifetime=timelimit]\n"
+ "\t\t[ocsp-ignore-response-sign=true|false]\n"
+ "\t\t[ocsp-responder-cert-name=Issuer DN]\n"
+ "\t\t[ocsp-responder-cert-serial=serial number]\n"
+ "\t\t[ocsp-none=true|false]\n"
+ "\t\t[crl-basefilename=basefilename]\n"
+ "\t\t[crl-directory=directory]\n"
+ "\t\t[crl-get-crl-uri=true|false]\n"
+ "\t\t[crl-proxy=URL]\n"
+ "\t\t[crl-ignore-crl-sign=true|false]\n"
+ "\t\t[crl-ignore-crl-date=true|false]\n"
+ "\t\t[crl-none=true|false]\n"
+ "\t\t[keyusage=digitalSignature|nonRepudiation\n\t"
+ "\t\t|keyEncipherment | dataEncipherment |\n\t"
+ "\t\tkeyAgreement |keyCertSign |\n\t"
+ "\t\tcRLSign | encipherOnly | decipherOnly],[...]\n"
+ "\t\t[keyusage-none=true|false]\n"
+ "\t\t[ekunames=serverAuth | clientAuth |\n\t"
+ "\t\tcodeSigning | emailProtection |\n\t"
+ "\t\tipsecEndSystem | ipsecTunnel |\n\t"
+ "\t\tipsecUser | timeStamping |\n\t"
+ "\t\tOCSPSigning],[...]\n"
+ "\t\t[ekuoids=OID,OID,OID...]\n"
+ "\t\t[eku-none=true|false]\n" },
+ { "import", kc_import, "import [dbfile=dbfile] policy=policyname "
+ "infile=inputdbfile\n" },
+ { "export", kc_export, "export [dbfile=dbfile] policy=policyname "
+ "outfile=newdbfile\n" },
+ { "-?", kc_help, "help"},
+ { "help", kc_help, ""}
+};
+
+static int num_cmds = sizeof (cmds) / sizeof (verbcmd);
+static char *prog;
+
+static void
+usage(void)
+{
+ int i;
+
+ /* Display this block only in command-line mode. */
+ (void) fprintf(stdout, gettext("Usage:\n"));
+ (void) fprintf(stdout, gettext("\t%s -?\t(help and usage)\n"), prog);
+ (void) fprintf(stdout, gettext("\t%s subcommand [options...]\n"), prog);
+ (void) fprintf(stdout, gettext("where subcommands may be:\n"));
+
+ /* Display only those verbs that match the current tool mode. */
+ for (i = 0; i < num_cmds; i++) {
+ /* Do NOT i18n/l10n. */
+ (void) fprintf(stdout, "\t%s\n", cmds[i].synopsis);
+ }
+}
+
+static int
+kc_help()
+{
+ usage();
+ return (0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ KMF_RETURN ret;
+ int found;
+ int i;
+
+ (void) setlocale(LC_ALL, "");
+#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D. */
+#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */
+#endif
+ (void) textdomain(TEXT_DOMAIN);
+
+ prog = basename(argv[0]);
+ argv++; argc--;
+
+ if (argc == 0) {
+ usage();
+ exit(1);
+ }
+
+ if (argc == 1 && argv[0][0] == '-') {
+ switch (argv[0][1]) {
+ case '?':
+ return (kc_help());
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ found = -1;
+ for (i = 0; i < num_cmds; i++) {
+ if (strcmp(cmds[i].verb, argv[0]) == 0) {
+ found = i;
+ break;
+ }
+ }
+
+ if (found < 0) {
+ (void) fprintf(stderr, gettext("Invalid command: %s\n"),
+ argv[0]);
+ exit(1);
+ }
+
+ ret = (*cmds[found].action)(argc, argv);
+
+ switch (ret) {
+ case KC_OK:
+ break;
+ case KC_ERR_USAGE:
+ break;
+ case KC_ERR_LOADDB:
+ (void) fprintf(stderr,
+ gettext("Error loading database\n"));
+ break;
+ case KC_ERR_FIND_POLICY:
+ break;
+ case KC_ERR_DELETE_POLICY:
+ (void) fprintf(stderr, gettext("Error deleting policy "
+ "from database.\n"));
+ break;
+ case KC_ERR_ADD_POLICY:
+ break;
+ case KC_ERR_VERIFY_POLICY:
+ break;
+ case KC_ERR_INCOMPLETE_POLICY:
+ break;
+ case KC_ERR_MEMORY:
+ (void) fprintf(stderr, gettext("Out of memory.\n"));
+ break;
+ case KC_ERR_ACCESS:
+ break;
+ default:
+ (void) fprintf(stderr, gettext("%s operation failed. "
+ "error 0x%02x\n"), cmds[found].verb, ret);
+ break;
+ }
+
+ return (ret);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd b/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd
new file mode 100644
index 0000000000..32fa28e99a
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd
@@ -0,0 +1,84 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+
+<!--
+ Copyright 2006 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"
+-->
+
+<!--Element Definitions-->
+
+<!ELEMENT kmf-policy-db (kmf-policy*)>
+<!ATTLIST kmf-policy-db allow-local-files (TRUE|FALSE) #IMPLIED>
+
+<!ELEMENT kmf-policy (validation-methods, key-usage-set?, ext-key-usage?)>
+<!ATTLIST kmf-policy name CDATA #REQUIRED>
+<!ATTLIST kmf-policy ignore-date (TRUE|FALSE) #IMPLIED>
+<!ATTLIST kmf-policy ignore-unknown-eku (TRUE|FALSE) #IMPLIED>
+<!ATTLIST kmf-policy ignore-trust-anchor (TRUE|FALSE) #IMPLIED>
+<!ATTLIST kmf-policy validity-adjusttime CDATA #IMPLIED>
+<!ATTLIST kmf-policy ta-name CDATA #IMPLIED>
+<!ATTLIST kmf-policy ta-serial CDATA #IMPLIED>
+
+<!ELEMENT validation-methods (ocsp?, crl?)>
+<!ELEMENT ocsp (ocsp-basic, responder-cert?)>
+
+<!ELEMENT ocsp-basic EMPTY>
+<!ATTLIST ocsp-basic
+ responder CDATA #IMPLIED
+ proxy CDATA #IMPLIED
+ uri-from-cert (TRUE|FALSE) #IMPLIED
+ response-lifetime CDATA #IMPLIED
+ ignore-response-sign (TRUE|FALSE) #IMPLIED
+>
+
+<!ELEMENT responder-cert EMPTY>
+<!ATTLIST responder-cert
+ name CDATA #REQUIRED
+ serial CDATA #REQUIRED
+>
+
+<!ELEMENT crl EMPTY>
+<!ATTLIST crl basefilename CDATA #IMPLIED>
+<!ATTLIST crl directory CDATA #IMPLIED>
+<!ATTLIST crl get-crl-uri (TRUE|FALSE) #IMPLIED>
+<!ATTLIST crl proxy CDATA #IMPLIED>
+<!ATTLIST crl ignore-crl-sign (TRUE|FALSE) #IMPLIED>
+<!ATTLIST crl ignore-crl-date (TRUE|FALSE) #IMPLIED>
+
+<!ELEMENT key-usage-set (key-usage+)>
+
+<!ELEMENT key-usage EMPTY>
+<!ATTLIST key-usage use (digitalSignature | nonRepudiation |
+ keyEncipherment | dataEncipherment | keyAgreement |
+ keyCertSign | cRLSign | encipherOnly | decipherOnly) #IMPLIED>
+
+<!ELEMENT ext-key-usage (eku-name*, eku-oid*)>
+
+<!ELEMENT eku-name EMPTY>
+<!ATTLIST eku-name name (serverAuth | clientAuth |
+ codeSigning | emailProtection |
+ ipsecEndSystem | ipsecTunnel | ipsecUser |
+ timeStamping | OCSPSigning) #IMPLIED >
+<!ELEMENT eku-oid EMPTY>
+<!ATTLIST eku-oid oid CDATA #IMPLIED>
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.xml b/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.xml
new file mode 100644
index 0000000000..2c2ed35e2c
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2006 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
+
+ Sample KMF Policy Database file.
+
+ ident "%Z%%M% %I% %E% SMI"
+-->
+<!DOCTYPE kmf-policy-db SYSTEM "/usr/share/lib/xml/dtd/kmfpolicy.dtd">
+<kmf-policy-db>
+
+<kmf-policy name="default" ignore-date="TRUE" ignore-trust-anchor="TRUE">
+ <validation-methods>
+ <ocsp>
+ <ocsp-basic uri-from-cert="TRUE"
+ ignore-response-sign="TRUE"/>
+ </ocsp>
+ </validation-methods>
+</kmf-policy>
+</kmf-policy-db>
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/list.c b/usr/src/cmd/cmd-crypto/kmfcfg/list.c
new file mode 100644
index 0000000000..e68e2b8643
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/list.c
@@ -0,0 +1,277 @@
+/*
+ * 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 2006 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 "util.h"
+
+static void
+show_policy(KMF_POLICY_RECORD *plc)
+{
+ int i;
+ if (plc == NULL)
+ return;
+
+ (void) printf("Name: %s\n", plc->name);
+
+ (void) printf(gettext("Ignore Date: %s\n"),
+ plc->ignore_date ? gettext("true") : gettext("false"));
+
+ (void) printf(gettext("Ignore Unknown EKUs: %s\n"),
+ plc->ignore_unknown_ekus ? gettext("true") : gettext("false"));
+
+ (void) printf(gettext("Ignore TA: %s\n"),
+ plc->ignore_trust_anchor ? gettext("true") : gettext("false"));
+
+ (void) printf(gettext("Validity Adjusted Time: %s\n"),
+ plc->validity_adjusttime ?
+ plc->validity_adjusttime : "<null>");
+
+ if (plc->ta_name == NULL && plc->ta_serial == NULL) {
+ (void) printf(gettext("Trust Anchor Certificate: <null>\n"));
+ } else {
+ (void) printf(gettext("Trust Anchor Certificate:\n"));
+ (void) printf(gettext("\tName: %s\n"),
+ plc->ta_name ? plc->ta_name : "<null>");
+ (void) printf(gettext("\tSerial Number: %s\n"),
+ plc->ta_serial ? plc->ta_serial : "<null>");
+ }
+
+ if (plc->ku_bits != 0) {
+ (void) printf(gettext("Key Usage Bits: "));
+ for (i = KULOWBIT; i <= KUHIGHBIT; i++) {
+ char *s = ku2str((plc->ku_bits & (1<<i)));
+ if (s != NULL) {
+ (void) printf("%s ", s);
+ }
+ }
+ (void) printf("\n");
+ } else {
+ (void) printf(gettext("Key Usage Bits: 0\n"));
+ }
+
+ if (plc->eku_set.eku_count > 0) {
+ (void) printf(gettext("Extended Key Usage Values:\n"));
+ for (i = 0; i < plc->eku_set.eku_count; i++) {
+ char *s = KMF_OID2EKUString(&plc->eku_set.ekulist[i]);
+ (void) printf("\t%s\t(%s)\n",
+ KMF_OID2String(&plc->eku_set.ekulist[i]),
+ s ? s : "unknown");
+ }
+ } else {
+ (void) printf(gettext("Extended Key Usage Values: <null>\n"));
+ }
+
+ (void) printf(gettext("Validation Policy Information:\n"));
+
+ if (plc->revocation & KMF_REVOCATION_METHOD_OCSP) {
+ (void) printf(gettext(" OCSP:\n"));
+
+ (void) printf(gettext("\tResponder URI: %s\n"),
+ plc->VAL_OCSP_BASIC.responderURI ?
+ plc->VAL_OCSP_BASIC.responderURI : "<null>");
+
+ (void) printf(gettext("\tProxy: %s\n"),
+ plc->VAL_OCSP_BASIC.proxy ?
+ plc->VAL_OCSP_BASIC.proxy : "<null>");
+
+ (void) printf(gettext("\tUse ResponderURI from Certificate: "
+ "%s\n"), plc->VAL_OCSP_BASIC.uri_from_cert ?
+ gettext("true") : gettext("false"));
+
+ (void) printf(gettext("\tResponse lifetime: %s\n"),
+ plc->VAL_OCSP_BASIC.response_lifetime ?
+ plc->VAL_OCSP_BASIC.response_lifetime : "<null>");
+
+ (void) printf(gettext("\tIgnore Response signature: %s\n"),
+ plc->VAL_OCSP_BASIC.ignore_response_sign ?
+ gettext("true") : gettext("false"));
+
+ if (!plc->VAL_OCSP.has_resp_cert) {
+ (void) printf(gettext("\tResponder Certificate:"
+ " <null>\n"));
+ } else {
+ (void) printf(gettext("\tResponder Certificate:\n"));
+ (void) printf(gettext("\t\tName: %s\n"),
+ plc->VAL_OCSP_RESP_CERT.name ?
+ plc->VAL_OCSP_RESP_CERT.name : "<null>");
+ (void) printf(gettext("\t\tSerial: %s\n"),
+ plc->VAL_OCSP_RESP_CERT.serial ?
+ plc->VAL_OCSP_RESP_CERT.serial : "<null>");
+ }
+ }
+
+ if (plc->revocation & KMF_REVOCATION_METHOD_CRL) {
+ (void) printf(gettext(" CRL:\n"));
+
+ (void) printf(gettext("\tBase filename: %s\n"),
+ plc->validation_info.crl_info.basefilename ?
+ plc->validation_info.crl_info.basefilename : "<null>");
+
+ (void) printf(gettext("\tDirectory: %s\n"),
+ plc->validation_info.crl_info.directory ?
+ plc->validation_info.crl_info.directory : "<null>");
+
+ (void) printf(gettext("\tDownload and cache CRL: %s\n"),
+ plc->validation_info.crl_info.get_crl_uri ?
+ gettext("true") : gettext("false"));
+
+ (void) printf(gettext("\tProxy: %s\n"),
+ plc->validation_info.crl_info.proxy ?
+ plc->validation_info.crl_info.proxy : "<null>");
+
+ (void) printf(gettext("\tIgnore CRL signature: %s\n"),
+ plc->validation_info.crl_info.ignore_crl_sign ?
+ gettext("true") : gettext("false"));
+
+ (void) printf(gettext("\tIgnore CRL validity date: %s\n"),
+ plc->validation_info.crl_info.ignore_crl_date ?
+ gettext("true") : gettext("false"));
+ }
+
+ (void) printf("\n");
+}
+
+int
+kc_list(int argc, char *argv[])
+{
+ int rv = KC_OK;
+ int opt, found = 0;
+ extern int optind_av;
+ extern char *optarg_av;
+ char *filename = NULL;
+ char *policyname = NULL;
+ POLICY_LIST *plclist = NULL, *pnode;
+ int sanity_err = 0;
+
+ while ((opt = getopt_av(argc, argv, "i:(dbfile)p:(policy)")) != EOF) {
+ switch (opt) {
+ case 'i':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ 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;
+ }
+ 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 (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ /* Check the access permission of the policy DB */
+ if (access(filename, R_OK) < 0) {
+ int err = errno;
+ (void) fprintf(stderr,
+ gettext("Cannot access \"%s\" for list - %s\n"), filename,
+ strerror(err));
+ rv = KC_ERR_ACCESS;
+ goto out;
+ }
+
+ rv = load_policies(filename, &plclist);
+ if (rv != KMF_OK) {
+ goto out;
+ }
+
+ pnode = plclist;
+ while (pnode != NULL) {
+ if (policyname == NULL ||
+ strcmp(policyname, pnode->plc.name) == 0) {
+ KMF_POLICY_RECORD *plc = &pnode->plc;
+
+ found++;
+ rv = KMF_VerifyPolicy(plc);
+ if (rv != KMF_OK) {
+ (void) fprintf(stderr, gettext(
+ "Policy Name: '%s' is invalid\n"),
+ plc->name);
+ sanity_err++;
+ } else {
+ show_policy(&pnode->plc);
+ }
+ }
+ pnode = pnode->next;
+ }
+
+ free_policy_list(plclist);
+
+ if (!found) {
+ if (policyname)
+ (void) fprintf(stderr, gettext(
+ "Cannot find policy '%s'\n"), policyname);
+ else
+ (void) fprintf(stderr, gettext("Cannot find "
+ "any policies to display\n"));
+ rv = KC_ERR_FIND_POLICY;
+ } else if (sanity_err) {
+ rv = KC_ERR_VERIFY_POLICY;
+ }
+
+out:
+
+ if (filename != NULL)
+ free(filename);
+
+ if (policyname != NULL)
+ free(policyname);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/modify.c b/usr/src/cmd/cmd-crypto/kmfcfg/modify.c
new file mode 100644
index 0000000000..413bda3be7
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/modify.c
@@ -0,0 +1,845 @@
+/*
+ * 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 2006 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 <cryptoutil.h>
+#include "util.h"
+
+#define KC_IGNORE_DATE 0x0000001
+#define KC_IGNORE_UNKNOWN_EKUS 0x0000002
+#define KC_IGNORE_TRUST_ANCHOR 0x0000004
+#define KC_VALIDITY_ADJUSTTIME 0x0000008
+#define KC_TA_NAME 0x0000010
+#define KC_TA_SERIAL 0x0000020
+#define KC_OCSP_RESPONDER_URI 0x0000040
+#define KC_OCSP_PROXY 0x0000080
+#define KC_OCSP_URI_FROM_CERT 0x0000100
+#define KC_OCSP_RESP_LIFETIME 0x0000200
+#define KC_OCSP_IGNORE_RESP_SIGN 0x0000400
+#define KC_OCSP_RESP_CERT_NAME 0x0000800
+#define KC_OCSP_RESP_CERT_SERIAL 0x0001000
+#define KC_OCSP_NONE 0x0002000
+#define KC_CRL_BASEFILENAME 0x0004000
+#define KC_CRL_DIRECTORY 0x0008000
+#define KC_CRL_GET_URI 0x0010000
+#define KC_CRL_PROXY 0x0020000
+#define KC_CRL_IGNORE_SIGN 0x0040000
+#define KC_CRL_IGNORE_DATE 0x0080000
+#define KC_CRL_NONE 0x0100000
+#define KC_KEYUSAGE 0x0200000
+#define KC_KEYUSAGE_NONE 0x0400000
+#define KC_EKUS 0x0800000
+#define KC_EKUS_NONE 0x1000000
+
+int
+kc_modify(int argc, char *argv[])
+{
+ KMF_RETURN ret;
+ int rv = KC_OK;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ char *filename = NULL;
+ uint32_t flags = 0;
+ boolean_t ocsp_none_opt = B_FALSE;
+ boolean_t crl_none_opt = B_FALSE;
+ boolean_t ku_none_opt = B_FALSE;
+ boolean_t eku_none_opt = B_FALSE;
+ int ocsp_set_attr = 0;
+ int crl_set_attr = 0;
+ KMF_POLICY_RECORD oplc, plc;
+
+ (void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
+ (void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD));
+
+ while ((opt = getopt_av(argc, argv,
+ "i:(dbfile)"
+ "p:(policy)"
+ "d:(ignore-date)"
+ "e:(ignore-unknown-eku)"
+ "a:(ignore-trust-anchor)"
+ "v:(validity-adjusttime)"
+ "t:(ta-name)"
+ "s:(ta-serial)"
+ "o:(ocsp-responder)"
+ "P:(ocsp-proxy)"
+ "r:(ocsp-use-cert-responder)"
+ "T:(ocsp-response-lifetime)"
+ "R:(ocsp-ignore-response-sign)"
+ "n:(ocsp-responder-cert-name)"
+ "A:(ocsp-responder-cert-serial)"
+ "y:(ocsp-none)"
+ "c:(crl-basefilename)"
+ "I:(crl-directory)"
+ "g:(crl-get-crl-uri)"
+ "X:(crl-proxy)"
+ "S:(crl-ignore-crl-sign)"
+ "D:(crl-ignore-crl-date)"
+ "z:(crl-none)"
+ "u:(keyusage)"
+ "Y:(keyusage-none)"
+ "E:(ekunames)"
+ "O:(ekuoids)"
+ "Z:(eku-none)")) != EOF) {
+ switch (opt) {
+ case 'i':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ plc.name = get_string(optarg_av, &rv);
+ if (plc.name == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ case 'd':
+ plc.ignore_date = get_boolean(optarg_av);
+ if (plc.ignore_date == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_IGNORE_DATE;
+ }
+ break;
+ case 'e':
+ plc.ignore_unknown_ekus =
+ get_boolean(optarg_av);
+ if (plc.ignore_unknown_ekus == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_IGNORE_UNKNOWN_EKUS;
+ }
+ break;
+ case 'a':
+ plc.ignore_trust_anchor =
+ get_boolean(optarg_av);
+ if (plc.ignore_trust_anchor == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_IGNORE_TRUST_ANCHOR;
+ }
+ break;
+ case 'v':
+ plc.validity_adjusttime =
+ get_string(optarg_av, &rv);
+ if (plc.validity_adjusttime == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error time input.\n"));
+ } else {
+ uint32_t adj;
+ /* for syntax checking */
+ if (str2lifetime(
+ plc.validity_adjusttime,
+ &adj) < 0) {
+ (void) fprintf(stderr,
+ gettext("Error time "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_VALIDITY_ADJUSTTIME;
+ }
+ }
+ break;
+ case 't':
+ plc.ta_name = get_string(optarg_av, &rv);
+ if (plc.ta_name == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error name input.\n"));
+ } else {
+ KMF_X509_NAME taDN;
+ /* for syntax checking */
+ if (KMF_DNParser(plc.ta_name,
+ &taDN) != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error name "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ KMF_FreeDN(&taDN);
+ flags |= KC_TA_NAME;
+ }
+ }
+ break;
+ case 's':
+ plc.ta_serial = get_string(optarg_av, &rv);
+ if (plc.ta_serial == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error serial input.\n"));
+ } else {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
+
+ ret = KMF_HexString2Bytes(
+ (uchar_t *)plc.ta_serial,
+ &bytes, &bytelen);
+ if (ret != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr,
+ gettext("serial number "
+ "must be specified as a "
+ "hex number "
+ "(ex: 0x0102030405"
+ "ffeeddee)\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ if (bytes != NULL)
+ free(bytes);
+ flags |= KC_TA_SERIAL;
+ }
+ break;
+ case 'o':
+ plc.VAL_OCSP_RESPONDER_URI =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error responder "
+ "input.\n"));
+ } else {
+ flags |= KC_OCSP_RESPONDER_URI;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'P':
+ plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_PROXY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error proxy input.\n"));
+ } else {
+ flags |= KC_OCSP_PROXY;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'r':
+ plc.VAL_OCSP_URI_FROM_CERT =
+ get_boolean(optarg_av);
+ if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_OCSP_URI_FROM_CERT;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'T':
+ plc.VAL_OCSP_RESP_LIFETIME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error time input.\n"));
+ } else {
+ uint32_t adj;
+ /* for syntax checking */
+ if (str2lifetime(
+ plc.VAL_OCSP_RESP_LIFETIME,
+ &adj) < 0) {
+ (void) fprintf(stderr,
+ gettext("Error time "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_OCSP_RESP_LIFETIME;
+ ocsp_set_attr++;
+ }
+ }
+ break;
+ case 'R':
+ plc.VAL_OCSP_IGNORE_RESP_SIGN =
+ get_boolean(optarg_av);
+ if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_OCSP_IGNORE_RESP_SIGN;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'n':
+ plc.VAL_OCSP_RESP_CERT_NAME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error name input.\n"));
+ } else {
+ KMF_X509_NAME respDN;
+ /* for syntax checking */
+ if (KMF_DNParser(
+ plc.VAL_OCSP_RESP_CERT_NAME,
+ &respDN) != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error name "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ KMF_FreeDN(&respDN);
+ flags |= KC_OCSP_RESP_CERT_NAME;
+ ocsp_set_attr++;
+ }
+ }
+ break;
+ case 'A':
+ plc.VAL_OCSP_RESP_CERT_SERIAL =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error serial input.\n"));
+ } else {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
+
+ ret = KMF_HexString2Bytes((uchar_t *)
+ plc.VAL_OCSP_RESP_CERT_SERIAL,
+ &bytes, &bytelen);
+ if (ret != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr,
+ gettext("serial number "
+ "must be specified as a "
+ "hex number "
+ "(ex: 0x0102030405"
+ "ffeeddee)\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ if (bytes != NULL)
+ free(bytes);
+ flags |= KC_OCSP_RESP_CERT_SERIAL;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'y':
+ ocsp_none_opt = get_boolean(optarg_av);
+ if (ocsp_none_opt == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_OCSP_NONE;
+ }
+ break;
+ case 'c':
+ plc.VAL_CRL_BASEFILENAME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_BASEFILENAME == NULL) {
+ (void) fprintf(stderr, gettext(
+ "Error basefilename input.\n"));
+ } else {
+ flags |= KC_CRL_BASEFILENAME;
+ crl_set_attr++;
+ }
+ break;
+ case 'I':
+ plc.VAL_CRL_DIRECTORY =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_DIRECTORY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ } else {
+ flags |= KC_CRL_DIRECTORY;
+ crl_set_attr++;
+ }
+ break;
+ case 'g':
+ plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
+ if (plc.VAL_CRL_GET_URI == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_CRL_GET_URI;
+ crl_set_attr++;
+ }
+ break;
+ case 'X':
+ plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_PROXY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error proxy input.\n"));
+ } else {
+ flags |= KC_CRL_PROXY;
+ crl_set_attr++;
+ }
+ break;
+ case 'S':
+ plc.VAL_CRL_IGNORE_SIGN =
+ get_boolean(optarg_av);
+ if (plc.VAL_CRL_IGNORE_SIGN == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_CRL_IGNORE_SIGN;
+ crl_set_attr++;
+ }
+ break;
+ case 'D':
+ plc.VAL_CRL_IGNORE_DATE =
+ get_boolean(optarg_av);
+ if (plc.VAL_CRL_IGNORE_DATE == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_CRL_IGNORE_DATE;
+ crl_set_attr++;
+ }
+ break;
+ case 'z':
+ crl_none_opt = get_boolean(optarg_av);
+ if (crl_none_opt == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_CRL_NONE;
+ }
+ break;
+ case 'u':
+ plc.ku_bits = parseKUlist(optarg_av);
+ if (plc.ku_bits == 0) {
+ (void) fprintf(stderr, gettext(
+ "Error keyusage input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_KEYUSAGE;
+ }
+ break;
+ case 'Y':
+ ku_none_opt = get_boolean(optarg_av);
+ if (ku_none_opt == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_KEYUSAGE_NONE;
+ }
+ break;
+ case 'E':
+ if (parseEKUNames(optarg_av, &plc) != 0) {
+ (void) fprintf(stderr,
+ gettext("Error EKU input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_EKUS;
+ }
+ break;
+ case 'O':
+ if (parseEKUOIDs(optarg_av, &plc) != 0) {
+ (void) fprintf(stderr,
+ gettext("Error EKU OID input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_EKUS;
+ }
+ break;
+ case 'Z':
+ eku_none_opt = get_boolean(optarg_av);
+ if (eku_none_opt == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_EKUS_NONE;
+ }
+ 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 (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ /*
+ * Must have a policy name. The policy name can not be default
+ * if using the default policy file.
+ */
+ if (plc.name == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not modify the default policy in the default "
+ "policy file.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /* Check the access permission of the policy DB */
+ if (access(filename, W_OK) < 0) {
+ int err = errno;
+ (void) fprintf(stderr,
+ gettext("Cannot access \"%s\" for modify - %s\n"),
+ filename, strerror(err));
+ rv = KC_ERR_ACCESS;
+ goto out;
+ }
+
+ /* Try to load the named policy from the DB */
+ ret = KMF_GetPolicy(filename, plc.name, &oplc);
+ if (ret != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error loading policy \"%s\" from %s\n"), filename,
+ plc.name);
+ return (KC_ERR_FIND_POLICY);
+ }
+
+ /* Update the general policy attributes. */
+ if (flags & KC_IGNORE_DATE)
+ oplc.ignore_date = plc.ignore_date;
+
+ if (flags & KC_IGNORE_UNKNOWN_EKUS)
+ oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
+
+ if (flags & KC_IGNORE_TRUST_ANCHOR)
+ oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
+
+ if (flags & KC_VALIDITY_ADJUSTTIME) {
+ if (oplc.validity_adjusttime)
+ free(oplc.validity_adjusttime);
+ oplc.validity_adjusttime =
+ plc.validity_adjusttime;
+ }
+
+ if (flags & KC_TA_NAME) {
+ if (oplc.ta_name)
+ free(oplc.ta_name);
+ oplc.ta_name = plc.ta_name;
+ }
+ if (flags & KC_TA_SERIAL) {
+ if (oplc.ta_serial)
+ free(oplc.ta_serial);
+ oplc.ta_serial = plc.ta_serial;
+ }
+
+ /* Update the OCSP policy */
+ if (ocsp_none_opt == B_TRUE) {
+ if (ocsp_set_attr > 0) {
+ (void) fprintf(stderr,
+ gettext("Can not set ocsp-none=true and other "
+ "OCSP attributes at the same time.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /*
+ * If the original policy does not have OCSP checking,
+ * then we do not need to do anything. If the original
+ * policy has the OCSP checking, then we need to release the
+ * space of OCSP attributes and turn the OCSP checking off.
+ */
+ if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
+ if (oplc.VAL_OCSP_BASIC.responderURI) {
+ free(oplc.VAL_OCSP_BASIC.responderURI);
+ oplc.VAL_OCSP_BASIC.responderURI = NULL;
+ }
+
+ if (oplc.VAL_OCSP_BASIC.proxy) {
+ free(oplc.VAL_OCSP_BASIC.proxy);
+ oplc.VAL_OCSP_BASIC.proxy = NULL;
+ }
+
+ if (oplc.VAL_OCSP_BASIC.response_lifetime) {
+ free(oplc.VAL_OCSP_BASIC.response_lifetime);
+ oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
+ }
+
+ if (flags & KC_OCSP_RESP_CERT_NAME) {
+ free(oplc.VAL_OCSP_RESP_CERT.name);
+ oplc.VAL_OCSP_RESP_CERT.name = NULL;
+ }
+
+ if (flags & KC_OCSP_RESP_CERT_SERIAL) {
+ free(oplc.VAL_OCSP_RESP_CERT.serial);
+ oplc.VAL_OCSP_RESP_CERT.serial = NULL;
+ }
+
+ /* Turn off the OCSP checking */
+ oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
+ }
+
+ } else {
+ /*
+ * If the "ocsp-none" option is not set or is set to false,
+ * then we only need to do the modification if there is at
+ * least one OCSP attribute is specified.
+ */
+ if (ocsp_set_attr > 0) {
+ if (flags & KC_OCSP_RESPONDER_URI) {
+ if (oplc.VAL_OCSP_RESPONDER_URI)
+ free(oplc.VAL_OCSP_RESPONDER_URI);
+ oplc.VAL_OCSP_RESPONDER_URI =
+ plc.VAL_OCSP_RESPONDER_URI;
+ }
+
+ if (flags & KC_OCSP_PROXY) {
+ if (oplc.VAL_OCSP_PROXY)
+ free(oplc.VAL_OCSP_PROXY);
+ oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
+ }
+
+ if (flags & KC_OCSP_URI_FROM_CERT)
+ oplc.VAL_OCSP_URI_FROM_CERT =
+ plc.VAL_OCSP_URI_FROM_CERT;
+
+ if (flags & KC_OCSP_RESP_LIFETIME) {
+ if (oplc.VAL_OCSP_RESP_LIFETIME)
+ free(oplc.VAL_OCSP_RESP_LIFETIME);
+ oplc.VAL_OCSP_RESP_LIFETIME =
+ plc.VAL_OCSP_RESP_LIFETIME;
+ }
+
+ if (flags & KC_OCSP_IGNORE_RESP_SIGN)
+ oplc.VAL_OCSP_IGNORE_RESP_SIGN =
+ plc.VAL_OCSP_IGNORE_RESP_SIGN;
+
+ if (flags & KC_OCSP_RESP_CERT_NAME) {
+ if (oplc.VAL_OCSP_RESP_CERT_NAME)
+ free(oplc.VAL_OCSP_RESP_CERT_NAME);
+ oplc.VAL_OCSP_RESP_CERT_NAME =
+ plc.VAL_OCSP_RESP_CERT_NAME;
+ }
+
+ if (flags & KC_OCSP_RESP_CERT_SERIAL) {
+ if (oplc.VAL_OCSP_RESP_CERT_SERIAL)
+ free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
+ oplc.VAL_OCSP_RESP_CERT_SERIAL =
+ plc.VAL_OCSP_RESP_CERT_SERIAL;
+ }
+
+ if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
+ oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
+ oplc.VAL_OCSP.has_resp_cert = B_TRUE;
+ else
+ oplc.VAL_OCSP.has_resp_cert = B_FALSE;
+
+ /* Turn on the OCSP checking */
+ oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
+ }
+ }
+
+ /* Update the CRL policy */
+ if (crl_none_opt == B_TRUE) {
+ if (crl_set_attr > 0) {
+ (void) fprintf(stderr,
+ gettext("Can not set crl-none=true and other CRL "
+ "attributes at the same time.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /*
+ * If the original policy does not have CRL checking,
+ * then we do not need to do anything. If the original
+ * policy has the CRL checking, then we need to release the
+ * space of CRL attributes and turn the CRL checking off.
+ */
+ if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
+ if (oplc.VAL_CRL_BASEFILENAME) {
+ free(oplc.VAL_CRL_BASEFILENAME);
+ oplc.VAL_CRL_BASEFILENAME = NULL;
+ }
+
+ if (oplc.VAL_CRL_DIRECTORY) {
+ free(oplc.VAL_CRL_DIRECTORY);
+ oplc.VAL_CRL_DIRECTORY = NULL;
+ }
+
+ if (oplc.VAL_CRL_PROXY) {
+ free(oplc.VAL_CRL_PROXY);
+ oplc.VAL_CRL_PROXY = NULL;
+ }
+
+ /* Turn off the CRL checking */
+ oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
+ }
+ } else {
+ /*
+ * If the "ocsp-none" option is not set or is set to false,
+ * then we only need to do the modification if there is at
+ * least one CRL attribute is specified.
+ */
+ if (crl_set_attr > 0) {
+ if (flags & KC_CRL_BASEFILENAME) {
+ if (oplc.VAL_CRL_BASEFILENAME)
+ free(oplc.VAL_CRL_BASEFILENAME);
+ oplc.VAL_CRL_BASEFILENAME =
+ plc.VAL_CRL_BASEFILENAME;
+ }
+
+ if (flags & KC_CRL_DIRECTORY) {
+ if (oplc.VAL_CRL_DIRECTORY)
+ free(oplc.VAL_CRL_DIRECTORY);
+ oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
+ }
+
+ if (flags & KC_CRL_GET_URI) {
+ oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
+ }
+
+ if (flags & KC_CRL_PROXY) {
+ if (oplc.VAL_CRL_PROXY)
+ free(oplc.VAL_CRL_PROXY);
+ oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
+ }
+
+ if (flags & KC_CRL_IGNORE_SIGN) {
+ oplc.VAL_CRL_IGNORE_SIGN =
+ plc.VAL_CRL_IGNORE_SIGN;
+ }
+
+ if (flags & KC_CRL_IGNORE_DATE) {
+ oplc.VAL_CRL_IGNORE_DATE =
+ plc.VAL_CRL_IGNORE_DATE;
+ }
+
+ /* Turn on the CRL checking */
+ oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
+ }
+ }
+
+ /* Update the Key Usage */
+ if (ku_none_opt == B_TRUE) {
+ if (flags & KC_KEYUSAGE) {
+ (void) fprintf(stderr,
+ gettext("Can not set keyusage-none=true and "
+ "modify the keyusage value at the same time.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ oplc.ku_bits = 0;
+ } else {
+ /*
+ * If the "keyusage-none" option is not set or is set to
+ * false, then we only need to do the modification if
+ * the keyusage value is specified.
+ */
+ if (flags & KC_KEYUSAGE)
+ oplc.ku_bits = plc.ku_bits;
+ }
+
+
+ /* Update the Extended Key Usage */
+ if (eku_none_opt == B_TRUE) {
+ if (flags & KC_EKUS) {
+ (void) fprintf(stderr,
+ gettext("Can not set eku-none=true and modify "
+ "EKU values at the same time.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /* Release current EKU list (if any) */
+ if (oplc.eku_set.eku_count > 0) {
+ KMF_FreeEKUPolicy(&oplc.eku_set);
+ oplc.eku_set.eku_count = 0;
+ oplc.eku_set.ekulist = NULL;
+ }
+ } else {
+ /*
+ * If the "eku-none" option is not set or is set to false,
+ * then we only need to do the modification if either
+ * "ekuname" or "ekuoids" is specified.
+ */
+ if (flags & KC_EKUS) {
+ /* Release current EKU list (if any) */
+ KMF_FreeEKUPolicy(&oplc.eku_set);
+ oplc.eku_set = plc.eku_set;
+ }
+ }
+
+ /* Do a sanity check on the modified policy */
+ ret = KMF_VerifyPolicy(&oplc);
+ if (ret != KMF_OK) {
+ print_sanity_error(ret);
+ rv = KC_ERR_VERIFY_POLICY;
+ goto out;
+ }
+
+ /* The modify operation is a delete followed by an add */
+ ret = KMF_DeletePolicyFromDB(oplc.name, filename);
+ if (ret != KMF_OK) {
+ rv = KC_ERR_DELETE_POLICY;
+ goto out;
+ }
+
+ /*
+ * Now add the modified policy back to the DB.
+ */
+ ret = KMF_AddPolicyToDB(&oplc, filename, B_FALSE);
+ if (ret != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error adding policy to database: 0x%04x\n"), ret);
+ rv = KC_ERR_ADD_POLICY;
+ goto out;
+ }
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ KMF_FreePolicyRecord(&oplc);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/util.c b/usr/src/cmd/cmd-crypto/kmfcfg/util.c
new file mode 100644
index 0000000000..f3bdc633f2
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/util.c
@@ -0,0 +1,497 @@
+/*
+ * 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 2006 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 <libxml/tree.h>
+#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 */
+ char *longnm; /* long name string, NOT terminated */
+ int longnm_len; /* length of long name string */
+ boolean_t has_arg; /* takes optional argument */
+} av_opts;
+
+static av_opts *opts_av = NULL;
+static const char *_save_optstr = NULL;
+static int _save_numopts = 0;
+int optind_av = 1;
+char *optarg_av = NULL;
+
+void
+free_policy_list(POLICY_LIST *plist)
+{
+ POLICY_LIST *n = plist, *old;
+
+ if (plist == NULL)
+ return;
+
+ while (n != NULL) {
+ old = n;
+ KMF_FreePolicyRecord(&n->plc);
+ n = n->next;
+ free(old);
+ }
+ plist = NULL;
+}
+
+int
+load_policies(char *file, POLICY_LIST **policy_list)
+{
+ int rv = KC_OK;
+ KMF_RETURN kmfrv = KMF_OK;
+ POLICY_LIST *newitem, *plist = NULL;
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr doc = NULL;
+ xmlNodePtr cur, node;
+
+ /* Create a parser context */
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL)
+ return (KMF_ERR_POLICY_DB_FORMAT);
+
+ /* Read the policy DB and verify it against the schema. */
+ doc = xmlCtxtReadFile(ctxt, file, NULL,
+ XML_PARSE_DTDVALID | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
+ if (doc == NULL || ctxt->valid == 0) {
+ kmfrv = KMF_ERR_POLICY_DB_FORMAT;
+ goto end;
+ }
+
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ kmfrv = KMF_ERR_POLICY_DB_FORMAT;
+ goto end;
+ }
+
+ node = cur->xmlChildrenNode;
+ while (node != NULL) {
+ char *c;
+ /*
+ * Search for the policy that matches the given name.
+ */
+ if (!xmlStrcmp((const xmlChar *)node->name,
+ (const xmlChar *)KMF_POLICY_ELEMENT)) {
+ /* Check the name attribute */
+ c = (char *)xmlGetProp(node,
+ (const xmlChar *)KMF_POLICY_NAME_ATTR);
+
+ /* If a match, parse the rest of the data */
+ if (c != NULL) {
+ xmlFree(c);
+ newitem = malloc(sizeof (POLICY_LIST));
+ if (newitem != NULL) {
+ (void) memset(newitem, 0,
+ sizeof (POLICY_LIST));
+ kmfrv = parsePolicyElement(node,
+ &newitem->plc);
+ } else {
+ kmfrv = KMF_ERR_MEMORY;
+ goto end;
+ }
+ /* add to linked list */
+ if (plist == NULL) {
+ plist = newitem;
+ } else {
+ POLICY_LIST *n = plist;
+ while (n->next != NULL)
+ n = n->next;
+
+ n->next = newitem;
+ newitem->next = NULL;
+ }
+ }
+ }
+ node = node->next;
+ }
+
+end:
+ if (ctxt != NULL)
+ xmlFreeParserCtxt(ctxt);
+
+ if (doc != NULL)
+ xmlFreeDoc(doc);
+
+ if (kmfrv != KMF_OK) {
+ free_policy_list(plist);
+ rv = KC_ERR_LOADDB;
+ } else {
+ *policy_list = plist;
+ }
+
+ return (rv);
+}
+
+/*
+ * Return 0 if there is any error in the input string.
+ */
+uint16_t
+parseKUlist(char *kustring)
+{
+ uint16_t cur_bit;
+ uint16_t kubits = 0;
+ char *p;
+
+ p = strtok(kustring, ",");
+ while (p != NULL) {
+ cur_bit = KMF_StringToKeyUsage(p);
+ if (cur_bit == 0) {
+ kubits = 0;
+ break;
+ }
+ kubits |= cur_bit;
+ p = strtok(NULL, ",");
+ }
+
+ return (kubits);
+}
+
+static void
+addToEKUList(KMF_EKU_POLICY *ekus, KMF_OID *newoid)
+{
+ if (newoid != NULL && ekus != NULL) {
+ ekus->eku_count++;
+ ekus->ekulist = realloc(
+ ekus->ekulist,
+ ekus->eku_count * sizeof (KMF_OID));
+ if (ekus->ekulist != NULL) {
+ ekus->ekulist[ekus->eku_count-1] = *newoid;
+ }
+ }
+}
+
+int
+parseEKUNames(char *ekulist, KMF_POLICY_RECORD *plc)
+{
+ int rv = KC_OK;
+ char *p;
+ KMF_OID *newoid;
+ KMF_EKU_POLICY *ekus = &plc->eku_set;
+
+ if (ekulist == NULL || !strlen(ekulist))
+ return (0);
+
+ /*
+ * The list should be comma separated list of EKU Names.
+ */
+ p = strtok(ekulist, ",");
+
+ /* If no tokens found, then maybe its just a single EKU value */
+ if (p == NULL) {
+ newoid = kmf_ekuname2oid(ekulist);
+ if (newoid != NULL) {
+ addToEKUList(ekus, newoid);
+ free(newoid);
+ } else {
+ rv = KC_ERR_USAGE;
+ }
+ }
+
+ while (p != NULL) {
+ newoid = kmf_ekuname2oid(p);
+ if (newoid != NULL) {
+ addToEKUList(ekus, newoid);
+ free(newoid);
+ } else {
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ p = strtok(NULL, ",");
+ }
+
+ if (rv != KC_OK)
+ KMF_FreeEKUPolicy(ekus);
+
+ return (rv);
+}
+
+int
+parseEKUOIDs(char *ekulist, KMF_POLICY_RECORD *plc)
+{
+ int rv = KC_OK;
+ char *p;
+ KMF_OID *newoid;
+ KMF_EKU_POLICY *ekus = &plc->eku_set;
+
+ if (ekulist == NULL || !strlen(ekulist))
+ return (0);
+
+ /*
+ * The list should be comma separated list of EKU Names.
+ */
+ p = strtok(ekulist, ",");
+ if (p == NULL) {
+ newoid = kmf_string2oid(ekulist);
+ if (newoid != NULL) {
+ addToEKUList(ekus, newoid);
+ free(newoid);
+ } else {
+ rv = KC_ERR_USAGE;
+ }
+ }
+
+ while (p != NULL && rv == 0) {
+ newoid = kmf_string2oid(p);
+ if (newoid != NULL) {
+ addToEKUList(ekus, newoid);
+ free(newoid);
+ } else {
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ p = strtok(NULL, ",");
+ }
+
+ if (rv != KC_OK)
+ KMF_FreeEKUPolicy(ekus);
+
+ return (rv);
+}
+
+int
+get_boolean(char *arg)
+{
+ if (arg == NULL)
+ return (-1);
+ if (strcasecmp(arg, "true") == 0)
+ return (1);
+ if (strcasecmp(arg, "false") == 0)
+ return (0);
+ return (-1);
+}
+
+/*
+ * This function processes the input string. It removes the beginning
+ * and ending blank's first, makes a copy of the resulting string and
+ * return it.
+ *
+ * This function returns NULL, if there is an error in the
+ * input string or when the system is out of memory. The output
+ * "err_flag" argument will record the error code, if it is not NULL.
+ */
+char *
+get_string(char *str, int *err_flag)
+{
+ char *p;
+ int len, i;
+ char *retstr = NULL;
+
+ if (str == NULL) {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_USAGE;
+ return (NULL);
+ }
+
+ /* Remove beginning whitespace */
+ p = str;
+ while (p != NULL && isspace(*p))
+ p++;
+
+ if (p == NULL) {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_USAGE;
+ return (NULL);
+ }
+
+ /* Remove the trailing blanks */
+ len = strlen(p);
+ while (len > 0 && isspace(p[len-1]))
+ len--;
+
+ if (len == 0) {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_USAGE;
+ return (NULL);
+ }
+
+ /* Check if there is any non-printable character */
+ i = 0;
+ while (i < len) {
+ if (isprint(p[i]))
+ i++;
+ else {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_USAGE;
+ return (NULL);
+ }
+ }
+
+ /* Make a copy of the string and return it */
+ retstr = malloc(len + 1);
+ if (retstr == NULL) {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_MEMORY;
+ return (NULL);
+ }
+
+ if (err_flag != NULL)
+ *err_flag = KC_OK;
+
+ (void) strncpy(retstr, p, len);
+ retstr[len] = '\0';
+ return (retstr);
+}
+
+/*
+ * Breaks out the getopt-style option string into a structure that can be
+ * traversed later for calls to getopt_av(). Option string is NOT altered,
+ * but the struct fields point to locations within option string.
+ */
+static int
+populate_opts(char *optstring)
+{
+ int i;
+ av_opts *temp;
+ char *marker;
+
+ if (optstring == NULL || *optstring == '\0')
+ return (0);
+
+ /*
+ * This tries to imitate getopt(3c) Each option must conform to:
+ * <short name char> [ ':' ] [ '(' <long name string> ')' ]
+ * If long name is missing, the short name is used for long name.
+ */
+ for (i = 0; *optstring != '\0'; i++) {
+ if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
+ realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
+ free(opts_av);
+ opts_av = NULL;
+ return (0);
+ } else
+ opts_av = (av_opts *)temp;
+
+ marker = optstring; /* may need optstring later */
+
+ opts_av[i].shortnm = *marker++; /* set short name */
+
+ if (*marker == ':') { /* check for opt arg */
+ marker++;
+ opts_av[i].has_arg = B_TRUE;
+ }
+
+ if (*marker == '(') { /* check and set long name */
+ marker++;
+ opts_av[i].longnm = marker;
+ opts_av[i].longnm_len = strcspn(marker, ")");
+ optstring = marker + opts_av[i].longnm_len + 1;
+ } else {
+ /* use short name option character */
+ opts_av[i].longnm = optstring;
+ opts_av[i].longnm_len = 1;
+ optstring = marker;
+ }
+ }
+
+ return (i);
+}
+
+/*
+ * getopt_av() is very similar to getopt(3c) in that the takes an option
+ * string, compares command line arguments for matches, and returns a single
+ * letter option when a match is found. However, getopt_av() differs from
+ * getopt(3c) by allowing both longname options and values be found
+ * on the command line.
+ */
+int
+getopt_av(int argc, char * const *argv, const char *optstring)
+{
+ int i;
+ int len;
+
+ if (optind_av >= argc)
+ return (EOF);
+
+ /* First time or when optstring changes from previous one */
+ if (_save_optstr != optstring) {
+ if (opts_av != NULL)
+ free(opts_av);
+ opts_av = NULL;
+ _save_optstr = optstring;
+ _save_numopts = populate_opts((char *)optstring);
+ }
+
+ for (i = 0; i < _save_numopts; i++) {
+ if (strcmp(argv[optind_av], "--") == 0) {
+ optind_av++;
+ break;
+ }
+
+ len = strcspn(argv[optind_av], "=");
+
+ if (len == opts_av[i].longnm_len && strncmp(argv[optind_av],
+ opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
+ /* matched */
+ if (!opts_av[i].has_arg) {
+ optind_av++;
+ return (opts_av[i].shortnm);
+ }
+
+ /* needs optarg */
+ if (argv[optind_av][len] == '=') {
+ optarg_av = &(argv[optind_av][len+1]);
+ optind_av++;
+ return (opts_av[i].shortnm);
+ }
+
+ optarg_av = NULL;
+ optind_av++;
+ return ((int)'?');
+ }
+ }
+
+ return (EOF);
+}
+
+void
+print_sanity_error(KMF_RETURN ret)
+{
+ switch (ret) {
+ case KMF_ERR_POLICY_NAME:
+ (void) fprintf(stderr, gettext("Error in the policy name\n"));
+ break;
+ case KMF_ERR_TA_POLICY:
+ (void) fprintf(stderr,
+ gettext("Error in trust anchor attributes\n"));
+ break;
+ case KMF_ERR_OCSP_POLICY:
+ (void) fprintf(stderr,
+ gettext("Error in OCSP policy attributes\n"));
+ break;
+ default:
+ break;
+ }
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/util.h b/usr/src/cmd/cmd-crypto/kmfcfg/util.h
new file mode 100644
index 0000000000..74f4b0be9b
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/util.h
@@ -0,0 +1,66 @@
+/*
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _UTIL_H
+#define _UTIL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <kmfapiP.h>
+
+
+typedef struct _policy_list {
+ KMF_POLICY_RECORD plc;
+ struct _policy_list *next;
+} POLICY_LIST;
+
+void free_policy_list(POLICY_LIST *);
+int getopt_av(int, char * const *, const char *);
+
+int load_policies(char *, POLICY_LIST **);
+int get_boolean(char *);
+char *get_string(char *, int *err_flag);
+int parseEKUOIDs(char *, KMF_POLICY_RECORD *);
+int parseEKUNames(char *, KMF_POLICY_RECORD *);
+uint16_t parseKUlist(char *);
+void print_sanity_error(KMF_RETURN);
+
+#define KC_OK 0
+#define KC_ERR_USAGE 1
+#define KC_ERR_LOADDB 2
+#define KC_ERR_FIND_POLICY 3
+#define KC_ERR_DELETE_POLICY 4
+#define KC_ERR_ADD_POLICY 5
+#define KC_ERR_VERIFY_POLICY 6
+#define KC_ERR_INCOMPLETE_POLICY 7
+#define KC_ERR_MEMORY 8
+#define KC_ERR_ACCESS 9
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _UTIL_H */