xref: /titanic_51/usr/src/cmd/cmd-crypto/kmfcfg/create.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 int
38*99ebb4caSwyllys kc_create(int argc, char *argv[])
39*99ebb4caSwyllys {
40*99ebb4caSwyllys 	KMF_RETURN	ret;
41*99ebb4caSwyllys 	int 		rv = KC_OK;
42*99ebb4caSwyllys 	int		opt;
43*99ebb4caSwyllys 	extern int	optind_av;
44*99ebb4caSwyllys 	extern char	*optarg_av;
45*99ebb4caSwyllys 	char		*filename = NULL;
46*99ebb4caSwyllys 	int		ocsp_set_attr = 0;
47*99ebb4caSwyllys 	boolean_t	crl_set_attr = 0;
48*99ebb4caSwyllys 	KMF_POLICY_RECORD plc;
49*99ebb4caSwyllys 
50*99ebb4caSwyllys 	(void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
51*99ebb4caSwyllys 
52*99ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
53*99ebb4caSwyllys 		"i:(dbfile)"
54*99ebb4caSwyllys 		"p:(policy)"
55*99ebb4caSwyllys 		"d:(ignore-date)"
56*99ebb4caSwyllys 		"e:(ignore-unknown-eku)"
57*99ebb4caSwyllys 		"a:(ignore-trust-anchor)"
58*99ebb4caSwyllys 		"v:(validity-adjusttime)"
59*99ebb4caSwyllys 		"t:(ta-name)"
60*99ebb4caSwyllys 		"s:(ta-serial)"
61*99ebb4caSwyllys 		"o:(ocsp-responder)"
62*99ebb4caSwyllys 		"P:(ocsp-proxy)"
63*99ebb4caSwyllys 		"r:(ocsp-use-cert-responder)"
64*99ebb4caSwyllys 		"T:(ocsp-response-lifetime)"
65*99ebb4caSwyllys 		"R:(ocsp-ignore-response-sign)"
66*99ebb4caSwyllys 		"n:(ocsp-responder-cert-name)"
67*99ebb4caSwyllys 		"A:(ocsp-responder-cert-serial)"
68*99ebb4caSwyllys 		"c:(crl-basefilename)"
69*99ebb4caSwyllys 		"I:(crl-directory)"
70*99ebb4caSwyllys 		"g:(crl-get-crl-uri)"
71*99ebb4caSwyllys 		"X:(crl-proxy)"
72*99ebb4caSwyllys 		"S:(crl-ignore-crl-sign)"
73*99ebb4caSwyllys 		"D:(crl-ignore-crl-date)"
74*99ebb4caSwyllys 		"u:(keyusage)"
75*99ebb4caSwyllys 		"E:(ekunames)"
76*99ebb4caSwyllys 		"O:(ekuoids)")) != EOF) {
77*99ebb4caSwyllys 		switch (opt) {
78*99ebb4caSwyllys 			case 'i':
79*99ebb4caSwyllys 				filename = get_string(optarg_av, &rv);
80*99ebb4caSwyllys 				if (filename == NULL) {
81*99ebb4caSwyllys 					(void) fprintf(stderr,
82*99ebb4caSwyllys 					    gettext("Error dbfile input.\n"));
83*99ebb4caSwyllys 				}
84*99ebb4caSwyllys 				break;
85*99ebb4caSwyllys 			case 'p':
86*99ebb4caSwyllys 				plc.name = get_string(optarg_av, &rv);
87*99ebb4caSwyllys 				if (plc.name == NULL) {
88*99ebb4caSwyllys 					(void) fprintf(stderr,
89*99ebb4caSwyllys 					    gettext("Error policy name.\n"));
90*99ebb4caSwyllys 				}
91*99ebb4caSwyllys 				break;
92*99ebb4caSwyllys 			case 'd':
93*99ebb4caSwyllys 				plc.ignore_date = get_boolean(optarg_av);
94*99ebb4caSwyllys 				if (plc.ignore_date == -1) {
95*99ebb4caSwyllys 					(void) fprintf(stderr,
96*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
97*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
98*99ebb4caSwyllys 				}
99*99ebb4caSwyllys 				break;
100*99ebb4caSwyllys 			case 'e':
101*99ebb4caSwyllys 				plc.ignore_unknown_ekus =
102*99ebb4caSwyllys 				    get_boolean(optarg_av);
103*99ebb4caSwyllys 				if (plc.ignore_unknown_ekus == -1) {
104*99ebb4caSwyllys 					(void) fprintf(stderr,
105*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
106*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
107*99ebb4caSwyllys 				}
108*99ebb4caSwyllys 				break;
109*99ebb4caSwyllys 			case 'a':
110*99ebb4caSwyllys 				plc.ignore_trust_anchor =
111*99ebb4caSwyllys 				    get_boolean(optarg_av);
112*99ebb4caSwyllys 				if (plc.ignore_trust_anchor == -1) {
113*99ebb4caSwyllys 					(void) fprintf(stderr,
114*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
115*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
116*99ebb4caSwyllys 				}
117*99ebb4caSwyllys 				break;
118*99ebb4caSwyllys 			case 'v':
119*99ebb4caSwyllys 				plc.validity_adjusttime =
120*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
121*99ebb4caSwyllys 				if (plc.validity_adjusttime == NULL) {
122*99ebb4caSwyllys 					(void) fprintf(stderr,
123*99ebb4caSwyllys 					    gettext("Error time input.\n"));
124*99ebb4caSwyllys 				} else {
125*99ebb4caSwyllys 					uint32_t adj;
126*99ebb4caSwyllys 					/* for syntax checking */
127*99ebb4caSwyllys 					if (str2lifetime(
128*99ebb4caSwyllys 					    plc.validity_adjusttime,
129*99ebb4caSwyllys 					    &adj) < 0) {
130*99ebb4caSwyllys 						(void) fprintf(stderr,
131*99ebb4caSwyllys 						    gettext("Error time "
132*99ebb4caSwyllys 						    "input.\n"));
133*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
134*99ebb4caSwyllys 					}
135*99ebb4caSwyllys 				}
136*99ebb4caSwyllys 				break;
137*99ebb4caSwyllys 			case 't':
138*99ebb4caSwyllys 				plc.ta_name = get_string(optarg_av, &rv);
139*99ebb4caSwyllys 				if (plc.ta_name == NULL) {
140*99ebb4caSwyllys 					(void) fprintf(stderr,
141*99ebb4caSwyllys 					    gettext("Error name input.\n"));
142*99ebb4caSwyllys 				} else {
143*99ebb4caSwyllys 					KMF_X509_NAME taDN;
144*99ebb4caSwyllys 					/* for syntax checking */
145*99ebb4caSwyllys 					if (KMF_DNParser(plc.ta_name,
146*99ebb4caSwyllys 					    &taDN) != KMF_OK) {
147*99ebb4caSwyllys 						(void) fprintf(stderr,
148*99ebb4caSwyllys 						    gettext("Error name "
149*99ebb4caSwyllys 						    "input.\n"));
150*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
151*99ebb4caSwyllys 					} else {
152*99ebb4caSwyllys 						KMF_FreeDN(&taDN);
153*99ebb4caSwyllys 					}
154*99ebb4caSwyllys 				}
155*99ebb4caSwyllys 				break;
156*99ebb4caSwyllys 			case 's':
157*99ebb4caSwyllys 				plc.ta_serial = get_string(optarg_av, &rv);
158*99ebb4caSwyllys 				if (plc.ta_serial == NULL) {
159*99ebb4caSwyllys 					(void) fprintf(stderr,
160*99ebb4caSwyllys 					    gettext("Error serial input.\n"));
161*99ebb4caSwyllys 				} else {
162*99ebb4caSwyllys 					uchar_t *bytes = NULL;
163*99ebb4caSwyllys 					size_t bytelen;
164*99ebb4caSwyllys 
165*99ebb4caSwyllys 					ret = KMF_HexString2Bytes(
166*99ebb4caSwyllys 					    (uchar_t *)plc.ta_serial,
167*99ebb4caSwyllys 					    &bytes, &bytelen);
168*99ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
169*99ebb4caSwyllys 						(void) fprintf(stderr,
170*99ebb4caSwyllys 						    gettext("serial number "
171*99ebb4caSwyllys 						    "must be specified as a "
172*99ebb4caSwyllys 						    "hex number "
173*99ebb4caSwyllys 						    "(ex: 0x0102030405"
174*99ebb4caSwyllys 						    "ffeeddee)\n"));
175*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
176*99ebb4caSwyllys 					}
177*99ebb4caSwyllys 					if (bytes != NULL)
178*99ebb4caSwyllys 						free(bytes);
179*99ebb4caSwyllys 				}
180*99ebb4caSwyllys 				break;
181*99ebb4caSwyllys 			case 'o':
182*99ebb4caSwyllys 				plc.VAL_OCSP_RESPONDER_URI =
183*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
184*99ebb4caSwyllys 				if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
185*99ebb4caSwyllys 					(void) fprintf(stderr, gettext(
186*99ebb4caSwyllys 					    "Error responder input.\n"));
187*99ebb4caSwyllys 				} else {
188*99ebb4caSwyllys 					ocsp_set_attr++;
189*99ebb4caSwyllys 				}
190*99ebb4caSwyllys 				break;
191*99ebb4caSwyllys 			case 'P':
192*99ebb4caSwyllys 				plc.VAL_OCSP_PROXY =
193*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
194*99ebb4caSwyllys 				if (plc.VAL_OCSP_PROXY == NULL) {
195*99ebb4caSwyllys 					(void) fprintf(stderr,
196*99ebb4caSwyllys 					    gettext("Error proxy input.\n"));
197*99ebb4caSwyllys 				} else {
198*99ebb4caSwyllys 					ocsp_set_attr++;
199*99ebb4caSwyllys 				}
200*99ebb4caSwyllys 				break;
201*99ebb4caSwyllys 			case 'r':
202*99ebb4caSwyllys 				plc.VAL_OCSP_URI_FROM_CERT =
203*99ebb4caSwyllys 				    get_boolean(optarg_av);
204*99ebb4caSwyllys 				if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
205*99ebb4caSwyllys 					(void) fprintf(stderr,
206*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
207*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
208*99ebb4caSwyllys 				} else {
209*99ebb4caSwyllys 					ocsp_set_attr++;
210*99ebb4caSwyllys 				}
211*99ebb4caSwyllys 				break;
212*99ebb4caSwyllys 			case 'T':
213*99ebb4caSwyllys 				plc.VAL_OCSP_RESP_LIFETIME =
214*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
215*99ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
216*99ebb4caSwyllys 					(void) fprintf(stderr,
217*99ebb4caSwyllys 					    gettext("Error time input.\n"));
218*99ebb4caSwyllys 				} else {
219*99ebb4caSwyllys 					uint32_t adj;
220*99ebb4caSwyllys 					/* for syntax checking */
221*99ebb4caSwyllys 					if (str2lifetime(
222*99ebb4caSwyllys 					    plc.VAL_OCSP_RESP_LIFETIME,
223*99ebb4caSwyllys 					    &adj) < 0) {
224*99ebb4caSwyllys 						(void) fprintf(stderr,
225*99ebb4caSwyllys 						    gettext("Error time "
226*99ebb4caSwyllys 						    "input.\n"));
227*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
228*99ebb4caSwyllys 					} else {
229*99ebb4caSwyllys 						ocsp_set_attr++;
230*99ebb4caSwyllys 					}
231*99ebb4caSwyllys 				}
232*99ebb4caSwyllys 				break;
233*99ebb4caSwyllys 			case 'R':
234*99ebb4caSwyllys 				plc.VAL_OCSP_IGNORE_RESP_SIGN =
235*99ebb4caSwyllys 				    get_boolean(optarg_av);
236*99ebb4caSwyllys 				if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
237*99ebb4caSwyllys 					(void) fprintf(stderr,
238*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
239*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
240*99ebb4caSwyllys 				} else {
241*99ebb4caSwyllys 					ocsp_set_attr++;
242*99ebb4caSwyllys 				}
243*99ebb4caSwyllys 				break;
244*99ebb4caSwyllys 			case 'n':
245*99ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_NAME =
246*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
247*99ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
248*99ebb4caSwyllys 					(void) fprintf(stderr,
249*99ebb4caSwyllys 					    gettext("Error name input.\n"));
250*99ebb4caSwyllys 				} else {
251*99ebb4caSwyllys 					KMF_X509_NAME respDN;
252*99ebb4caSwyllys 					/* for syntax checking */
253*99ebb4caSwyllys 					if (KMF_DNParser(
254*99ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_NAME,
255*99ebb4caSwyllys 					    &respDN) != KMF_OK) {
256*99ebb4caSwyllys 						(void) fprintf(stderr,
257*99ebb4caSwyllys 						    gettext("Error name "
258*99ebb4caSwyllys 						    "input.\n"));
259*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
260*99ebb4caSwyllys 					} else {
261*99ebb4caSwyllys 						KMF_FreeDN(&respDN);
262*99ebb4caSwyllys 						ocsp_set_attr++;
263*99ebb4caSwyllys 					}
264*99ebb4caSwyllys 				}
265*99ebb4caSwyllys 				break;
266*99ebb4caSwyllys 			case 'A':
267*99ebb4caSwyllys 				plc.VAL_OCSP_RESP_CERT_SERIAL =
268*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
269*99ebb4caSwyllys 				if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
270*99ebb4caSwyllys 					(void) fprintf(stderr,
271*99ebb4caSwyllys 					    gettext("Error serial input.\n"));
272*99ebb4caSwyllys 				} else {
273*99ebb4caSwyllys 					uchar_t *bytes = NULL;
274*99ebb4caSwyllys 					size_t bytelen;
275*99ebb4caSwyllys 
276*99ebb4caSwyllys 					ret = KMF_HexString2Bytes((uchar_t *)
277*99ebb4caSwyllys 					    plc.VAL_OCSP_RESP_CERT_SERIAL,
278*99ebb4caSwyllys 					    &bytes, &bytelen);
279*99ebb4caSwyllys 					if (ret != KMF_OK || bytes == NULL) {
280*99ebb4caSwyllys 						(void) fprintf(stderr,
281*99ebb4caSwyllys 						    gettext("serial number "
282*99ebb4caSwyllys 						    "must be specified as a "
283*99ebb4caSwyllys 						    "hex number "
284*99ebb4caSwyllys 						    "(ex: 0x0102030405"
285*99ebb4caSwyllys 						    "ffeeddee)\n"));
286*99ebb4caSwyllys 						rv = KC_ERR_USAGE;
287*99ebb4caSwyllys 						break;
288*99ebb4caSwyllys 					}
289*99ebb4caSwyllys 					if (bytes != NULL)
290*99ebb4caSwyllys 						free(bytes);
291*99ebb4caSwyllys 					ocsp_set_attr++;
292*99ebb4caSwyllys 				}
293*99ebb4caSwyllys 				break;
294*99ebb4caSwyllys 			case 'c':
295*99ebb4caSwyllys 				plc.VAL_CRL_BASEFILENAME =
296*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
297*99ebb4caSwyllys 				if (plc.VAL_CRL_BASEFILENAME == NULL) {
298*99ebb4caSwyllys 					(void) fprintf(stderr,
299*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
300*99ebb4caSwyllys 				} else {
301*99ebb4caSwyllys 					crl_set_attr++;
302*99ebb4caSwyllys 				}
303*99ebb4caSwyllys 				break;
304*99ebb4caSwyllys 			case 'I':
305*99ebb4caSwyllys 				plc.VAL_CRL_DIRECTORY =
306*99ebb4caSwyllys 				    get_string(optarg_av, &rv);
307*99ebb4caSwyllys 				if (plc.VAL_CRL_DIRECTORY == NULL) {
308*99ebb4caSwyllys 					(void) fprintf(stderr,
309*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
310*99ebb4caSwyllys 				} else {
311*99ebb4caSwyllys 					crl_set_attr++;
312*99ebb4caSwyllys 				}
313*99ebb4caSwyllys 				break;
314*99ebb4caSwyllys 			case 'g':
315*99ebb4caSwyllys 				plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
316*99ebb4caSwyllys 				if (plc.VAL_CRL_GET_URI == -1) {
317*99ebb4caSwyllys 					(void) fprintf(stderr,
318*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
319*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
320*99ebb4caSwyllys 				} else {
321*99ebb4caSwyllys 					crl_set_attr++;
322*99ebb4caSwyllys 				}
323*99ebb4caSwyllys 				break;
324*99ebb4caSwyllys 			case 'X':
325*99ebb4caSwyllys 				plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
326*99ebb4caSwyllys 				if (plc.VAL_CRL_PROXY == NULL) {
327*99ebb4caSwyllys 					(void) fprintf(stderr,
328*99ebb4caSwyllys 					    gettext("Error proxy input.\n"));
329*99ebb4caSwyllys 				} else {
330*99ebb4caSwyllys 					crl_set_attr++;
331*99ebb4caSwyllys 				}
332*99ebb4caSwyllys 				break;
333*99ebb4caSwyllys 			case 'S':
334*99ebb4caSwyllys 				plc.VAL_CRL_IGNORE_SIGN =
335*99ebb4caSwyllys 				    get_boolean(optarg_av);
336*99ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_SIGN == -1) {
337*99ebb4caSwyllys 					(void) fprintf(stderr,
338*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
339*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
340*99ebb4caSwyllys 				} else {
341*99ebb4caSwyllys 					crl_set_attr++;
342*99ebb4caSwyllys 				}
343*99ebb4caSwyllys 				break;
344*99ebb4caSwyllys 			case 'D':
345*99ebb4caSwyllys 				plc.VAL_CRL_IGNORE_DATE =
346*99ebb4caSwyllys 					get_boolean(optarg_av);
347*99ebb4caSwyllys 				if (plc.VAL_CRL_IGNORE_DATE == -1) {
348*99ebb4caSwyllys 					(void) fprintf(stderr,
349*99ebb4caSwyllys 					    gettext("Error boolean input.\n"));
350*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
351*99ebb4caSwyllys 				} else {
352*99ebb4caSwyllys 					crl_set_attr++;
353*99ebb4caSwyllys 				}
354*99ebb4caSwyllys 				break;
355*99ebb4caSwyllys 			case 'u':
356*99ebb4caSwyllys 				plc.ku_bits = parseKUlist(optarg_av);
357*99ebb4caSwyllys 				if (plc.ku_bits == 0) {
358*99ebb4caSwyllys 					(void) fprintf(stderr, gettext(
359*99ebb4caSwyllys 					    "Error keyusage input.\n"));
360*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
361*99ebb4caSwyllys 				}
362*99ebb4caSwyllys 				break;
363*99ebb4caSwyllys 			case 'E':
364*99ebb4caSwyllys 				if (parseEKUNames(optarg_av, &plc) != 0) {
365*99ebb4caSwyllys 					(void) fprintf(stderr,
366*99ebb4caSwyllys 					    gettext("Error EKU input.\n"));
367*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
368*99ebb4caSwyllys 				}
369*99ebb4caSwyllys 				break;
370*99ebb4caSwyllys 			case 'O':
371*99ebb4caSwyllys 				if (parseEKUOIDs(optarg_av, &plc) != 0) {
372*99ebb4caSwyllys 					(void) fprintf(stderr,
373*99ebb4caSwyllys 					    gettext("Error EKU OID input.\n"));
374*99ebb4caSwyllys 					rv = KC_ERR_USAGE;
375*99ebb4caSwyllys 				}
376*99ebb4caSwyllys 				break;
377*99ebb4caSwyllys 			default:
378*99ebb4caSwyllys 				(void) fprintf(stderr,
379*99ebb4caSwyllys 				    gettext("Error input option.\n"));
380*99ebb4caSwyllys 				rv = KC_ERR_USAGE;
381*99ebb4caSwyllys 				break;
382*99ebb4caSwyllys 		}
383*99ebb4caSwyllys 
384*99ebb4caSwyllys 		if (rv != KC_OK)
385*99ebb4caSwyllys 			goto out;
386*99ebb4caSwyllys 	}
387*99ebb4caSwyllys 
388*99ebb4caSwyllys 	/* No additional args allowed. */
389*99ebb4caSwyllys 	argc -= optind_av;
390*99ebb4caSwyllys 	if (argc) {
391*99ebb4caSwyllys 		(void) fprintf(stderr,
392*99ebb4caSwyllys 		    gettext("Error input option\n"));
393*99ebb4caSwyllys 		rv = KC_ERR_USAGE;
394*99ebb4caSwyllys 		goto out;
395*99ebb4caSwyllys 	}
396*99ebb4caSwyllys 
397*99ebb4caSwyllys 	if (filename == NULL) {
398*99ebb4caSwyllys 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
399*99ebb4caSwyllys 		if (filename == NULL) {
400*99ebb4caSwyllys 			rv = KC_ERR_MEMORY;
401*99ebb4caSwyllys 			goto out;
402*99ebb4caSwyllys 		}
403*99ebb4caSwyllys 	}
404*99ebb4caSwyllys 
405*99ebb4caSwyllys 	/*
406*99ebb4caSwyllys 	 * Must have a policy name. The policy name can not be default
407*99ebb4caSwyllys 	 * if using the default policy file.
408*99ebb4caSwyllys 	 */
409*99ebb4caSwyllys 	if (plc.name == NULL) {
410*99ebb4caSwyllys 		(void) fprintf(stderr,
411*99ebb4caSwyllys 		    gettext("You must specify a policy name\n"));
412*99ebb4caSwyllys 		rv = KC_ERR_USAGE;
413*99ebb4caSwyllys 		goto out;
414*99ebb4caSwyllys 	} else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
415*99ebb4caSwyllys 	    strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
416*99ebb4caSwyllys 		(void) fprintf(stderr,
417*99ebb4caSwyllys 		    gettext("Can not create a default policy in the default "
418*99ebb4caSwyllys 		    "policy file\n"));
419*99ebb4caSwyllys 		rv = KC_ERR_USAGE;
420*99ebb4caSwyllys 		goto out;
421*99ebb4caSwyllys 	}
422*99ebb4caSwyllys 
423*99ebb4caSwyllys 	/*
424*99ebb4caSwyllys 	 * If the policy file exists and the policy is in the policy file
425*99ebb4caSwyllys 	 * already, we will not create it again.
426*99ebb4caSwyllys 	 */
427*99ebb4caSwyllys 	if (access(filename, R_OK) == 0) {
428*99ebb4caSwyllys 		POLICY_LIST *plclist = NULL, *pnode;
429*99ebb4caSwyllys 		int found = 0;
430*99ebb4caSwyllys 
431*99ebb4caSwyllys 		rv = load_policies(filename, &plclist);
432*99ebb4caSwyllys 		if (rv != KMF_OK)
433*99ebb4caSwyllys 			goto out;
434*99ebb4caSwyllys 
435*99ebb4caSwyllys 		pnode = plclist;
436*99ebb4caSwyllys 		while (pnode != NULL && !found) {
437*99ebb4caSwyllys 			if (strcmp(plc.name, pnode->plc.name) == 0)
438*99ebb4caSwyllys 				found++;
439*99ebb4caSwyllys 			pnode = pnode->next;
440*99ebb4caSwyllys 		}
441*99ebb4caSwyllys 		free_policy_list(plclist);
442*99ebb4caSwyllys 
443*99ebb4caSwyllys 		if (found) {
444*99ebb4caSwyllys 			(void) fprintf(stderr,
445*99ebb4caSwyllys 			    gettext("Could not create policy \"%s\" - exists "
446*99ebb4caSwyllys 			    "already\n"), plc.name);
447*99ebb4caSwyllys 			rv = KC_ERR_USAGE;
448*99ebb4caSwyllys 			goto out;
449*99ebb4caSwyllys 		}
450*99ebb4caSwyllys 	}
451*99ebb4caSwyllys 
452*99ebb4caSwyllys 	/*
453*99ebb4caSwyllys 	 * If any OCSP attribute is set, turn on the OCSP checking flag.
454*99ebb4caSwyllys 	 * Also set "has_resp_cert" to be true, if the responder cert
455*99ebb4caSwyllys 	 * is provided.
456*99ebb4caSwyllys 	 */
457*99ebb4caSwyllys 	if (ocsp_set_attr > 0)
458*99ebb4caSwyllys 		plc.revocation |= KMF_REVOCATION_METHOD_OCSP;
459*99ebb4caSwyllys 
460*99ebb4caSwyllys 	if (plc.VAL_OCSP_RESP_CERT.name != NULL &&
461*99ebb4caSwyllys 	    plc.VAL_OCSP_RESP_CERT.serial != NULL) {
462*99ebb4caSwyllys 		plc.VAL_OCSP.has_resp_cert = B_TRUE;
463*99ebb4caSwyllys 	}
464*99ebb4caSwyllys 
465*99ebb4caSwyllys 	/*
466*99ebb4caSwyllys 	 * If any CRL attribute is set, turn on the CRL checking flag.
467*99ebb4caSwyllys 	 */
468*99ebb4caSwyllys 	if (crl_set_attr > 0)
469*99ebb4caSwyllys 		plc.revocation |= KMF_REVOCATION_METHOD_CRL;
470*99ebb4caSwyllys 
471*99ebb4caSwyllys 	/*
472*99ebb4caSwyllys 	 * Does a sanity check on the new policy.
473*99ebb4caSwyllys 	 */
474*99ebb4caSwyllys 	ret = KMF_VerifyPolicy(&plc);
475*99ebb4caSwyllys 	if (ret != KMF_OK) {
476*99ebb4caSwyllys 		print_sanity_error(ret);
477*99ebb4caSwyllys 		rv = KC_ERR_ADD_POLICY;
478*99ebb4caSwyllys 		goto out;
479*99ebb4caSwyllys 	}
480*99ebb4caSwyllys 
481*99ebb4caSwyllys 	/*
482*99ebb4caSwyllys 	 * Add to the DB.
483*99ebb4caSwyllys 	 */
484*99ebb4caSwyllys 	ret = KMF_AddPolicyToDB(&plc, filename, B_FALSE);
485*99ebb4caSwyllys 	if (ret != KMF_OK) {
486*99ebb4caSwyllys 		(void) fprintf(stderr,
487*99ebb4caSwyllys 		    gettext("Error adding policy to database: 0x%04x\n"), ret);
488*99ebb4caSwyllys 		rv = KC_ERR_ADD_POLICY;
489*99ebb4caSwyllys 	}
490*99ebb4caSwyllys 
491*99ebb4caSwyllys out:
492*99ebb4caSwyllys 	if (filename != NULL)
493*99ebb4caSwyllys 		free(filename);
494*99ebb4caSwyllys 
495*99ebb4caSwyllys 	KMF_FreePolicyRecord(&plc);
496*99ebb4caSwyllys 
497*99ebb4caSwyllys 	return (rv);
498*99ebb4caSwyllys }
499