xref: /titanic_50/usr/src/cmd/cmd-crypto/kmfcfg/modify.c (revision 431deaa01ac039d796fdfaf86b909a75e7d9ac48)
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  *
2130a5e8faSwyllys  * 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>
35*431deaa0Shylee #include <sys/stat.h>
36*431deaa0Shylee #include <sys/param.h>
3799ebb4caSwyllys #include "util.h"
3899ebb4caSwyllys 
3999ebb4caSwyllys #define	KC_IGNORE_DATE			0x0000001
4099ebb4caSwyllys #define	KC_IGNORE_UNKNOWN_EKUS		0x0000002
4199ebb4caSwyllys #define	KC_IGNORE_TRUST_ANCHOR		0x0000004
4299ebb4caSwyllys #define	KC_VALIDITY_ADJUSTTIME		0x0000008
4399ebb4caSwyllys #define	KC_TA_NAME			0x0000010
4499ebb4caSwyllys #define	KC_TA_SERIAL			0x0000020
4599ebb4caSwyllys #define	KC_OCSP_RESPONDER_URI		0x0000040
4699ebb4caSwyllys #define	KC_OCSP_PROXY			0x0000080
4799ebb4caSwyllys #define	KC_OCSP_URI_FROM_CERT		0x0000100
4899ebb4caSwyllys #define	KC_OCSP_RESP_LIFETIME		0x0000200
4999ebb4caSwyllys #define	KC_OCSP_IGNORE_RESP_SIGN 	0x0000400
5099ebb4caSwyllys #define	KC_OCSP_RESP_CERT_NAME		0x0000800
5199ebb4caSwyllys #define	KC_OCSP_RESP_CERT_SERIAL	0x0001000
5299ebb4caSwyllys #define	KC_OCSP_NONE			0x0002000
5399ebb4caSwyllys #define	KC_CRL_BASEFILENAME		0x0004000
5499ebb4caSwyllys #define	KC_CRL_DIRECTORY		0x0008000
5599ebb4caSwyllys #define	KC_CRL_GET_URI			0x0010000
5699ebb4caSwyllys #define	KC_CRL_PROXY			0x0020000
5799ebb4caSwyllys #define	KC_CRL_IGNORE_SIGN		0x0040000
5899ebb4caSwyllys #define	KC_CRL_IGNORE_DATE		0x0080000
5999ebb4caSwyllys #define	KC_CRL_NONE			0x0100000
6099ebb4caSwyllys #define	KC_KEYUSAGE			0x0200000
6199ebb4caSwyllys #define	KC_KEYUSAGE_NONE		0x0400000
6299ebb4caSwyllys #define	KC_EKUS				0x0800000
6399ebb4caSwyllys #define	KC_EKUS_NONE			0x1000000
6499ebb4caSwyllys 
65*431deaa0Shylee static int err; /* To store errno which may be overwritten by gettext() */
66*431deaa0Shylee 
67*431deaa0Shylee 
6899ebb4caSwyllys int
69*431deaa0Shylee kc_modify_policy(int argc, char *argv[])
7099ebb4caSwyllys {
7199ebb4caSwyllys 	KMF_RETURN	ret;
7299ebb4caSwyllys 	int 		rv = KC_OK;
7399ebb4caSwyllys 	int		opt;
7499ebb4caSwyllys 	extern int	optind_av;
7599ebb4caSwyllys 	extern char	*optarg_av;
7699ebb4caSwyllys 	char		*filename = NULL;
7799ebb4caSwyllys 	uint32_t	flags = 0;
7899ebb4caSwyllys 	boolean_t	ocsp_none_opt = B_FALSE;
7999ebb4caSwyllys 	boolean_t	crl_none_opt = B_FALSE;
8099ebb4caSwyllys 	boolean_t	ku_none_opt = B_FALSE;
8199ebb4caSwyllys 	boolean_t	eku_none_opt = B_FALSE;
8299ebb4caSwyllys 	int		ocsp_set_attr = 0;
8399ebb4caSwyllys 	int		crl_set_attr = 0;
8499ebb4caSwyllys 	KMF_POLICY_RECORD oplc, plc;
8599ebb4caSwyllys 
8699ebb4caSwyllys 	(void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
8799ebb4caSwyllys 	(void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD));
8899ebb4caSwyllys 
8999ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
9099ebb4caSwyllys 	    "i:(dbfile)"
9199ebb4caSwyllys 	    "p:(policy)"
9299ebb4caSwyllys 	    "d:(ignore-date)"
9399ebb4caSwyllys 	    "e:(ignore-unknown-eku)"
9499ebb4caSwyllys 	    "a:(ignore-trust-anchor)"
9599ebb4caSwyllys 	    "v:(validity-adjusttime)"
9699ebb4caSwyllys 	    "t:(ta-name)"
9799ebb4caSwyllys 	    "s:(ta-serial)"
9899ebb4caSwyllys 	    "o:(ocsp-responder)"
9999ebb4caSwyllys 	    "P:(ocsp-proxy)"
10099ebb4caSwyllys 	    "r:(ocsp-use-cert-responder)"
10199ebb4caSwyllys 	    "T:(ocsp-response-lifetime)"
10299ebb4caSwyllys 	    "R:(ocsp-ignore-response-sign)"
10399ebb4caSwyllys 	    "n:(ocsp-responder-cert-name)"
10499ebb4caSwyllys 	    "A:(ocsp-responder-cert-serial)"
10599ebb4caSwyllys 	    "y:(ocsp-none)"
10699ebb4caSwyllys 	    "c:(crl-basefilename)"
10799ebb4caSwyllys 	    "I:(crl-directory)"
10899ebb4caSwyllys 	    "g:(crl-get-crl-uri)"
10999ebb4caSwyllys 	    "X:(crl-proxy)"
11099ebb4caSwyllys 	    "S:(crl-ignore-crl-sign)"
11199ebb4caSwyllys 	    "D:(crl-ignore-crl-date)"
11299ebb4caSwyllys 	    "z:(crl-none)"
11399ebb4caSwyllys 	    "u:(keyusage)"
11499ebb4caSwyllys 	    "Y:(keyusage-none)"
11599ebb4caSwyllys 	    "E:(ekunames)"
11699ebb4caSwyllys 	    "O:(ekuoids)"
11799ebb4caSwyllys 	    "Z:(eku-none)")) != EOF) {
11899ebb4caSwyllys 		switch (opt) {
11999ebb4caSwyllys 			case 'i':
12099ebb4caSwyllys 				filename = get_string(optarg_av, &rv);
12199ebb4caSwyllys 				if (filename == NULL) {
12299ebb4caSwyllys 					(void) fprintf(stderr,
12399ebb4caSwyllys 					    gettext("Error dbfile input.\n"));
12499ebb4caSwyllys 				}
12599ebb4caSwyllys 				break;
12699ebb4caSwyllys 			case 'p':
12799ebb4caSwyllys 				plc.name = get_string(optarg_av, &rv);
12899ebb4caSwyllys 				if (plc.name == NULL) {
12999ebb4caSwyllys 					(void) fprintf(stderr,
13099ebb4caSwyllys 					    gettext("Error policy name.\n"));
13199ebb4caSwyllys 				}
13299ebb4caSwyllys 				break;
13399ebb4caSwyllys 			case 'd':
13499ebb4caSwyllys 				plc.ignore_date = get_boolean(optarg_av);
13599ebb4caSwyllys 				if (plc.ignore_date == -1) {
13699ebb4caSwyllys 					(void) fprintf(stderr,
13799ebb4caSwyllys 					    gettext("Error boolean input.\n"));
13899ebb4caSwyllys 					rv = KC_ERR_USAGE;
13999ebb4caSwyllys 				} else {
14099ebb4caSwyllys 					flags |= KC_IGNORE_DATE;
14199ebb4caSwyllys 				}
14299ebb4caSwyllys 				break;
14399ebb4caSwyllys 			case 'e':
14499ebb4caSwyllys 				plc.ignore_unknown_ekus =
14599ebb4caSwyllys 				    get_boolean(optarg_av);
14699ebb4caSwyllys 				if (plc.ignore_unknown_ekus == -1) {
14799ebb4caSwyllys 					(void) fprintf(stderr,
14899ebb4caSwyllys 					    gettext("Error boolean input.\n"));
14999ebb4caSwyllys 					rv = KC_ERR_USAGE;
15099ebb4caSwyllys 				} else {
15199ebb4caSwyllys 					flags |= KC_IGNORE_UNKNOWN_EKUS;
15299ebb4caSwyllys 				}
15399ebb4caSwyllys 				break;
15499ebb4caSwyllys 			case 'a':
15599ebb4caSwyllys 				plc.ignore_trust_anchor =
15699ebb4caSwyllys 				    get_boolean(optarg_av);
15799ebb4caSwyllys 				if (plc.ignore_trust_anchor == -1) {
15899ebb4caSwyllys 					(void) fprintf(stderr,
15999ebb4caSwyllys 					    gettext("Error boolean input.\n"));
16099ebb4caSwyllys 					rv = KC_ERR_USAGE;
16199ebb4caSwyllys 				} else {
16299ebb4caSwyllys 					flags |= KC_IGNORE_TRUST_ANCHOR;
16399ebb4caSwyllys 				}
16499ebb4caSwyllys 				break;
16599ebb4caSwyllys 			case 'v':
16699ebb4caSwyllys 				plc.validity_adjusttime =
16799ebb4caSwyllys 				    get_string(optarg_av, &rv);
16899ebb4caSwyllys 				if (plc.validity_adjusttime == NULL) {
16999ebb4caSwyllys 					(void) fprintf(stderr,
17099ebb4caSwyllys 					    gettext("Error time input.\n"));
17199ebb4caSwyllys 				} else {
17299ebb4caSwyllys 					uint32_t adj;
17399ebb4caSwyllys 					/* for syntax checking */
17499ebb4caSwyllys 					if (str2lifetime(
17599ebb4caSwyllys 					    plc.validity_adjusttime,
17699ebb4caSwyllys 					    &adj) < 0) {
17799ebb4caSwyllys 						(void) fprintf(stderr,
17899ebb4caSwyllys 						    gettext("Error time "
17999ebb4caSwyllys 						    "input.\n"));
18099ebb4caSwyllys 						rv = KC_ERR_USAGE;
18199ebb4caSwyllys 					} else {
18299ebb4caSwyllys 						flags |= KC_VALIDITY_ADJUSTTIME;
18399ebb4caSwyllys 					}
18499ebb4caSwyllys 				}
18599ebb4caSwyllys 				break;
18699ebb4caSwyllys 			case 't':
18799ebb4caSwyllys 				plc.ta_name = get_string(optarg_av, &rv);
18899ebb4caSwyllys 				if (plc.ta_name == NULL) {
18999ebb4caSwyllys 					(void) fprintf(stderr,
19099ebb4caSwyllys 					    gettext("Error name input.\n"));
19199ebb4caSwyllys 				} else {
19299ebb4caSwyllys 					KMF_X509_NAME taDN;
19399ebb4caSwyllys 					/* for syntax checking */
19430a5e8faSwyllys 					if (kmf_dn_parser(plc.ta_name,
19599ebb4caSwyllys 					    &taDN) != KMF_OK) {
19699ebb4caSwyllys 						(void) fprintf(stderr,
19799ebb4caSwyllys 						    gettext("Error name "
19899ebb4caSwyllys 						    "input.\n"));
19999ebb4caSwyllys 						rv = KC_ERR_USAGE;
20099ebb4caSwyllys 					} else {
20130a5e8faSwyllys 						kmf_free_dn(&taDN);
20299ebb4caSwyllys 						flags |= KC_TA_NAME;
20399ebb4caSwyllys 					}
20499ebb4caSwyllys 				}
20599ebb4caSwyllys 				break;
20699ebb4caSwyllys 			case 's':
20799ebb4caSwyllys 				plc.ta_serial = get_string(optarg_av, &rv);
20899ebb4caSwyllys 				if (plc.ta_serial == NULL) {
20999ebb4caSwyllys 					(void) fprintf(stderr,
21099ebb4caSwyllys 					    gettext("Error serial input.\n"));
21199ebb4caSwyllys 				} else {
21299ebb4caSwyllys 					uchar_t *bytes = NULL;
21399ebb4caSwyllys 					size_t bytelen;
21499ebb4caSwyllys 
21530a5e8faSwyllys 					ret = kmf_hexstr_to_bytes(
21699ebb4caSwyllys 					    (uchar_t *)plc.ta_serial,
21799ebb4caSwyllys 					    &bytes, &bytelen);
21899ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
21999ebb4caSwyllys 						(void) fprintf(stderr,
22099ebb4caSwyllys 						    gettext("serial number "
22199ebb4caSwyllys 						    "must be specified as a "
22299ebb4caSwyllys 						    "hex number "
22399ebb4caSwyllys 						    "(ex: 0x0102030405"
22499ebb4caSwyllys 						    "ffeeddee)\n"));
22599ebb4caSwyllys 						rv = KC_ERR_USAGE;
22699ebb4caSwyllys 						break;
22799ebb4caSwyllys 					}
22899ebb4caSwyllys 					if (bytes != NULL)
22999ebb4caSwyllys 						free(bytes);
23099ebb4caSwyllys 					flags |= KC_TA_SERIAL;
23199ebb4caSwyllys 				}
23299ebb4caSwyllys 				break;
23399ebb4caSwyllys 			case 'o':
23499ebb4caSwyllys 				plc.VAL_OCSP_RESPONDER_URI =
23599ebb4caSwyllys 				    get_string(optarg_av, &rv);
23699ebb4caSwyllys 				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
23799ebb4caSwyllys 					(void) fprintf(stderr,
23899ebb4caSwyllys 					    gettext("Error responder "
23999ebb4caSwyllys 					    "input.\n"));
24099ebb4caSwyllys 				} else {
24199ebb4caSwyllys 					flags |= KC_OCSP_RESPONDER_URI;
24299ebb4caSwyllys 					ocsp_set_attr++;
24399ebb4caSwyllys 				}
24499ebb4caSwyllys 				break;
24599ebb4caSwyllys 			case 'P':
24699ebb4caSwyllys 				plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
24799ebb4caSwyllys 				if (plc.VAL_OCSP_PROXY == NULL) {
24899ebb4caSwyllys 					(void) fprintf(stderr,
24999ebb4caSwyllys 					    gettext("Error proxy input.\n"));
25099ebb4caSwyllys 				} else {
25199ebb4caSwyllys 					flags |= KC_OCSP_PROXY;
25299ebb4caSwyllys 					ocsp_set_attr++;
25399ebb4caSwyllys 				}
25499ebb4caSwyllys 				break;
25599ebb4caSwyllys 			case 'r':
25699ebb4caSwyllys 				plc.VAL_OCSP_URI_FROM_CERT =
25799ebb4caSwyllys 				    get_boolean(optarg_av);
25899ebb4caSwyllys 				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
25999ebb4caSwyllys 					(void) fprintf(stderr,
26099ebb4caSwyllys 					    gettext("Error boolean input.\n"));
26199ebb4caSwyllys 					rv = KC_ERR_USAGE;
26299ebb4caSwyllys 				} else {
26399ebb4caSwyllys 					flags |= KC_OCSP_URI_FROM_CERT;
26499ebb4caSwyllys 					ocsp_set_attr++;
26599ebb4caSwyllys 				}
26699ebb4caSwyllys 				break;
26799ebb4caSwyllys 			case 'T':
26899ebb4caSwyllys 				plc.VAL_OCSP_RESP_LIFETIME =
26999ebb4caSwyllys 				    get_string(optarg_av, &rv);
27099ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
27199ebb4caSwyllys 					(void) fprintf(stderr,
27299ebb4caSwyllys 					    gettext("Error time input.\n"));
27399ebb4caSwyllys 				} else {
27499ebb4caSwyllys 					uint32_t adj;
27599ebb4caSwyllys 					/* for syntax checking */
27699ebb4caSwyllys 					if (str2lifetime(
27799ebb4caSwyllys 					    plc.VAL_OCSP_RESP_LIFETIME,
27899ebb4caSwyllys 					    &adj) < 0) {
27999ebb4caSwyllys 						(void) fprintf(stderr,
28099ebb4caSwyllys 						    gettext("Error time "
28199ebb4caSwyllys 						    "input.\n"));
28299ebb4caSwyllys 						rv = KC_ERR_USAGE;
28399ebb4caSwyllys 					} else {
28499ebb4caSwyllys 						flags |= KC_OCSP_RESP_LIFETIME;
28599ebb4caSwyllys 						ocsp_set_attr++;
28699ebb4caSwyllys 					}
28799ebb4caSwyllys 				}
28899ebb4caSwyllys 				break;
28999ebb4caSwyllys 			case 'R':
29099ebb4caSwyllys 				plc.VAL_OCSP_IGNORE_RESP_SIGN =
29199ebb4caSwyllys 				    get_boolean(optarg_av);
29299ebb4caSwyllys 				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
29399ebb4caSwyllys 					(void) fprintf(stderr,
29499ebb4caSwyllys 					    gettext("Error boolean input.\n"));
29599ebb4caSwyllys 					rv = KC_ERR_USAGE;
29699ebb4caSwyllys 				} else {
29799ebb4caSwyllys 					flags |= KC_OCSP_IGNORE_RESP_SIGN;
29899ebb4caSwyllys 					ocsp_set_attr++;
29999ebb4caSwyllys 				}
30099ebb4caSwyllys 				break;
30199ebb4caSwyllys 			case 'n':
30299ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_NAME =
30399ebb4caSwyllys 				    get_string(optarg_av, &rv);
30499ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
30599ebb4caSwyllys 					(void) fprintf(stderr,
30699ebb4caSwyllys 					    gettext("Error name input.\n"));
30799ebb4caSwyllys 				} else {
30899ebb4caSwyllys 					KMF_X509_NAME respDN;
30999ebb4caSwyllys 					/* for syntax checking */
31030a5e8faSwyllys 					if (kmf_dn_parser(
31199ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_NAME,
31299ebb4caSwyllys 					    &respDN) != KMF_OK) {
31399ebb4caSwyllys 						(void) fprintf(stderr,
31499ebb4caSwyllys 						    gettext("Error name "
31599ebb4caSwyllys 						    "input.\n"));
31699ebb4caSwyllys 						rv = KC_ERR_USAGE;
31799ebb4caSwyllys 					} else {
31830a5e8faSwyllys 						kmf_free_dn(&respDN);
31999ebb4caSwyllys 						flags |= KC_OCSP_RESP_CERT_NAME;
32099ebb4caSwyllys 						ocsp_set_attr++;
32199ebb4caSwyllys 					}
32299ebb4caSwyllys 				}
32399ebb4caSwyllys 				break;
32499ebb4caSwyllys 			case 'A':
32599ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_SERIAL =
32699ebb4caSwyllys 				    get_string(optarg_av, &rv);
32799ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
32899ebb4caSwyllys 					(void) fprintf(stderr,
32999ebb4caSwyllys 					    gettext("Error serial input.\n"));
33099ebb4caSwyllys 				} else {
33199ebb4caSwyllys 					uchar_t *bytes = NULL;
33299ebb4caSwyllys 					size_t bytelen;
33399ebb4caSwyllys 
33430a5e8faSwyllys 					ret = kmf_hexstr_to_bytes((uchar_t *)
33599ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_SERIAL,
33699ebb4caSwyllys 					    &bytes, &bytelen);
33799ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
33899ebb4caSwyllys 						(void) fprintf(stderr,
33999ebb4caSwyllys 						    gettext("serial number "
34099ebb4caSwyllys 						    "must be specified as a "
34199ebb4caSwyllys 						    "hex number "
34299ebb4caSwyllys 						    "(ex: 0x0102030405"
34399ebb4caSwyllys 						    "ffeeddee)\n"));
34499ebb4caSwyllys 						rv = KC_ERR_USAGE;
34599ebb4caSwyllys 						break;
34699ebb4caSwyllys 					}
34799ebb4caSwyllys 					if (bytes != NULL)
34899ebb4caSwyllys 						free(bytes);
34999ebb4caSwyllys 					flags |= KC_OCSP_RESP_CERT_SERIAL;
35099ebb4caSwyllys 					ocsp_set_attr++;
35199ebb4caSwyllys 				}
35299ebb4caSwyllys 				break;
35399ebb4caSwyllys 			case 'y':
35499ebb4caSwyllys 				ocsp_none_opt = get_boolean(optarg_av);
35599ebb4caSwyllys 				if (ocsp_none_opt == -1) {
35699ebb4caSwyllys 					(void) fprintf(stderr,
35799ebb4caSwyllys 					    gettext("Error boolean input.\n"));
35899ebb4caSwyllys 					rv = KC_ERR_USAGE;
35999ebb4caSwyllys 				} else {
36099ebb4caSwyllys 					flags |= KC_OCSP_NONE;
36199ebb4caSwyllys 				}
36299ebb4caSwyllys 				break;
36399ebb4caSwyllys 			case 'c':
36499ebb4caSwyllys 				plc.VAL_CRL_BASEFILENAME =
36599ebb4caSwyllys 				    get_string(optarg_av, &rv);
36699ebb4caSwyllys 				if (plc.VAL_CRL_BASEFILENAME == NULL) {
36799ebb4caSwyllys 					(void) fprintf(stderr, gettext(
36899ebb4caSwyllys 					    "Error basefilename input.\n"));
36999ebb4caSwyllys 				} else {
37099ebb4caSwyllys 					flags |= KC_CRL_BASEFILENAME;
37199ebb4caSwyllys 					crl_set_attr++;
37299ebb4caSwyllys 				}
37399ebb4caSwyllys 				break;
37499ebb4caSwyllys 			case 'I':
37599ebb4caSwyllys 				plc.VAL_CRL_DIRECTORY =
37699ebb4caSwyllys 				    get_string(optarg_av, &rv);
37799ebb4caSwyllys 				if (plc.VAL_CRL_DIRECTORY == NULL) {
37899ebb4caSwyllys 					(void) fprintf(stderr,
37999ebb4caSwyllys 					    gettext("Error boolean input.\n"));
38099ebb4caSwyllys 				} else {
38199ebb4caSwyllys 					flags |= KC_CRL_DIRECTORY;
38299ebb4caSwyllys 					crl_set_attr++;
38399ebb4caSwyllys 				}
38499ebb4caSwyllys 				break;
38599ebb4caSwyllys 			case 'g':
38699ebb4caSwyllys 				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
38799ebb4caSwyllys 				if (plc.VAL_CRL_GET_URI == -1) {
38899ebb4caSwyllys 					(void) fprintf(stderr,
38999ebb4caSwyllys 					    gettext("Error boolean input.\n"));
39099ebb4caSwyllys 					rv = KC_ERR_USAGE;
39199ebb4caSwyllys 				} else {
39299ebb4caSwyllys 					flags |= KC_CRL_GET_URI;
39399ebb4caSwyllys 					crl_set_attr++;
39499ebb4caSwyllys 				}
39599ebb4caSwyllys 				break;
39699ebb4caSwyllys 			case 'X':
39799ebb4caSwyllys 				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
39899ebb4caSwyllys 				if (plc.VAL_CRL_PROXY == NULL) {
39999ebb4caSwyllys 					(void) fprintf(stderr,
40099ebb4caSwyllys 					    gettext("Error proxy input.\n"));
40199ebb4caSwyllys 				} else {
40299ebb4caSwyllys 					flags |= KC_CRL_PROXY;
40399ebb4caSwyllys 					crl_set_attr++;
40499ebb4caSwyllys 				}
40599ebb4caSwyllys 				break;
40699ebb4caSwyllys 			case 'S':
40799ebb4caSwyllys 				plc.VAL_CRL_IGNORE_SIGN =
40899ebb4caSwyllys 				    get_boolean(optarg_av);
40999ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
41099ebb4caSwyllys 					(void) fprintf(stderr,
41199ebb4caSwyllys 					    gettext("Error boolean input.\n"));
41299ebb4caSwyllys 					rv = KC_ERR_USAGE;
41399ebb4caSwyllys 				} else {
41499ebb4caSwyllys 					flags |= KC_CRL_IGNORE_SIGN;
41599ebb4caSwyllys 					crl_set_attr++;
41699ebb4caSwyllys 				}
41799ebb4caSwyllys 				break;
41899ebb4caSwyllys 			case 'D':
41999ebb4caSwyllys 				plc.VAL_CRL_IGNORE_DATE =
42099ebb4caSwyllys 				    get_boolean(optarg_av);
42199ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_DATE == -1) {
42299ebb4caSwyllys 					(void) fprintf(stderr,
42399ebb4caSwyllys 					    gettext("Error boolean input.\n"));
42499ebb4caSwyllys 					rv = KC_ERR_USAGE;
42599ebb4caSwyllys 				} else {
42699ebb4caSwyllys 					flags |= KC_CRL_IGNORE_DATE;
42799ebb4caSwyllys 					crl_set_attr++;
42899ebb4caSwyllys 				}
42999ebb4caSwyllys 				break;
43099ebb4caSwyllys 			case 'z':
43199ebb4caSwyllys 				crl_none_opt = get_boolean(optarg_av);
43299ebb4caSwyllys 				if (crl_none_opt == -1) {
43399ebb4caSwyllys 					(void) fprintf(stderr,
43499ebb4caSwyllys 					    gettext("Error boolean input.\n"));
43599ebb4caSwyllys 					rv = KC_ERR_USAGE;
43699ebb4caSwyllys 				} else {
43799ebb4caSwyllys 					flags |= KC_CRL_NONE;
43899ebb4caSwyllys 				}
43999ebb4caSwyllys 				break;
44099ebb4caSwyllys 			case 'u':
44199ebb4caSwyllys 				plc.ku_bits = parseKUlist(optarg_av);
44299ebb4caSwyllys 				if (plc.ku_bits == 0) {
44399ebb4caSwyllys 					(void) fprintf(stderr, gettext(
44499ebb4caSwyllys 					    "Error keyusage input.\n"));
44599ebb4caSwyllys 					rv = KC_ERR_USAGE;
44699ebb4caSwyllys 				} else {
44799ebb4caSwyllys 					flags |= KC_KEYUSAGE;
44899ebb4caSwyllys 				}
44999ebb4caSwyllys 				break;
45099ebb4caSwyllys 			case 'Y':
45199ebb4caSwyllys 				ku_none_opt = get_boolean(optarg_av);
45299ebb4caSwyllys 				if (ku_none_opt == -1) {
45399ebb4caSwyllys 					(void) fprintf(stderr,
45499ebb4caSwyllys 					    gettext("Error boolean input.\n"));
45599ebb4caSwyllys 					rv = KC_ERR_USAGE;
45699ebb4caSwyllys 				} else {
45799ebb4caSwyllys 					flags |= KC_KEYUSAGE_NONE;
45899ebb4caSwyllys 				}
45999ebb4caSwyllys 				break;
46099ebb4caSwyllys 			case 'E':
46199ebb4caSwyllys 				if (parseEKUNames(optarg_av, &plc) != 0) {
46299ebb4caSwyllys 					(void) fprintf(stderr,
46399ebb4caSwyllys 					    gettext("Error EKU input.\n"));
46499ebb4caSwyllys 					rv = KC_ERR_USAGE;
46599ebb4caSwyllys 				} else {
46699ebb4caSwyllys 					flags |= KC_EKUS;
46799ebb4caSwyllys 				}
46899ebb4caSwyllys 				break;
46999ebb4caSwyllys 			case 'O':
47099ebb4caSwyllys 				if (parseEKUOIDs(optarg_av, &plc) != 0) {
47199ebb4caSwyllys 					(void) fprintf(stderr,
47299ebb4caSwyllys 					    gettext("Error EKU OID input.\n"));
47399ebb4caSwyllys 					rv = KC_ERR_USAGE;
47499ebb4caSwyllys 				} else {
47599ebb4caSwyllys 					flags |= KC_EKUS;
47699ebb4caSwyllys 				}
47799ebb4caSwyllys 				break;
47899ebb4caSwyllys 			case 'Z':
47999ebb4caSwyllys 				eku_none_opt = get_boolean(optarg_av);
48099ebb4caSwyllys 				if (eku_none_opt == -1) {
48199ebb4caSwyllys 					(void) fprintf(stderr,
48299ebb4caSwyllys 					    gettext("Error boolean input.\n"));
48399ebb4caSwyllys 					rv = KC_ERR_USAGE;
48499ebb4caSwyllys 				} else {
48599ebb4caSwyllys 					flags |= KC_EKUS_NONE;
48699ebb4caSwyllys 				}
48799ebb4caSwyllys 				break;
48899ebb4caSwyllys 			default:
48999ebb4caSwyllys 				(void) fprintf(stderr,
49099ebb4caSwyllys 				    gettext("Error input option.\n"));
49199ebb4caSwyllys 				rv = KC_ERR_USAGE;
49299ebb4caSwyllys 				break;
49399ebb4caSwyllys 		}
49499ebb4caSwyllys 		if (rv != KC_OK)
49599ebb4caSwyllys 			goto out;
49699ebb4caSwyllys 	}
49799ebb4caSwyllys 
49899ebb4caSwyllys 	/* No additional args allowed. */
49999ebb4caSwyllys 	argc -= optind_av;
50099ebb4caSwyllys 	if (argc) {
50199ebb4caSwyllys 		(void) fprintf(stderr,
50299ebb4caSwyllys 		    gettext("Error input option\n"));
50399ebb4caSwyllys 		rv = KC_ERR_USAGE;
50499ebb4caSwyllys 		goto out;
50599ebb4caSwyllys 	}
50699ebb4caSwyllys 
50799ebb4caSwyllys 	if (filename == NULL) {
50899ebb4caSwyllys 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
50999ebb4caSwyllys 		if (filename == NULL) {
51099ebb4caSwyllys 			rv = KC_ERR_MEMORY;
51199ebb4caSwyllys 			goto out;
51299ebb4caSwyllys 		}
51399ebb4caSwyllys 	}
51499ebb4caSwyllys 
51599ebb4caSwyllys 	/*
51699ebb4caSwyllys 	 * Must have a policy name. The policy name can not be default
51799ebb4caSwyllys 	 * if using the default policy file.
51899ebb4caSwyllys 	 */
51999ebb4caSwyllys 	if (plc.name == NULL) {
52099ebb4caSwyllys 		(void) fprintf(stderr,
52199ebb4caSwyllys 		    gettext("You must specify a policy name.\n"));
52299ebb4caSwyllys 		rv = KC_ERR_USAGE;
52399ebb4caSwyllys 		goto out;
52499ebb4caSwyllys 	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
52599ebb4caSwyllys 	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
52699ebb4caSwyllys 		(void) fprintf(stderr,
52799ebb4caSwyllys 		    gettext("Can not modify the default policy in the default "
52899ebb4caSwyllys 		    "policy file.\n"));
52999ebb4caSwyllys 		rv = KC_ERR_USAGE;
53099ebb4caSwyllys 		goto out;
53199ebb4caSwyllys 	}
53299ebb4caSwyllys 
53399ebb4caSwyllys 	/* Check the access permission of the policy DB */
53499ebb4caSwyllys 	if (access(filename, W_OK) < 0) {
53599ebb4caSwyllys 		int err = errno;
53699ebb4caSwyllys 		(void) fprintf(stderr,
53799ebb4caSwyllys 		    gettext("Cannot access \"%s\" for modify - %s\n"),
53899ebb4caSwyllys 		    filename, strerror(err));
53999ebb4caSwyllys 		rv = KC_ERR_ACCESS;
54099ebb4caSwyllys 		goto out;
54199ebb4caSwyllys 	}
54299ebb4caSwyllys 
54399ebb4caSwyllys 	/* Try to load the named policy from the DB */
54430a5e8faSwyllys 	ret = kmf_get_policy(filename, plc.name, &oplc);
54599ebb4caSwyllys 	if (ret != KMF_OK) {
54699ebb4caSwyllys 		(void) fprintf(stderr,
54799ebb4caSwyllys 		    gettext("Error loading policy \"%s\" from %s\n"), filename,
54899ebb4caSwyllys 		    plc.name);
54999ebb4caSwyllys 		return (KC_ERR_FIND_POLICY);
55099ebb4caSwyllys 	}
55199ebb4caSwyllys 
55299ebb4caSwyllys 	/* Update the general policy attributes. */
55399ebb4caSwyllys 	if (flags & KC_IGNORE_DATE)
55499ebb4caSwyllys 		oplc.ignore_date = plc.ignore_date;
55599ebb4caSwyllys 
55699ebb4caSwyllys 	if (flags & KC_IGNORE_UNKNOWN_EKUS)
55799ebb4caSwyllys 		oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
55899ebb4caSwyllys 
55999ebb4caSwyllys 	if (flags & KC_IGNORE_TRUST_ANCHOR)
56099ebb4caSwyllys 		oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
56199ebb4caSwyllys 
56299ebb4caSwyllys 	if (flags & KC_VALIDITY_ADJUSTTIME) {
56399ebb4caSwyllys 		if (oplc.validity_adjusttime)
56499ebb4caSwyllys 			free(oplc.validity_adjusttime);
56599ebb4caSwyllys 		oplc.validity_adjusttime =
56699ebb4caSwyllys 		    plc.validity_adjusttime;
56799ebb4caSwyllys 	}
56899ebb4caSwyllys 
56999ebb4caSwyllys 	if (flags & KC_TA_NAME) {
57099ebb4caSwyllys 		if (oplc.ta_name)
57199ebb4caSwyllys 			free(oplc.ta_name);
57299ebb4caSwyllys 		oplc.ta_name = plc.ta_name;
57399ebb4caSwyllys 	}
57499ebb4caSwyllys 	if (flags & KC_TA_SERIAL) {
57599ebb4caSwyllys 		if (oplc.ta_serial)
57699ebb4caSwyllys 			free(oplc.ta_serial);
57799ebb4caSwyllys 		oplc.ta_serial = plc.ta_serial;
57899ebb4caSwyllys 	}
57999ebb4caSwyllys 
58099ebb4caSwyllys 	/* Update the OCSP policy */
58199ebb4caSwyllys 	if (ocsp_none_opt == B_TRUE) {
58299ebb4caSwyllys 		if (ocsp_set_attr > 0) {
58399ebb4caSwyllys 			(void) fprintf(stderr,
58499ebb4caSwyllys 			    gettext("Can not set ocsp-none=true and other "
58599ebb4caSwyllys 			    "OCSP attributes at the same time.\n"));
58699ebb4caSwyllys 			rv = KC_ERR_USAGE;
58799ebb4caSwyllys 			goto out;
58899ebb4caSwyllys 		}
58999ebb4caSwyllys 
59099ebb4caSwyllys 		/*
59199ebb4caSwyllys 		 * If the original policy does not have OCSP checking,
59299ebb4caSwyllys 		 * then we do not need to do anything.  If the original
59399ebb4caSwyllys 		 * policy has the OCSP checking, then we need to release the
59499ebb4caSwyllys 		 * space of OCSP attributes and turn the OCSP checking off.
59599ebb4caSwyllys 		 */
59699ebb4caSwyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
59799ebb4caSwyllys 			if (oplc.VAL_OCSP_BASIC.responderURI) {
59899ebb4caSwyllys 				free(oplc.VAL_OCSP_BASIC.responderURI);
59999ebb4caSwyllys 				oplc.VAL_OCSP_BASIC.responderURI = NULL;
60099ebb4caSwyllys 			}
60199ebb4caSwyllys 
60299ebb4caSwyllys 			if (oplc.VAL_OCSP_BASIC.proxy) {
60399ebb4caSwyllys 				free(oplc.VAL_OCSP_BASIC.proxy);
60499ebb4caSwyllys 				oplc.VAL_OCSP_BASIC.proxy = NULL;
60599ebb4caSwyllys 			}
60699ebb4caSwyllys 
60799ebb4caSwyllys 			if (oplc.VAL_OCSP_BASIC.response_lifetime) {
60899ebb4caSwyllys 				free(oplc.VAL_OCSP_BASIC.response_lifetime);
60999ebb4caSwyllys 				oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
61099ebb4caSwyllys 			}
61199ebb4caSwyllys 
61299ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
61399ebb4caSwyllys 				free(oplc.VAL_OCSP_RESP_CERT.name);
61499ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT.name = NULL;
61599ebb4caSwyllys 			}
61699ebb4caSwyllys 
61799ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
61899ebb4caSwyllys 				free(oplc.VAL_OCSP_RESP_CERT.serial);
61999ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT.serial = NULL;
62099ebb4caSwyllys 			}
62199ebb4caSwyllys 
62299ebb4caSwyllys 			/* Turn off the OCSP checking */
62399ebb4caSwyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
62499ebb4caSwyllys 		}
62599ebb4caSwyllys 
62699ebb4caSwyllys 	} else {
62799ebb4caSwyllys 		/*
62899ebb4caSwyllys 		 * If the "ocsp-none" option is not set or is set to false,
62999ebb4caSwyllys 		 * then we only need to do the modification if there is at
63099ebb4caSwyllys 		 * least one OCSP attribute is specified.
63199ebb4caSwyllys 		 */
63299ebb4caSwyllys 		if (ocsp_set_attr > 0) {
63399ebb4caSwyllys 			if (flags & KC_OCSP_RESPONDER_URI) {
63499ebb4caSwyllys 				if (oplc.VAL_OCSP_RESPONDER_URI)
63599ebb4caSwyllys 					free(oplc.VAL_OCSP_RESPONDER_URI);
63699ebb4caSwyllys 				oplc.VAL_OCSP_RESPONDER_URI =
63799ebb4caSwyllys 				    plc.VAL_OCSP_RESPONDER_URI;
63899ebb4caSwyllys 			}
63999ebb4caSwyllys 
64099ebb4caSwyllys 			if (flags & KC_OCSP_PROXY) {
64199ebb4caSwyllys 				if (oplc.VAL_OCSP_PROXY)
64299ebb4caSwyllys 					free(oplc.VAL_OCSP_PROXY);
64399ebb4caSwyllys 				oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
64499ebb4caSwyllys 			}
64599ebb4caSwyllys 
64699ebb4caSwyllys 			if (flags & KC_OCSP_URI_FROM_CERT)
64799ebb4caSwyllys 				oplc.VAL_OCSP_URI_FROM_CERT =
64899ebb4caSwyllys 				    plc.VAL_OCSP_URI_FROM_CERT;
64999ebb4caSwyllys 
65099ebb4caSwyllys 			if (flags & KC_OCSP_RESP_LIFETIME) {
65199ebb4caSwyllys 				if (oplc.VAL_OCSP_RESP_LIFETIME)
65299ebb4caSwyllys 					free(oplc.VAL_OCSP_RESP_LIFETIME);
65399ebb4caSwyllys 				oplc.VAL_OCSP_RESP_LIFETIME =
65499ebb4caSwyllys 				    plc.VAL_OCSP_RESP_LIFETIME;
65599ebb4caSwyllys 			}
65699ebb4caSwyllys 
65799ebb4caSwyllys 			if (flags & KC_OCSP_IGNORE_RESP_SIGN)
65899ebb4caSwyllys 				oplc.VAL_OCSP_IGNORE_RESP_SIGN =
65999ebb4caSwyllys 				    plc.VAL_OCSP_IGNORE_RESP_SIGN;
66099ebb4caSwyllys 
66199ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
66299ebb4caSwyllys 				if (oplc.VAL_OCSP_RESP_CERT_NAME)
66399ebb4caSwyllys 					free(oplc.VAL_OCSP_RESP_CERT_NAME);
66499ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT_NAME =
66599ebb4caSwyllys 				    plc.VAL_OCSP_RESP_CERT_NAME;
66699ebb4caSwyllys 			}
66799ebb4caSwyllys 
66899ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
66999ebb4caSwyllys 				if (oplc.VAL_OCSP_RESP_CERT_SERIAL)
67099ebb4caSwyllys 					free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
67199ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT_SERIAL =
67299ebb4caSwyllys 				    plc.VAL_OCSP_RESP_CERT_SERIAL;
67399ebb4caSwyllys 			}
67499ebb4caSwyllys 
67599ebb4caSwyllys 			if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
67699ebb4caSwyllys 			    oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
67799ebb4caSwyllys 				oplc.VAL_OCSP.has_resp_cert = B_TRUE;
67899ebb4caSwyllys 			else
67999ebb4caSwyllys 				oplc.VAL_OCSP.has_resp_cert = B_FALSE;
68099ebb4caSwyllys 
68199ebb4caSwyllys 			/* Turn on the OCSP checking */
68299ebb4caSwyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
68399ebb4caSwyllys 		}
68499ebb4caSwyllys 	}
68599ebb4caSwyllys 
68699ebb4caSwyllys 	/* Update the CRL policy */
68799ebb4caSwyllys 	if (crl_none_opt == B_TRUE) {
68899ebb4caSwyllys 		if (crl_set_attr > 0) {
68999ebb4caSwyllys 			(void) fprintf(stderr,
69099ebb4caSwyllys 			    gettext("Can not set crl-none=true and other CRL "
69199ebb4caSwyllys 			    "attributes at the same time.\n"));
69299ebb4caSwyllys 			rv = KC_ERR_USAGE;
69399ebb4caSwyllys 			goto out;
69499ebb4caSwyllys 		}
69599ebb4caSwyllys 
69699ebb4caSwyllys 		/*
69799ebb4caSwyllys 		 * If the original policy does not have CRL checking,
69899ebb4caSwyllys 		 * then we do not need to do anything.  If the original
69999ebb4caSwyllys 		 * policy has the CRL checking, then we need to release the
70099ebb4caSwyllys 		 * space of CRL attributes and turn the CRL checking off.
70199ebb4caSwyllys 		 */
70299ebb4caSwyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
70399ebb4caSwyllys 			if (oplc.VAL_CRL_BASEFILENAME) {
70499ebb4caSwyllys 				free(oplc.VAL_CRL_BASEFILENAME);
70599ebb4caSwyllys 				oplc.VAL_CRL_BASEFILENAME = NULL;
70699ebb4caSwyllys 			}
70799ebb4caSwyllys 
70899ebb4caSwyllys 			if (oplc.VAL_CRL_DIRECTORY) {
70999ebb4caSwyllys 				free(oplc.VAL_CRL_DIRECTORY);
71099ebb4caSwyllys 				oplc.VAL_CRL_DIRECTORY = NULL;
71199ebb4caSwyllys 			}
71299ebb4caSwyllys 
71399ebb4caSwyllys 			if (oplc.VAL_CRL_PROXY) {
71499ebb4caSwyllys 				free(oplc.VAL_CRL_PROXY);
71599ebb4caSwyllys 				oplc.VAL_CRL_PROXY = NULL;
71699ebb4caSwyllys 			}
71799ebb4caSwyllys 
71899ebb4caSwyllys 			/* Turn off the CRL checking */
71999ebb4caSwyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
72099ebb4caSwyllys 		}
72199ebb4caSwyllys 	} else {
72299ebb4caSwyllys 		/*
72399ebb4caSwyllys 		 * If the "ocsp-none" option is not set or is set to false,
72499ebb4caSwyllys 		 * then we only need to do the modification if there is at
72599ebb4caSwyllys 		 * least one CRL attribute is specified.
72699ebb4caSwyllys 		 */
72799ebb4caSwyllys 		if (crl_set_attr > 0) {
72899ebb4caSwyllys 			if (flags & KC_CRL_BASEFILENAME) {
72999ebb4caSwyllys 				if (oplc.VAL_CRL_BASEFILENAME)
73099ebb4caSwyllys 					free(oplc.VAL_CRL_BASEFILENAME);
73199ebb4caSwyllys 				oplc.VAL_CRL_BASEFILENAME =
73299ebb4caSwyllys 				    plc.VAL_CRL_BASEFILENAME;
73399ebb4caSwyllys 			}
73499ebb4caSwyllys 
73599ebb4caSwyllys 			if (flags & KC_CRL_DIRECTORY) {
73699ebb4caSwyllys 				if (oplc.VAL_CRL_DIRECTORY)
73799ebb4caSwyllys 					free(oplc.VAL_CRL_DIRECTORY);
73899ebb4caSwyllys 				oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
73999ebb4caSwyllys 			}
74099ebb4caSwyllys 
74199ebb4caSwyllys 			if (flags & KC_CRL_GET_URI) {
74299ebb4caSwyllys 				oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
74399ebb4caSwyllys 			}
74499ebb4caSwyllys 
74599ebb4caSwyllys 			if (flags & KC_CRL_PROXY) {
74699ebb4caSwyllys 				if (oplc.VAL_CRL_PROXY)
74799ebb4caSwyllys 					free(oplc.VAL_CRL_PROXY);
74899ebb4caSwyllys 				oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
74999ebb4caSwyllys 			}
75099ebb4caSwyllys 
75199ebb4caSwyllys 			if (flags & KC_CRL_IGNORE_SIGN) {
75299ebb4caSwyllys 				oplc.VAL_CRL_IGNORE_SIGN =
75399ebb4caSwyllys 				    plc.VAL_CRL_IGNORE_SIGN;
75499ebb4caSwyllys 			}
75599ebb4caSwyllys 
75699ebb4caSwyllys 			if (flags & KC_CRL_IGNORE_DATE) {
75799ebb4caSwyllys 				oplc.VAL_CRL_IGNORE_DATE =
75899ebb4caSwyllys 				    plc.VAL_CRL_IGNORE_DATE;
75999ebb4caSwyllys 			}
76099ebb4caSwyllys 
76199ebb4caSwyllys 			/* Turn on the CRL checking */
76299ebb4caSwyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
76399ebb4caSwyllys 		}
76499ebb4caSwyllys 	}
76599ebb4caSwyllys 
76699ebb4caSwyllys 	/* Update the Key Usage */
76799ebb4caSwyllys 	if (ku_none_opt == B_TRUE) {
76899ebb4caSwyllys 		if (flags & KC_KEYUSAGE) {
76999ebb4caSwyllys 			(void) fprintf(stderr,
77099ebb4caSwyllys 			    gettext("Can not set keyusage-none=true and "
77199ebb4caSwyllys 			    "modify the keyusage value at the same time.\n"));
77299ebb4caSwyllys 			rv = KC_ERR_USAGE;
77399ebb4caSwyllys 			goto out;
77499ebb4caSwyllys 		}
77599ebb4caSwyllys 
77699ebb4caSwyllys 		oplc.ku_bits = 0;
77799ebb4caSwyllys 	} else {
77899ebb4caSwyllys 		/*
77999ebb4caSwyllys 		 * If the "keyusage-none" option is not set or is set to
78099ebb4caSwyllys 		 * false, then we only need to do the modification if
78199ebb4caSwyllys 		 * the keyusage value is specified.
78299ebb4caSwyllys 		 */
78399ebb4caSwyllys 		if (flags & KC_KEYUSAGE)
78499ebb4caSwyllys 			oplc.ku_bits = plc.ku_bits;
78599ebb4caSwyllys 	}
78699ebb4caSwyllys 
78799ebb4caSwyllys 
78899ebb4caSwyllys 	/* Update the Extended Key Usage */
78999ebb4caSwyllys 	if (eku_none_opt == B_TRUE) {
79099ebb4caSwyllys 		if (flags & KC_EKUS) {
79199ebb4caSwyllys 			(void) fprintf(stderr,
79299ebb4caSwyllys 			    gettext("Can not set eku-none=true and modify "
79399ebb4caSwyllys 			    "EKU values at the same time.\n"));
79499ebb4caSwyllys 			rv = KC_ERR_USAGE;
79599ebb4caSwyllys 			goto out;
79699ebb4caSwyllys 		}
79799ebb4caSwyllys 
79899ebb4caSwyllys 		/* Release current EKU list (if any) */
79999ebb4caSwyllys 		if (oplc.eku_set.eku_count > 0) {
80030a5e8faSwyllys 			kmf_free_eku_policy(&oplc.eku_set);
80199ebb4caSwyllys 			oplc.eku_set.eku_count = 0;
80299ebb4caSwyllys 			oplc.eku_set.ekulist = NULL;
80399ebb4caSwyllys 		}
80499ebb4caSwyllys 	} else {
80599ebb4caSwyllys 		/*
80699ebb4caSwyllys 		 * If the "eku-none" option is not set or is set to false,
80799ebb4caSwyllys 		 * then we only need to do the modification if either
80899ebb4caSwyllys 		 * "ekuname" or "ekuoids" is specified.
80999ebb4caSwyllys 		 */
81099ebb4caSwyllys 		if (flags & KC_EKUS) {
81199ebb4caSwyllys 			/* Release current EKU list (if any) */
81230a5e8faSwyllys 			kmf_free_eku_policy(&oplc.eku_set);
81399ebb4caSwyllys 			oplc.eku_set = plc.eku_set;
81499ebb4caSwyllys 		}
81599ebb4caSwyllys 	}
81699ebb4caSwyllys 
81799ebb4caSwyllys 	/* Do a sanity check on the modified policy */
81830a5e8faSwyllys 	ret = kmf_verify_policy(&oplc);
81999ebb4caSwyllys 	if (ret != KMF_OK) {
82099ebb4caSwyllys 		print_sanity_error(ret);
82199ebb4caSwyllys 		rv = KC_ERR_VERIFY_POLICY;
82299ebb4caSwyllys 		goto out;
82399ebb4caSwyllys 	}
82499ebb4caSwyllys 
82599ebb4caSwyllys 	/* The modify operation is a delete followed by an add */
82630a5e8faSwyllys 	ret = kmf_delete_policy_from_db(oplc.name, filename);
82799ebb4caSwyllys 	if (ret != KMF_OK) {
82899ebb4caSwyllys 		rv = KC_ERR_DELETE_POLICY;
82999ebb4caSwyllys 		goto out;
83099ebb4caSwyllys 	}
83199ebb4caSwyllys 
83299ebb4caSwyllys 	/*
83399ebb4caSwyllys 	 * Now add the modified policy back to the DB.
83499ebb4caSwyllys 	 */
83530a5e8faSwyllys 	ret = kmf_add_policy_to_db(&oplc, filename, B_FALSE);
83699ebb4caSwyllys 	if (ret != KMF_OK) {
83799ebb4caSwyllys 		(void) fprintf(stderr,
83899ebb4caSwyllys 		    gettext("Error adding policy to database: 0x%04x\n"), ret);
83999ebb4caSwyllys 		rv = KC_ERR_ADD_POLICY;
84099ebb4caSwyllys 		goto out;
84199ebb4caSwyllys 	}
84299ebb4caSwyllys 
84399ebb4caSwyllys out:
84499ebb4caSwyllys 	if (filename != NULL)
84599ebb4caSwyllys 		free(filename);
84699ebb4caSwyllys 
84730a5e8faSwyllys 	kmf_free_policy_record(&oplc);
84899ebb4caSwyllys 
84999ebb4caSwyllys 	return (rv);
85099ebb4caSwyllys }
851*431deaa0Shylee 
852*431deaa0Shylee 
853*431deaa0Shylee static int
854*431deaa0Shylee kc_modify_plugin(int argc, char *argv[])
855*431deaa0Shylee {
856*431deaa0Shylee 	int 		rv = KC_OK;
857*431deaa0Shylee 	int		opt;
858*431deaa0Shylee 	extern int	optind_av;
859*431deaa0Shylee 	extern char	*optarg_av;
860*431deaa0Shylee 	char 		*keystore_name = NULL;
861*431deaa0Shylee 	char		*option = NULL;
862*431deaa0Shylee 	boolean_t	modify_plugin = B_FALSE;
863*431deaa0Shylee 	boolean_t 	has_option_arg = B_FALSE;
864*431deaa0Shylee 	conf_entry_t	*entry = NULL;
865*431deaa0Shylee 	FILE		*pfile = NULL;
866*431deaa0Shylee 	FILE		*pfile_tmp = NULL;
867*431deaa0Shylee 	char		tmpfile_name[MAXPATHLEN];
868*431deaa0Shylee 	char 		buffer[MAXPATHLEN];
869*431deaa0Shylee 	char 		buffer2[MAXPATHLEN];
870*431deaa0Shylee 
871*431deaa0Shylee 	while ((opt = getopt_av(argc, argv, "p(plugin)k:(keystore)o:(option)"))
872*431deaa0Shylee 	    != EOF) {
873*431deaa0Shylee 		switch (opt) {
874*431deaa0Shylee 		case 'p':
875*431deaa0Shylee 			if (modify_plugin) {
876*431deaa0Shylee 				(void) fprintf(stderr,
877*431deaa0Shylee 				    gettext("duplicate plugin input.\n"));
878*431deaa0Shylee 				rv = KC_ERR_USAGE;
879*431deaa0Shylee 			} else {
880*431deaa0Shylee 				modify_plugin = B_TRUE;
881*431deaa0Shylee 			}
882*431deaa0Shylee 			break;
883*431deaa0Shylee 		case 'k':
884*431deaa0Shylee 			if (keystore_name != NULL)
885*431deaa0Shylee 				rv = KC_ERR_USAGE;
886*431deaa0Shylee 			else {
887*431deaa0Shylee 				keystore_name = get_string(optarg_av, &rv);
888*431deaa0Shylee 				if (keystore_name == NULL) {
889*431deaa0Shylee 					(void) fprintf(stderr, gettext(
890*431deaa0Shylee 					    "Error keystore input.\n"));
891*431deaa0Shylee 					rv = KC_ERR_USAGE;
892*431deaa0Shylee 				}
893*431deaa0Shylee 			}
894*431deaa0Shylee 			break;
895*431deaa0Shylee 		case 'o':
896*431deaa0Shylee 			if (has_option_arg) {
897*431deaa0Shylee 				(void) fprintf(stderr,
898*431deaa0Shylee 				    gettext("duplicate option input.\n"));
899*431deaa0Shylee 				rv = KC_ERR_USAGE;
900*431deaa0Shylee 			} else {
901*431deaa0Shylee 				has_option_arg = B_TRUE;
902*431deaa0Shylee 				option = get_string(optarg_av, NULL);
903*431deaa0Shylee 			}
904*431deaa0Shylee 			break;
905*431deaa0Shylee 		default:
906*431deaa0Shylee 			(void) fprintf(stderr,
907*431deaa0Shylee 			    gettext("Error input option.\n"));
908*431deaa0Shylee 			rv = KC_ERR_USAGE;
909*431deaa0Shylee 			break;
910*431deaa0Shylee 		}
911*431deaa0Shylee 
912*431deaa0Shylee 		if (rv != KC_OK)
913*431deaa0Shylee 			goto out;
914*431deaa0Shylee 	}
915*431deaa0Shylee 
916*431deaa0Shylee 	/* No additional args allowed. */
917*431deaa0Shylee 	argc -= optind_av;
918*431deaa0Shylee 	if (argc) {
919*431deaa0Shylee 		(void) fprintf(stderr,
920*431deaa0Shylee 		    gettext("Error input option\n"));
921*431deaa0Shylee 		rv = KC_ERR_USAGE;
922*431deaa0Shylee 		goto out;
923*431deaa0Shylee 	}
924*431deaa0Shylee 
925*431deaa0Shylee 	if (keystore_name == NULL || has_option_arg == B_FALSE) {
926*431deaa0Shylee 		(void) fprintf(stderr,
927*431deaa0Shylee 		    gettext("Error input option\n"));
928*431deaa0Shylee 		rv = KC_ERR_USAGE;
929*431deaa0Shylee 		goto out;
930*431deaa0Shylee 	}
931*431deaa0Shylee 
932*431deaa0Shylee 	if (strcasecmp(keystore_name, "nss") == 0 ||
933*431deaa0Shylee 	    strcasecmp(keystore_name, "pkcs11") == 0 ||
934*431deaa0Shylee 	    strcasecmp(keystore_name, "file") == 0) {
935*431deaa0Shylee 		(void) fprintf(stderr,
936*431deaa0Shylee 		    gettext("Can not modify the built-in keystore %s\n"),
937*431deaa0Shylee 		    keystore_name);
938*431deaa0Shylee 		rv = KC_ERR_USAGE;
939*431deaa0Shylee 		goto out;
940*431deaa0Shylee 	}
941*431deaa0Shylee 
942*431deaa0Shylee 	entry = get_keystore_entry(keystore_name);
943*431deaa0Shylee 	if (entry == NULL) {
944*431deaa0Shylee 		(void) fprintf(stderr, gettext("%s does not exist.\n"),
945*431deaa0Shylee 		    keystore_name);
946*431deaa0Shylee 		rv = KC_ERR_USAGE;
947*431deaa0Shylee 		goto out;
948*431deaa0Shylee 	}
949*431deaa0Shylee 
950*431deaa0Shylee 	if ((entry->option == NULL && option == NULL) ||
951*431deaa0Shylee 	    (entry->option != NULL && option != NULL &&
952*431deaa0Shylee 	    strcmp(entry->option, option) == 0)) {
953*431deaa0Shylee 		(void) fprintf(stderr, gettext("No change - "
954*431deaa0Shylee 		    "the new option is same as the old option.\n"));
955*431deaa0Shylee 		rv = KC_OK;
956*431deaa0Shylee 		goto out;
957*431deaa0Shylee 	}
958*431deaa0Shylee 
959*431deaa0Shylee 	if ((pfile = fopen(_PATH_KMF_CONF, "r+")) == NULL) {
960*431deaa0Shylee 		err = errno;
961*431deaa0Shylee 		(void) fprintf(stderr,
962*431deaa0Shylee 		    gettext("failed to update the configuration - %s\n"),
963*431deaa0Shylee 		    strerror(err));
964*431deaa0Shylee 		rv = KC_ERR_ACCESS;
965*431deaa0Shylee 		goto out;
966*431deaa0Shylee 	}
967*431deaa0Shylee 
968*431deaa0Shylee 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
969*431deaa0Shylee 		err = errno;
970*431deaa0Shylee 		(void) fprintf(stderr,
971*431deaa0Shylee 		    gettext("failed to lock the configuration - %s\n"),
972*431deaa0Shylee 		    strerror(err));
973*431deaa0Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
974*431deaa0Shylee 		goto out;
975*431deaa0Shylee 	}
976*431deaa0Shylee 
977*431deaa0Shylee 	/*
978*431deaa0Shylee 	 * Create a temporary file in the /etc/crypto directory.
979*431deaa0Shylee 	 */
980*431deaa0Shylee 	(void) strlcpy(tmpfile_name, CONF_TEMPFILE, sizeof (tmpfile_name));
981*431deaa0Shylee 	if (mkstemp(tmpfile_name) == -1) {
982*431deaa0Shylee 		err = errno;
983*431deaa0Shylee 		(void) fprintf(stderr,
984*431deaa0Shylee 		    gettext("failed to create a temporary file - %s\n"),
985*431deaa0Shylee 		    strerror(err));
986*431deaa0Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
987*431deaa0Shylee 		goto out;
988*431deaa0Shylee 	}
989*431deaa0Shylee 
990*431deaa0Shylee 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
991*431deaa0Shylee 		err = errno;
992*431deaa0Shylee 		(void) fprintf(stderr,
993*431deaa0Shylee 		    gettext("failed to open %s - %s\n"),
994*431deaa0Shylee 		    tmpfile_name, strerror(err));
995*431deaa0Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
996*431deaa0Shylee 		goto out;
997*431deaa0Shylee 	}
998*431deaa0Shylee 
999*431deaa0Shylee 	/*
1000*431deaa0Shylee 	 * Loop thru the config file and update the entry.
1001*431deaa0Shylee 	 */
1002*431deaa0Shylee 	while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
1003*431deaa0Shylee 		char *name;
1004*431deaa0Shylee 		int len;
1005*431deaa0Shylee 
1006*431deaa0Shylee 		if (buffer[0] == '#') {
1007*431deaa0Shylee 			if (fputs(buffer, pfile_tmp) == EOF) {
1008*431deaa0Shylee 				rv = KC_ERR_MODIFY_PLUGIN;
1009*431deaa0Shylee 				goto out;
1010*431deaa0Shylee 			} else {
1011*431deaa0Shylee 				continue;
1012*431deaa0Shylee 			}
1013*431deaa0Shylee 		}
1014*431deaa0Shylee 
1015*431deaa0Shylee 		/*
1016*431deaa0Shylee 		 * make a copy of the original buffer to buffer2.  Also get
1017*431deaa0Shylee 		 * rid of the trailing '\n' from buffer2.
1018*431deaa0Shylee 		 */
1019*431deaa0Shylee 		(void) strlcpy(buffer2, buffer, MAXPATHLEN);
1020*431deaa0Shylee 		len = strlen(buffer2);
1021*431deaa0Shylee 		if (buffer2[len-1] == '\n') {
1022*431deaa0Shylee 			len--;
1023*431deaa0Shylee 		}
1024*431deaa0Shylee 		buffer2[len] = '\0';
1025*431deaa0Shylee 
1026*431deaa0Shylee 		if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
1027*431deaa0Shylee 			rv = KC_ERR_UNINSTALL;
1028*431deaa0Shylee 			goto out;
1029*431deaa0Shylee 		}
1030*431deaa0Shylee 
1031*431deaa0Shylee 		if (strcmp(name, keystore_name) == 0) {
1032*431deaa0Shylee 			/* found the entry */
1033*431deaa0Shylee 			if (option == NULL)
1034*431deaa0Shylee 				(void) snprintf(buffer, MAXPATHLEN,
1035*431deaa0Shylee 				    "%s:%s%s\n", keystore_name,
1036*431deaa0Shylee 				    CONF_MODULEPATH, entry->modulepath);
1037*431deaa0Shylee 			else
1038*431deaa0Shylee 				(void) snprintf(buffer, MAXPATHLEN,
1039*431deaa0Shylee 				    "%s:%s%s;%s%s\n", keystore_name,
1040*431deaa0Shylee 				    CONF_MODULEPATH, entry->modulepath,
1041*431deaa0Shylee 				    CONF_OPTION, option);
1042*431deaa0Shylee 
1043*431deaa0Shylee 			if (fputs(buffer, pfile_tmp) == EOF) {
1044*431deaa0Shylee 				err = errno;
1045*431deaa0Shylee 				(void) fprintf(stderr, gettext(
1046*431deaa0Shylee 				    "failed to write to %s: %s\n"),
1047*431deaa0Shylee 				    tmpfile_name, strerror(err));
1048*431deaa0Shylee 				rv = KC_ERR_MODIFY_PLUGIN;
1049*431deaa0Shylee 				goto out;
1050*431deaa0Shylee 			}
1051*431deaa0Shylee 		} else {
1052*431deaa0Shylee 
1053*431deaa0Shylee 			if (fputs(buffer, pfile_tmp) == EOF) {
1054*431deaa0Shylee 				rv = KC_ERR_UNINSTALL;
1055*431deaa0Shylee 				goto out;
1056*431deaa0Shylee 			}
1057*431deaa0Shylee 		}
1058*431deaa0Shylee 	}
1059*431deaa0Shylee 
1060*431deaa0Shylee 	if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) {
1061*431deaa0Shylee 		err = errno;
1062*431deaa0Shylee 		(void) fprintf(stderr, gettext(
1063*431deaa0Shylee 		    "failed to update the configuration - %s"), strerror(err));
1064*431deaa0Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
1065*431deaa0Shylee 		goto out;
1066*431deaa0Shylee 	}
1067*431deaa0Shylee 
1068*431deaa0Shylee 	if (chmod(_PATH_KMF_CONF,
1069*431deaa0Shylee 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1070*431deaa0Shylee 		err = errno;
1071*431deaa0Shylee 		(void) fprintf(stderr, gettext(
1072*431deaa0Shylee 		    "failed to update the configuration - %s\n"),
1073*431deaa0Shylee 		    strerror(err));
1074*431deaa0Shylee 		rv = KC_ERR_MODIFY_PLUGIN;
1075*431deaa0Shylee 		goto out;
1076*431deaa0Shylee 	}
1077*431deaa0Shylee 
1078*431deaa0Shylee out:
1079*431deaa0Shylee 	if (entry != NULL)
1080*431deaa0Shylee 		free_entry(entry);
1081*431deaa0Shylee 
1082*431deaa0Shylee 	if (pfile != NULL)
1083*431deaa0Shylee 		(void) fclose(pfile);
1084*431deaa0Shylee 
1085*431deaa0Shylee 	if (rv != KC_OK && pfile_tmp != NULL)
1086*431deaa0Shylee 		(void) unlink(tmpfile_name);
1087*431deaa0Shylee 
1088*431deaa0Shylee 	if (pfile_tmp != NULL)
1089*431deaa0Shylee 		(void) fclose(pfile_tmp);
1090*431deaa0Shylee 
1091*431deaa0Shylee 	return (rv);
1092*431deaa0Shylee }
1093*431deaa0Shylee 
1094*431deaa0Shylee 
1095*431deaa0Shylee int
1096*431deaa0Shylee kc_modify(int argc, char *argv[])
1097*431deaa0Shylee {
1098*431deaa0Shylee 	if (argc > 2 &&
1099*431deaa0Shylee 	    strcmp(argv[0], "modify") == 0 &&
1100*431deaa0Shylee 	    strcmp(argv[1], "plugin") == 0) {
1101*431deaa0Shylee 		return (kc_modify_plugin(argc, argv));
1102*431deaa0Shylee 	} else {
1103*431deaa0Shylee 		return (kc_modify_policy(argc, argv));
1104*431deaa0Shylee 	}
1105*431deaa0Shylee }
1106