xref: /illumos-gate/usr/src/cmd/cmd-crypto/kmfcfg/create.c (revision 30a5e8fa1253cb33980ee4514743cf683f584b4e)
199ebb4caSwyllys /*
299ebb4caSwyllys  * CDDL HEADER START
399ebb4caSwyllys  *
499ebb4caSwyllys  * The contents of this file are subject to the terms of the
599ebb4caSwyllys  * Common Development and Distribution License (the "License").
699ebb4caSwyllys  * You may not use this file except in compliance with the License.
799ebb4caSwyllys  *
899ebb4caSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999ebb4caSwyllys  * or http://www.opensolaris.org/os/licensing.
1099ebb4caSwyllys  * See the License for the specific language governing permissions
1199ebb4caSwyllys  * and limitations under the License.
1299ebb4caSwyllys  *
1399ebb4caSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
1499ebb4caSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599ebb4caSwyllys  * If applicable, add the following below this CDDL HEADER, with the
1699ebb4caSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
1799ebb4caSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
1899ebb4caSwyllys  *
1999ebb4caSwyllys  * CDDL HEADER END
2099ebb4caSwyllys  *
21*30a5e8faSwyllys  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2299ebb4caSwyllys  * Use is subject to license terms.
2399ebb4caSwyllys  */
2499ebb4caSwyllys 
2599ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
2699ebb4caSwyllys 
2799ebb4caSwyllys #include <stdio.h>
2899ebb4caSwyllys #include <strings.h>
2999ebb4caSwyllys #include <ctype.h>
3099ebb4caSwyllys #include <libgen.h>
3199ebb4caSwyllys #include <libintl.h>
3299ebb4caSwyllys #include <errno.h>
3399ebb4caSwyllys #include <kmfapiP.h>
3499ebb4caSwyllys #include <cryptoutil.h>
3599ebb4caSwyllys #include "util.h"
3699ebb4caSwyllys 
3799ebb4caSwyllys int
3899ebb4caSwyllys kc_create(int argc, char *argv[])
3999ebb4caSwyllys {
4099ebb4caSwyllys 	KMF_RETURN	ret;
4199ebb4caSwyllys 	int 		rv = KC_OK;
4299ebb4caSwyllys 	int		opt;
4399ebb4caSwyllys 	extern int	optind_av;
4499ebb4caSwyllys 	extern char	*optarg_av;
4599ebb4caSwyllys 	char		*filename = NULL;
4699ebb4caSwyllys 	int		ocsp_set_attr = 0;
4799ebb4caSwyllys 	boolean_t	crl_set_attr = 0;
4899ebb4caSwyllys 	KMF_POLICY_RECORD plc;
4999ebb4caSwyllys 
5099ebb4caSwyllys 	(void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
5199ebb4caSwyllys 
5299ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
53*30a5e8faSwyllys 	    "i:(dbfile)"
54*30a5e8faSwyllys 	    "p:(policy)"
55*30a5e8faSwyllys 	    "d:(ignore-date)"
56*30a5e8faSwyllys 	    "e:(ignore-unknown-eku)"
57*30a5e8faSwyllys 	    "a:(ignore-trust-anchor)"
58*30a5e8faSwyllys 	    "v:(validity-adjusttime)"
59*30a5e8faSwyllys 	    "t:(ta-name)"
60*30a5e8faSwyllys 	    "s:(ta-serial)"
61*30a5e8faSwyllys 	    "o:(ocsp-responder)"
62*30a5e8faSwyllys 	    "P:(ocsp-proxy)"
63*30a5e8faSwyllys 	    "r:(ocsp-use-cert-responder)"
64*30a5e8faSwyllys 	    "T:(ocsp-response-lifetime)"
65*30a5e8faSwyllys 	    "R:(ocsp-ignore-response-sign)"
66*30a5e8faSwyllys 	    "n:(ocsp-responder-cert-name)"
67*30a5e8faSwyllys 	    "A:(ocsp-responder-cert-serial)"
68*30a5e8faSwyllys 	    "c:(crl-basefilename)"
69*30a5e8faSwyllys 	    "I:(crl-directory)"
70*30a5e8faSwyllys 	    "g:(crl-get-crl-uri)"
71*30a5e8faSwyllys 	    "X:(crl-proxy)"
72*30a5e8faSwyllys 	    "S:(crl-ignore-crl-sign)"
73*30a5e8faSwyllys 	    "D:(crl-ignore-crl-date)"
74*30a5e8faSwyllys 	    "u:(keyusage)"
75*30a5e8faSwyllys 	    "E:(ekunames)"
76*30a5e8faSwyllys 	    "O:(ekuoids)")) != EOF) {
7799ebb4caSwyllys 		switch (opt) {
7899ebb4caSwyllys 			case 'i':
7999ebb4caSwyllys 				filename = get_string(optarg_av, &rv);
8099ebb4caSwyllys 				if (filename == NULL) {
8199ebb4caSwyllys 					(void) fprintf(stderr,
8299ebb4caSwyllys 					    gettext("Error dbfile input.\n"));
8399ebb4caSwyllys 				}
8499ebb4caSwyllys 				break;
8599ebb4caSwyllys 			case 'p':
8699ebb4caSwyllys 				plc.name = get_string(optarg_av, &rv);
8799ebb4caSwyllys 				if (plc.name == NULL) {
8899ebb4caSwyllys 					(void) fprintf(stderr,
8999ebb4caSwyllys 					    gettext("Error policy name.\n"));
9099ebb4caSwyllys 				}
9199ebb4caSwyllys 				break;
9299ebb4caSwyllys 			case 'd':
9399ebb4caSwyllys 				plc.ignore_date = get_boolean(optarg_av);
9499ebb4caSwyllys 				if (plc.ignore_date == -1) {
9599ebb4caSwyllys 					(void) fprintf(stderr,
9699ebb4caSwyllys 					    gettext("Error boolean input.\n"));
9799ebb4caSwyllys 					rv = KC_ERR_USAGE;
9899ebb4caSwyllys 				}
9999ebb4caSwyllys 				break;
10099ebb4caSwyllys 			case 'e':
10199ebb4caSwyllys 				plc.ignore_unknown_ekus =
10299ebb4caSwyllys 				    get_boolean(optarg_av);
10399ebb4caSwyllys 				if (plc.ignore_unknown_ekus == -1) {
10499ebb4caSwyllys 					(void) fprintf(stderr,
10599ebb4caSwyllys 					    gettext("Error boolean input.\n"));
10699ebb4caSwyllys 					rv = KC_ERR_USAGE;
10799ebb4caSwyllys 				}
10899ebb4caSwyllys 				break;
10999ebb4caSwyllys 			case 'a':
11099ebb4caSwyllys 				plc.ignore_trust_anchor =
11199ebb4caSwyllys 				    get_boolean(optarg_av);
11299ebb4caSwyllys 				if (plc.ignore_trust_anchor == -1) {
11399ebb4caSwyllys 					(void) fprintf(stderr,
11499ebb4caSwyllys 					    gettext("Error boolean input.\n"));
11599ebb4caSwyllys 					rv = KC_ERR_USAGE;
11699ebb4caSwyllys 				}
11799ebb4caSwyllys 				break;
11899ebb4caSwyllys 			case 'v':
11999ebb4caSwyllys 				plc.validity_adjusttime =
12099ebb4caSwyllys 				    get_string(optarg_av, &rv);
12199ebb4caSwyllys 				if (plc.validity_adjusttime == NULL) {
12299ebb4caSwyllys 					(void) fprintf(stderr,
12399ebb4caSwyllys 					    gettext("Error time input.\n"));
12499ebb4caSwyllys 				} else {
12599ebb4caSwyllys 					uint32_t adj;
12699ebb4caSwyllys 					/* for syntax checking */
12799ebb4caSwyllys 					if (str2lifetime(
12899ebb4caSwyllys 					    plc.validity_adjusttime,
12999ebb4caSwyllys 					    &adj) < 0) {
13099ebb4caSwyllys 						(void) fprintf(stderr,
13199ebb4caSwyllys 						    gettext("Error time "
13299ebb4caSwyllys 						    "input.\n"));
13399ebb4caSwyllys 						rv = KC_ERR_USAGE;
13499ebb4caSwyllys 					}
13599ebb4caSwyllys 				}
13699ebb4caSwyllys 				break;
13799ebb4caSwyllys 			case 't':
13899ebb4caSwyllys 				plc.ta_name = get_string(optarg_av, &rv);
13999ebb4caSwyllys 				if (plc.ta_name == NULL) {
14099ebb4caSwyllys 					(void) fprintf(stderr,
14199ebb4caSwyllys 					    gettext("Error name input.\n"));
14299ebb4caSwyllys 				} else {
14399ebb4caSwyllys 					KMF_X509_NAME taDN;
14499ebb4caSwyllys 					/* for syntax checking */
145*30a5e8faSwyllys 					if (kmf_dn_parser(plc.ta_name,
14699ebb4caSwyllys 					    &taDN) != KMF_OK) {
14799ebb4caSwyllys 						(void) fprintf(stderr,
14899ebb4caSwyllys 						    gettext("Error name "
14999ebb4caSwyllys 						    "input.\n"));
15099ebb4caSwyllys 						rv = KC_ERR_USAGE;
15199ebb4caSwyllys 					} else {
152*30a5e8faSwyllys 						kmf_free_dn(&taDN);
15399ebb4caSwyllys 					}
15499ebb4caSwyllys 				}
15599ebb4caSwyllys 				break;
15699ebb4caSwyllys 			case 's':
15799ebb4caSwyllys 				plc.ta_serial = get_string(optarg_av, &rv);
15899ebb4caSwyllys 				if (plc.ta_serial == NULL) {
15999ebb4caSwyllys 					(void) fprintf(stderr,
16099ebb4caSwyllys 					    gettext("Error serial input.\n"));
16199ebb4caSwyllys 				} else {
16299ebb4caSwyllys 					uchar_t *bytes = NULL;
16399ebb4caSwyllys 					size_t bytelen;
16499ebb4caSwyllys 
165*30a5e8faSwyllys 					ret = kmf_hexstr_to_bytes(
16699ebb4caSwyllys 					    (uchar_t *)plc.ta_serial,
16799ebb4caSwyllys 					    &bytes, &bytelen);
16899ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
16999ebb4caSwyllys 						(void) fprintf(stderr,
17099ebb4caSwyllys 						    gettext("serial number "
17199ebb4caSwyllys 						    "must be specified as a "
17299ebb4caSwyllys 						    "hex number "
17399ebb4caSwyllys 						    "(ex: 0x0102030405"
17499ebb4caSwyllys 						    "ffeeddee)\n"));
17599ebb4caSwyllys 						rv = KC_ERR_USAGE;
17699ebb4caSwyllys 					}
17799ebb4caSwyllys 					if (bytes != NULL)
17899ebb4caSwyllys 						free(bytes);
17999ebb4caSwyllys 				}
18099ebb4caSwyllys 				break;
18199ebb4caSwyllys 			case 'o':
18299ebb4caSwyllys 				plc.VAL_OCSP_RESPONDER_URI =
18399ebb4caSwyllys 				    get_string(optarg_av, &rv);
18499ebb4caSwyllys 				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
18599ebb4caSwyllys 					(void) fprintf(stderr, gettext(
18699ebb4caSwyllys 					    "Error responder input.\n"));
18799ebb4caSwyllys 				} else {
18899ebb4caSwyllys 					ocsp_set_attr++;
18999ebb4caSwyllys 				}
19099ebb4caSwyllys 				break;
19199ebb4caSwyllys 			case 'P':
19299ebb4caSwyllys 				plc.VAL_OCSP_PROXY =
19399ebb4caSwyllys 				    get_string(optarg_av, &rv);
19499ebb4caSwyllys 				if (plc.VAL_OCSP_PROXY == NULL) {
19599ebb4caSwyllys 					(void) fprintf(stderr,
19699ebb4caSwyllys 					    gettext("Error proxy input.\n"));
19799ebb4caSwyllys 				} else {
19899ebb4caSwyllys 					ocsp_set_attr++;
19999ebb4caSwyllys 				}
20099ebb4caSwyllys 				break;
20199ebb4caSwyllys 			case 'r':
20299ebb4caSwyllys 				plc.VAL_OCSP_URI_FROM_CERT =
20399ebb4caSwyllys 				    get_boolean(optarg_av);
20499ebb4caSwyllys 				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
20599ebb4caSwyllys 					(void) fprintf(stderr,
20699ebb4caSwyllys 					    gettext("Error boolean input.\n"));
20799ebb4caSwyllys 					rv = KC_ERR_USAGE;
20899ebb4caSwyllys 				} else {
20999ebb4caSwyllys 					ocsp_set_attr++;
21099ebb4caSwyllys 				}
21199ebb4caSwyllys 				break;
21299ebb4caSwyllys 			case 'T':
21399ebb4caSwyllys 				plc.VAL_OCSP_RESP_LIFETIME =
21499ebb4caSwyllys 				    get_string(optarg_av, &rv);
21599ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
21699ebb4caSwyllys 					(void) fprintf(stderr,
21799ebb4caSwyllys 					    gettext("Error time input.\n"));
21899ebb4caSwyllys 				} else {
21999ebb4caSwyllys 					uint32_t adj;
22099ebb4caSwyllys 					/* for syntax checking */
22199ebb4caSwyllys 					if (str2lifetime(
22299ebb4caSwyllys 					    plc.VAL_OCSP_RESP_LIFETIME,
22399ebb4caSwyllys 					    &adj) < 0) {
22499ebb4caSwyllys 						(void) fprintf(stderr,
22599ebb4caSwyllys 						    gettext("Error time "
22699ebb4caSwyllys 						    "input.\n"));
22799ebb4caSwyllys 						rv = KC_ERR_USAGE;
22899ebb4caSwyllys 					} else {
22999ebb4caSwyllys 						ocsp_set_attr++;
23099ebb4caSwyllys 					}
23199ebb4caSwyllys 				}
23299ebb4caSwyllys 				break;
23399ebb4caSwyllys 			case 'R':
23499ebb4caSwyllys 				plc.VAL_OCSP_IGNORE_RESP_SIGN =
23599ebb4caSwyllys 				    get_boolean(optarg_av);
23699ebb4caSwyllys 				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
23799ebb4caSwyllys 					(void) fprintf(stderr,
23899ebb4caSwyllys 					    gettext("Error boolean input.\n"));
23999ebb4caSwyllys 					rv = KC_ERR_USAGE;
24099ebb4caSwyllys 				} else {
24199ebb4caSwyllys 					ocsp_set_attr++;
24299ebb4caSwyllys 				}
24399ebb4caSwyllys 				break;
24499ebb4caSwyllys 			case 'n':
24599ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_NAME =
24699ebb4caSwyllys 				    get_string(optarg_av, &rv);
24799ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
24899ebb4caSwyllys 					(void) fprintf(stderr,
24999ebb4caSwyllys 					    gettext("Error name input.\n"));
25099ebb4caSwyllys 				} else {
25199ebb4caSwyllys 					KMF_X509_NAME respDN;
25299ebb4caSwyllys 					/* for syntax checking */
253*30a5e8faSwyllys 					if (kmf_dn_parser(
25499ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_NAME,
25599ebb4caSwyllys 					    &respDN) != KMF_OK) {
25699ebb4caSwyllys 						(void) fprintf(stderr,
25799ebb4caSwyllys 						    gettext("Error name "
25899ebb4caSwyllys 						    "input.\n"));
25999ebb4caSwyllys 						rv = KC_ERR_USAGE;
26099ebb4caSwyllys 					} else {
261*30a5e8faSwyllys 						kmf_free_dn(&respDN);
26299ebb4caSwyllys 						ocsp_set_attr++;
26399ebb4caSwyllys 					}
26499ebb4caSwyllys 				}
26599ebb4caSwyllys 				break;
26699ebb4caSwyllys 			case 'A':
26799ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_SERIAL =
26899ebb4caSwyllys 				    get_string(optarg_av, &rv);
26999ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
27099ebb4caSwyllys 					(void) fprintf(stderr,
27199ebb4caSwyllys 					    gettext("Error serial input.\n"));
27299ebb4caSwyllys 				} else {
27399ebb4caSwyllys 					uchar_t *bytes = NULL;
27499ebb4caSwyllys 					size_t bytelen;
27599ebb4caSwyllys 
276*30a5e8faSwyllys 					ret = kmf_hexstr_to_bytes((uchar_t *)
27799ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_SERIAL,
27899ebb4caSwyllys 					    &bytes, &bytelen);
27999ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
28099ebb4caSwyllys 						(void) fprintf(stderr,
28199ebb4caSwyllys 						    gettext("serial number "
28299ebb4caSwyllys 						    "must be specified as a "
28399ebb4caSwyllys 						    "hex number "
28499ebb4caSwyllys 						    "(ex: 0x0102030405"
28599ebb4caSwyllys 						    "ffeeddee)\n"));
28699ebb4caSwyllys 						rv = KC_ERR_USAGE;
28799ebb4caSwyllys 						break;
28899ebb4caSwyllys 					}
28999ebb4caSwyllys 					if (bytes != NULL)
29099ebb4caSwyllys 						free(bytes);
29199ebb4caSwyllys 					ocsp_set_attr++;
29299ebb4caSwyllys 				}
29399ebb4caSwyllys 				break;
29499ebb4caSwyllys 			case 'c':
29599ebb4caSwyllys 				plc.VAL_CRL_BASEFILENAME =
29699ebb4caSwyllys 				    get_string(optarg_av, &rv);
29799ebb4caSwyllys 				if (plc.VAL_CRL_BASEFILENAME == NULL) {
29899ebb4caSwyllys 					(void) fprintf(stderr,
29999ebb4caSwyllys 					    gettext("Error boolean input.\n"));
30099ebb4caSwyllys 				} else {
30199ebb4caSwyllys 					crl_set_attr++;
30299ebb4caSwyllys 				}
30399ebb4caSwyllys 				break;
30499ebb4caSwyllys 			case 'I':
30599ebb4caSwyllys 				plc.VAL_CRL_DIRECTORY =
30699ebb4caSwyllys 				    get_string(optarg_av, &rv);
30799ebb4caSwyllys 				if (plc.VAL_CRL_DIRECTORY == NULL) {
30899ebb4caSwyllys 					(void) fprintf(stderr,
30999ebb4caSwyllys 					    gettext("Error boolean input.\n"));
31099ebb4caSwyllys 				} else {
31199ebb4caSwyllys 					crl_set_attr++;
31299ebb4caSwyllys 				}
31399ebb4caSwyllys 				break;
31499ebb4caSwyllys 			case 'g':
31599ebb4caSwyllys 				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
31699ebb4caSwyllys 				if (plc.VAL_CRL_GET_URI == -1) {
31799ebb4caSwyllys 					(void) fprintf(stderr,
31899ebb4caSwyllys 					    gettext("Error boolean input.\n"));
31999ebb4caSwyllys 					rv = KC_ERR_USAGE;
32099ebb4caSwyllys 				} else {
32199ebb4caSwyllys 					crl_set_attr++;
32299ebb4caSwyllys 				}
32399ebb4caSwyllys 				break;
32499ebb4caSwyllys 			case 'X':
32599ebb4caSwyllys 				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
32699ebb4caSwyllys 				if (plc.VAL_CRL_PROXY == NULL) {
32799ebb4caSwyllys 					(void) fprintf(stderr,
32899ebb4caSwyllys 					    gettext("Error proxy input.\n"));
32999ebb4caSwyllys 				} else {
33099ebb4caSwyllys 					crl_set_attr++;
33199ebb4caSwyllys 				}
33299ebb4caSwyllys 				break;
33399ebb4caSwyllys 			case 'S':
33499ebb4caSwyllys 				plc.VAL_CRL_IGNORE_SIGN =
33599ebb4caSwyllys 				    get_boolean(optarg_av);
33699ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
33799ebb4caSwyllys 					(void) fprintf(stderr,
33899ebb4caSwyllys 					    gettext("Error boolean input.\n"));
33999ebb4caSwyllys 					rv = KC_ERR_USAGE;
34099ebb4caSwyllys 				} else {
34199ebb4caSwyllys 					crl_set_attr++;
34299ebb4caSwyllys 				}
34399ebb4caSwyllys 				break;
34499ebb4caSwyllys 			case 'D':
34599ebb4caSwyllys 				plc.VAL_CRL_IGNORE_DATE =
346*30a5e8faSwyllys 				    get_boolean(optarg_av);
34799ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_DATE == -1) {
34899ebb4caSwyllys 					(void) fprintf(stderr,
34999ebb4caSwyllys 					    gettext("Error boolean input.\n"));
35099ebb4caSwyllys 					rv = KC_ERR_USAGE;
35199ebb4caSwyllys 				} else {
35299ebb4caSwyllys 					crl_set_attr++;
35399ebb4caSwyllys 				}
35499ebb4caSwyllys 				break;
35599ebb4caSwyllys 			case 'u':
35699ebb4caSwyllys 				plc.ku_bits = parseKUlist(optarg_av);
35799ebb4caSwyllys 				if (plc.ku_bits == 0) {
35899ebb4caSwyllys 					(void) fprintf(stderr, gettext(
35999ebb4caSwyllys 					    "Error keyusage input.\n"));
36099ebb4caSwyllys 					rv = KC_ERR_USAGE;
36199ebb4caSwyllys 				}
36299ebb4caSwyllys 				break;
36399ebb4caSwyllys 			case 'E':
36499ebb4caSwyllys 				if (parseEKUNames(optarg_av, &plc) != 0) {
36599ebb4caSwyllys 					(void) fprintf(stderr,
36699ebb4caSwyllys 					    gettext("Error EKU input.\n"));
36799ebb4caSwyllys 					rv = KC_ERR_USAGE;
36899ebb4caSwyllys 				}
36999ebb4caSwyllys 				break;
37099ebb4caSwyllys 			case 'O':
37199ebb4caSwyllys 				if (parseEKUOIDs(optarg_av, &plc) != 0) {
37299ebb4caSwyllys 					(void) fprintf(stderr,
37399ebb4caSwyllys 					    gettext("Error EKU OID input.\n"));
37499ebb4caSwyllys 					rv = KC_ERR_USAGE;
37599ebb4caSwyllys 				}
37699ebb4caSwyllys 				break;
37799ebb4caSwyllys 			default:
37899ebb4caSwyllys 				(void) fprintf(stderr,
37999ebb4caSwyllys 				    gettext("Error input option.\n"));
38099ebb4caSwyllys 				rv = KC_ERR_USAGE;
38199ebb4caSwyllys 				break;
38299ebb4caSwyllys 		}
38399ebb4caSwyllys 
38499ebb4caSwyllys 		if (rv != KC_OK)
38599ebb4caSwyllys 			goto out;
38699ebb4caSwyllys 	}
38799ebb4caSwyllys 
38899ebb4caSwyllys 	/* No additional args allowed. */
38999ebb4caSwyllys 	argc -= optind_av;
39099ebb4caSwyllys 	if (argc) {
39199ebb4caSwyllys 		(void) fprintf(stderr,
39299ebb4caSwyllys 		    gettext("Error input option\n"));
39399ebb4caSwyllys 		rv = KC_ERR_USAGE;
39499ebb4caSwyllys 		goto out;
39599ebb4caSwyllys 	}
39699ebb4caSwyllys 
39799ebb4caSwyllys 	if (filename == NULL) {
39899ebb4caSwyllys 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
39999ebb4caSwyllys 		if (filename == NULL) {
40099ebb4caSwyllys 			rv = KC_ERR_MEMORY;
40199ebb4caSwyllys 			goto out;
40299ebb4caSwyllys 		}
40399ebb4caSwyllys 	}
40499ebb4caSwyllys 
40599ebb4caSwyllys 	/*
40699ebb4caSwyllys 	 * Must have a policy name. The policy name can not be default
40799ebb4caSwyllys 	 * if using the default policy file.
40899ebb4caSwyllys 	 */
40999ebb4caSwyllys 	if (plc.name == NULL) {
41099ebb4caSwyllys 		(void) fprintf(stderr,
41199ebb4caSwyllys 		    gettext("You must specify a policy name\n"));
41299ebb4caSwyllys 		rv = KC_ERR_USAGE;
41399ebb4caSwyllys 		goto out;
41499ebb4caSwyllys 	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
41599ebb4caSwyllys 	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
41699ebb4caSwyllys 		(void) fprintf(stderr,
41799ebb4caSwyllys 		    gettext("Can not create a default policy in the default "
41899ebb4caSwyllys 		    "policy file\n"));
41999ebb4caSwyllys 		rv = KC_ERR_USAGE;
42099ebb4caSwyllys 		goto out;
42199ebb4caSwyllys 	}
42299ebb4caSwyllys 
42399ebb4caSwyllys 	/*
42499ebb4caSwyllys 	 * If the policy file exists and the policy is in the policy file
42599ebb4caSwyllys 	 * already, we will not create it again.
42699ebb4caSwyllys 	 */
42799ebb4caSwyllys 	if (access(filename, R_OK) == 0) {
42899ebb4caSwyllys 		POLICY_LIST *plclist = NULL, *pnode;
42999ebb4caSwyllys 		int found = 0;
43099ebb4caSwyllys 
43199ebb4caSwyllys 		rv = load_policies(filename, &plclist);
43299ebb4caSwyllys 		if (rv != KMF_OK)
43399ebb4caSwyllys 			goto out;
43499ebb4caSwyllys 
43599ebb4caSwyllys 		pnode = plclist;
43699ebb4caSwyllys 		while (pnode != NULL && !found) {
43799ebb4caSwyllys 			if (strcmp(plc.name, pnode->plc.name) == 0)
43899ebb4caSwyllys 				found++;
43999ebb4caSwyllys 			pnode = pnode->next;
44099ebb4caSwyllys 		}
44199ebb4caSwyllys 		free_policy_list(plclist);
44299ebb4caSwyllys 
44399ebb4caSwyllys 		if (found) {
44499ebb4caSwyllys 			(void) fprintf(stderr,
44599ebb4caSwyllys 			    gettext("Could not create policy \"%s\" - exists "
44699ebb4caSwyllys 			    "already\n"), plc.name);
44799ebb4caSwyllys 			rv = KC_ERR_USAGE;
44899ebb4caSwyllys 			goto out;
44999ebb4caSwyllys 		}
45099ebb4caSwyllys 	}
45199ebb4caSwyllys 
45299ebb4caSwyllys 	/*
45399ebb4caSwyllys 	 * If any OCSP attribute is set, turn on the OCSP checking flag.
45499ebb4caSwyllys 	 * Also set "has_resp_cert" to be true, if the responder cert
45599ebb4caSwyllys 	 * is provided.
45699ebb4caSwyllys 	 */
45799ebb4caSwyllys 	if (ocsp_set_attr > 0)
45899ebb4caSwyllys 		plc.revocation |= KMF_REVOCATION_METHOD_OCSP;
45999ebb4caSwyllys 
46099ebb4caSwyllys 	if (plc.VAL_OCSP_RESP_CERT.name != NULL &&
46199ebb4caSwyllys 	    plc.VAL_OCSP_RESP_CERT.serial != NULL) {
46299ebb4caSwyllys 		plc.VAL_OCSP.has_resp_cert = B_TRUE;
46399ebb4caSwyllys 	}
46499ebb4caSwyllys 
46599ebb4caSwyllys 	/*
46699ebb4caSwyllys 	 * If any CRL attribute is set, turn on the CRL checking flag.
46799ebb4caSwyllys 	 */
46899ebb4caSwyllys 	if (crl_set_attr > 0)
46999ebb4caSwyllys 		plc.revocation |= KMF_REVOCATION_METHOD_CRL;
47099ebb4caSwyllys 
47199ebb4caSwyllys 	/*
47299ebb4caSwyllys 	 * Does a sanity check on the new policy.
47399ebb4caSwyllys 	 */
474*30a5e8faSwyllys 	ret = kmf_verify_policy(&plc);
47599ebb4caSwyllys 	if (ret != KMF_OK) {
47699ebb4caSwyllys 		print_sanity_error(ret);
47799ebb4caSwyllys 		rv = KC_ERR_ADD_POLICY;
47899ebb4caSwyllys 		goto out;
47999ebb4caSwyllys 	}
48099ebb4caSwyllys 
48199ebb4caSwyllys 	/*
48299ebb4caSwyllys 	 * Add to the DB.
48399ebb4caSwyllys 	 */
484*30a5e8faSwyllys 	ret = kmf_add_policy_to_db(&plc, filename, B_FALSE);
48599ebb4caSwyllys 	if (ret != KMF_OK) {
48699ebb4caSwyllys 		(void) fprintf(stderr,
48799ebb4caSwyllys 		    gettext("Error adding policy to database: 0x%04x\n"), ret);
48899ebb4caSwyllys 		rv = KC_ERR_ADD_POLICY;
48999ebb4caSwyllys 	}
49099ebb4caSwyllys 
49199ebb4caSwyllys out:
49299ebb4caSwyllys 	if (filename != NULL)
49399ebb4caSwyllys 		free(filename);
49499ebb4caSwyllys 
495*30a5e8faSwyllys 	kmf_free_policy_record(&plc);
49699ebb4caSwyllys 
49799ebb4caSwyllys 	return (rv);
49899ebb4caSwyllys }
499