xref: /titanic_51/usr/src/cmd/cmd-crypto/kmfcfg/modify.c (revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8)
1*99ebb4caSwyllys /*
2*99ebb4caSwyllys  * CDDL HEADER START
3*99ebb4caSwyllys  *
4*99ebb4caSwyllys  * The contents of this file are subject to the terms of the
5*99ebb4caSwyllys  * Common Development and Distribution License (the "License").
6*99ebb4caSwyllys  * You may not use this file except in compliance with the License.
7*99ebb4caSwyllys  *
8*99ebb4caSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*99ebb4caSwyllys  * or http://www.opensolaris.org/os/licensing.
10*99ebb4caSwyllys  * See the License for the specific language governing permissions
11*99ebb4caSwyllys  * and limitations under the License.
12*99ebb4caSwyllys  *
13*99ebb4caSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
14*99ebb4caSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*99ebb4caSwyllys  * If applicable, add the following below this CDDL HEADER, with the
16*99ebb4caSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
17*99ebb4caSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
18*99ebb4caSwyllys  *
19*99ebb4caSwyllys  * CDDL HEADER END
20*99ebb4caSwyllys  *
21*99ebb4caSwyllys  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
22*99ebb4caSwyllys  * Use is subject to license terms.
23*99ebb4caSwyllys  */
24*99ebb4caSwyllys 
25*99ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
26*99ebb4caSwyllys 
27*99ebb4caSwyllys #include <stdio.h>
28*99ebb4caSwyllys #include <strings.h>
29*99ebb4caSwyllys #include <ctype.h>
30*99ebb4caSwyllys #include <libgen.h>
31*99ebb4caSwyllys #include <libintl.h>
32*99ebb4caSwyllys #include <errno.h>
33*99ebb4caSwyllys #include <kmfapiP.h>
34*99ebb4caSwyllys #include <cryptoutil.h>
35*99ebb4caSwyllys #include "util.h"
36*99ebb4caSwyllys 
37*99ebb4caSwyllys #define	KC_IGNORE_DATE			0x0000001
38*99ebb4caSwyllys #define	KC_IGNORE_UNKNOWN_EKUS		0x0000002
39*99ebb4caSwyllys #define	KC_IGNORE_TRUST_ANCHOR		0x0000004
40*99ebb4caSwyllys #define	KC_VALIDITY_ADJUSTTIME		0x0000008
41*99ebb4caSwyllys #define	KC_TA_NAME			0x0000010
42*99ebb4caSwyllys #define	KC_TA_SERIAL			0x0000020
43*99ebb4caSwyllys #define	KC_OCSP_RESPONDER_URI		0x0000040
44*99ebb4caSwyllys #define	KC_OCSP_PROXY			0x0000080
45*99ebb4caSwyllys #define	KC_OCSP_URI_FROM_CERT		0x0000100
46*99ebb4caSwyllys #define	KC_OCSP_RESP_LIFETIME		0x0000200
47*99ebb4caSwyllys #define	KC_OCSP_IGNORE_RESP_SIGN 	0x0000400
48*99ebb4caSwyllys #define	KC_OCSP_RESP_CERT_NAME		0x0000800
49*99ebb4caSwyllys #define	KC_OCSP_RESP_CERT_SERIAL	0x0001000
50*99ebb4caSwyllys #define	KC_OCSP_NONE			0x0002000
51*99ebb4caSwyllys #define	KC_CRL_BASEFILENAME		0x0004000
52*99ebb4caSwyllys #define	KC_CRL_DIRECTORY		0x0008000
53*99ebb4caSwyllys #define	KC_CRL_GET_URI			0x0010000
54*99ebb4caSwyllys #define	KC_CRL_PROXY			0x0020000
55*99ebb4caSwyllys #define	KC_CRL_IGNORE_SIGN		0x0040000
56*99ebb4caSwyllys #define	KC_CRL_IGNORE_DATE		0x0080000
57*99ebb4caSwyllys #define	KC_CRL_NONE			0x0100000
58*99ebb4caSwyllys #define	KC_KEYUSAGE			0x0200000
59*99ebb4caSwyllys #define	KC_KEYUSAGE_NONE		0x0400000
60*99ebb4caSwyllys #define	KC_EKUS				0x0800000
61*99ebb4caSwyllys #define	KC_EKUS_NONE			0x1000000
62*99ebb4caSwyllys 
63*99ebb4caSwyllys int
64*99ebb4caSwyllys kc_modify(int argc, char *argv[])
65*99ebb4caSwyllys {
66*99ebb4caSwyllys 	KMF_RETURN	ret;
67*99ebb4caSwyllys 	int 		rv = KC_OK;
68*99ebb4caSwyllys 	int		opt;
69*99ebb4caSwyllys 	extern int	optind_av;
70*99ebb4caSwyllys 	extern char	*optarg_av;
71*99ebb4caSwyllys 	char		*filename = NULL;
72*99ebb4caSwyllys 	uint32_t	flags = 0;
73*99ebb4caSwyllys 	boolean_t	ocsp_none_opt = B_FALSE;
74*99ebb4caSwyllys 	boolean_t	crl_none_opt = B_FALSE;
75*99ebb4caSwyllys 	boolean_t	ku_none_opt = B_FALSE;
76*99ebb4caSwyllys 	boolean_t	eku_none_opt = B_FALSE;
77*99ebb4caSwyllys 	int		ocsp_set_attr = 0;
78*99ebb4caSwyllys 	int		crl_set_attr = 0;
79*99ebb4caSwyllys 	KMF_POLICY_RECORD oplc, plc;
80*99ebb4caSwyllys 
81*99ebb4caSwyllys 	(void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
82*99ebb4caSwyllys 	(void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD));
83*99ebb4caSwyllys 
84*99ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
85*99ebb4caSwyllys 		"i:(dbfile)"
86*99ebb4caSwyllys 		"p:(policy)"
87*99ebb4caSwyllys 		"d:(ignore-date)"
88*99ebb4caSwyllys 		"e:(ignore-unknown-eku)"
89*99ebb4caSwyllys 		"a:(ignore-trust-anchor)"
90*99ebb4caSwyllys 		"v:(validity-adjusttime)"
91*99ebb4caSwyllys 		"t:(ta-name)"
92*99ebb4caSwyllys 		"s:(ta-serial)"
93*99ebb4caSwyllys 		"o:(ocsp-responder)"
94*99ebb4caSwyllys 		"P:(ocsp-proxy)"
95*99ebb4caSwyllys 		"r:(ocsp-use-cert-responder)"
96*99ebb4caSwyllys 		"T:(ocsp-response-lifetime)"
97*99ebb4caSwyllys 		"R:(ocsp-ignore-response-sign)"
98*99ebb4caSwyllys 		"n:(ocsp-responder-cert-name)"
99*99ebb4caSwyllys 		"A:(ocsp-responder-cert-serial)"
100*99ebb4caSwyllys 		"y:(ocsp-none)"
101*99ebb4caSwyllys 		"c:(crl-basefilename)"
102*99ebb4caSwyllys 		"I:(crl-directory)"
103*99ebb4caSwyllys 		"g:(crl-get-crl-uri)"
104*99ebb4caSwyllys 		"X:(crl-proxy)"
105*99ebb4caSwyllys 		"S:(crl-ignore-crl-sign)"
106*99ebb4caSwyllys 		"D:(crl-ignore-crl-date)"
107*99ebb4caSwyllys 		"z:(crl-none)"
108*99ebb4caSwyllys 		"u:(keyusage)"
109*99ebb4caSwyllys 		"Y:(keyusage-none)"
110*99ebb4caSwyllys 		"E:(ekunames)"
111*99ebb4caSwyllys 		"O:(ekuoids)"
112*99ebb4caSwyllys 		"Z:(eku-none)")) != EOF) {
113*99ebb4caSwyllys 		switch (opt) {
114*99ebb4caSwyllys 			case 'i':
115*99ebb4caSwyllys 				filename = get_string(optarg_av, &rv);
116*99ebb4caSwyllys 				if (filename == NULL) {
117*99ebb4caSwyllys 					(void) fprintf(stderr,
118*99ebb4caSwyllys 					    gettext("Error dbfile input.\n"));
119*99ebb4caSwyllys 				}
120*99ebb4caSwyllys 				break;
121*99ebb4caSwyllys 			case 'p':
122*99ebb4caSwyllys 				plc.name = get_string(optarg_av, &rv);
123*99ebb4caSwyllys 				if (plc.name == NULL) {
124*99ebb4caSwyllys 					(void) fprintf(stderr,
125*99ebb4caSwyllys 					    gettext("Error policy name.\n"));
126*99ebb4caSwyllys 				}
127*99ebb4caSwyllys 				break;
128*99ebb4caSwyllys 			case 'd':
129*99ebb4caSwyllys 				plc.ignore_date = get_boolean(optarg_av);
130*99ebb4caSwyllys 				if (plc.ignore_date == -1) {
131*99ebb4caSwyllys 					(void) fprintf(stderr,
132*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
133*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
134*99ebb4caSwyllys 				} else {
135*99ebb4caSwyllys 					flags |= KC_IGNORE_DATE;
136*99ebb4caSwyllys 				}
137*99ebb4caSwyllys 				break;
138*99ebb4caSwyllys 			case 'e':
139*99ebb4caSwyllys 				plc.ignore_unknown_ekus =
140*99ebb4caSwyllys 				    get_boolean(optarg_av);
141*99ebb4caSwyllys 				if (plc.ignore_unknown_ekus == -1) {
142*99ebb4caSwyllys 					(void) fprintf(stderr,
143*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
144*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
145*99ebb4caSwyllys 				} else {
146*99ebb4caSwyllys 					flags |= KC_IGNORE_UNKNOWN_EKUS;
147*99ebb4caSwyllys 				}
148*99ebb4caSwyllys 				break;
149*99ebb4caSwyllys 			case 'a':
150*99ebb4caSwyllys 				plc.ignore_trust_anchor =
151*99ebb4caSwyllys 				    get_boolean(optarg_av);
152*99ebb4caSwyllys 				if (plc.ignore_trust_anchor == -1) {
153*99ebb4caSwyllys 					(void) fprintf(stderr,
154*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
155*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
156*99ebb4caSwyllys 				} else {
157*99ebb4caSwyllys 					flags |= KC_IGNORE_TRUST_ANCHOR;
158*99ebb4caSwyllys 				}
159*99ebb4caSwyllys 				break;
160*99ebb4caSwyllys 			case 'v':
161*99ebb4caSwyllys 				plc.validity_adjusttime =
162*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
163*99ebb4caSwyllys 				if (plc.validity_adjusttime == NULL) {
164*99ebb4caSwyllys 					(void) fprintf(stderr,
165*99ebb4caSwyllys 					    gettext("Error time input.\n"));
166*99ebb4caSwyllys 				} else {
167*99ebb4caSwyllys 					uint32_t adj;
168*99ebb4caSwyllys 					/* for syntax checking */
169*99ebb4caSwyllys 					if (str2lifetime(
170*99ebb4caSwyllys 					    plc.validity_adjusttime,
171*99ebb4caSwyllys 					    &adj) < 0) {
172*99ebb4caSwyllys 						(void) fprintf(stderr,
173*99ebb4caSwyllys 						    gettext("Error time "
174*99ebb4caSwyllys 						    "input.\n"));
175*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
176*99ebb4caSwyllys 					} else {
177*99ebb4caSwyllys 						flags |= KC_VALIDITY_ADJUSTTIME;
178*99ebb4caSwyllys 					}
179*99ebb4caSwyllys 				}
180*99ebb4caSwyllys 				break;
181*99ebb4caSwyllys 			case 't':
182*99ebb4caSwyllys 				plc.ta_name = get_string(optarg_av, &rv);
183*99ebb4caSwyllys 				if (plc.ta_name == NULL) {
184*99ebb4caSwyllys 					(void) fprintf(stderr,
185*99ebb4caSwyllys 					    gettext("Error name input.\n"));
186*99ebb4caSwyllys 				} else {
187*99ebb4caSwyllys 					KMF_X509_NAME taDN;
188*99ebb4caSwyllys 					/* for syntax checking */
189*99ebb4caSwyllys 					if (KMF_DNParser(plc.ta_name,
190*99ebb4caSwyllys 					    &taDN) != KMF_OK) {
191*99ebb4caSwyllys 						(void) fprintf(stderr,
192*99ebb4caSwyllys 						    gettext("Error name "
193*99ebb4caSwyllys 						    "input.\n"));
194*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
195*99ebb4caSwyllys 					} else {
196*99ebb4caSwyllys 						KMF_FreeDN(&taDN);
197*99ebb4caSwyllys 						flags |= KC_TA_NAME;
198*99ebb4caSwyllys 					}
199*99ebb4caSwyllys 				}
200*99ebb4caSwyllys 				break;
201*99ebb4caSwyllys 			case 's':
202*99ebb4caSwyllys 				plc.ta_serial = get_string(optarg_av, &rv);
203*99ebb4caSwyllys 				if (plc.ta_serial == NULL) {
204*99ebb4caSwyllys 					(void) fprintf(stderr,
205*99ebb4caSwyllys 					    gettext("Error serial input.\n"));
206*99ebb4caSwyllys 				} else {
207*99ebb4caSwyllys 					uchar_t *bytes = NULL;
208*99ebb4caSwyllys 					size_t bytelen;
209*99ebb4caSwyllys 
210*99ebb4caSwyllys 					ret = KMF_HexString2Bytes(
211*99ebb4caSwyllys 					    (uchar_t *)plc.ta_serial,
212*99ebb4caSwyllys 					    &bytes, &bytelen);
213*99ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
214*99ebb4caSwyllys 						(void) fprintf(stderr,
215*99ebb4caSwyllys 						    gettext("serial number "
216*99ebb4caSwyllys 						    "must be specified as a "
217*99ebb4caSwyllys 						    "hex number "
218*99ebb4caSwyllys 						    "(ex: 0x0102030405"
219*99ebb4caSwyllys 						    "ffeeddee)\n"));
220*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
221*99ebb4caSwyllys 						break;
222*99ebb4caSwyllys 					}
223*99ebb4caSwyllys 					if (bytes != NULL)
224*99ebb4caSwyllys 						free(bytes);
225*99ebb4caSwyllys 					flags |= KC_TA_SERIAL;
226*99ebb4caSwyllys 				}
227*99ebb4caSwyllys 				break;
228*99ebb4caSwyllys 			case 'o':
229*99ebb4caSwyllys 				plc.VAL_OCSP_RESPONDER_URI =
230*99ebb4caSwyllys 					get_string(optarg_av, &rv);
231*99ebb4caSwyllys 				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
232*99ebb4caSwyllys 					(void) fprintf(stderr,
233*99ebb4caSwyllys 					    gettext("Error responder "
234*99ebb4caSwyllys 					    "input.\n"));
235*99ebb4caSwyllys 				} else {
236*99ebb4caSwyllys 					flags |= KC_OCSP_RESPONDER_URI;
237*99ebb4caSwyllys 					ocsp_set_attr++;
238*99ebb4caSwyllys 				}
239*99ebb4caSwyllys 				break;
240*99ebb4caSwyllys 			case 'P':
241*99ebb4caSwyllys 				plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
242*99ebb4caSwyllys 				if (plc.VAL_OCSP_PROXY == NULL) {
243*99ebb4caSwyllys 					(void) fprintf(stderr,
244*99ebb4caSwyllys 					    gettext("Error proxy input.\n"));
245*99ebb4caSwyllys 				} else {
246*99ebb4caSwyllys 					flags |= KC_OCSP_PROXY;
247*99ebb4caSwyllys 					ocsp_set_attr++;
248*99ebb4caSwyllys 				}
249*99ebb4caSwyllys 				break;
250*99ebb4caSwyllys 			case 'r':
251*99ebb4caSwyllys 				plc.VAL_OCSP_URI_FROM_CERT =
252*99ebb4caSwyllys 				    get_boolean(optarg_av);
253*99ebb4caSwyllys 				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
254*99ebb4caSwyllys 					(void) fprintf(stderr,
255*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
256*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
257*99ebb4caSwyllys 				} else {
258*99ebb4caSwyllys 					flags |= KC_OCSP_URI_FROM_CERT;
259*99ebb4caSwyllys 					ocsp_set_attr++;
260*99ebb4caSwyllys 				}
261*99ebb4caSwyllys 				break;
262*99ebb4caSwyllys 			case 'T':
263*99ebb4caSwyllys 				plc.VAL_OCSP_RESP_LIFETIME =
264*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
265*99ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
266*99ebb4caSwyllys 					(void) fprintf(stderr,
267*99ebb4caSwyllys 					    gettext("Error time input.\n"));
268*99ebb4caSwyllys 				} else {
269*99ebb4caSwyllys 					uint32_t adj;
270*99ebb4caSwyllys 					/* for syntax checking */
271*99ebb4caSwyllys 					if (str2lifetime(
272*99ebb4caSwyllys 					    plc.VAL_OCSP_RESP_LIFETIME,
273*99ebb4caSwyllys 					    &adj) < 0) {
274*99ebb4caSwyllys 						(void) fprintf(stderr,
275*99ebb4caSwyllys 						    gettext("Error time "
276*99ebb4caSwyllys 						    "input.\n"));
277*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
278*99ebb4caSwyllys 					} else {
279*99ebb4caSwyllys 						flags |= KC_OCSP_RESP_LIFETIME;
280*99ebb4caSwyllys 						ocsp_set_attr++;
281*99ebb4caSwyllys 					}
282*99ebb4caSwyllys 				}
283*99ebb4caSwyllys 				break;
284*99ebb4caSwyllys 			case 'R':
285*99ebb4caSwyllys 				plc.VAL_OCSP_IGNORE_RESP_SIGN =
286*99ebb4caSwyllys 				    get_boolean(optarg_av);
287*99ebb4caSwyllys 				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
288*99ebb4caSwyllys 					(void) fprintf(stderr,
289*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
290*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
291*99ebb4caSwyllys 				} else {
292*99ebb4caSwyllys 					flags |= KC_OCSP_IGNORE_RESP_SIGN;
293*99ebb4caSwyllys 					ocsp_set_attr++;
294*99ebb4caSwyllys 				}
295*99ebb4caSwyllys 				break;
296*99ebb4caSwyllys 			case 'n':
297*99ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_NAME =
298*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
299*99ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
300*99ebb4caSwyllys 					(void) fprintf(stderr,
301*99ebb4caSwyllys 					    gettext("Error name input.\n"));
302*99ebb4caSwyllys 				} else {
303*99ebb4caSwyllys 					KMF_X509_NAME respDN;
304*99ebb4caSwyllys 					/* for syntax checking */
305*99ebb4caSwyllys 					if (KMF_DNParser(
306*99ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_NAME,
307*99ebb4caSwyllys 					    &respDN) != KMF_OK) {
308*99ebb4caSwyllys 						(void) fprintf(stderr,
309*99ebb4caSwyllys 						    gettext("Error name "
310*99ebb4caSwyllys 						    "input.\n"));
311*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
312*99ebb4caSwyllys 					} else {
313*99ebb4caSwyllys 						KMF_FreeDN(&respDN);
314*99ebb4caSwyllys 						flags |= KC_OCSP_RESP_CERT_NAME;
315*99ebb4caSwyllys 						ocsp_set_attr++;
316*99ebb4caSwyllys 					}
317*99ebb4caSwyllys 				}
318*99ebb4caSwyllys 				break;
319*99ebb4caSwyllys 			case 'A':
320*99ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_SERIAL =
321*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
322*99ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
323*99ebb4caSwyllys 					(void) fprintf(stderr,
324*99ebb4caSwyllys 					    gettext("Error serial input.\n"));
325*99ebb4caSwyllys 				} else {
326*99ebb4caSwyllys 					uchar_t *bytes = NULL;
327*99ebb4caSwyllys 					size_t bytelen;
328*99ebb4caSwyllys 
329*99ebb4caSwyllys 					ret = KMF_HexString2Bytes((uchar_t *)
330*99ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_SERIAL,
331*99ebb4caSwyllys 					    &bytes, &bytelen);
332*99ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
333*99ebb4caSwyllys 						(void) fprintf(stderr,
334*99ebb4caSwyllys 						    gettext("serial number "
335*99ebb4caSwyllys 						    "must be specified as a "
336*99ebb4caSwyllys 						    "hex number "
337*99ebb4caSwyllys 						    "(ex: 0x0102030405"
338*99ebb4caSwyllys 						    "ffeeddee)\n"));
339*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
340*99ebb4caSwyllys 						break;
341*99ebb4caSwyllys 					}
342*99ebb4caSwyllys 					if (bytes != NULL)
343*99ebb4caSwyllys 						free(bytes);
344*99ebb4caSwyllys 					flags |= KC_OCSP_RESP_CERT_SERIAL;
345*99ebb4caSwyllys 					ocsp_set_attr++;
346*99ebb4caSwyllys 				}
347*99ebb4caSwyllys 				break;
348*99ebb4caSwyllys 			case 'y':
349*99ebb4caSwyllys 				ocsp_none_opt = get_boolean(optarg_av);
350*99ebb4caSwyllys 				if (ocsp_none_opt == -1) {
351*99ebb4caSwyllys 					(void) fprintf(stderr,
352*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
353*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
354*99ebb4caSwyllys 				} else {
355*99ebb4caSwyllys 					flags |= KC_OCSP_NONE;
356*99ebb4caSwyllys 				}
357*99ebb4caSwyllys 				break;
358*99ebb4caSwyllys 			case 'c':
359*99ebb4caSwyllys 				plc.VAL_CRL_BASEFILENAME =
360*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
361*99ebb4caSwyllys 				if (plc.VAL_CRL_BASEFILENAME == NULL) {
362*99ebb4caSwyllys 					(void) fprintf(stderr, gettext(
363*99ebb4caSwyllys 					    "Error basefilename input.\n"));
364*99ebb4caSwyllys 				} else {
365*99ebb4caSwyllys 					flags |= KC_CRL_BASEFILENAME;
366*99ebb4caSwyllys 					crl_set_attr++;
367*99ebb4caSwyllys 				}
368*99ebb4caSwyllys 				break;
369*99ebb4caSwyllys 			case 'I':
370*99ebb4caSwyllys 				plc.VAL_CRL_DIRECTORY =
371*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
372*99ebb4caSwyllys 				if (plc.VAL_CRL_DIRECTORY == NULL) {
373*99ebb4caSwyllys 					(void) fprintf(stderr,
374*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
375*99ebb4caSwyllys 				} else {
376*99ebb4caSwyllys 					flags |= KC_CRL_DIRECTORY;
377*99ebb4caSwyllys 					crl_set_attr++;
378*99ebb4caSwyllys 				}
379*99ebb4caSwyllys 				break;
380*99ebb4caSwyllys 			case 'g':
381*99ebb4caSwyllys 				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
382*99ebb4caSwyllys 				if (plc.VAL_CRL_GET_URI == -1) {
383*99ebb4caSwyllys 					(void) fprintf(stderr,
384*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
385*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
386*99ebb4caSwyllys 				} else {
387*99ebb4caSwyllys 					flags |= KC_CRL_GET_URI;
388*99ebb4caSwyllys 					crl_set_attr++;
389*99ebb4caSwyllys 				}
390*99ebb4caSwyllys 				break;
391*99ebb4caSwyllys 			case 'X':
392*99ebb4caSwyllys 				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
393*99ebb4caSwyllys 				if (plc.VAL_CRL_PROXY == NULL) {
394*99ebb4caSwyllys 					(void) fprintf(stderr,
395*99ebb4caSwyllys 					    gettext("Error proxy input.\n"));
396*99ebb4caSwyllys 				} else {
397*99ebb4caSwyllys 					flags |= KC_CRL_PROXY;
398*99ebb4caSwyllys 					crl_set_attr++;
399*99ebb4caSwyllys 				}
400*99ebb4caSwyllys 				break;
401*99ebb4caSwyllys 			case 'S':
402*99ebb4caSwyllys 				plc.VAL_CRL_IGNORE_SIGN =
403*99ebb4caSwyllys 				    get_boolean(optarg_av);
404*99ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
405*99ebb4caSwyllys 					(void) fprintf(stderr,
406*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
407*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
408*99ebb4caSwyllys 				} else {
409*99ebb4caSwyllys 					flags |= KC_CRL_IGNORE_SIGN;
410*99ebb4caSwyllys 					crl_set_attr++;
411*99ebb4caSwyllys 				}
412*99ebb4caSwyllys 				break;
413*99ebb4caSwyllys 			case 'D':
414*99ebb4caSwyllys 				plc.VAL_CRL_IGNORE_DATE =
415*99ebb4caSwyllys 					get_boolean(optarg_av);
416*99ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_DATE == -1) {
417*99ebb4caSwyllys 					(void) fprintf(stderr,
418*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
419*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
420*99ebb4caSwyllys 				} else {
421*99ebb4caSwyllys 					flags |= KC_CRL_IGNORE_DATE;
422*99ebb4caSwyllys 					crl_set_attr++;
423*99ebb4caSwyllys 				}
424*99ebb4caSwyllys 				break;
425*99ebb4caSwyllys 			case 'z':
426*99ebb4caSwyllys 				crl_none_opt = get_boolean(optarg_av);
427*99ebb4caSwyllys 				if (crl_none_opt == -1) {
428*99ebb4caSwyllys 					(void) fprintf(stderr,
429*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
430*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
431*99ebb4caSwyllys 				} else {
432*99ebb4caSwyllys 					flags |= KC_CRL_NONE;
433*99ebb4caSwyllys 				}
434*99ebb4caSwyllys 				break;
435*99ebb4caSwyllys 			case 'u':
436*99ebb4caSwyllys 				plc.ku_bits = parseKUlist(optarg_av);
437*99ebb4caSwyllys 				if (plc.ku_bits == 0) {
438*99ebb4caSwyllys 					(void) fprintf(stderr, gettext(
439*99ebb4caSwyllys 					    "Error keyusage input.\n"));
440*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
441*99ebb4caSwyllys 				} else {
442*99ebb4caSwyllys 					flags |= KC_KEYUSAGE;
443*99ebb4caSwyllys 				}
444*99ebb4caSwyllys 				break;
445*99ebb4caSwyllys 			case 'Y':
446*99ebb4caSwyllys 				ku_none_opt = get_boolean(optarg_av);
447*99ebb4caSwyllys 				if (ku_none_opt == -1) {
448*99ebb4caSwyllys 					(void) fprintf(stderr,
449*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
450*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
451*99ebb4caSwyllys 				} else {
452*99ebb4caSwyllys 					flags |= KC_KEYUSAGE_NONE;
453*99ebb4caSwyllys 				}
454*99ebb4caSwyllys 				break;
455*99ebb4caSwyllys 			case 'E':
456*99ebb4caSwyllys 				if (parseEKUNames(optarg_av, &plc) != 0) {
457*99ebb4caSwyllys 					(void) fprintf(stderr,
458*99ebb4caSwyllys 					    gettext("Error EKU input.\n"));
459*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
460*99ebb4caSwyllys 				} else {
461*99ebb4caSwyllys 					flags |= KC_EKUS;
462*99ebb4caSwyllys 				}
463*99ebb4caSwyllys 				break;
464*99ebb4caSwyllys 			case 'O':
465*99ebb4caSwyllys 				if (parseEKUOIDs(optarg_av, &plc) != 0) {
466*99ebb4caSwyllys 					(void) fprintf(stderr,
467*99ebb4caSwyllys 					    gettext("Error EKU OID input.\n"));
468*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
469*99ebb4caSwyllys 				} else {
470*99ebb4caSwyllys 					flags |= KC_EKUS;
471*99ebb4caSwyllys 				}
472*99ebb4caSwyllys 				break;
473*99ebb4caSwyllys 			case 'Z':
474*99ebb4caSwyllys 				eku_none_opt = get_boolean(optarg_av);
475*99ebb4caSwyllys 				if (eku_none_opt == -1) {
476*99ebb4caSwyllys 					(void) fprintf(stderr,
477*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
478*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
479*99ebb4caSwyllys 				} else {
480*99ebb4caSwyllys 					flags |= KC_EKUS_NONE;
481*99ebb4caSwyllys 				}
482*99ebb4caSwyllys 				break;
483*99ebb4caSwyllys 			default:
484*99ebb4caSwyllys 				(void) fprintf(stderr,
485*99ebb4caSwyllys 				    gettext("Error input option.\n"));
486*99ebb4caSwyllys 				rv = KC_ERR_USAGE;
487*99ebb4caSwyllys 				break;
488*99ebb4caSwyllys 		}
489*99ebb4caSwyllys 		if (rv != KC_OK)
490*99ebb4caSwyllys 			goto out;
491*99ebb4caSwyllys 	}
492*99ebb4caSwyllys 
493*99ebb4caSwyllys 	/* No additional args allowed. */
494*99ebb4caSwyllys 	argc -= optind_av;
495*99ebb4caSwyllys 	if (argc) {
496*99ebb4caSwyllys 		(void) fprintf(stderr,
497*99ebb4caSwyllys 		    gettext("Error input option\n"));
498*99ebb4caSwyllys 		rv = KC_ERR_USAGE;
499*99ebb4caSwyllys 		goto out;
500*99ebb4caSwyllys 	}
501*99ebb4caSwyllys 
502*99ebb4caSwyllys 	if (filename == NULL) {
503*99ebb4caSwyllys 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
504*99ebb4caSwyllys 		if (filename == NULL) {
505*99ebb4caSwyllys 			rv = KC_ERR_MEMORY;
506*99ebb4caSwyllys 			goto out;
507*99ebb4caSwyllys 		}
508*99ebb4caSwyllys 	}
509*99ebb4caSwyllys 
510*99ebb4caSwyllys 	/*
511*99ebb4caSwyllys 	 * Must have a policy name. The policy name can not be default
512*99ebb4caSwyllys 	 * if using the default policy file.
513*99ebb4caSwyllys 	 */
514*99ebb4caSwyllys 	if (plc.name == NULL) {
515*99ebb4caSwyllys 		(void) fprintf(stderr,
516*99ebb4caSwyllys 		    gettext("You must specify a policy name.\n"));
517*99ebb4caSwyllys 		rv = KC_ERR_USAGE;
518*99ebb4caSwyllys 		goto out;
519*99ebb4caSwyllys 	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
520*99ebb4caSwyllys 	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
521*99ebb4caSwyllys 		(void) fprintf(stderr,
522*99ebb4caSwyllys 		    gettext("Can not modify the default policy in the default "
523*99ebb4caSwyllys 		    "policy file.\n"));
524*99ebb4caSwyllys 		rv = KC_ERR_USAGE;
525*99ebb4caSwyllys 		goto out;
526*99ebb4caSwyllys 	}
527*99ebb4caSwyllys 
528*99ebb4caSwyllys 	/* Check the access permission of the policy DB */
529*99ebb4caSwyllys 	if (access(filename, W_OK) < 0) {
530*99ebb4caSwyllys 		int err = errno;
531*99ebb4caSwyllys 		(void) fprintf(stderr,
532*99ebb4caSwyllys 		    gettext("Cannot access \"%s\" for modify - %s\n"),
533*99ebb4caSwyllys 		    filename, strerror(err));
534*99ebb4caSwyllys 		rv = KC_ERR_ACCESS;
535*99ebb4caSwyllys 		goto out;
536*99ebb4caSwyllys 	}
537*99ebb4caSwyllys 
538*99ebb4caSwyllys 	/* Try to load the named policy from the DB */
539*99ebb4caSwyllys 	ret = KMF_GetPolicy(filename, plc.name, &oplc);
540*99ebb4caSwyllys 	if (ret != KMF_OK) {
541*99ebb4caSwyllys 		(void) fprintf(stderr,
542*99ebb4caSwyllys 		    gettext("Error loading policy \"%s\" from %s\n"), filename,
543*99ebb4caSwyllys 		    plc.name);
544*99ebb4caSwyllys 		return (KC_ERR_FIND_POLICY);
545*99ebb4caSwyllys 	}
546*99ebb4caSwyllys 
547*99ebb4caSwyllys 	/* Update the general policy attributes. */
548*99ebb4caSwyllys 	if (flags & KC_IGNORE_DATE)
549*99ebb4caSwyllys 		oplc.ignore_date = plc.ignore_date;
550*99ebb4caSwyllys 
551*99ebb4caSwyllys 	if (flags & KC_IGNORE_UNKNOWN_EKUS)
552*99ebb4caSwyllys 		oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
553*99ebb4caSwyllys 
554*99ebb4caSwyllys 	if (flags & KC_IGNORE_TRUST_ANCHOR)
555*99ebb4caSwyllys 		oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
556*99ebb4caSwyllys 
557*99ebb4caSwyllys 	if (flags & KC_VALIDITY_ADJUSTTIME) {
558*99ebb4caSwyllys 		if (oplc.validity_adjusttime)
559*99ebb4caSwyllys 			free(oplc.validity_adjusttime);
560*99ebb4caSwyllys 		oplc.validity_adjusttime =
561*99ebb4caSwyllys 			plc.validity_adjusttime;
562*99ebb4caSwyllys 	}
563*99ebb4caSwyllys 
564*99ebb4caSwyllys 	if (flags & KC_TA_NAME) {
565*99ebb4caSwyllys 		if (oplc.ta_name)
566*99ebb4caSwyllys 			free(oplc.ta_name);
567*99ebb4caSwyllys 		oplc.ta_name = plc.ta_name;
568*99ebb4caSwyllys 	}
569*99ebb4caSwyllys 	if (flags & KC_TA_SERIAL) {
570*99ebb4caSwyllys 		if (oplc.ta_serial)
571*99ebb4caSwyllys 			free(oplc.ta_serial);
572*99ebb4caSwyllys 		oplc.ta_serial = plc.ta_serial;
573*99ebb4caSwyllys 	}
574*99ebb4caSwyllys 
575*99ebb4caSwyllys 	/* Update the OCSP policy */
576*99ebb4caSwyllys 	if (ocsp_none_opt == B_TRUE) {
577*99ebb4caSwyllys 		if (ocsp_set_attr > 0) {
578*99ebb4caSwyllys 			(void) fprintf(stderr,
579*99ebb4caSwyllys 			    gettext("Can not set ocsp-none=true and other "
580*99ebb4caSwyllys 			    "OCSP attributes at the same time.\n"));
581*99ebb4caSwyllys 			rv = KC_ERR_USAGE;
582*99ebb4caSwyllys 			goto out;
583*99ebb4caSwyllys 		}
584*99ebb4caSwyllys 
585*99ebb4caSwyllys 		/*
586*99ebb4caSwyllys 		 * If the original policy does not have OCSP checking,
587*99ebb4caSwyllys 		 * then we do not need to do anything.  If the original
588*99ebb4caSwyllys 		 * policy has the OCSP checking, then we need to release the
589*99ebb4caSwyllys 		 * space of OCSP attributes and turn the OCSP checking off.
590*99ebb4caSwyllys 		 */
591*99ebb4caSwyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
592*99ebb4caSwyllys 			if (oplc.VAL_OCSP_BASIC.responderURI) {
593*99ebb4caSwyllys 				free(oplc.VAL_OCSP_BASIC.responderURI);
594*99ebb4caSwyllys 				oplc.VAL_OCSP_BASIC.responderURI = NULL;
595*99ebb4caSwyllys 			}
596*99ebb4caSwyllys 
597*99ebb4caSwyllys 			if (oplc.VAL_OCSP_BASIC.proxy) {
598*99ebb4caSwyllys 				free(oplc.VAL_OCSP_BASIC.proxy);
599*99ebb4caSwyllys 				oplc.VAL_OCSP_BASIC.proxy = NULL;
600*99ebb4caSwyllys 			}
601*99ebb4caSwyllys 
602*99ebb4caSwyllys 			if (oplc.VAL_OCSP_BASIC.response_lifetime) {
603*99ebb4caSwyllys 				free(oplc.VAL_OCSP_BASIC.response_lifetime);
604*99ebb4caSwyllys 				oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
605*99ebb4caSwyllys 			}
606*99ebb4caSwyllys 
607*99ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
608*99ebb4caSwyllys 				free(oplc.VAL_OCSP_RESP_CERT.name);
609*99ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT.name = NULL;
610*99ebb4caSwyllys 			}
611*99ebb4caSwyllys 
612*99ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
613*99ebb4caSwyllys 				free(oplc.VAL_OCSP_RESP_CERT.serial);
614*99ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT.serial = NULL;
615*99ebb4caSwyllys 			}
616*99ebb4caSwyllys 
617*99ebb4caSwyllys 			/* Turn off the OCSP checking */
618*99ebb4caSwyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
619*99ebb4caSwyllys 		}
620*99ebb4caSwyllys 
621*99ebb4caSwyllys 	} else {
622*99ebb4caSwyllys 		/*
623*99ebb4caSwyllys 		 * If the "ocsp-none" option is not set or is set to false,
624*99ebb4caSwyllys 		 * then we only need to do the modification if there is at
625*99ebb4caSwyllys 		 * least one OCSP attribute is specified.
626*99ebb4caSwyllys 		 */
627*99ebb4caSwyllys 		if (ocsp_set_attr > 0) {
628*99ebb4caSwyllys 			if (flags & KC_OCSP_RESPONDER_URI) {
629*99ebb4caSwyllys 				if (oplc.VAL_OCSP_RESPONDER_URI)
630*99ebb4caSwyllys 					free(oplc.VAL_OCSP_RESPONDER_URI);
631*99ebb4caSwyllys 				oplc.VAL_OCSP_RESPONDER_URI =
632*99ebb4caSwyllys 					plc.VAL_OCSP_RESPONDER_URI;
633*99ebb4caSwyllys 			}
634*99ebb4caSwyllys 
635*99ebb4caSwyllys 			if (flags & KC_OCSP_PROXY) {
636*99ebb4caSwyllys 				if (oplc.VAL_OCSP_PROXY)
637*99ebb4caSwyllys 					free(oplc.VAL_OCSP_PROXY);
638*99ebb4caSwyllys 				oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
639*99ebb4caSwyllys 			}
640*99ebb4caSwyllys 
641*99ebb4caSwyllys 			if (flags & KC_OCSP_URI_FROM_CERT)
642*99ebb4caSwyllys 				oplc.VAL_OCSP_URI_FROM_CERT =
643*99ebb4caSwyllys 					plc.VAL_OCSP_URI_FROM_CERT;
644*99ebb4caSwyllys 
645*99ebb4caSwyllys 			if (flags & KC_OCSP_RESP_LIFETIME) {
646*99ebb4caSwyllys 				if (oplc.VAL_OCSP_RESP_LIFETIME)
647*99ebb4caSwyllys 					free(oplc.VAL_OCSP_RESP_LIFETIME);
648*99ebb4caSwyllys 				oplc.VAL_OCSP_RESP_LIFETIME =
649*99ebb4caSwyllys 					plc.VAL_OCSP_RESP_LIFETIME;
650*99ebb4caSwyllys 			}
651*99ebb4caSwyllys 
652*99ebb4caSwyllys 			if (flags & KC_OCSP_IGNORE_RESP_SIGN)
653*99ebb4caSwyllys 				oplc.VAL_OCSP_IGNORE_RESP_SIGN =
654*99ebb4caSwyllys 					plc.VAL_OCSP_IGNORE_RESP_SIGN;
655*99ebb4caSwyllys 
656*99ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_NAME) {
657*99ebb4caSwyllys 				if (oplc.VAL_OCSP_RESP_CERT_NAME)
658*99ebb4caSwyllys 					free(oplc.VAL_OCSP_RESP_CERT_NAME);
659*99ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT_NAME =
660*99ebb4caSwyllys 					plc.VAL_OCSP_RESP_CERT_NAME;
661*99ebb4caSwyllys 			}
662*99ebb4caSwyllys 
663*99ebb4caSwyllys 			if (flags & KC_OCSP_RESP_CERT_SERIAL) {
664*99ebb4caSwyllys 				if (oplc.VAL_OCSP_RESP_CERT_SERIAL)
665*99ebb4caSwyllys 					free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
666*99ebb4caSwyllys 				oplc.VAL_OCSP_RESP_CERT_SERIAL =
667*99ebb4caSwyllys 					plc.VAL_OCSP_RESP_CERT_SERIAL;
668*99ebb4caSwyllys 			}
669*99ebb4caSwyllys 
670*99ebb4caSwyllys 			if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
671*99ebb4caSwyllys 			    oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
672*99ebb4caSwyllys 				oplc.VAL_OCSP.has_resp_cert = B_TRUE;
673*99ebb4caSwyllys 			else
674*99ebb4caSwyllys 				oplc.VAL_OCSP.has_resp_cert = B_FALSE;
675*99ebb4caSwyllys 
676*99ebb4caSwyllys 			/* Turn on the OCSP checking */
677*99ebb4caSwyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
678*99ebb4caSwyllys 		}
679*99ebb4caSwyllys 	}
680*99ebb4caSwyllys 
681*99ebb4caSwyllys 	/* Update the CRL policy */
682*99ebb4caSwyllys 	if (crl_none_opt == B_TRUE) {
683*99ebb4caSwyllys 		if (crl_set_attr > 0) {
684*99ebb4caSwyllys 			(void) fprintf(stderr,
685*99ebb4caSwyllys 			    gettext("Can not set crl-none=true and other CRL "
686*99ebb4caSwyllys 			    "attributes at the same time.\n"));
687*99ebb4caSwyllys 			rv = KC_ERR_USAGE;
688*99ebb4caSwyllys 			goto out;
689*99ebb4caSwyllys 		}
690*99ebb4caSwyllys 
691*99ebb4caSwyllys 		/*
692*99ebb4caSwyllys 		 * If the original policy does not have CRL checking,
693*99ebb4caSwyllys 		 * then we do not need to do anything.  If the original
694*99ebb4caSwyllys 		 * policy has the CRL checking, then we need to release the
695*99ebb4caSwyllys 		 * space of CRL attributes and turn the CRL checking off.
696*99ebb4caSwyllys 		 */
697*99ebb4caSwyllys 		if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
698*99ebb4caSwyllys 			if (oplc.VAL_CRL_BASEFILENAME) {
699*99ebb4caSwyllys 				free(oplc.VAL_CRL_BASEFILENAME);
700*99ebb4caSwyllys 				oplc.VAL_CRL_BASEFILENAME = NULL;
701*99ebb4caSwyllys 			}
702*99ebb4caSwyllys 
703*99ebb4caSwyllys 			if (oplc.VAL_CRL_DIRECTORY) {
704*99ebb4caSwyllys 				free(oplc.VAL_CRL_DIRECTORY);
705*99ebb4caSwyllys 				oplc.VAL_CRL_DIRECTORY = NULL;
706*99ebb4caSwyllys 			}
707*99ebb4caSwyllys 
708*99ebb4caSwyllys 			if (oplc.VAL_CRL_PROXY) {
709*99ebb4caSwyllys 				free(oplc.VAL_CRL_PROXY);
710*99ebb4caSwyllys 				oplc.VAL_CRL_PROXY = NULL;
711*99ebb4caSwyllys 			}
712*99ebb4caSwyllys 
713*99ebb4caSwyllys 			/* Turn off the CRL checking */
714*99ebb4caSwyllys 			oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
715*99ebb4caSwyllys 		}
716*99ebb4caSwyllys 	} else {
717*99ebb4caSwyllys 		/*
718*99ebb4caSwyllys 		 * If the "ocsp-none" option is not set or is set to false,
719*99ebb4caSwyllys 		 * then we only need to do the modification if there is at
720*99ebb4caSwyllys 		 * least one CRL attribute is specified.
721*99ebb4caSwyllys 		 */
722*99ebb4caSwyllys 		if (crl_set_attr > 0) {
723*99ebb4caSwyllys 			if (flags & KC_CRL_BASEFILENAME) {
724*99ebb4caSwyllys 				if (oplc.VAL_CRL_BASEFILENAME)
725*99ebb4caSwyllys 					free(oplc.VAL_CRL_BASEFILENAME);
726*99ebb4caSwyllys 				oplc.VAL_CRL_BASEFILENAME =
727*99ebb4caSwyllys 				    plc.VAL_CRL_BASEFILENAME;
728*99ebb4caSwyllys 			}
729*99ebb4caSwyllys 
730*99ebb4caSwyllys 			if (flags & KC_CRL_DIRECTORY) {
731*99ebb4caSwyllys 				if (oplc.VAL_CRL_DIRECTORY)
732*99ebb4caSwyllys 					free(oplc.VAL_CRL_DIRECTORY);
733*99ebb4caSwyllys 				oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
734*99ebb4caSwyllys 			}
735*99ebb4caSwyllys 
736*99ebb4caSwyllys 			if (flags & KC_CRL_GET_URI) {
737*99ebb4caSwyllys 				oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
738*99ebb4caSwyllys 			}
739*99ebb4caSwyllys 
740*99ebb4caSwyllys 			if (flags & KC_CRL_PROXY) {
741*99ebb4caSwyllys 				if (oplc.VAL_CRL_PROXY)
742*99ebb4caSwyllys 					free(oplc.VAL_CRL_PROXY);
743*99ebb4caSwyllys 				oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
744*99ebb4caSwyllys 			}
745*99ebb4caSwyllys 
746*99ebb4caSwyllys 			if (flags & KC_CRL_IGNORE_SIGN) {
747*99ebb4caSwyllys 				oplc.VAL_CRL_IGNORE_SIGN =
748*99ebb4caSwyllys 				    plc.VAL_CRL_IGNORE_SIGN;
749*99ebb4caSwyllys 			}
750*99ebb4caSwyllys 
751*99ebb4caSwyllys 			if (flags & KC_CRL_IGNORE_DATE) {
752*99ebb4caSwyllys 				oplc.VAL_CRL_IGNORE_DATE =
753*99ebb4caSwyllys 				    plc.VAL_CRL_IGNORE_DATE;
754*99ebb4caSwyllys 			}
755*99ebb4caSwyllys 
756*99ebb4caSwyllys 			/* Turn on the CRL checking */
757*99ebb4caSwyllys 			oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
758*99ebb4caSwyllys 		}
759*99ebb4caSwyllys 	}
760*99ebb4caSwyllys 
761*99ebb4caSwyllys 	/* Update the Key Usage */
762*99ebb4caSwyllys 	if (ku_none_opt == B_TRUE) {
763*99ebb4caSwyllys 		if (flags & KC_KEYUSAGE) {
764*99ebb4caSwyllys 			(void) fprintf(stderr,
765*99ebb4caSwyllys 			    gettext("Can not set keyusage-none=true and "
766*99ebb4caSwyllys 			    "modify the keyusage value at the same time.\n"));
767*99ebb4caSwyllys 			rv = KC_ERR_USAGE;
768*99ebb4caSwyllys 			goto out;
769*99ebb4caSwyllys 		}
770*99ebb4caSwyllys 
771*99ebb4caSwyllys 		oplc.ku_bits = 0;
772*99ebb4caSwyllys 	} else {
773*99ebb4caSwyllys 		/*
774*99ebb4caSwyllys 		 * If the "keyusage-none" option is not set or is set to
775*99ebb4caSwyllys 		 * false, then we only need to do the modification if
776*99ebb4caSwyllys 		 * the keyusage value is specified.
777*99ebb4caSwyllys 		 */
778*99ebb4caSwyllys 		if (flags & KC_KEYUSAGE)
779*99ebb4caSwyllys 			oplc.ku_bits = plc.ku_bits;
780*99ebb4caSwyllys 	}
781*99ebb4caSwyllys 
782*99ebb4caSwyllys 
783*99ebb4caSwyllys 	/* Update the Extended Key Usage */
784*99ebb4caSwyllys 	if (eku_none_opt == B_TRUE) {
785*99ebb4caSwyllys 		if (flags & KC_EKUS) {
786*99ebb4caSwyllys 			(void) fprintf(stderr,
787*99ebb4caSwyllys 			    gettext("Can not set eku-none=true and modify "
788*99ebb4caSwyllys 			    "EKU values at the same time.\n"));
789*99ebb4caSwyllys 			rv = KC_ERR_USAGE;
790*99ebb4caSwyllys 			goto out;
791*99ebb4caSwyllys 		}
792*99ebb4caSwyllys 
793*99ebb4caSwyllys 		/* Release current EKU list (if any) */
794*99ebb4caSwyllys 		if (oplc.eku_set.eku_count > 0) {
795*99ebb4caSwyllys 			KMF_FreeEKUPolicy(&oplc.eku_set);
796*99ebb4caSwyllys 			oplc.eku_set.eku_count = 0;
797*99ebb4caSwyllys 			oplc.eku_set.ekulist = NULL;
798*99ebb4caSwyllys 		}
799*99ebb4caSwyllys 	} else {
800*99ebb4caSwyllys 		/*
801*99ebb4caSwyllys 		 * If the "eku-none" option is not set or is set to false,
802*99ebb4caSwyllys 		 * then we only need to do the modification if either
803*99ebb4caSwyllys 		 * "ekuname" or "ekuoids" is specified.
804*99ebb4caSwyllys 		 */
805*99ebb4caSwyllys 		if (flags & KC_EKUS) {
806*99ebb4caSwyllys 			/* Release current EKU list (if any) */
807*99ebb4caSwyllys 			KMF_FreeEKUPolicy(&oplc.eku_set);
808*99ebb4caSwyllys 			oplc.eku_set = plc.eku_set;
809*99ebb4caSwyllys 		}
810*99ebb4caSwyllys 	}
811*99ebb4caSwyllys 
812*99ebb4caSwyllys 	/* Do a sanity check on the modified policy */
813*99ebb4caSwyllys 	ret = KMF_VerifyPolicy(&oplc);
814*99ebb4caSwyllys 	if (ret != KMF_OK) {
815*99ebb4caSwyllys 		print_sanity_error(ret);
816*99ebb4caSwyllys 		rv = KC_ERR_VERIFY_POLICY;
817*99ebb4caSwyllys 		goto out;
818*99ebb4caSwyllys 	}
819*99ebb4caSwyllys 
820*99ebb4caSwyllys 	/* The modify operation is a delete followed by an add */
821*99ebb4caSwyllys 	ret = KMF_DeletePolicyFromDB(oplc.name, filename);
822*99ebb4caSwyllys 	if (ret != KMF_OK) {
823*99ebb4caSwyllys 		rv = KC_ERR_DELETE_POLICY;
824*99ebb4caSwyllys 		goto out;
825*99ebb4caSwyllys 	}
826*99ebb4caSwyllys 
827*99ebb4caSwyllys 	/*
828*99ebb4caSwyllys 	 * Now add the modified policy back to the DB.
829*99ebb4caSwyllys 	 */
830*99ebb4caSwyllys 	ret = KMF_AddPolicyToDB(&oplc, filename, B_FALSE);
831*99ebb4caSwyllys 	if (ret != KMF_OK) {
832*99ebb4caSwyllys 		(void) fprintf(stderr,
833*99ebb4caSwyllys 		    gettext("Error adding policy to database: 0x%04x\n"), ret);
834*99ebb4caSwyllys 		rv = KC_ERR_ADD_POLICY;
835*99ebb4caSwyllys 		goto out;
836*99ebb4caSwyllys 	}
837*99ebb4caSwyllys 
838*99ebb4caSwyllys out:
839*99ebb4caSwyllys 	if (filename != NULL)
840*99ebb4caSwyllys 		free(filename);
841*99ebb4caSwyllys 
842*99ebb4caSwyllys 	KMF_FreePolicyRecord(&oplc);
843*99ebb4caSwyllys 
844*99ebb4caSwyllys 	return (rv);
845*99ebb4caSwyllys }
846