199ebb4cwyllys/*
299ebb4cwyllys * CDDL HEADER START
399ebb4cwyllys *
499ebb4cwyllys * The contents of this file are subject to the terms of the
599ebb4cwyllys * Common Development and Distribution License (the "License").
699ebb4cwyllys * You may not use this file except in compliance with the License.
799ebb4cwyllys *
899ebb4cwyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999ebb4cwyllys * or http://www.opensolaris.org/os/licensing.
1099ebb4cwyllys * See the License for the specific language governing permissions
1199ebb4cwyllys * and limitations under the License.
1299ebb4cwyllys *
1399ebb4cwyllys * When distributing Covered Code, include this CDDL HEADER in each
1499ebb4cwyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599ebb4cwyllys * If applicable, add the following below this CDDL HEADER, with the
1699ebb4cwyllys * fields enclosed by brackets "[]" replaced with your own identifying
1799ebb4cwyllys * information: Portions Copyright [yyyy] [name of copyright owner]
1899ebb4cwyllys *
1999ebb4cwyllys * CDDL HEADER END
2099ebb4cwyllys *
21269e59fJan Pechanec * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
2299ebb4cwyllys */
2399ebb4cwyllys
2499ebb4cwyllys#include <stdio.h>
2599ebb4cwyllys#include <strings.h>
2699ebb4cwyllys#include <ctype.h>
2799ebb4cwyllys#include <libgen.h>
2899ebb4cwyllys#include <libintl.h>
2999ebb4cwyllys#include <errno.h>
3099ebb4cwyllys#include <kmfapiP.h>
3199ebb4cwyllys#include <cryptoutil.h>
3299ebb4cwyllys#include "util.h"
3399ebb4cwyllys
3499ebb4cwyllysint
3599ebb4cwyllyskc_create(int argc, char *argv[])
3699ebb4cwyllys{
3799ebb4cwyllys	KMF_RETURN	ret;
3899ebb4cwyllys	int 		rv = KC_OK;
3999ebb4cwyllys	int		opt;
4099ebb4cwyllys	extern int	optind_av;
4199ebb4cwyllys	extern char	*optarg_av;
4299ebb4cwyllys	char		*filename = NULL;
4399ebb4cwyllys	int		ocsp_set_attr = 0;
4499ebb4cwyllys	boolean_t	crl_set_attr = 0;
4599ebb4cwyllys	KMF_POLICY_RECORD plc;
4699ebb4cwyllys
4799ebb4cwyllys	(void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
4899ebb4cwyllys
4999ebb4cwyllys	while ((opt = getopt_av(argc, argv,
5030a5e8fwyllys	    "i:(dbfile)"
5130a5e8fwyllys	    "p:(policy)"
5230a5e8fwyllys	    "d:(ignore-date)"
5330a5e8fwyllys	    "e:(ignore-unknown-eku)"
5430a5e8fwyllys	    "a:(ignore-trust-anchor)"
5530a5e8fwyllys	    "v:(validity-adjusttime)"
5630a5e8fwyllys	    "t:(ta-name)"
5730a5e8fwyllys	    "s:(ta-serial)"
5830a5e8fwyllys	    "o:(ocsp-responder)"
5930a5e8fwyllys	    "P:(ocsp-proxy)"
6030a5e8fwyllys	    "r:(ocsp-use-cert-responder)"
6130a5e8fwyllys	    "T:(ocsp-response-lifetime)"
6230a5e8fwyllys	    "R:(ocsp-ignore-response-sign)"
6330a5e8fwyllys	    "n:(ocsp-responder-cert-name)"
6430a5e8fwyllys	    "A:(ocsp-responder-cert-serial)"
6530a5e8fwyllys	    "c:(crl-basefilename)"
6630a5e8fwyllys	    "I:(crl-directory)"
6730a5e8fwyllys	    "g:(crl-get-crl-uri)"
6830a5e8fwyllys	    "X:(crl-proxy)"
6930a5e8fwyllys	    "S:(crl-ignore-crl-sign)"
7030a5e8fwyllys	    "D:(crl-ignore-crl-date)"
71269e59fJan Pechanec	    "m:(mapper-name)"
72269e59fJan Pechanec	    "M:(mapper-directory)"
73269e59fJan Pechanec	    "Q:(mapper-pathname)"
74269e59fJan Pechanec	    "q:(mapper-options)"
7530a5e8fwyllys	    "u:(keyusage)"
7630a5e8fwyllys	    "E:(ekunames)"
7730a5e8fwyllys	    "O:(ekuoids)")) != EOF) {
7899ebb4cwyllys		switch (opt) {
7999ebb4cwyllys			case 'i':
8099ebb4cwyllys				filename = get_string(optarg_av, &rv);
8199ebb4cwyllys				if (filename == NULL) {
8299ebb4cwyllys					(void) fprintf(stderr,
8399ebb4cwyllys					    gettext("Error dbfile input.\n"));
8499ebb4cwyllys				}
8599ebb4cwyllys				break;
8699ebb4cwyllys			case 'p':
8799ebb4cwyllys				plc.name = get_string(optarg_av, &rv);
8899ebb4cwyllys				if (plc.name == NULL) {
8999ebb4cwyllys					(void) fprintf(stderr,
9099ebb4cwyllys					    gettext("Error policy name.\n"));
9199ebb4cwyllys				}
9299ebb4cwyllys				break;
9399ebb4cwyllys			case 'd':
9499ebb4cwyllys				plc.ignore_date = get_boolean(optarg_av);
9599ebb4cwyllys				if (plc.ignore_date == -1) {
9699ebb4cwyllys					(void) fprintf(stderr,
9799ebb4cwyllys					    gettext("Error boolean input.\n"));
9899ebb4cwyllys					rv = KC_ERR_USAGE;
9999ebb4cwyllys				}
10099ebb4cwyllys				break;
10199ebb4cwyllys			case 'e':
10299ebb4cwyllys				plc.ignore_unknown_ekus =
10399ebb4cwyllys				    get_boolean(optarg_av);
10499ebb4cwyllys				if (plc.ignore_unknown_ekus == -1) {
10599ebb4cwyllys					(void) fprintf(stderr,
10699ebb4cwyllys					    gettext("Error boolean input.\n"));
10799ebb4cwyllys					rv = KC_ERR_USAGE;
10899ebb4cwyllys				}
10999ebb4cwyllys				break;
11099ebb4cwyllys			case 'a':
11199ebb4cwyllys				plc.ignore_trust_anchor =
11299ebb4cwyllys				    get_boolean(optarg_av);
11399ebb4cwyllys				if (plc.ignore_trust_anchor == -1) {
11499ebb4cwyllys					(void) fprintf(stderr,
11599ebb4cwyllys					    gettext("Error boolean input.\n"));
11699ebb4cwyllys					rv = KC_ERR_USAGE;
11799ebb4cwyllys				}
11899ebb4cwyllys				break;
11999ebb4cwyllys			case 'v':
12099ebb4cwyllys				plc.validity_adjusttime =
12199ebb4cwyllys				    get_string(optarg_av, &rv);
12299ebb4cwyllys				if (plc.validity_adjusttime == NULL) {
12399ebb4cwyllys					(void) fprintf(stderr,
12499ebb4cwyllys					    gettext("Error time input.\n"));
12599ebb4cwyllys				} else {
12699ebb4cwyllys					uint32_t adj;
12799ebb4cwyllys					/* for syntax checking */
12899ebb4cwyllys					if (str2lifetime(
12999ebb4cwyllys					    plc.validity_adjusttime,
13099ebb4cwyllys					    &adj) < 0) {
13199ebb4cwyllys						(void) fprintf(stderr,
13299ebb4cwyllys						    gettext("Error time "
13399ebb4cwyllys						    "input.\n"));
13499ebb4cwyllys						rv = KC_ERR_USAGE;
13599ebb4cwyllys					}
13699ebb4cwyllys				}
13799ebb4cwyllys				break;
13899ebb4cwyllys			case 't':
13999ebb4cwyllys				plc.ta_name = get_string(optarg_av, &rv);
14099ebb4cwyllys				if (plc.ta_name == NULL) {
14199ebb4cwyllys					(void) fprintf(stderr,
14299ebb4cwyllys					    gettext("Error name input.\n"));
143fc2613bWyllys Ingersoll				} else if (strcasecmp(plc.ta_name,
144fc2613bWyllys Ingersoll				    "search") != 0) {
14599ebb4cwyllys					KMF_X509_NAME taDN;
14699ebb4cwyllys					/* for syntax checking */
14730a5e8fwyllys					if (kmf_dn_parser(plc.ta_name,
14899ebb4cwyllys					    &taDN) != KMF_OK) {
14999ebb4cwyllys						(void) fprintf(stderr,
15099ebb4cwyllys						    gettext("Error name "
15199ebb4cwyllys						    "input.\n"));
15299ebb4cwyllys						rv = KC_ERR_USAGE;
15399ebb4cwyllys					} else {
15430a5e8fwyllys						kmf_free_dn(&taDN);
15599ebb4cwyllys					}
15699ebb4cwyllys				}
15799ebb4cwyllys				break;
15899ebb4cwyllys			case 's':
15999ebb4cwyllys				plc.ta_serial = get_string(optarg_av, &rv);
16099ebb4cwyllys				if (plc.ta_serial == NULL) {
16199ebb4cwyllys					(void) fprintf(stderr,
16299ebb4cwyllys					    gettext("Error serial input.\n"));
16399ebb4cwyllys				} else {
16499ebb4cwyllys					uchar_t *bytes = NULL;
16599ebb4cwyllys					size_t bytelen;
16699ebb4cwyllys
16730a5e8fwyllys					ret = kmf_hexstr_to_bytes(
16899ebb4cwyllys					    (uchar_t *)plc.ta_serial,
16999ebb4cwyllys					    &bytes, &bytelen);
17099ebb4cwyllys					if (ret != KMF_OK || bytes == NULL) {
17199ebb4cwyllys						(void) fprintf(stderr,
17299ebb4cwyllys						    gettext("serial number "
17399ebb4cwyllys						    "must be specified as a "
17499ebb4cwyllys						    "hex number "
17599ebb4cwyllys						    "(ex: 0x0102030405"
17699ebb4cwyllys						    "ffeeddee)\n"));
17799ebb4cwyllys						rv = KC_ERR_USAGE;
17899ebb4cwyllys					}
17999ebb4cwyllys					if (bytes != NULL)
18099ebb4cwyllys						free(bytes);
18199ebb4cwyllys				}
18299ebb4cwyllys				break;
18399ebb4cwyllys			case 'o':
18499ebb4cwyllys				plc.VAL_OCSP_RESPONDER_URI =
18599ebb4cwyllys				    get_string(optarg_av, &rv);
18699ebb4cwyllys				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
18799ebb4cwyllys					(void) fprintf(stderr, gettext(
18899ebb4cwyllys					    "Error responder input.\n"));
18999ebb4cwyllys				} else {
19099ebb4cwyllys					ocsp_set_attr++;
19199ebb4cwyllys				}
19299ebb4cwyllys				break;
19399ebb4cwyllys			case 'P':
19499ebb4cwyllys				plc.VAL_OCSP_PROXY =
19599ebb4cwyllys				    get_string(optarg_av, &rv);
19699ebb4cwyllys				if (plc.VAL_OCSP_PROXY == NULL) {
19799ebb4cwyllys					(void) fprintf(stderr,
19899ebb4cwyllys					    gettext("Error proxy input.\n"));
19999ebb4cwyllys				} else {
20099ebb4cwyllys					ocsp_set_attr++;
20199ebb4cwyllys				}
20299ebb4cwyllys				break;
20399ebb4cwyllys			case 'r':
20499ebb4cwyllys				plc.VAL_OCSP_URI_FROM_CERT =
20599ebb4cwyllys				    get_boolean(optarg_av);
20699ebb4cwyllys				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
20799ebb4cwyllys					(void) fprintf(stderr,
20899ebb4cwyllys					    gettext("Error boolean input.\n"));
20999ebb4cwyllys					rv = KC_ERR_USAGE;
21099ebb4cwyllys				} else {
21199ebb4cwyllys					ocsp_set_attr++;
21299ebb4cwyllys				}
21399ebb4cwyllys				break;
21499ebb4cwyllys			case 'T':
21599ebb4cwyllys				plc.VAL_OCSP_RESP_LIFETIME =
21699ebb4cwyllys				    get_string(optarg_av, &rv);
21799ebb4cwyllys				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
21899ebb4cwyllys					(void) fprintf(stderr,
21999ebb4cwyllys					    gettext("Error time input.\n"));
22099ebb4cwyllys				} else {
22199ebb4cwyllys					uint32_t adj;
22299ebb4cwyllys					/* for syntax checking */
22399ebb4cwyllys					if (str2lifetime(
22499ebb4cwyllys					    plc.VAL_OCSP_RESP_LIFETIME,
22599ebb4cwyllys					    &adj) < 0) {
22699ebb4cwyllys						(void) fprintf(stderr,
22799ebb4cwyllys						    gettext("Error time "
22899ebb4cwyllys						    "input.\n"));
22999ebb4cwyllys						rv = KC_ERR_USAGE;
23099ebb4cwyllys					} else {
23199ebb4cwyllys						ocsp_set_attr++;
23299ebb4cwyllys					}
23399ebb4cwyllys				}
23499ebb4cwyllys				break;
23599ebb4cwyllys			case 'R':
23699ebb4cwyllys				plc.VAL_OCSP_IGNORE_RESP_SIGN =
23799ebb4cwyllys				    get_boolean(optarg_av);
23899ebb4cwyllys				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
23999ebb4cwyllys					(void) fprintf(stderr,
24099ebb4cwyllys					    gettext("Error boolean input.\n"));
24199ebb4cwyllys					rv = KC_ERR_USAGE;
24299ebb4cwyllys				} else {
24399ebb4cwyllys					ocsp_set_attr++;
24499ebb4cwyllys				}
24599ebb4cwyllys				break;
24699ebb4cwyllys			case 'n':
24799ebb4cwyllys				plc.VAL_OCSP_RESP_CERT_NAME =
24899ebb4cwyllys				    get_string(optarg_av, &rv);
24999ebb4cwyllys				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
25099ebb4cwyllys					(void) fprintf(stderr,
25199ebb4cwyllys					    gettext("Error name input.\n"));
25299ebb4cwyllys				} else {
25399ebb4cwyllys					KMF_X509_NAME respDN;
25499ebb4cwyllys					/* for syntax checking */
25530a5e8fwyllys					if (kmf_dn_parser(
25699ebb4cwyllys					    plc.VAL_OCSP_RESP_CERT_NAME,
25799ebb4cwyllys					    &respDN) != KMF_OK) {
25899ebb4cwyllys						(void) fprintf(stderr,
25999ebb4cwyllys						    gettext("Error name "
26099ebb4cwyllys						    "input.\n"));
26199ebb4cwyllys						rv = KC_ERR_USAGE;
26299ebb4cwyllys					} else {
26330a5e8fwyllys						kmf_free_dn(&respDN);
26499ebb4cwyllys						ocsp_set_attr++;
26599ebb4cwyllys					}
26699ebb4cwyllys				}
26799ebb4cwyllys				break;
26899ebb4cwyllys			case 'A':
26999ebb4cwyllys				plc.VAL_OCSP_RESP_CERT_SERIAL =
27099ebb4cwyllys				    get_string(optarg_av, &rv);
27199ebb4cwyllys				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
27299ebb4cwyllys					(void) fprintf(stderr,
27399ebb4cwyllys					    gettext("Error serial input.\n"));
27499ebb4cwyllys				} else {
27599ebb4cwyllys					uchar_t *bytes = NULL;
27699ebb4cwyllys					size_t bytelen;
27799ebb4cwyllys
27830a5e8fwyllys					ret = kmf_hexstr_to_bytes((uchar_t *)
27999ebb4cwyllys					    plc.VAL_OCSP_RESP_CERT_SERIAL,
28099ebb4cwyllys					    &bytes, &bytelen);
28199ebb4cwyllys					if (ret != KMF_OK || bytes == NULL) {
28299ebb4cwyllys						(void) fprintf(stderr,
28399ebb4cwyllys						    gettext("serial number "
28499ebb4cwyllys						    "must be specified as a "
28599ebb4cwyllys						    "hex number "
28699ebb4cwyllys						    "(ex: 0x0102030405"
28799ebb4cwyllys						    "ffeeddee)\n"));
28899ebb4cwyllys						rv = KC_ERR_USAGE;
28999ebb4cwyllys						break;
29099ebb4cwyllys					}
29199ebb4cwyllys					if (bytes != NULL)
29299ebb4cwyllys						free(bytes);
29399ebb4cwyllys					ocsp_set_attr++;
29499ebb4cwyllys				}
29599ebb4cwyllys				break;
29699ebb4cwyllys			case 'c':
29799ebb4cwyllys				plc.VAL_CRL_BASEFILENAME =
29899ebb4cwyllys				    get_string(optarg_av, &rv);
29999ebb4cwyllys				if (plc.VAL_CRL_BASEFILENAME == NULL) {
30099ebb4cwyllys					(void) fprintf(stderr,
30199ebb4cwyllys					    gettext("Error boolean input.\n"));
30299ebb4cwyllys				} else {
30399ebb4cwyllys					crl_set_attr++;
30499ebb4cwyllys				}
30599ebb4cwyllys				break;
30699ebb4cwyllys			case 'I':
30799ebb4cwyllys				plc.VAL_CRL_DIRECTORY =
30899ebb4cwyllys				    get_string(optarg_av, &rv);
30999ebb4cwyllys				if (plc.VAL_CRL_DIRECTORY == NULL) {
31099ebb4cwyllys					(void) fprintf(stderr,
31199ebb4cwyllys					    gettext("Error boolean input.\n"));
31299ebb4cwyllys				} else {
31399ebb4cwyllys					crl_set_attr++;
31499ebb4cwyllys				}
31599ebb4cwyllys				break;
31699ebb4cwyllys			case 'g':
31799ebb4cwyllys				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
31899ebb4cwyllys				if (plc.VAL_CRL_GET_URI == -1) {
31999ebb4cwyllys					(void) fprintf(stderr,
32099ebb4cwyllys					    gettext("Error boolean input.\n"));
32199ebb4cwyllys					rv = KC_ERR_USAGE;
32299ebb4cwyllys				} else {
32399ebb4cwyllys					crl_set_attr++;
32499ebb4cwyllys				}
32599ebb4cwyllys				break;
32699ebb4cwyllys			case 'X':
32799ebb4cwyllys				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
32899ebb4cwyllys				if (plc.VAL_CRL_PROXY == NULL) {
32999ebb4cwyllys					(void) fprintf(stderr,
33099ebb4cwyllys					    gettext("Error proxy input.\n"));
33199ebb4cwyllys				} else {
33299ebb4cwyllys					crl_set_attr++;
33399ebb4cwyllys				}
33499ebb4cwyllys				break;
33599ebb4cwyllys			case 'S':
33699ebb4cwyllys				plc.VAL_CRL_IGNORE_SIGN =
33799ebb4cwyllys				    get_boolean(optarg_av);
33899ebb4cwyllys				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
33999ebb4cwyllys					(void) fprintf(stderr,
34099ebb4cwyllys					    gettext("Error boolean input.\n"));
34199ebb4cwyllys					rv = KC_ERR_USAGE;
34299ebb4cwyllys				} else {
34399ebb4cwyllys					crl_set_attr++;
34499ebb4cwyllys				}
34599ebb4cwyllys				break;
34699ebb4cwyllys			case 'D':
34799ebb4cwyllys				plc.VAL_CRL_IGNORE_DATE =
34830a5e8fwyllys				    get_boolean(optarg_av);
34999ebb4cwyllys				if (plc.VAL_CRL_IGNORE_DATE == -1) {
35099ebb4cwyllys					(void) fprintf(stderr,
35199ebb4cwyllys					    gettext("Error boolean input.\n"));
35299ebb4cwyllys					rv = KC_ERR_USAGE;
35399ebb4cwyllys				} else {
35499ebb4cwyllys					crl_set_attr++;
35599ebb4cwyllys				}
35699ebb4cwyllys				break;
35799ebb4cwyllys			case 'u':
35899ebb4cwyllys				plc.ku_bits = parseKUlist(optarg_av);
35999ebb4cwyllys				if (plc.ku_bits == 0) {
36099ebb4cwyllys					(void) fprintf(stderr, gettext(
36199ebb4cwyllys					    "Error keyusage input.\n"));
36299ebb4cwyllys					rv = KC_ERR_USAGE;
36399ebb4cwyllys				}
36499ebb4cwyllys				break;
36599ebb4cwyllys			case 'E':
36699ebb4cwyllys				if (parseEKUNames(optarg_av, &plc) != 0) {
36799ebb4cwyllys					(void) fprintf(stderr,
36899ebb4cwyllys					    gettext("Error EKU input.\n"));
36999ebb4cwyllys					rv = KC_ERR_USAGE;
37099ebb4cwyllys				}
37199ebb4cwyllys				break;
37299ebb4cwyllys			case 'O':
37399ebb4cwyllys				if (parseEKUOIDs(optarg_av, &plc) != 0) {
37499ebb4cwyllys					(void) fprintf(stderr,
37599ebb4cwyllys					    gettext("Error EKU OID input.\n"));
37699ebb4cwyllys					rv = KC_ERR_USAGE;
37799ebb4cwyllys				}
37899ebb4cwyllys				break;
379269e59fJan Pechanec			case 'm':
380269e59fJan Pechanec				plc.mapper.mapname = get_string(optarg_av, &rv);
381269e59fJan Pechanec				if (plc.mapper.mapname == NULL) {
382269e59fJan Pechanec					(void) fprintf(stderr,
383269e59fJan Pechanec					    gettext("Error mapper-name "
384269e59fJan Pechanec					    "input.\n"));
385269e59fJan Pechanec				}
386269e59fJan Pechanec				break;
387269e59fJan Pechanec			case 'M':
388269e59fJan Pechanec				plc.mapper.dir = get_string(optarg_av, &rv);
389269e59fJan Pechanec				if (plc.mapper.dir == NULL) {
390269e59fJan Pechanec					(void) fprintf(stderr,
391269e59fJan Pechanec					    gettext("Error mapper-dir "
392269e59fJan Pechanec					    "input.\n"));
393269e59fJan Pechanec				}
394269e59fJan Pechanec				break;
395269e59fJan Pechanec			case 'Q':
396269e59fJan Pechanec				plc.mapper.pathname = get_string(optarg_av,
397269e59fJan Pechanec				    &rv);
398269e59fJan Pechanec				if (plc.mapper.pathname == NULL) {
399269e59fJan Pechanec					(void) fprintf(stderr,
400269e59fJan Pechanec					    gettext("Error mapper-pathname "
401269e59fJan Pechanec					    "input.\n"));
402269e59fJan Pechanec				}
403269e59fJan Pechanec				break;
404269e59fJan Pechanec			case 'q':
405269e59fJan Pechanec				plc.mapper.options = get_string(optarg_av, &rv);
406269e59fJan Pechanec				if (plc.mapper.options == NULL) {
407269e59fJan Pechanec					(void) fprintf(stderr,
408269e59fJan Pechanec					    gettext("Error mapper-options "
409269e59fJan Pechanec					    "input.\n"));
410269e59fJan Pechanec				}
411269e59fJan Pechanec				break;
41299ebb4cwyllys			default:
41399ebb4cwyllys				(void) fprintf(stderr,
41499ebb4cwyllys				    gettext("Error input option.\n"));
41599ebb4cwyllys				rv = KC_ERR_USAGE;
41699ebb4cwyllys				break;
41799ebb4cwyllys		}
41899ebb4cwyllys
41999ebb4cwyllys		if (rv != KC_OK)
42099ebb4cwyllys			goto out;
42199ebb4cwyllys	}
42299ebb4cwyllys
42399ebb4cwyllys	/* No additional args allowed. */
42499ebb4cwyllys	argc -= optind_av;
42599ebb4cwyllys	if (argc) {
42699ebb4cwyllys		(void) fprintf(stderr,
42799ebb4cwyllys		    gettext("Error input option\n"));
42899ebb4cwyllys		rv = KC_ERR_USAGE;
42999ebb4cwyllys		goto out;
43099ebb4cwyllys	}
43199ebb4cwyllys
43299ebb4cwyllys	if (filename == NULL) {
43399ebb4cwyllys		filename = strdup(KMF_DEFAULT_POLICY_FILE);
43499ebb4cwyllys		if (filename == NULL) {
43599ebb4cwyllys			rv = KC_ERR_MEMORY;
43699ebb4cwyllys			goto out;
43799ebb4cwyllys		}
43899ebb4cwyllys	}
43999ebb4cwyllys
44099ebb4cwyllys	/*
44199ebb4cwyllys	 * Must have a policy name. The policy name can not be default
44299ebb4cwyllys	 * if using the default policy file.
44399ebb4cwyllys	 */
44499ebb4cwyllys	if (plc.name == NULL) {
44599ebb4cwyllys		(void) fprintf(stderr,
44699ebb4cwyllys		    gettext("You must specify a policy name\n"));
44799ebb4cwyllys		rv = KC_ERR_USAGE;
44899ebb4cwyllys		goto out;
44999ebb4cwyllys	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
45099ebb4cwyllys	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
45199ebb4cwyllys		(void) fprintf(stderr,
45299ebb4cwyllys		    gettext("Can not create a default policy in the default "
45399ebb4cwyllys		    "policy file\n"));
45499ebb4cwyllys		rv = KC_ERR_USAGE;
45599ebb4cwyllys		goto out;
45699ebb4cwyllys	}
45799ebb4cwyllys
45899ebb4cwyllys	/*
45999ebb4cwyllys	 * If the policy file exists and the policy is in the policy file
46099ebb4cwyllys	 * already, we will not create it again.
46199ebb4cwyllys	 */
46299ebb4cwyllys	if (access(filename, R_OK) == 0) {
46399ebb4cwyllys		POLICY_LIST *plclist = NULL, *pnode;
46499ebb4cwyllys		int found = 0;
46599ebb4cwyllys
46699ebb4cwyllys		rv = load_policies(filename, &plclist);
46799ebb4cwyllys		if (rv != KMF_OK)
46899ebb4cwyllys			goto out;
46999ebb4cwyllys
47099ebb4cwyllys		pnode = plclist;
47199ebb4cwyllys		while (pnode != NULL && !found) {
47299ebb4cwyllys			if (strcmp(plc.name, pnode->plc.name) == 0)
47399ebb4cwyllys				found++;
47499ebb4cwyllys			pnode = pnode->next;
47599ebb4cwyllys		}
47699ebb4cwyllys		free_policy_list(plclist);
47799ebb4cwyllys
47899ebb4cwyllys		if (found) {
47999ebb4cwyllys			(void) fprintf(stderr,
48099ebb4cwyllys			    gettext("Could not create policy \"%s\" - exists "
48199ebb4cwyllys			    "already\n"), plc.name);
48299ebb4cwyllys			rv = KC_ERR_USAGE;
48399ebb4cwyllys			goto out;
48499ebb4cwyllys		}
48599ebb4cwyllys	}
48699ebb4cwyllys
48799ebb4cwyllys	/*
48899ebb4cwyllys	 * If any OCSP attribute is set, turn on the OCSP checking flag.
48999ebb4cwyllys	 * Also set "has_resp_cert" to be true, if the responder cert
49099ebb4cwyllys	 * is provided.
49199ebb4cwyllys	 */
49299ebb4cwyllys	if (ocsp_set_attr > 0)
49399ebb4cwyllys		plc.revocation |= KMF_REVOCATION_METHOD_OCSP;
49499ebb4cwyllys
49599ebb4cwyllys	if (plc.VAL_OCSP_RESP_CERT.name != NULL &&
49699ebb4cwyllys	    plc.VAL_OCSP_RESP_CERT.serial != NULL) {
49799ebb4cwyllys		plc.VAL_OCSP.has_resp_cert = B_TRUE;
49899ebb4cwyllys	}
49999ebb4cwyllys
50099ebb4cwyllys	/*
501269e59fJan Pechanec	 * Setting mapper-name (with optional mapper-dir) and mapper-pathname is
502269e59fJan Pechanec	 * mutually exclusive. Also, you cannot set options only, you need the
503269e59fJan Pechanec	 * name or pathname, and you can set the directory only with the name,
504269e59fJan Pechanec	 * not the pathname.
505269e59fJan Pechanec	 */
506269e59fJan Pechanec	if ((plc.mapper.mapname != NULL && plc.mapper.pathname != NULL) ||
507269e59fJan Pechanec	    (plc.mapper.dir != NULL && plc.mapper.pathname != NULL) ||
508269e59fJan Pechanec	    (plc.mapper.dir != NULL && plc.mapper.mapname == NULL) ||
509269e59fJan Pechanec	    (plc.mapper.options != NULL && plc.mapper.mapname == NULL &&
510269e59fJan Pechanec	    plc.mapper.pathname == NULL)) {
511269e59fJan Pechanec		(void) fprintf(stderr,
512269e59fJan Pechanec		    gettext("Error in mapper input options\n"));
513269e59fJan Pechanec		rv = KC_ERR_USAGE;
514269e59fJan Pechanec		goto out;
515269e59fJan Pechanec	}
516269e59fJan Pechanec
517269e59fJan Pechanec	/*
51899ebb4cwyllys	 * If any CRL attribute is set, turn on the CRL checking flag.
51999ebb4cwyllys	 */
52099ebb4cwyllys	if (crl_set_attr > 0)
52199ebb4cwyllys		plc.revocation |= KMF_REVOCATION_METHOD_CRL;
52299ebb4cwyllys
52399ebb4cwyllys	/*
52499ebb4cwyllys	 * Does a sanity check on the new policy.
52599ebb4cwyllys	 */
52630a5e8fwyllys	ret = kmf_verify_policy(&plc);
52799ebb4cwyllys	if (ret != KMF_OK) {
52899ebb4cwyllys		print_sanity_error(ret);
52999ebb4cwyllys		rv = KC_ERR_ADD_POLICY;
53099ebb4cwyllys		goto out;
53199ebb4cwyllys	}
53299ebb4cwyllys
53399ebb4cwyllys	/*
53499ebb4cwyllys	 * Add to the DB.
53599ebb4cwyllys	 */
53630a5e8fwyllys	ret = kmf_add_policy_to_db(&plc, filename, B_FALSE);
53799ebb4cwyllys	if (ret != KMF_OK) {
53899ebb4cwyllys		(void) fprintf(stderr,
53999ebb4cwyllys		    gettext("Error adding policy to database: 0x%04x\n"), ret);
54099ebb4cwyllys		rv = KC_ERR_ADD_POLICY;
54199ebb4cwyllys	}
54299ebb4cwyllys
54399ebb4cwyllysout:
54499ebb4cwyllys	if (filename != NULL)
54599ebb4cwyllys		free(filename);
54699ebb4cwyllys
54730a5e8fwyllys	kmf_free_policy_record(&plc);
54899ebb4cwyllys
54999ebb4cwyllys	return (rv);
55099ebb4cwyllys}
551