dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-crypto / kmfcfg / create.c
blob0d6fd944b2b5d791fdb679fda808ef3418b46d66
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
21 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 #include <stdio.h>
25 #include <strings.h>
26 #include <ctype.h>
27 #include <libgen.h>
28 #include <libintl.h>
29 #include <errno.h>
30 #include <kmfapiP.h>
31 #include <cryptoutil.h>
32 #include "util.h"
34 int
35 kc_create(int argc, char *argv[])
37 KMF_RETURN ret;
38 int rv = KC_OK;
39 int opt;
40 extern int optind_av;
41 extern char *optarg_av;
42 char *filename = NULL;
43 int ocsp_set_attr = 0;
44 boolean_t crl_set_attr = 0;
45 KMF_POLICY_RECORD plc;
47 (void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
49 while ((opt = getopt_av(argc, argv,
50 "i:(dbfile)"
51 "p:(policy)"
52 "d:(ignore-date)"
53 "e:(ignore-unknown-eku)"
54 "a:(ignore-trust-anchor)"
55 "v:(validity-adjusttime)"
56 "t:(ta-name)"
57 "s:(ta-serial)"
58 "o:(ocsp-responder)"
59 "P:(ocsp-proxy)"
60 "r:(ocsp-use-cert-responder)"
61 "T:(ocsp-response-lifetime)"
62 "R:(ocsp-ignore-response-sign)"
63 "n:(ocsp-responder-cert-name)"
64 "A:(ocsp-responder-cert-serial)"
65 "c:(crl-basefilename)"
66 "I:(crl-directory)"
67 "g:(crl-get-crl-uri)"
68 "X:(crl-proxy)"
69 "S:(crl-ignore-crl-sign)"
70 "D:(crl-ignore-crl-date)"
71 "m:(mapper-name)"
72 "M:(mapper-directory)"
73 "Q:(mapper-pathname)"
74 "q:(mapper-options)"
75 "u:(keyusage)"
76 "E:(ekunames)"
77 "O:(ekuoids)")) != EOF) {
78 switch (opt) {
79 case 'i':
80 filename = get_string(optarg_av, &rv);
81 if (filename == NULL) {
82 (void) fprintf(stderr,
83 gettext("Error dbfile input.\n"));
85 break;
86 case 'p':
87 plc.name = get_string(optarg_av, &rv);
88 if (plc.name == NULL) {
89 (void) fprintf(stderr,
90 gettext("Error policy name.\n"));
92 break;
93 case 'd':
94 plc.ignore_date = get_boolean(optarg_av);
95 if (plc.ignore_date == -1) {
96 (void) fprintf(stderr,
97 gettext("Error boolean input.\n"));
98 rv = KC_ERR_USAGE;
100 break;
101 case 'e':
102 plc.ignore_unknown_ekus =
103 get_boolean(optarg_av);
104 if (plc.ignore_unknown_ekus == -1) {
105 (void) fprintf(stderr,
106 gettext("Error boolean input.\n"));
107 rv = KC_ERR_USAGE;
109 break;
110 case 'a':
111 plc.ignore_trust_anchor =
112 get_boolean(optarg_av);
113 if (plc.ignore_trust_anchor == -1) {
114 (void) fprintf(stderr,
115 gettext("Error boolean input.\n"));
116 rv = KC_ERR_USAGE;
118 break;
119 case 'v':
120 plc.validity_adjusttime =
121 get_string(optarg_av, &rv);
122 if (plc.validity_adjusttime == NULL) {
123 (void) fprintf(stderr,
124 gettext("Error time input.\n"));
125 } else {
126 uint32_t adj;
127 /* for syntax checking */
128 if (str2lifetime(
129 plc.validity_adjusttime,
130 &adj) < 0) {
131 (void) fprintf(stderr,
132 gettext("Error time "
133 "input.\n"));
134 rv = KC_ERR_USAGE;
137 break;
138 case 't':
139 plc.ta_name = get_string(optarg_av, &rv);
140 if (plc.ta_name == NULL) {
141 (void) fprintf(stderr,
142 gettext("Error name input.\n"));
143 } else if (strcasecmp(plc.ta_name,
144 "search") != 0) {
145 KMF_X509_NAME taDN;
146 /* for syntax checking */
147 if (kmf_dn_parser(plc.ta_name,
148 &taDN) != KMF_OK) {
149 (void) fprintf(stderr,
150 gettext("Error name "
151 "input.\n"));
152 rv = KC_ERR_USAGE;
153 } else {
154 kmf_free_dn(&taDN);
157 break;
158 case 's':
159 plc.ta_serial = get_string(optarg_av, &rv);
160 if (plc.ta_serial == NULL) {
161 (void) fprintf(stderr,
162 gettext("Error serial input.\n"));
163 } else {
164 uchar_t *bytes = NULL;
165 size_t bytelen;
167 ret = kmf_hexstr_to_bytes(
168 (uchar_t *)plc.ta_serial,
169 &bytes, &bytelen);
170 if (ret != KMF_OK || bytes == NULL) {
171 (void) fprintf(stderr,
172 gettext("serial number "
173 "must be specified as a "
174 "hex number "
175 "(ex: 0x0102030405"
176 "ffeeddee)\n"));
177 rv = KC_ERR_USAGE;
179 free(bytes);
181 break;
182 case 'o':
183 plc.VAL_OCSP_RESPONDER_URI =
184 get_string(optarg_av, &rv);
185 if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
186 (void) fprintf(stderr, gettext(
187 "Error responder input.\n"));
188 } else {
189 ocsp_set_attr++;
191 break;
192 case 'P':
193 plc.VAL_OCSP_PROXY =
194 get_string(optarg_av, &rv);
195 if (plc.VAL_OCSP_PROXY == NULL) {
196 (void) fprintf(stderr,
197 gettext("Error proxy input.\n"));
198 } else {
199 ocsp_set_attr++;
201 break;
202 case 'r':
203 plc.VAL_OCSP_URI_FROM_CERT =
204 get_boolean(optarg_av);
205 if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
206 (void) fprintf(stderr,
207 gettext("Error boolean input.\n"));
208 rv = KC_ERR_USAGE;
209 } else {
210 ocsp_set_attr++;
212 break;
213 case 'T':
214 plc.VAL_OCSP_RESP_LIFETIME =
215 get_string(optarg_av, &rv);
216 if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
217 (void) fprintf(stderr,
218 gettext("Error time input.\n"));
219 } else {
220 uint32_t adj;
221 /* for syntax checking */
222 if (str2lifetime(
223 plc.VAL_OCSP_RESP_LIFETIME,
224 &adj) < 0) {
225 (void) fprintf(stderr,
226 gettext("Error time "
227 "input.\n"));
228 rv = KC_ERR_USAGE;
229 } else {
230 ocsp_set_attr++;
233 break;
234 case 'R':
235 plc.VAL_OCSP_IGNORE_RESP_SIGN =
236 get_boolean(optarg_av);
237 if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
238 (void) fprintf(stderr,
239 gettext("Error boolean input.\n"));
240 rv = KC_ERR_USAGE;
241 } else {
242 ocsp_set_attr++;
244 break;
245 case 'n':
246 plc.VAL_OCSP_RESP_CERT_NAME =
247 get_string(optarg_av, &rv);
248 if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
249 (void) fprintf(stderr,
250 gettext("Error name input.\n"));
251 } else {
252 KMF_X509_NAME respDN;
253 /* for syntax checking */
254 if (kmf_dn_parser(
255 plc.VAL_OCSP_RESP_CERT_NAME,
256 &respDN) != KMF_OK) {
257 (void) fprintf(stderr,
258 gettext("Error name "
259 "input.\n"));
260 rv = KC_ERR_USAGE;
261 } else {
262 kmf_free_dn(&respDN);
263 ocsp_set_attr++;
266 break;
267 case 'A':
268 plc.VAL_OCSP_RESP_CERT_SERIAL =
269 get_string(optarg_av, &rv);
270 if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
271 (void) fprintf(stderr,
272 gettext("Error serial input.\n"));
273 } else {
274 uchar_t *bytes = NULL;
275 size_t bytelen;
277 ret = kmf_hexstr_to_bytes((uchar_t *)
278 plc.VAL_OCSP_RESP_CERT_SERIAL,
279 &bytes, &bytelen);
280 if (ret != KMF_OK || bytes == NULL) {
281 (void) fprintf(stderr,
282 gettext("serial number "
283 "must be specified as a "
284 "hex number "
285 "(ex: 0x0102030405"
286 "ffeeddee)\n"));
287 rv = KC_ERR_USAGE;
288 break;
290 free(bytes);
291 ocsp_set_attr++;
293 break;
294 case 'c':
295 plc.VAL_CRL_BASEFILENAME =
296 get_string(optarg_av, &rv);
297 if (plc.VAL_CRL_BASEFILENAME == NULL) {
298 (void) fprintf(stderr,
299 gettext("Error boolean input.\n"));
300 } else {
301 crl_set_attr++;
303 break;
304 case 'I':
305 plc.VAL_CRL_DIRECTORY =
306 get_string(optarg_av, &rv);
307 if (plc.VAL_CRL_DIRECTORY == NULL) {
308 (void) fprintf(stderr,
309 gettext("Error boolean input.\n"));
310 } else {
311 crl_set_attr++;
313 break;
314 case 'g':
315 plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
316 if (plc.VAL_CRL_GET_URI == -1) {
317 (void) fprintf(stderr,
318 gettext("Error boolean input.\n"));
319 rv = KC_ERR_USAGE;
320 } else {
321 crl_set_attr++;
323 break;
324 case 'X':
325 plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
326 if (plc.VAL_CRL_PROXY == NULL) {
327 (void) fprintf(stderr,
328 gettext("Error proxy input.\n"));
329 } else {
330 crl_set_attr++;
332 break;
333 case 'S':
334 plc.VAL_CRL_IGNORE_SIGN =
335 get_boolean(optarg_av);
336 if (plc.VAL_CRL_IGNORE_SIGN == -1) {
337 (void) fprintf(stderr,
338 gettext("Error boolean input.\n"));
339 rv = KC_ERR_USAGE;
340 } else {
341 crl_set_attr++;
343 break;
344 case 'D':
345 plc.VAL_CRL_IGNORE_DATE =
346 get_boolean(optarg_av);
347 if (plc.VAL_CRL_IGNORE_DATE == -1) {
348 (void) fprintf(stderr,
349 gettext("Error boolean input.\n"));
350 rv = KC_ERR_USAGE;
351 } else {
352 crl_set_attr++;
354 break;
355 case 'u':
356 plc.ku_bits = parseKUlist(optarg_av);
357 if (plc.ku_bits == 0) {
358 (void) fprintf(stderr, gettext(
359 "Error keyusage input.\n"));
360 rv = KC_ERR_USAGE;
362 break;
363 case 'E':
364 if (parseEKUNames(optarg_av, &plc) != 0) {
365 (void) fprintf(stderr,
366 gettext("Error EKU input.\n"));
367 rv = KC_ERR_USAGE;
369 break;
370 case 'O':
371 if (parseEKUOIDs(optarg_av, &plc) != 0) {
372 (void) fprintf(stderr,
373 gettext("Error EKU OID input.\n"));
374 rv = KC_ERR_USAGE;
376 break;
377 case 'm':
378 plc.mapper.mapname = get_string(optarg_av, &rv);
379 if (plc.mapper.mapname == NULL) {
380 (void) fprintf(stderr,
381 gettext("Error mapper-name "
382 "input.\n"));
384 break;
385 case 'M':
386 plc.mapper.dir = get_string(optarg_av, &rv);
387 if (plc.mapper.dir == NULL) {
388 (void) fprintf(stderr,
389 gettext("Error mapper-dir "
390 "input.\n"));
392 break;
393 case 'Q':
394 plc.mapper.pathname = get_string(optarg_av,
395 &rv);
396 if (plc.mapper.pathname == NULL) {
397 (void) fprintf(stderr,
398 gettext("Error mapper-pathname "
399 "input.\n"));
401 break;
402 case 'q':
403 plc.mapper.options = get_string(optarg_av, &rv);
404 if (plc.mapper.options == NULL) {
405 (void) fprintf(stderr,
406 gettext("Error mapper-options "
407 "input.\n"));
409 break;
410 default:
411 (void) fprintf(stderr,
412 gettext("Error input option.\n"));
413 rv = KC_ERR_USAGE;
414 break;
417 if (rv != KC_OK)
418 goto out;
421 /* No additional args allowed. */
422 argc -= optind_av;
423 if (argc) {
424 (void) fprintf(stderr,
425 gettext("Error input option\n"));
426 rv = KC_ERR_USAGE;
427 goto out;
430 if (filename == NULL) {
431 filename = strdup(KMF_DEFAULT_POLICY_FILE);
432 if (filename == NULL) {
433 rv = KC_ERR_MEMORY;
434 goto out;
439 * Must have a policy name. The policy name can not be default
440 * if using the default policy file.
442 if (plc.name == NULL) {
443 (void) fprintf(stderr,
444 gettext("You must specify a policy name\n"));
445 rv = KC_ERR_USAGE;
446 goto out;
447 } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
448 strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
449 (void) fprintf(stderr,
450 gettext("Can not create a default policy in the default "
451 "policy file\n"));
452 rv = KC_ERR_USAGE;
453 goto out;
457 * If the policy file exists and the policy is in the policy file
458 * already, we will not create it again.
460 if (access(filename, R_OK) == 0) {
461 POLICY_LIST *plclist = NULL, *pnode;
462 int found = 0;
464 rv = load_policies(filename, &plclist);
465 if (rv != KMF_OK)
466 goto out;
468 pnode = plclist;
469 while (pnode != NULL && !found) {
470 if (strcmp(plc.name, pnode->plc.name) == 0)
471 found++;
472 pnode = pnode->next;
474 free_policy_list(plclist);
476 if (found) {
477 (void) fprintf(stderr,
478 gettext("Could not create policy \"%s\" - exists "
479 "already\n"), plc.name);
480 rv = KC_ERR_USAGE;
481 goto out;
486 * If any OCSP attribute is set, turn on the OCSP checking flag.
487 * Also set "has_resp_cert" to be true, if the responder cert
488 * is provided.
490 if (ocsp_set_attr > 0)
491 plc.revocation |= KMF_REVOCATION_METHOD_OCSP;
493 if (plc.VAL_OCSP_RESP_CERT.name != NULL &&
494 plc.VAL_OCSP_RESP_CERT.serial != NULL) {
495 plc.VAL_OCSP.has_resp_cert = B_TRUE;
499 * Setting mapper-name (with optional mapper-dir) and mapper-pathname is
500 * mutually exclusive. Also, you cannot set options only, you need the
501 * name or pathname, and you can set the directory only with the name,
502 * not the pathname.
504 if ((plc.mapper.mapname != NULL && plc.mapper.pathname != NULL) ||
505 (plc.mapper.dir != NULL && plc.mapper.pathname != NULL) ||
506 (plc.mapper.dir != NULL && plc.mapper.mapname == NULL) ||
507 (plc.mapper.options != NULL && plc.mapper.mapname == NULL &&
508 plc.mapper.pathname == NULL)) {
509 (void) fprintf(stderr,
510 gettext("Error in mapper input options\n"));
511 rv = KC_ERR_USAGE;
512 goto out;
516 * If any CRL attribute is set, turn on the CRL checking flag.
518 if (crl_set_attr > 0)
519 plc.revocation |= KMF_REVOCATION_METHOD_CRL;
522 * Does a sanity check on the new policy.
524 ret = kmf_verify_policy(&plc);
525 if (ret != KMF_OK) {
526 print_sanity_error(ret);
527 rv = KC_ERR_ADD_POLICY;
528 goto out;
532 * Add to the DB.
534 ret = kmf_add_policy_to_db(&plc, filename, B_FALSE);
535 if (ret != KMF_OK) {
536 (void) fprintf(stderr,
537 gettext("Error adding policy to database: 0x%04x\n"), ret);
538 rv = KC_ERR_ADD_POLICY;
541 out:
542 free(filename);
544 kmf_free_policy_record(&plc);
546 return (rv);