xref: /titanic_51/usr/src/cmd/cmd-crypto/kmfcfg/modify.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 #define	KC_IGNORE_DATE			0x0000001
3899ebb4caSwyllys #define	KC_IGNORE_UNKNOWN_EKUS		0x0000002
3999ebb4caSwyllys #define	KC_IGNORE_TRUST_ANCHOR		0x0000004
4099ebb4caSwyllys #define	KC_VALIDITY_ADJUSTTIME		0x0000008
4199ebb4caSwyllys #define	KC_TA_NAME			0x0000010
4299ebb4caSwyllys #define	KC_TA_SERIAL			0x0000020
4399ebb4caSwyllys #define	KC_OCSP_RESPONDER_URI		0x0000040
4499ebb4caSwyllys #define	KC_OCSP_PROXY			0x0000080
4599ebb4caSwyllys #define	KC_OCSP_URI_FROM_CERT		0x0000100
4699ebb4caSwyllys #define	KC_OCSP_RESP_LIFETIME		0x0000200
4799ebb4caSwyllys #define	KC_OCSP_IGNORE_RESP_SIGN 	0x0000400
4899ebb4caSwyllys #define	KC_OCSP_RESP_CERT_NAME		0x0000800
4999ebb4caSwyllys #define	KC_OCSP_RESP_CERT_SERIAL	0x0001000
5099ebb4caSwyllys #define	KC_OCSP_NONE			0x0002000
5199ebb4caSwyllys #define	KC_CRL_BASEFILENAME		0x0004000
5299ebb4caSwyllys #define	KC_CRL_DIRECTORY		0x0008000
5399ebb4caSwyllys #define	KC_CRL_GET_URI			0x0010000
5499ebb4caSwyllys #define	KC_CRL_PROXY			0x0020000
5599ebb4caSwyllys #define	KC_CRL_IGNORE_SIGN		0x0040000
5699ebb4caSwyllys #define	KC_CRL_IGNORE_DATE		0x0080000
5799ebb4caSwyllys #define	KC_CRL_NONE			0x0100000
5899ebb4caSwyllys #define	KC_KEYUSAGE			0x0200000
5999ebb4caSwyllys #define	KC_KEYUSAGE_NONE		0x0400000
6099ebb4caSwyllys #define	KC_EKUS				0x0800000
6199ebb4caSwyllys #define	KC_EKUS_NONE			0x1000000
6299ebb4caSwyllys 
6399ebb4caSwyllys int
6499ebb4caSwyllys kc_modify(int argc, char *argv[])
6599ebb4caSwyllys {
6699ebb4caSwyllys 	KMF_RETURN	ret;
6799ebb4caSwyllys 	int 		rv = KC_OK;
6899ebb4caSwyllys 	int		opt;
6999ebb4caSwyllys 	extern int	optind_av;
7099ebb4caSwyllys 	extern char	*optarg_av;
7199ebb4caSwyllys 	char		*filename = NULL;
7299ebb4caSwyllys 	uint32_t	flags = 0;
7399ebb4caSwyllys 	boolean_t	ocsp_none_opt = B_FALSE;
7499ebb4caSwyllys 	boolean_t	crl_none_opt = B_FALSE;
7599ebb4caSwyllys 	boolean_t	ku_none_opt = B_FALSE;
7699ebb4caSwyllys 	boolean_t	eku_none_opt = B_FALSE;
7799ebb4caSwyllys 	int		ocsp_set_attr = 0;
7899ebb4caSwyllys 	int		crl_set_attr = 0;
7999ebb4caSwyllys 	KMF_POLICY_RECORD oplc, plc;
8099ebb4caSwyllys 
8199ebb4caSwyllys 	(void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
8299ebb4caSwyllys 	(void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD));
8399ebb4caSwyllys 
8499ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
8599ebb4caSwyllys 	    "i:(dbfile)"
8699ebb4caSwyllys 	    "p:(policy)"
8799ebb4caSwyllys 	    "d:(ignore-date)"
8899ebb4caSwyllys 	    "e:(ignore-unknown-eku)"
8999ebb4caSwyllys 	    "a:(ignore-trust-anchor)"
9099ebb4caSwyllys 	    "v:(validity-adjusttime)"
9199ebb4caSwyllys 	    "t:(ta-name)"
9299ebb4caSwyllys 	    "s:(ta-serial)"
9399ebb4caSwyllys 	    "o:(ocsp-responder)"
9499ebb4caSwyllys 	    "P:(ocsp-proxy)"
9599ebb4caSwyllys 	    "r:(ocsp-use-cert-responder)"
9699ebb4caSwyllys 	    "T:(ocsp-response-lifetime)"
9799ebb4caSwyllys 	    "R:(ocsp-ignore-response-sign)"
9899ebb4caSwyllys 	    "n:(ocsp-responder-cert-name)"
9999ebb4caSwyllys 	    "A:(ocsp-responder-cert-serial)"
10099ebb4caSwyllys 	    "y:(ocsp-none)"
10199ebb4caSwyllys 	    "c:(crl-basefilename)"
10299ebb4caSwyllys 	    "I:(crl-directory)"
10399ebb4caSwyllys 	    "g:(crl-get-crl-uri)"
10499ebb4caSwyllys 	    "X:(crl-proxy)"
10599ebb4caSwyllys 	    "S:(crl-ignore-crl-sign)"
10699ebb4caSwyllys 	    "D:(crl-ignore-crl-date)"
10799ebb4caSwyllys 	    "z:(crl-none)"
10899ebb4caSwyllys 	    "u:(keyusage)"
10999ebb4caSwyllys 	    "Y:(keyusage-none)"
11099ebb4caSwyllys 	    "E:(ekunames)"
11199ebb4caSwyllys 	    "O:(ekuoids)"
11299ebb4caSwyllys 	    "Z:(eku-none)")) != EOF) {
11399ebb4caSwyllys 		switch (opt) {
11499ebb4caSwyllys 			case 'i':
11599ebb4caSwyllys 				filename = get_string(optarg_av, &rv);
11699ebb4caSwyllys 				if (filename == NULL) {
11799ebb4caSwyllys 					(void) fprintf(stderr,
11899ebb4caSwyllys 					    gettext("Error dbfile input.\n"));
11999ebb4caSwyllys 				}
12099ebb4caSwyllys 				break;
12199ebb4caSwyllys 			case 'p':
12299ebb4caSwyllys 				plc.name = get_string(optarg_av, &rv);
12399ebb4caSwyllys 				if (plc.name == NULL) {
12499ebb4caSwyllys 					(void) fprintf(stderr,
12599ebb4caSwyllys 					    gettext("Error policy name.\n"));
12699ebb4caSwyllys 				}
12799ebb4caSwyllys 				break;
12899ebb4caSwyllys 			case 'd':
12999ebb4caSwyllys 				plc.ignore_date = get_boolean(optarg_av);
13099ebb4caSwyllys 				if (plc.ignore_date == -1) {
13199ebb4caSwyllys 					(void) fprintf(stderr,
13299ebb4caSwyllys 					    gettext("Error boolean input.\n"));
13399ebb4caSwyllys 					rv = KC_ERR_USAGE;
13499ebb4caSwyllys 				} else {
13599ebb4caSwyllys 					flags |= KC_IGNORE_DATE;
13699ebb4caSwyllys 				}
13799ebb4caSwyllys 				break;
13899ebb4caSwyllys 			case 'e':
13999ebb4caSwyllys 				plc.ignore_unknown_ekus =
14099ebb4caSwyllys 				    get_boolean(optarg_av);
14199ebb4caSwyllys 				if (plc.ignore_unknown_ekus == -1) {
14299ebb4caSwyllys 					(void) fprintf(stderr,
14399ebb4caSwyllys 					    gettext("Error boolean input.\n"));
14499ebb4caSwyllys 					rv = KC_ERR_USAGE;
14599ebb4caSwyllys 				} else {
14699ebb4caSwyllys 					flags |= KC_IGNORE_UNKNOWN_EKUS;
14799ebb4caSwyllys 				}
14899ebb4caSwyllys 				break;
14999ebb4caSwyllys 			case 'a':
15099ebb4caSwyllys 				plc.ignore_trust_anchor =
15199ebb4caSwyllys 				    get_boolean(optarg_av);
15299ebb4caSwyllys 				if (plc.ignore_trust_anchor == -1) {
15399ebb4caSwyllys 					(void) fprintf(stderr,
15499ebb4caSwyllys 					    gettext("Error boolean input.\n"));
15599ebb4caSwyllys 					rv = KC_ERR_USAGE;
15699ebb4caSwyllys 				} else {
15799ebb4caSwyllys 					flags |= KC_IGNORE_TRUST_ANCHOR;
15899ebb4caSwyllys 				}
15999ebb4caSwyllys 				break;
16099ebb4caSwyllys 			case 'v':
16199ebb4caSwyllys 				plc.validity_adjusttime =
16299ebb4caSwyllys 				    get_string(optarg_av, &rv);
16399ebb4caSwyllys 				if (plc.validity_adjusttime == NULL) {
16499ebb4caSwyllys 					(void) fprintf(stderr,
16599ebb4caSwyllys 					    gettext("Error time input.\n"));
16699ebb4caSwyllys 				} else {
16799ebb4caSwyllys 					uint32_t adj;
16899ebb4caSwyllys 					/* for syntax checking */
16999ebb4caSwyllys 					if (str2lifetime(
17099ebb4caSwyllys 					    plc.validity_adjusttime,
17199ebb4caSwyllys 					    &adj) < 0) {
17299ebb4caSwyllys 						(void) fprintf(stderr,
17399ebb4caSwyllys 						    gettext("Error time "
17499ebb4caSwyllys 						    "input.\n"));
17599ebb4caSwyllys 						rv = KC_ERR_USAGE;
17699ebb4caSwyllys 					} else {
17799ebb4caSwyllys 						flags |= KC_VALIDITY_ADJUSTTIME;
17899ebb4caSwyllys 					}
17999ebb4caSwyllys 				}
18099ebb4caSwyllys 				break;
18199ebb4caSwyllys 			case 't':
18299ebb4caSwyllys 				plc.ta_name = get_string(optarg_av, &rv);
18399ebb4caSwyllys 				if (plc.ta_name == NULL) {
18499ebb4caSwyllys 					(void) fprintf(stderr,
18599ebb4caSwyllys 					    gettext("Error name input.\n"));
18699ebb4caSwyllys 				} else {
18799ebb4caSwyllys 					KMF_X509_NAME taDN;
18899ebb4caSwyllys 					/* for syntax checking */
189*30a5e8faSwyllys 					if (kmf_dn_parser(plc.ta_name,
19099ebb4caSwyllys 					    &taDN) != KMF_OK) {
19199ebb4caSwyllys 						(void) fprintf(stderr,
19299ebb4caSwyllys 						    gettext("Error name "
19399ebb4caSwyllys 						    "input.\n"));
19499ebb4caSwyllys 						rv = KC_ERR_USAGE;
19599ebb4caSwyllys 					} else {
196*30a5e8faSwyllys 						kmf_free_dn(&taDN);
19799ebb4caSwyllys 						flags |= KC_TA_NAME;
19899ebb4caSwyllys 					}
19999ebb4caSwyllys 				}
20099ebb4caSwyllys 				break;
20199ebb4caSwyllys 			case 's':
20299ebb4caSwyllys 				plc.ta_serial = get_string(optarg_av, &rv);
20399ebb4caSwyllys 				if (plc.ta_serial == NULL) {
20499ebb4caSwyllys 					(void) fprintf(stderr,
20599ebb4caSwyllys 					    gettext("Error serial input.\n"));
20699ebb4caSwyllys 				} else {
20799ebb4caSwyllys 					uchar_t *bytes = NULL;
20899ebb4caSwyllys 					size_t bytelen;
20999ebb4caSwyllys 
210*30a5e8faSwyllys 					ret = kmf_hexstr_to_bytes(
21199ebb4caSwyllys 					    (uchar_t *)plc.ta_serial,
21299ebb4caSwyllys 					    &bytes, &bytelen);
21399ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
21499ebb4caSwyllys 						(void) fprintf(stderr,
21599ebb4caSwyllys 						    gettext("serial number "
21699ebb4caSwyllys 						    "must be specified as a "
21799ebb4caSwyllys 						    "hex number "
21899ebb4caSwyllys 						    "(ex: 0x0102030405"
21999ebb4caSwyllys 						    "ffeeddee)\n"));
22099ebb4caSwyllys 						rv = KC_ERR_USAGE;
22199ebb4caSwyllys 						break;
22299ebb4caSwyllys 					}
22399ebb4caSwyllys 					if (bytes != NULL)
22499ebb4caSwyllys 						free(bytes);
22599ebb4caSwyllys 					flags |= KC_TA_SERIAL;
22699ebb4caSwyllys 				}
22799ebb4caSwyllys 				break;
22899ebb4caSwyllys 			case 'o':
22999ebb4caSwyllys 				plc.VAL_OCSP_RESPONDER_URI =
23099ebb4caSwyllys 				    get_string(optarg_av, &rv);
23199ebb4caSwyllys 				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
23299ebb4caSwyllys 					(void) fprintf(stderr,
23399ebb4caSwyllys 					    gettext("Error responder "
23499ebb4caSwyllys 					    "input.\n"));
23599ebb4caSwyllys 				} else {
23699ebb4caSwyllys 					flags |= KC_OCSP_RESPONDER_URI;
23799ebb4caSwyllys 					ocsp_set_attr++;
23899ebb4caSwyllys 				}
23999ebb4caSwyllys 				break;
24099ebb4caSwyllys 			case 'P':
24199ebb4caSwyllys 				plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
24299ebb4caSwyllys 				if (plc.VAL_OCSP_PROXY == NULL) {
24399ebb4caSwyllys 					(void) fprintf(stderr,
24499ebb4caSwyllys 					    gettext("Error proxy input.\n"));
24599ebb4caSwyllys 				} else {
24699ebb4caSwyllys 					flags |= KC_OCSP_PROXY;
24799ebb4caSwyllys 					ocsp_set_attr++;
24899ebb4caSwyllys 				}
24999ebb4caSwyllys 				break;
25099ebb4caSwyllys 			case 'r':
25199ebb4caSwyllys 				plc.VAL_OCSP_URI_FROM_CERT =
25299ebb4caSwyllys 				    get_boolean(optarg_av);
25399ebb4caSwyllys 				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
25499ebb4caSwyllys 					(void) fprintf(stderr,
25599ebb4caSwyllys 					    gettext("Error boolean input.\n"));
25699ebb4caSwyllys 					rv = KC_ERR_USAGE;
25799ebb4caSwyllys 				} else {
25899ebb4caSwyllys 					flags |= KC_OCSP_URI_FROM_CERT;
25999ebb4caSwyllys 					ocsp_set_attr++;
26099ebb4caSwyllys 				}
26199ebb4caSwyllys 				break;
26299ebb4caSwyllys 			case 'T':
26399ebb4caSwyllys 				plc.VAL_OCSP_RESP_LIFETIME =
26499ebb4caSwyllys 				    get_string(optarg_av, &rv);
26599ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
26699ebb4caSwyllys 					(void) fprintf(stderr,
26799ebb4caSwyllys 					    gettext("Error time input.\n"));
26899ebb4caSwyllys 				} else {
26999ebb4caSwyllys 					uint32_t adj;
27099ebb4caSwyllys 					/* for syntax checking */
27199ebb4caSwyllys 					if (str2lifetime(
27299ebb4caSwyllys 					    plc.VAL_OCSP_RESP_LIFETIME,
27399ebb4caSwyllys 					    &adj) < 0) {
27499ebb4caSwyllys 						(void) fprintf(stderr,
27599ebb4caSwyllys 						    gettext("Error time "
27699ebb4caSwyllys 						    "input.\n"));
27799ebb4caSwyllys 						rv = KC_ERR_USAGE;
27899ebb4caSwyllys 					} else {
27999ebb4caSwyllys 						flags |= KC_OCSP_RESP_LIFETIME;
28099ebb4caSwyllys 						ocsp_set_attr++;
28199ebb4caSwyllys 					}
28299ebb4caSwyllys 				}
28399ebb4caSwyllys 				break;
28499ebb4caSwyllys 			case 'R':
28599ebb4caSwyllys 				plc.VAL_OCSP_IGNORE_RESP_SIGN =
28699ebb4caSwyllys 				    get_boolean(optarg_av);
28799ebb4caSwyllys 				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
28899ebb4caSwyllys 					(void) fprintf(stderr,
28999ebb4caSwyllys 					    gettext("Error boolean input.\n"));
29099ebb4caSwyllys 					rv = KC_ERR_USAGE;
29199ebb4caSwyllys 				} else {
29299ebb4caSwyllys 					flags |= KC_OCSP_IGNORE_RESP_SIGN;
29399ebb4caSwyllys 					ocsp_set_attr++;
29499ebb4caSwyllys 				}
29599ebb4caSwyllys 				break;
29699ebb4caSwyllys 			case 'n':
29799ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_NAME =
29899ebb4caSwyllys 				    get_string(optarg_av, &rv);
29999ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
30099ebb4caSwyllys 					(void) fprintf(stderr,
30199ebb4caSwyllys 					    gettext("Error name input.\n"));
30299ebb4caSwyllys 				} else {
30399ebb4caSwyllys 					KMF_X509_NAME respDN;
30499ebb4caSwyllys 					/* for syntax checking */
305*30a5e8faSwyllys 					if (kmf_dn_parser(
30699ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_NAME,
30799ebb4caSwyllys 					    &respDN) != KMF_OK) {
30899ebb4caSwyllys 						(void) fprintf(stderr,
30999ebb4caSwyllys 						    gettext("Error name "
31099ebb4caSwyllys 						    "input.\n"));
31199ebb4caSwyllys 						rv = KC_ERR_USAGE;
31299ebb4caSwyllys 					} else {
313*30a5e8faSwyllys 						kmf_free_dn(&respDN);
31499ebb4caSwyllys 						flags |= KC_OCSP_RESP_CERT_NAME;
31599ebb4caSwyllys 						ocsp_set_attr++;
31699ebb4caSwyllys 					}
31799ebb4caSwyllys 				}
31899ebb4caSwyllys 				break;
31999ebb4caSwyllys 			case 'A':
32099ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_SERIAL =
32199ebb4caSwyllys 				    get_string(optarg_av, &rv);
32299ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
32399ebb4caSwyllys 					(void) fprintf(stderr,
32499ebb4caSwyllys 					    gettext("Error serial input.\n"));
32599ebb4caSwyllys 				} else {
32699ebb4caSwyllys 					uchar_t *bytes = NULL;
32799ebb4caSwyllys 					size_t bytelen;
32899ebb4caSwyllys 
329*30a5e8faSwyllys 					ret = kmf_hexstr_to_bytes((uchar_t *)
33099ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_SERIAL,
33199ebb4caSwyllys 					    &bytes, &bytelen);
33299ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
33399ebb4caSwyllys 						(void) fprintf(stderr,
33499ebb4caSwyllys 						    gettext("serial number "
33599ebb4caSwyllys 						    "must be specified as a "
33699ebb4caSwyllys 						    "hex number "
33799ebb4caSwyllys 						    "(ex: 0x0102030405"
33899ebb4caSwyllys 						    "ffeeddee)\n"));
33999ebb4caSwyllys 						rv = KC_ERR_USAGE;
34099ebb4caSwyllys 						break;
34199ebb4caSwyllys 					}
34299ebb4caSwyllys 					if (bytes != NULL)
34399ebb4caSwyllys 						free(bytes);
34499ebb4caSwyllys 					flags |= KC_OCSP_RESP_CERT_SERIAL;
34599ebb4caSwyllys 					ocsp_set_attr++;
34699ebb4caSwyllys 				}
34799ebb4caSwyllys 				break;
34899ebb4caSwyllys 			case 'y':
34999ebb4caSwyllys 				ocsp_none_opt = get_boolean(optarg_av);
35099ebb4caSwyllys 				if (ocsp_none_opt == -1) {
35199ebb4caSwyllys 					(void) fprintf(stderr,
35299ebb4caSwyllys 					    gettext("Error boolean input.\n"));
35399ebb4caSwyllys 					rv = KC_ERR_USAGE;
35499ebb4caSwyllys 				} else {
35599ebb4caSwyllys 					flags |= KC_OCSP_NONE;
35699ebb4caSwyllys 				}
35799ebb4caSwyllys 				break;
35899ebb4caSwyllys 			case 'c':
35999ebb4caSwyllys 				plc.VAL_CRL_BASEFILENAME =
36099ebb4caSwyllys 				    get_string(optarg_av, &rv);
36199ebb4caSwyllys 				if (plc.VAL_CRL_BASEFILENAME == NULL) {
36299ebb4caSwyllys 					(void) fprintf(stderr, gettext(
36399ebb4caSwyllys 					    "Error basefilename input.\n"));
36499ebb4caSwyllys 				} else {
36599ebb4caSwyllys 					flags |= KC_CRL_BASEFILENAME;
36699ebb4caSwyllys 					crl_set_attr++;
36799ebb4caSwyllys 				}
36899ebb4caSwyllys 				break;
36999ebb4caSwyllys 			case 'I':
37099ebb4caSwyllys 				plc.VAL_CRL_DIRECTORY =
37199ebb4caSwyllys 				    get_string(optarg_av, &rv);
37299ebb4caSwyllys 				if (plc.VAL_CRL_DIRECTORY == NULL) {
37399ebb4caSwyllys 					(void) fprintf(stderr,
37499ebb4caSwyllys 					    gettext("Error boolean input.\n"));
37599ebb4caSwyllys 				} else {
37699ebb4caSwyllys 					flags |= KC_CRL_DIRECTORY;
37799ebb4caSwyllys 					crl_set_attr++;
37899ebb4caSwyllys 				}
37999ebb4caSwyllys 				break;
38099ebb4caSwyllys 			case 'g':
38199ebb4caSwyllys 				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
38299ebb4caSwyllys 				if (plc.VAL_CRL_GET_URI == -1) {
38399ebb4caSwyllys 					(void) fprintf(stderr,
38499ebb4caSwyllys 					    gettext("Error boolean input.\n"));
38599ebb4caSwyllys 					rv = KC_ERR_USAGE;
38699ebb4caSwyllys 				} else {
38799ebb4caSwyllys 					flags |= KC_CRL_GET_URI;
38899ebb4caSwyllys 					crl_set_attr++;
38999ebb4caSwyllys 				}
39099ebb4caSwyllys 				break;
39199ebb4caSwyllys 			case 'X':
39299ebb4caSwyllys 				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
39399ebb4caSwyllys 				if (plc.VAL_CRL_PROXY == NULL) {
39499ebb4caSwyllys 					(void) fprintf(stderr,
39599ebb4caSwyllys 					    gettext("Error proxy input.\n"));
39699ebb4caSwyllys 				} else {
39799ebb4caSwyllys 					flags |= KC_CRL_PROXY;
39899ebb4caSwyllys 					crl_set_attr++;
39999ebb4caSwyllys 				}
40099ebb4caSwyllys 				break;
40199ebb4caSwyllys 			case 'S':
40299ebb4caSwyllys 				plc.VAL_CRL_IGNORE_SIGN =
40399ebb4caSwyllys 				    get_boolean(optarg_av);
40499ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
40599ebb4caSwyllys 					(void) fprintf(stderr,
40699ebb4caSwyllys 					    gettext("Error boolean input.\n"));
40799ebb4caSwyllys 					rv = KC_ERR_USAGE;
40899ebb4caSwyllys 				} else {
40999ebb4caSwyllys 					flags |= KC_CRL_IGNORE_SIGN;
41099ebb4caSwyllys 					crl_set_attr++;
41199ebb4caSwyllys 				}
41299ebb4caSwyllys 				break;
41399ebb4caSwyllys 			case 'D':
41499ebb4caSwyllys 				plc.VAL_CRL_IGNORE_DATE =
41599ebb4caSwyllys 				    get_boolean(optarg_av);
41699ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_DATE == -1) {
41799ebb4caSwyllys 					(void) fprintf(stderr,
41899ebb4caSwyllys 					    gettext("Error boolean input.\n"));
41999ebb4caSwyllys 					rv = KC_ERR_USAGE;
42099ebb4caSwyllys 				} else {
42199ebb4caSwyllys 					flags |= KC_CRL_IGNORE_DATE;
42299ebb4caSwyllys 					crl_set_attr++;
42399ebb4caSwyllys 				}
42499ebb4caSwyllys 				break;
42599ebb4caSwyllys 			case 'z':
42699ebb4caSwyllys 				crl_none_opt = get_boolean(optarg_av);
42799ebb4caSwyllys 				if (crl_none_opt == -1) {
42899ebb4caSwyllys 					(void) fprintf(stderr,
42999ebb4caSwyllys 					    gettext("Error boolean input.\n"));
43099ebb4caSwyllys 					rv = KC_ERR_USAGE;
43199ebb4caSwyllys 				} else {
43299ebb4caSwyllys 					flags |= KC_CRL_NONE;
43399ebb4caSwyllys 				}
43499ebb4caSwyllys 				break;
43599ebb4caSwyllys 			case 'u':
43699ebb4caSwyllys 				plc.ku_bits = parseKUlist(optarg_av);
43799ebb4caSwyllys 				if (plc.ku_bits == 0) {
43899ebb4caSwyllys 					(void) fprintf(stderr, gettext(
43999ebb4caSwyllys 					    "Error keyusage input.\n"));
44099ebb4caSwyllys 					rv = KC_ERR_USAGE;
44199ebb4caSwyllys 				} else {
44299ebb4caSwyllys 					flags |= KC_KEYUSAGE;
44399ebb4caSwyllys 				}
44499ebb4caSwyllys 				break;
44599ebb4caSwyllys 			case 'Y':
44699ebb4caSwyllys 				ku_none_opt = get_boolean(optarg_av);
44799ebb4caSwyllys 				if (ku_none_opt == -1) {
44899ebb4caSwyllys 					(void) fprintf(stderr,
44999ebb4caSwyllys 					    gettext("Error boolean input.\n"));
45099ebb4caSwyllys 					rv = KC_ERR_USAGE;
45199ebb4caSwyllys 				} else {
45299ebb4caSwyllys 					flags |= KC_KEYUSAGE_NONE;
45399ebb4caSwyllys 				}
45499ebb4caSwyllys 				break;
45599ebb4caSwyllys 			case 'E':
45699ebb4caSwyllys 				if (parseEKUNames(optarg_av, &plc) != 0) {
45799ebb4caSwyllys 					(void) fprintf(stderr,
45899ebb4caSwyllys 					    gettext("Error EKU input.\n"));
45999ebb4caSwyllys 					rv = KC_ERR_USAGE;
46099ebb4caSwyllys 				} else {
46199ebb4caSwyllys 					flags |= KC_EKUS;
46299ebb4caSwyllys 				}
46399ebb4caSwyllys 				break;
46499ebb4caSwyllys 			case 'O':
46599ebb4caSwyllys 				if (parseEKUOIDs(optarg_av, &plc) != 0) {
46699ebb4caSwyllys 					(void) fprintf(stderr,
46799ebb4caSwyllys 					    gettext("Error EKU OID input.\n"));
46899ebb4caSwyllys 					rv = KC_ERR_USAGE;
46999ebb4caSwyllys 				} else {
47099ebb4caSwyllys 					flags |= KC_EKUS;
47199ebb4caSwyllys 				}
47299ebb4caSwyllys 				break;
47399ebb4caSwyllys 			case 'Z':
47499ebb4caSwyllys 				eku_none_opt = get_boolean(optarg_av);
47599ebb4caSwyllys 				if (eku_none_opt == -1) {
47699ebb4caSwyllys 					(void) fprintf(stderr,
47799ebb4caSwyllys 					    gettext("Error boolean input.\n"));
47899ebb4caSwyllys 					rv = KC_ERR_USAGE;
47999ebb4caSwyllys 				} else {
48099ebb4caSwyllys 					flags |= KC_EKUS_NONE;
48199ebb4caSwyllys 				}
48299ebb4caSwyllys 				break;
48399ebb4caSwyllys 			default:
48499ebb4caSwyllys 				(void) fprintf(stderr,
48599ebb4caSwyllys 				    gettext("Error input option.\n"));
48699ebb4caSwyllys 				rv = KC_ERR_USAGE;
48799ebb4caSwyllys 				break;
48899ebb4caSwyllys 		}
48999ebb4caSwyllys 		if (rv != KC_OK)
49099ebb4caSwyllys 			goto out;
49199ebb4caSwyllys 	}
49299ebb4caSwyllys 
49399ebb4caSwyllys 	/* No additional args allowed. */
49499ebb4caSwyllys 	argc -= optind_av;
49599ebb4caSwyllys 	if (argc) {
49699ebb4caSwyllys 		(void) fprintf(stderr,
49799ebb4caSwyllys 		    gettext("Error input option\n"));
49899ebb4caSwyllys 		rv = KC_ERR_USAGE;
49999ebb4caSwyllys 		goto out;
50099ebb4caSwyllys 	}
50199ebb4caSwyllys 
50299ebb4caSwyllys 	if (filename == NULL) {
50399ebb4caSwyllys 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
50499ebb4caSwyllys 		if (filename == NULL) {
50599ebb4caSwyllys 			rv = KC_ERR_MEMORY;
50699ebb4caSwyllys 			goto out;
50799ebb4caSwyllys 		}
50899ebb4caSwyllys 	}
50999ebb4caSwyllys 
51099ebb4caSwyllys 	/*
51199ebb4caSwyllys 	 * Must have a policy name. The policy name can not be default
51299ebb4caSwyllys 	 * if using the default policy file.
51399ebb4caSwyllys 	 */
51499ebb4caSwyllys 	if (plc.name == NULL) {
51599ebb4caSwyllys 		(void) fprintf(stderr,
51699ebb4caSwyllys 		    gettext("You must specify a policy name.\n"));
51799ebb4caSwyllys 		rv = KC_ERR_USAGE;
51899ebb4caSwyllys 		goto out;
51999ebb4caSwyllys 	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
52099ebb4caSwyllys 	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
52199ebb4caSwyllys 		(void) fprintf(stderr,
52299ebb4caSwyllys 		    gettext("Can not modify the default policy in the default "
52399ebb4caSwyllys 		    "policy file.\n"));
52499ebb4caSwyllys 		rv = KC_ERR_USAGE;
52599ebb4caSwyllys 		goto out;
52699ebb4caSwyllys 	}
52799ebb4caSwyllys 
52899ebb4caSwyllys 	/* Check the access permission of the policy DB */
52999ebb4caSwyllys 	if (access(filename, W_OK) < 0) {
53099ebb4caSwyllys 		int err = errno;
53199ebb4caSwyllys 		(void) fprintf(stderr,
53299ebb4caSwyllys 		    gettext("Cannot access \"%s\" for modify - %s\n"),
53399ebb4caSwyllys 		    filename, strerror(err));
53499ebb4caSwyllys 		rv = KC_ERR_ACCESS;
53599ebb4caSwyllys 		goto out;
53699ebb4caSwyllys 	}
53799ebb4caSwyllys 
53899ebb4caSwyllys 	/* Try to load the named policy from the DB */
539*30a5e8faSwyllys 	ret = kmf_get_policy(filename, plc.name, &oplc);
54099ebb4caSwyllys 	if (ret != KMF_OK) {
54199ebb4caSwyllys 		(void) fprintf(stderr,
54299ebb4caSwyllys 		    gettext("Error loading policy \"%s\" from %s\n"), filename,
54399ebb4caSwyllys 		    plc.name);
54499ebb4caSwyllys 		return (KC_ERR_FIND_POLICY);
54599ebb4caSwyllys 	}
54699ebb4caSwyllys 
54799ebb4caSwyllys 	/* Update the general policy attributes. */
54899ebb4caSwyllys 	if (flags & KC_IGNORE_DATE)
54999ebb4caSwyllys 		oplc.ignore_date = plc.ignore_date;
55099ebb4caSwyllys 
55199ebb4caSwyllys 	if (flags & KC_IGNORE_UNKNOWN_EKUS)
55299ebb4caSwyllys 		oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
55399ebb4caSwyllys 
55499ebb4caSwyllys 	if (flags & KC_IGNORE_TRUST_ANCHOR)
55599ebb4caSwyllys 		oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
55699ebb4caSwyllys 
55799ebb4caSwyllys 	if (flags & KC_VALIDITY_ADJUSTTIME) {
55899ebb4caSwyllys 		if (oplc.validity_adjusttime)
55999ebb4caSwyllys 			free(oplc.validity_adjusttime);
56099ebb4caSwyllys 		oplc.validity_adjusttime =
56199ebb4caSwyllys 		    plc.validity_adjusttime;
56299ebb4caSwyllys 	}
56399ebb4caSwyllys 
56499ebb4caSwyllys 	if (flags & KC_TA_NAME) {
56599ebb4caSwyllys 		if (oplc.ta_name)
56699ebb4caSwyllys 			free(oplc.ta_name);
56799ebb4caSwyllys 		oplc.ta_name = plc.ta_name;
56899ebb4caSwyllys 	}
56999ebb4caSwyllys 	if (flags & KC_TA_SERIAL) {
57099ebb4caSwyllys 		if (oplc.ta_serial)
57199ebb4caSwyllys 			free(oplc.ta_serial);
57299ebb4caSwyllys 		oplc.ta_serial = plc.ta_serial;
57399ebb4caSwyllys 	}
57499ebb4caSwyllys 
57599ebb4caSwyllys 	/* Update the OCSP policy */
57699ebb4caSwyllys 	if (ocsp_none_opt == B_TRUE) {
57799ebb4caSwyllys 		if (ocsp_set_attr > 0) {
57899ebb4caSwyllys 			(void) fprintf(stderr,
57999ebb4caSwyllys 			    gettext("Can not set ocsp-none=true and other "
58099ebb4caSwyllys 			    "OCSP attributes at the same time.\n"));
58199ebb4caSwyllys 			rv = KC_ERR_USAGE;
58299ebb4caSwyllys 			goto out;
58399ebb4caSwyllys 		}
58499ebb4caSwyllys 
58599ebb4caSwyllys 		/*
58699ebb4caSwyllys 		 * If the original policy does not have OCSP checking,
58799ebb4caSwyllys 		 * then we do not need to do anything.  If the original
58899ebb4caSwyllys 		 * policy has the OCSP checking, then we need to release the
58999ebb4caSwyllys 		 * space of OCSP attributes and turn the OCSP checking off.
59099ebb4caSwyllys 		 */
59199ebb4caSwyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
59299ebb4caSwyllys 			if (oplc.VAL_OCSP_BASIC.responderURI) {
59399ebb4caSwyllys 				free(oplc.VAL_OCSP_BASIC.responderURI);
59499ebb4caSwyllys 				oplc.VAL_OCSP_BASIC.responderURI = NULL;
59599ebb4caSwyllys 			}
59699ebb4caSwyllys 
59799ebb4caSwyllys 			if (oplc.VAL_OCSP_BASIC.proxy) {
59899ebb4caSwyllys 				free(oplc.VAL_OCSP_BASIC.proxy);
59999ebb4caSwyllys 				oplc.VAL_OCSP_BASIC.proxy = NULL;
60099ebb4caSwyllys 			}
60199ebb4caSwyllys 
60299ebb4caSwyllys 			if (oplc.VAL_OCSP_BASIC.response_lifetime) {
60399ebb4caSwyllys 				free(oplc.VAL_OCSP_BASIC.response_lifetime);
60499ebb4caSwyllys 				oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
60599ebb4caSwyllys 			}
60699ebb4caSwyllys 
60799ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
60899ebb4caSwyllys 				free(oplc.VAL_OCSP_RESP_CERT.name);
60999ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT.name = NULL;
61099ebb4caSwyllys 			}
61199ebb4caSwyllys 
61299ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
61399ebb4caSwyllys 				free(oplc.VAL_OCSP_RESP_CERT.serial);
61499ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT.serial = NULL;
61599ebb4caSwyllys 			}
61699ebb4caSwyllys 
61799ebb4caSwyllys 			/* Turn off the OCSP checking */
61899ebb4caSwyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
61999ebb4caSwyllys 		}
62099ebb4caSwyllys 
62199ebb4caSwyllys 	} else {
62299ebb4caSwyllys 		/*
62399ebb4caSwyllys 		 * If the "ocsp-none" option is not set or is set to false,
62499ebb4caSwyllys 		 * then we only need to do the modification if there is at
62599ebb4caSwyllys 		 * least one OCSP attribute is specified.
62699ebb4caSwyllys 		 */
62799ebb4caSwyllys 		if (ocsp_set_attr > 0) {
62899ebb4caSwyllys 			if (flags & KC_OCSP_RESPONDER_URI) {
62999ebb4caSwyllys 				if (oplc.VAL_OCSP_RESPONDER_URI)
63099ebb4caSwyllys 					free(oplc.VAL_OCSP_RESPONDER_URI);
63199ebb4caSwyllys 				oplc.VAL_OCSP_RESPONDER_URI =
63299ebb4caSwyllys 				    plc.VAL_OCSP_RESPONDER_URI;
63399ebb4caSwyllys 			}
63499ebb4caSwyllys 
63599ebb4caSwyllys 			if (flags & KC_OCSP_PROXY) {
63699ebb4caSwyllys 				if (oplc.VAL_OCSP_PROXY)
63799ebb4caSwyllys 					free(oplc.VAL_OCSP_PROXY);
63899ebb4caSwyllys 				oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
63999ebb4caSwyllys 			}
64099ebb4caSwyllys 
64199ebb4caSwyllys 			if (flags & KC_OCSP_URI_FROM_CERT)
64299ebb4caSwyllys 				oplc.VAL_OCSP_URI_FROM_CERT =
64399ebb4caSwyllys 				    plc.VAL_OCSP_URI_FROM_CERT;
64499ebb4caSwyllys 
64599ebb4caSwyllys 			if (flags & KC_OCSP_RESP_LIFETIME) {
64699ebb4caSwyllys 				if (oplc.VAL_OCSP_RESP_LIFETIME)
64799ebb4caSwyllys 					free(oplc.VAL_OCSP_RESP_LIFETIME);
64899ebb4caSwyllys 				oplc.VAL_OCSP_RESP_LIFETIME =
64999ebb4caSwyllys 				    plc.VAL_OCSP_RESP_LIFETIME;
65099ebb4caSwyllys 			}
65199ebb4caSwyllys 
65299ebb4caSwyllys 			if (flags & KC_OCSP_IGNORE_RESP_SIGN)
65399ebb4caSwyllys 				oplc.VAL_OCSP_IGNORE_RESP_SIGN =
65499ebb4caSwyllys 				    plc.VAL_OCSP_IGNORE_RESP_SIGN;
65599ebb4caSwyllys 
65699ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
65799ebb4caSwyllys 				if (oplc.VAL_OCSP_RESP_CERT_NAME)
65899ebb4caSwyllys 					free(oplc.VAL_OCSP_RESP_CERT_NAME);
65999ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT_NAME =
66099ebb4caSwyllys 				    plc.VAL_OCSP_RESP_CERT_NAME;
66199ebb4caSwyllys 			}
66299ebb4caSwyllys 
66399ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
66499ebb4caSwyllys 				if (oplc.VAL_OCSP_RESP_CERT_SERIAL)
66599ebb4caSwyllys 					free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
66699ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT_SERIAL =
66799ebb4caSwyllys 				    plc.VAL_OCSP_RESP_CERT_SERIAL;
66899ebb4caSwyllys 			}
66999ebb4caSwyllys 
67099ebb4caSwyllys 			if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
67199ebb4caSwyllys 			    oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
67299ebb4caSwyllys 				oplc.VAL_OCSP.has_resp_cert = B_TRUE;
67399ebb4caSwyllys 			else
67499ebb4caSwyllys 				oplc.VAL_OCSP.has_resp_cert = B_FALSE;
67599ebb4caSwyllys 
67699ebb4caSwyllys 			/* Turn on the OCSP checking */
67799ebb4caSwyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
67899ebb4caSwyllys 		}
67999ebb4caSwyllys 	}
68099ebb4caSwyllys 
68199ebb4caSwyllys 	/* Update the CRL policy */
68299ebb4caSwyllys 	if (crl_none_opt == B_TRUE) {
68399ebb4caSwyllys 		if (crl_set_attr > 0) {
68499ebb4caSwyllys 			(void) fprintf(stderr,
68599ebb4caSwyllys 			    gettext("Can not set crl-none=true and other CRL "
68699ebb4caSwyllys 			    "attributes at the same time.\n"));
68799ebb4caSwyllys 			rv = KC_ERR_USAGE;
68899ebb4caSwyllys 			goto out;
68999ebb4caSwyllys 		}
69099ebb4caSwyllys 
69199ebb4caSwyllys 		/*
69299ebb4caSwyllys 		 * If the original policy does not have CRL checking,
69399ebb4caSwyllys 		 * then we do not need to do anything.  If the original
69499ebb4caSwyllys 		 * policy has the CRL checking, then we need to release the
69599ebb4caSwyllys 		 * space of CRL attributes and turn the CRL checking off.
69699ebb4caSwyllys 		 */
69799ebb4caSwyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
69899ebb4caSwyllys 			if (oplc.VAL_CRL_BASEFILENAME) {
69999ebb4caSwyllys 				free(oplc.VAL_CRL_BASEFILENAME);
70099ebb4caSwyllys 				oplc.VAL_CRL_BASEFILENAME = NULL;
70199ebb4caSwyllys 			}
70299ebb4caSwyllys 
70399ebb4caSwyllys 			if (oplc.VAL_CRL_DIRECTORY) {
70499ebb4caSwyllys 				free(oplc.VAL_CRL_DIRECTORY);
70599ebb4caSwyllys 				oplc.VAL_CRL_DIRECTORY = NULL;
70699ebb4caSwyllys 			}
70799ebb4caSwyllys 
70899ebb4caSwyllys 			if (oplc.VAL_CRL_PROXY) {
70999ebb4caSwyllys 				free(oplc.VAL_CRL_PROXY);
71099ebb4caSwyllys 				oplc.VAL_CRL_PROXY = NULL;
71199ebb4caSwyllys 			}
71299ebb4caSwyllys 
71399ebb4caSwyllys 			/* Turn off the CRL checking */
71499ebb4caSwyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
71599ebb4caSwyllys 		}
71699ebb4caSwyllys 	} else {
71799ebb4caSwyllys 		/*
71899ebb4caSwyllys 		 * If the "ocsp-none" option is not set or is set to false,
71999ebb4caSwyllys 		 * then we only need to do the modification if there is at
72099ebb4caSwyllys 		 * least one CRL attribute is specified.
72199ebb4caSwyllys 		 */
72299ebb4caSwyllys 		if (crl_set_attr > 0) {
72399ebb4caSwyllys 			if (flags & KC_CRL_BASEFILENAME) {
72499ebb4caSwyllys 				if (oplc.VAL_CRL_BASEFILENAME)
72599ebb4caSwyllys 					free(oplc.VAL_CRL_BASEFILENAME);
72699ebb4caSwyllys 				oplc.VAL_CRL_BASEFILENAME =
72799ebb4caSwyllys 				    plc.VAL_CRL_BASEFILENAME;
72899ebb4caSwyllys 			}
72999ebb4caSwyllys 
73099ebb4caSwyllys 			if (flags & KC_CRL_DIRECTORY) {
73199ebb4caSwyllys 				if (oplc.VAL_CRL_DIRECTORY)
73299ebb4caSwyllys 					free(oplc.VAL_CRL_DIRECTORY);
73399ebb4caSwyllys 				oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
73499ebb4caSwyllys 			}
73599ebb4caSwyllys 
73699ebb4caSwyllys 			if (flags & KC_CRL_GET_URI) {
73799ebb4caSwyllys 				oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
73899ebb4caSwyllys 			}
73999ebb4caSwyllys 
74099ebb4caSwyllys 			if (flags & KC_CRL_PROXY) {
74199ebb4caSwyllys 				if (oplc.VAL_CRL_PROXY)
74299ebb4caSwyllys 					free(oplc.VAL_CRL_PROXY);
74399ebb4caSwyllys 				oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
74499ebb4caSwyllys 			}
74599ebb4caSwyllys 
74699ebb4caSwyllys 			if (flags & KC_CRL_IGNORE_SIGN) {
74799ebb4caSwyllys 				oplc.VAL_CRL_IGNORE_SIGN =
74899ebb4caSwyllys 				    plc.VAL_CRL_IGNORE_SIGN;
74999ebb4caSwyllys 			}
75099ebb4caSwyllys 
75199ebb4caSwyllys 			if (flags & KC_CRL_IGNORE_DATE) {
75299ebb4caSwyllys 				oplc.VAL_CRL_IGNORE_DATE =
75399ebb4caSwyllys 				    plc.VAL_CRL_IGNORE_DATE;
75499ebb4caSwyllys 			}
75599ebb4caSwyllys 
75699ebb4caSwyllys 			/* Turn on the CRL checking */
75799ebb4caSwyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
75899ebb4caSwyllys 		}
75999ebb4caSwyllys 	}
76099ebb4caSwyllys 
76199ebb4caSwyllys 	/* Update the Key Usage */
76299ebb4caSwyllys 	if (ku_none_opt == B_TRUE) {
76399ebb4caSwyllys 		if (flags & KC_KEYUSAGE) {
76499ebb4caSwyllys 			(void) fprintf(stderr,
76599ebb4caSwyllys 			    gettext("Can not set keyusage-none=true and "
76699ebb4caSwyllys 			    "modify the keyusage value at the same time.\n"));
76799ebb4caSwyllys 			rv = KC_ERR_USAGE;
76899ebb4caSwyllys 			goto out;
76999ebb4caSwyllys 		}
77099ebb4caSwyllys 
77199ebb4caSwyllys 		oplc.ku_bits = 0;
77299ebb4caSwyllys 	} else {
77399ebb4caSwyllys 		/*
77499ebb4caSwyllys 		 * If the "keyusage-none" option is not set or is set to
77599ebb4caSwyllys 		 * false, then we only need to do the modification if
77699ebb4caSwyllys 		 * the keyusage value is specified.
77799ebb4caSwyllys 		 */
77899ebb4caSwyllys 		if (flags & KC_KEYUSAGE)
77999ebb4caSwyllys 			oplc.ku_bits = plc.ku_bits;
78099ebb4caSwyllys 	}
78199ebb4caSwyllys 
78299ebb4caSwyllys 
78399ebb4caSwyllys 	/* Update the Extended Key Usage */
78499ebb4caSwyllys 	if (eku_none_opt == B_TRUE) {
78599ebb4caSwyllys 		if (flags & KC_EKUS) {
78699ebb4caSwyllys 			(void) fprintf(stderr,
78799ebb4caSwyllys 			    gettext("Can not set eku-none=true and modify "
78899ebb4caSwyllys 			    "EKU values at the same time.\n"));
78999ebb4caSwyllys 			rv = KC_ERR_USAGE;
79099ebb4caSwyllys 			goto out;
79199ebb4caSwyllys 		}
79299ebb4caSwyllys 
79399ebb4caSwyllys 		/* Release current EKU list (if any) */
79499ebb4caSwyllys 		if (oplc.eku_set.eku_count > 0) {
795*30a5e8faSwyllys 			kmf_free_eku_policy(&oplc.eku_set);
79699ebb4caSwyllys 			oplc.eku_set.eku_count = 0;
79799ebb4caSwyllys 			oplc.eku_set.ekulist = NULL;
79899ebb4caSwyllys 		}
79999ebb4caSwyllys 	} else {
80099ebb4caSwyllys 		/*
80199ebb4caSwyllys 		 * If the "eku-none" option is not set or is set to false,
80299ebb4caSwyllys 		 * then we only need to do the modification if either
80399ebb4caSwyllys 		 * "ekuname" or "ekuoids" is specified.
80499ebb4caSwyllys 		 */
80599ebb4caSwyllys 		if (flags & KC_EKUS) {
80699ebb4caSwyllys 			/* Release current EKU list (if any) */
807*30a5e8faSwyllys 			kmf_free_eku_policy(&oplc.eku_set);
80899ebb4caSwyllys 			oplc.eku_set = plc.eku_set;
80999ebb4caSwyllys 		}
81099ebb4caSwyllys 	}
81199ebb4caSwyllys 
81299ebb4caSwyllys 	/* Do a sanity check on the modified policy */
813*30a5e8faSwyllys 	ret = kmf_verify_policy(&oplc);
81499ebb4caSwyllys 	if (ret != KMF_OK) {
81599ebb4caSwyllys 		print_sanity_error(ret);
81699ebb4caSwyllys 		rv = KC_ERR_VERIFY_POLICY;
81799ebb4caSwyllys 		goto out;
81899ebb4caSwyllys 	}
81999ebb4caSwyllys 
82099ebb4caSwyllys 	/* The modify operation is a delete followed by an add */
821*30a5e8faSwyllys 	ret = kmf_delete_policy_from_db(oplc.name, filename);
82299ebb4caSwyllys 	if (ret != KMF_OK) {
82399ebb4caSwyllys 		rv = KC_ERR_DELETE_POLICY;
82499ebb4caSwyllys 		goto out;
82599ebb4caSwyllys 	}
82699ebb4caSwyllys 
82799ebb4caSwyllys 	/*
82899ebb4caSwyllys 	 * Now add the modified policy back to the DB.
82999ebb4caSwyllys 	 */
830*30a5e8faSwyllys 	ret = kmf_add_policy_to_db(&oplc, filename, B_FALSE);
83199ebb4caSwyllys 	if (ret != KMF_OK) {
83299ebb4caSwyllys 		(void) fprintf(stderr,
83399ebb4caSwyllys 		    gettext("Error adding policy to database: 0x%04x\n"), ret);
83499ebb4caSwyllys 		rv = KC_ERR_ADD_POLICY;
83599ebb4caSwyllys 		goto out;
83699ebb4caSwyllys 	}
83799ebb4caSwyllys 
83899ebb4caSwyllys out:
83999ebb4caSwyllys 	if (filename != NULL)
84099ebb4caSwyllys 		free(filename);
84199ebb4caSwyllys 
842*30a5e8faSwyllys 	kmf_free_policy_record(&oplc);
84399ebb4caSwyllys 
84499ebb4caSwyllys 	return (rv);
84599ebb4caSwyllys }
846