xref: /onnv-gate/usr/src/cmd/cmd-crypto/kmfcfg/create.c (revision 5051:cbbb7c8b40a9)
13089Swyllys /*
23089Swyllys  * CDDL HEADER START
33089Swyllys  *
43089Swyllys  * The contents of this file are subject to the terms of the
53089Swyllys  * Common Development and Distribution License (the "License").
63089Swyllys  * You may not use this file except in compliance with the License.
73089Swyllys  *
83089Swyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93089Swyllys  * or http://www.opensolaris.org/os/licensing.
103089Swyllys  * See the License for the specific language governing permissions
113089Swyllys  * and limitations under the License.
123089Swyllys  *
133089Swyllys  * When distributing Covered Code, include this CDDL HEADER in each
143089Swyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153089Swyllys  * If applicable, add the following below this CDDL HEADER, with the
163089Swyllys  * fields enclosed by brackets "[]" replaced with your own identifying
173089Swyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
183089Swyllys  *
193089Swyllys  * CDDL HEADER END
203089Swyllys  *
21*5051Swyllys  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
223089Swyllys  * Use is subject to license terms.
233089Swyllys  */
243089Swyllys 
253089Swyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
263089Swyllys 
273089Swyllys #include <stdio.h>
283089Swyllys #include <strings.h>
293089Swyllys #include <ctype.h>
303089Swyllys #include <libgen.h>
313089Swyllys #include <libintl.h>
323089Swyllys #include <errno.h>
333089Swyllys #include <kmfapiP.h>
343089Swyllys #include <cryptoutil.h>
353089Swyllys #include "util.h"
363089Swyllys 
373089Swyllys int
383089Swyllys kc_create(int argc, char *argv[])
393089Swyllys {
403089Swyllys 	KMF_RETURN	ret;
413089Swyllys 	int 		rv = KC_OK;
423089Swyllys 	int		opt;
433089Swyllys 	extern int	optind_av;
443089Swyllys 	extern char	*optarg_av;
453089Swyllys 	char		*filename = NULL;
463089Swyllys 	int		ocsp_set_attr = 0;
473089Swyllys 	boolean_t	crl_set_attr = 0;
483089Swyllys 	KMF_POLICY_RECORD plc;
493089Swyllys 
503089Swyllys 	(void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
513089Swyllys 
523089Swyllys 	while ((opt = getopt_av(argc, argv,
53*5051Swyllys 	    "i:(dbfile)"
54*5051Swyllys 	    "p:(policy)"
55*5051Swyllys 	    "d:(ignore-date)"
56*5051Swyllys 	    "e:(ignore-unknown-eku)"
57*5051Swyllys 	    "a:(ignore-trust-anchor)"
58*5051Swyllys 	    "v:(validity-adjusttime)"
59*5051Swyllys 	    "t:(ta-name)"
60*5051Swyllys 	    "s:(ta-serial)"
61*5051Swyllys 	    "o:(ocsp-responder)"
62*5051Swyllys 	    "P:(ocsp-proxy)"
63*5051Swyllys 	    "r:(ocsp-use-cert-responder)"
64*5051Swyllys 	    "T:(ocsp-response-lifetime)"
65*5051Swyllys 	    "R:(ocsp-ignore-response-sign)"
66*5051Swyllys 	    "n:(ocsp-responder-cert-name)"
67*5051Swyllys 	    "A:(ocsp-responder-cert-serial)"
68*5051Swyllys 	    "c:(crl-basefilename)"
69*5051Swyllys 	    "I:(crl-directory)"
70*5051Swyllys 	    "g:(crl-get-crl-uri)"
71*5051Swyllys 	    "X:(crl-proxy)"
72*5051Swyllys 	    "S:(crl-ignore-crl-sign)"
73*5051Swyllys 	    "D:(crl-ignore-crl-date)"
74*5051Swyllys 	    "u:(keyusage)"
75*5051Swyllys 	    "E:(ekunames)"
76*5051Swyllys 	    "O:(ekuoids)")) != EOF) {
773089Swyllys 		switch (opt) {
783089Swyllys 			case 'i':
793089Swyllys 				filename = get_string(optarg_av, &rv);
803089Swyllys 				if (filename == NULL) {
813089Swyllys 					(void) fprintf(stderr,
823089Swyllys 					    gettext("Error dbfile input.\n"));
833089Swyllys 				}
843089Swyllys 				break;
853089Swyllys 			case 'p':
863089Swyllys 				plc.name = get_string(optarg_av, &rv);
873089Swyllys 				if (plc.name == NULL) {
883089Swyllys 					(void) fprintf(stderr,
893089Swyllys 					    gettext("Error policy name.\n"));
903089Swyllys 				}
913089Swyllys 				break;
923089Swyllys 			case 'd':
933089Swyllys 				plc.ignore_date = get_boolean(optarg_av);
943089Swyllys 				if (plc.ignore_date == -1) {
953089Swyllys 					(void) fprintf(stderr,
963089Swyllys 					    gettext("Error boolean input.\n"));
973089Swyllys 					rv = KC_ERR_USAGE;
983089Swyllys 				}
993089Swyllys 				break;
1003089Swyllys 			case 'e':
1013089Swyllys 				plc.ignore_unknown_ekus =
1023089Swyllys 				    get_boolean(optarg_av);
1033089Swyllys 				if (plc.ignore_unknown_ekus == -1) {
1043089Swyllys 					(void) fprintf(stderr,
1053089Swyllys 					    gettext("Error boolean input.\n"));
1063089Swyllys 					rv = KC_ERR_USAGE;
1073089Swyllys 				}
1083089Swyllys 				break;
1093089Swyllys 			case 'a':
1103089Swyllys 				plc.ignore_trust_anchor =
1113089Swyllys 				    get_boolean(optarg_av);
1123089Swyllys 				if (plc.ignore_trust_anchor == -1) {
1133089Swyllys 					(void) fprintf(stderr,
1143089Swyllys 					    gettext("Error boolean input.\n"));
1153089Swyllys 					rv = KC_ERR_USAGE;
1163089Swyllys 				}
1173089Swyllys 				break;
1183089Swyllys 			case 'v':
1193089Swyllys 				plc.validity_adjusttime =
1203089Swyllys 				    get_string(optarg_av, &rv);
1213089Swyllys 				if (plc.validity_adjusttime == NULL) {
1223089Swyllys 					(void) fprintf(stderr,
1233089Swyllys 					    gettext("Error time input.\n"));
1243089Swyllys 				} else {
1253089Swyllys 					uint32_t adj;
1263089Swyllys 					/* for syntax checking */
1273089Swyllys 					if (str2lifetime(
1283089Swyllys 					    plc.validity_adjusttime,
1293089Swyllys 					    &adj) < 0) {
1303089Swyllys 						(void) fprintf(stderr,
1313089Swyllys 						    gettext("Error time "
1323089Swyllys 						    "input.\n"));
1333089Swyllys 						rv = KC_ERR_USAGE;
1343089Swyllys 					}
1353089Swyllys 				}
1363089Swyllys 				break;
1373089Swyllys 			case 't':
1383089Swyllys 				plc.ta_name = get_string(optarg_av, &rv);
1393089Swyllys 				if (plc.ta_name == NULL) {
1403089Swyllys 					(void) fprintf(stderr,
1413089Swyllys 					    gettext("Error name input.\n"));
1423089Swyllys 				} else {
1433089Swyllys 					KMF_X509_NAME taDN;
1443089Swyllys 					/* for syntax checking */
145*5051Swyllys 					if (kmf_dn_parser(plc.ta_name,
1463089Swyllys 					    &taDN) != KMF_OK) {
1473089Swyllys 						(void) fprintf(stderr,
1483089Swyllys 						    gettext("Error name "
1493089Swyllys 						    "input.\n"));
1503089Swyllys 						rv = KC_ERR_USAGE;
1513089Swyllys 					} else {
152*5051Swyllys 						kmf_free_dn(&taDN);
1533089Swyllys 					}
1543089Swyllys 				}
1553089Swyllys 				break;
1563089Swyllys 			case 's':
1573089Swyllys 				plc.ta_serial = get_string(optarg_av, &rv);
1583089Swyllys 				if (plc.ta_serial == NULL) {
1593089Swyllys 					(void) fprintf(stderr,
1603089Swyllys 					    gettext("Error serial input.\n"));
1613089Swyllys 				} else {
1623089Swyllys 					uchar_t *bytes = NULL;
1633089Swyllys 					size_t bytelen;
1643089Swyllys 
165*5051Swyllys 					ret = kmf_hexstr_to_bytes(
1663089Swyllys 					    (uchar_t *)plc.ta_serial,
1673089Swyllys 					    &bytes, &bytelen);
1683089Swyllys 					if (ret != KMF_OK || bytes == NULL) {
1693089Swyllys 						(void) fprintf(stderr,
1703089Swyllys 						    gettext("serial number "
1713089Swyllys 						    "must be specified as a "
1723089Swyllys 						    "hex number "
1733089Swyllys 						    "(ex: 0x0102030405"
1743089Swyllys 						    "ffeeddee)\n"));
1753089Swyllys 						rv = KC_ERR_USAGE;
1763089Swyllys 					}
1773089Swyllys 					if (bytes != NULL)
1783089Swyllys 						free(bytes);
1793089Swyllys 				}
1803089Swyllys 				break;
1813089Swyllys 			case 'o':
1823089Swyllys 				plc.VAL_OCSP_RESPONDER_URI =
1833089Swyllys 				    get_string(optarg_av, &rv);
1843089Swyllys 				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
1853089Swyllys 					(void) fprintf(stderr, gettext(
1863089Swyllys 					    "Error responder input.\n"));
1873089Swyllys 				} else {
1883089Swyllys 					ocsp_set_attr++;
1893089Swyllys 				}
1903089Swyllys 				break;
1913089Swyllys 			case 'P':
1923089Swyllys 				plc.VAL_OCSP_PROXY =
1933089Swyllys 				    get_string(optarg_av, &rv);
1943089Swyllys 				if (plc.VAL_OCSP_PROXY == NULL) {
1953089Swyllys 					(void) fprintf(stderr,
1963089Swyllys 					    gettext("Error proxy input.\n"));
1973089Swyllys 				} else {
1983089Swyllys 					ocsp_set_attr++;
1993089Swyllys 				}
2003089Swyllys 				break;
2013089Swyllys 			case 'r':
2023089Swyllys 				plc.VAL_OCSP_URI_FROM_CERT =
2033089Swyllys 				    get_boolean(optarg_av);
2043089Swyllys 				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
2053089Swyllys 					(void) fprintf(stderr,
2063089Swyllys 					    gettext("Error boolean input.\n"));
2073089Swyllys 					rv = KC_ERR_USAGE;
2083089Swyllys 				} else {
2093089Swyllys 					ocsp_set_attr++;
2103089Swyllys 				}
2113089Swyllys 				break;
2123089Swyllys 			case 'T':
2133089Swyllys 				plc.VAL_OCSP_RESP_LIFETIME =
2143089Swyllys 				    get_string(optarg_av, &rv);
2153089Swyllys 				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
2163089Swyllys 					(void) fprintf(stderr,
2173089Swyllys 					    gettext("Error time input.\n"));
2183089Swyllys 				} else {
2193089Swyllys 					uint32_t adj;
2203089Swyllys 					/* for syntax checking */
2213089Swyllys 					if (str2lifetime(
2223089Swyllys 					    plc.VAL_OCSP_RESP_LIFETIME,
2233089Swyllys 					    &adj) < 0) {
2243089Swyllys 						(void) fprintf(stderr,
2253089Swyllys 						    gettext("Error time "
2263089Swyllys 						    "input.\n"));
2273089Swyllys 						rv = KC_ERR_USAGE;
2283089Swyllys 					} else {
2293089Swyllys 						ocsp_set_attr++;
2303089Swyllys 					}
2313089Swyllys 				}
2323089Swyllys 				break;
2333089Swyllys 			case 'R':
2343089Swyllys 				plc.VAL_OCSP_IGNORE_RESP_SIGN =
2353089Swyllys 				    get_boolean(optarg_av);
2363089Swyllys 				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
2373089Swyllys 					(void) fprintf(stderr,
2383089Swyllys 					    gettext("Error boolean input.\n"));
2393089Swyllys 					rv = KC_ERR_USAGE;
2403089Swyllys 				} else {
2413089Swyllys 					ocsp_set_attr++;
2423089Swyllys 				}
2433089Swyllys 				break;
2443089Swyllys 			case 'n':
2453089Swyllys 				plc.VAL_OCSP_RESP_CERT_NAME =
2463089Swyllys 				    get_string(optarg_av, &rv);
2473089Swyllys 				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
2483089Swyllys 					(void) fprintf(stderr,
2493089Swyllys 					    gettext("Error name input.\n"));
2503089Swyllys 				} else {
2513089Swyllys 					KMF_X509_NAME respDN;
2523089Swyllys 					/* for syntax checking */
253*5051Swyllys 					if (kmf_dn_parser(
2543089Swyllys 					    plc.VAL_OCSP_RESP_CERT_NAME,
2553089Swyllys 					    &respDN) != KMF_OK) {
2563089Swyllys 						(void) fprintf(stderr,
2573089Swyllys 						    gettext("Error name "
2583089Swyllys 						    "input.\n"));
2593089Swyllys 						rv = KC_ERR_USAGE;
2603089Swyllys 					} else {
261*5051Swyllys 						kmf_free_dn(&respDN);
2623089Swyllys 						ocsp_set_attr++;
2633089Swyllys 					}
2643089Swyllys 				}
2653089Swyllys 				break;
2663089Swyllys 			case 'A':
2673089Swyllys 				plc.VAL_OCSP_RESP_CERT_SERIAL =
2683089Swyllys 				    get_string(optarg_av, &rv);
2693089Swyllys 				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
2703089Swyllys 					(void) fprintf(stderr,
2713089Swyllys 					    gettext("Error serial input.\n"));
2723089Swyllys 				} else {
2733089Swyllys 					uchar_t *bytes = NULL;
2743089Swyllys 					size_t bytelen;
2753089Swyllys 
276*5051Swyllys 					ret = kmf_hexstr_to_bytes((uchar_t *)
2773089Swyllys 					    plc.VAL_OCSP_RESP_CERT_SERIAL,
2783089Swyllys 					    &bytes, &bytelen);
2793089Swyllys 					if (ret != KMF_OK || bytes == NULL) {
2803089Swyllys 						(void) fprintf(stderr,
2813089Swyllys 						    gettext("serial number "
2823089Swyllys 						    "must be specified as a "
2833089Swyllys 						    "hex number "
2843089Swyllys 						    "(ex: 0x0102030405"
2853089Swyllys 						    "ffeeddee)\n"));
2863089Swyllys 						rv = KC_ERR_USAGE;
2873089Swyllys 						break;
2883089Swyllys 					}
2893089Swyllys 					if (bytes != NULL)
2903089Swyllys 						free(bytes);
2913089Swyllys 					ocsp_set_attr++;
2923089Swyllys 				}
2933089Swyllys 				break;
2943089Swyllys 			case 'c':
2953089Swyllys 				plc.VAL_CRL_BASEFILENAME =
2963089Swyllys 				    get_string(optarg_av, &rv);
2973089Swyllys 				if (plc.VAL_CRL_BASEFILENAME == NULL) {
2983089Swyllys 					(void) fprintf(stderr,
2993089Swyllys 					    gettext("Error boolean input.\n"));
3003089Swyllys 				} else {
3013089Swyllys 					crl_set_attr++;
3023089Swyllys 				}
3033089Swyllys 				break;
3043089Swyllys 			case 'I':
3053089Swyllys 				plc.VAL_CRL_DIRECTORY =
3063089Swyllys 				    get_string(optarg_av, &rv);
3073089Swyllys 				if (plc.VAL_CRL_DIRECTORY == NULL) {
3083089Swyllys 					(void) fprintf(stderr,
3093089Swyllys 					    gettext("Error boolean input.\n"));
3103089Swyllys 				} else {
3113089Swyllys 					crl_set_attr++;
3123089Swyllys 				}
3133089Swyllys 				break;
3143089Swyllys 			case 'g':
3153089Swyllys 				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
3163089Swyllys 				if (plc.VAL_CRL_GET_URI == -1) {
3173089Swyllys 					(void) fprintf(stderr,
3183089Swyllys 					    gettext("Error boolean input.\n"));
3193089Swyllys 					rv = KC_ERR_USAGE;
3203089Swyllys 				} else {
3213089Swyllys 					crl_set_attr++;
3223089Swyllys 				}
3233089Swyllys 				break;
3243089Swyllys 			case 'X':
3253089Swyllys 				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
3263089Swyllys 				if (plc.VAL_CRL_PROXY == NULL) {
3273089Swyllys 					(void) fprintf(stderr,
3283089Swyllys 					    gettext("Error proxy input.\n"));
3293089Swyllys 				} else {
3303089Swyllys 					crl_set_attr++;
3313089Swyllys 				}
3323089Swyllys 				break;
3333089Swyllys 			case 'S':
3343089Swyllys 				plc.VAL_CRL_IGNORE_SIGN =
3353089Swyllys 				    get_boolean(optarg_av);
3363089Swyllys 				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
3373089Swyllys 					(void) fprintf(stderr,
3383089Swyllys 					    gettext("Error boolean input.\n"));
3393089Swyllys 					rv = KC_ERR_USAGE;
3403089Swyllys 				} else {
3413089Swyllys 					crl_set_attr++;
3423089Swyllys 				}
3433089Swyllys 				break;
3443089Swyllys 			case 'D':
3453089Swyllys 				plc.VAL_CRL_IGNORE_DATE =
346*5051Swyllys 				    get_boolean(optarg_av);
3473089Swyllys 				if (plc.VAL_CRL_IGNORE_DATE == -1) {
3483089Swyllys 					(void) fprintf(stderr,
3493089Swyllys 					    gettext("Error boolean input.\n"));
3503089Swyllys 					rv = KC_ERR_USAGE;
3513089Swyllys 				} else {
3523089Swyllys 					crl_set_attr++;
3533089Swyllys 				}
3543089Swyllys 				break;
3553089Swyllys 			case 'u':
3563089Swyllys 				plc.ku_bits = parseKUlist(optarg_av);
3573089Swyllys 				if (plc.ku_bits == 0) {
3583089Swyllys 					(void) fprintf(stderr, gettext(
3593089Swyllys 					    "Error keyusage input.\n"));
3603089Swyllys 					rv = KC_ERR_USAGE;
3613089Swyllys 				}
3623089Swyllys 				break;
3633089Swyllys 			case 'E':
3643089Swyllys 				if (parseEKUNames(optarg_av, &plc) != 0) {
3653089Swyllys 					(void) fprintf(stderr,
3663089Swyllys 					    gettext("Error EKU input.\n"));
3673089Swyllys 					rv = KC_ERR_USAGE;
3683089Swyllys 				}
3693089Swyllys 				break;
3703089Swyllys 			case 'O':
3713089Swyllys 				if (parseEKUOIDs(optarg_av, &plc) != 0) {
3723089Swyllys 					(void) fprintf(stderr,
3733089Swyllys 					    gettext("Error EKU OID input.\n"));
3743089Swyllys 					rv = KC_ERR_USAGE;
3753089Swyllys 				}
3763089Swyllys 				break;
3773089Swyllys 			default:
3783089Swyllys 				(void) fprintf(stderr,
3793089Swyllys 				    gettext("Error input option.\n"));
3803089Swyllys 				rv = KC_ERR_USAGE;
3813089Swyllys 				break;
3823089Swyllys 		}
3833089Swyllys 
3843089Swyllys 		if (rv != KC_OK)
3853089Swyllys 			goto out;
3863089Swyllys 	}
3873089Swyllys 
3883089Swyllys 	/* No additional args allowed. */
3893089Swyllys 	argc -= optind_av;
3903089Swyllys 	if (argc) {
3913089Swyllys 		(void) fprintf(stderr,
3923089Swyllys 		    gettext("Error input option\n"));
3933089Swyllys 		rv = KC_ERR_USAGE;
3943089Swyllys 		goto out;
3953089Swyllys 	}
3963089Swyllys 
3973089Swyllys 	if (filename == NULL) {
3983089Swyllys 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
3993089Swyllys 		if (filename == NULL) {
4003089Swyllys 			rv = KC_ERR_MEMORY;
4013089Swyllys 			goto out;
4023089Swyllys 		}
4033089Swyllys 	}
4043089Swyllys 
4053089Swyllys 	/*
4063089Swyllys 	 * Must have a policy name. The policy name can not be default
4073089Swyllys 	 * if using the default policy file.
4083089Swyllys 	 */
4093089Swyllys 	if (plc.name == NULL) {
4103089Swyllys 		(void) fprintf(stderr,
4113089Swyllys 		    gettext("You must specify a policy name\n"));
4123089Swyllys 		rv = KC_ERR_USAGE;
4133089Swyllys 		goto out;
4143089Swyllys 	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
4153089Swyllys 	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
4163089Swyllys 		(void) fprintf(stderr,
4173089Swyllys 		    gettext("Can not create a default policy in the default "
4183089Swyllys 		    "policy file\n"));
4193089Swyllys 		rv = KC_ERR_USAGE;
4203089Swyllys 		goto out;
4213089Swyllys 	}
4223089Swyllys 
4233089Swyllys 	/*
4243089Swyllys 	 * If the policy file exists and the policy is in the policy file
4253089Swyllys 	 * already, we will not create it again.
4263089Swyllys 	 */
4273089Swyllys 	if (access(filename, R_OK) == 0) {
4283089Swyllys 		POLICY_LIST *plclist = NULL, *pnode;
4293089Swyllys 		int found = 0;
4303089Swyllys 
4313089Swyllys 		rv = load_policies(filename, &plclist);
4323089Swyllys 		if (rv != KMF_OK)
4333089Swyllys 			goto out;
4343089Swyllys 
4353089Swyllys 		pnode = plclist;
4363089Swyllys 		while (pnode != NULL && !found) {
4373089Swyllys 			if (strcmp(plc.name, pnode->plc.name) == 0)
4383089Swyllys 				found++;
4393089Swyllys 			pnode = pnode->next;
4403089Swyllys 		}
4413089Swyllys 		free_policy_list(plclist);
4423089Swyllys 
4433089Swyllys 		if (found) {
4443089Swyllys 			(void) fprintf(stderr,
4453089Swyllys 			    gettext("Could not create policy \"%s\" - exists "
4463089Swyllys 			    "already\n"), plc.name);
4473089Swyllys 			rv = KC_ERR_USAGE;
4483089Swyllys 			goto out;
4493089Swyllys 		}
4503089Swyllys 	}
4513089Swyllys 
4523089Swyllys 	/*
4533089Swyllys 	 * If any OCSP attribute is set, turn on the OCSP checking flag.
4543089Swyllys 	 * Also set "has_resp_cert" to be true, if the responder cert
4553089Swyllys 	 * is provided.
4563089Swyllys 	 */
4573089Swyllys 	if (ocsp_set_attr > 0)
4583089Swyllys 		plc.revocation |= KMF_REVOCATION_METHOD_OCSP;
4593089Swyllys 
4603089Swyllys 	if (plc.VAL_OCSP_RESP_CERT.name != NULL &&
4613089Swyllys 	    plc.VAL_OCSP_RESP_CERT.serial != NULL) {
4623089Swyllys 		plc.VAL_OCSP.has_resp_cert = B_TRUE;
4633089Swyllys 	}
4643089Swyllys 
4653089Swyllys 	/*
4663089Swyllys 	 * If any CRL attribute is set, turn on the CRL checking flag.
4673089Swyllys 	 */
4683089Swyllys 	if (crl_set_attr > 0)
4693089Swyllys 		plc.revocation |= KMF_REVOCATION_METHOD_CRL;
4703089Swyllys 
4713089Swyllys 	/*
4723089Swyllys 	 * Does a sanity check on the new policy.
4733089Swyllys 	 */
474*5051Swyllys 	ret = kmf_verify_policy(&plc);
4753089Swyllys 	if (ret != KMF_OK) {
4763089Swyllys 		print_sanity_error(ret);
4773089Swyllys 		rv = KC_ERR_ADD_POLICY;
4783089Swyllys 		goto out;
4793089Swyllys 	}
4803089Swyllys 
4813089Swyllys 	/*
4823089Swyllys 	 * Add to the DB.
4833089Swyllys 	 */
484*5051Swyllys 	ret = kmf_add_policy_to_db(&plc, filename, B_FALSE);
4853089Swyllys 	if (ret != KMF_OK) {
4863089Swyllys 		(void) fprintf(stderr,
4873089Swyllys 		    gettext("Error adding policy to database: 0x%04x\n"), ret);
4883089Swyllys 		rv = KC_ERR_ADD_POLICY;
4893089Swyllys 	}
4903089Swyllys 
4913089Swyllys out:
4923089Swyllys 	if (filename != NULL)
4933089Swyllys 		free(filename);
4943089Swyllys 
495*5051Swyllys 	kmf_free_policy_record(&plc);
4963089Swyllys 
4973089Swyllys 	return (rv);
4983089Swyllys }
499