dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-crypto / kmfcfg / modify.c
blob7a71ce2a379581dc49fa04b73b0b123442325d5e
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 <sys/stat.h>
33 #include <sys/param.h>
34 #include "util.h"
36 #define KC_IGNORE_DATE 0x0000001
37 #define KC_IGNORE_UNKNOWN_EKUS 0x0000002
38 #define KC_IGNORE_TRUST_ANCHOR 0x0000004
39 #define KC_VALIDITY_ADJUSTTIME 0x0000008
40 #define KC_TA_NAME 0x0000010
41 #define KC_TA_SERIAL 0x0000020
42 #define KC_OCSP_RESPONDER_URI 0x0000040
43 #define KC_OCSP_PROXY 0x0000080
44 #define KC_OCSP_URI_FROM_CERT 0x0000100
45 #define KC_OCSP_RESP_LIFETIME 0x0000200
46 #define KC_OCSP_IGNORE_RESP_SIGN 0x0000400
47 #define KC_OCSP_RESP_CERT_NAME 0x0000800
48 #define KC_OCSP_RESP_CERT_SERIAL 0x0001000
49 #define KC_OCSP_NONE 0x0002000
50 #define KC_CRL_BASEFILENAME 0x0004000
51 #define KC_CRL_DIRECTORY 0x0008000
52 #define KC_CRL_GET_URI 0x0010000
53 #define KC_CRL_PROXY 0x0020000
54 #define KC_CRL_IGNORE_SIGN 0x0040000
55 #define KC_CRL_IGNORE_DATE 0x0080000
56 #define KC_CRL_NONE 0x0100000
57 #define KC_KEYUSAGE 0x0200000
58 #define KC_KEYUSAGE_NONE 0x0400000
59 #define KC_EKUS 0x0800000
60 #define KC_EKUS_NONE 0x1000000
61 #define KC_MAPPER_OPTIONS 0x2000000
63 static int err; /* To store errno which may be overwritten by gettext() */
65 #define UPDATE_IF_DIFFERENT(old, new) \
66 if ((old != NULL && new != NULL && strcmp(old, new) != 0) || \
67 (old == NULL && new != NULL)) { \
68 free(old); \
69 old = new; \
72 int
73 kc_modify_policy(int argc, char *argv[])
75 KMF_RETURN ret;
76 int rv = KC_OK;
77 int opt;
78 extern int optind_av;
79 extern char *optarg_av;
80 char *filename = NULL;
81 char *mapper_name = NULL;
82 char *mapper_dir = NULL;
83 char *mapper_pathname = NULL;
84 uint32_t flags = 0;
85 boolean_t ocsp_none_opt = B_FALSE;
86 boolean_t crl_none_opt = B_FALSE;
87 boolean_t ku_none_opt = B_FALSE;
88 boolean_t eku_none_opt = B_FALSE;
89 int ocsp_set_attr = 0;
90 int crl_set_attr = 0;
91 KMF_POLICY_RECORD oplc, plc;
93 (void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
94 (void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD));
96 while ((opt = getopt_av(argc, argv,
97 "i:(dbfile)"
98 "p:(policy)"
99 "d:(ignore-date)"
100 "e:(ignore-unknown-eku)"
101 "a:(ignore-trust-anchor)"
102 "v:(validity-adjusttime)"
103 "t:(ta-name)"
104 "s:(ta-serial)"
105 "o:(ocsp-responder)"
106 "P:(ocsp-proxy)"
107 "r:(ocsp-use-cert-responder)"
108 "T:(ocsp-response-lifetime)"
109 "R:(ocsp-ignore-response-sign)"
110 "n:(ocsp-responder-cert-name)"
111 "A:(ocsp-responder-cert-serial)"
112 "y:(ocsp-none)"
113 "c:(crl-basefilename)"
114 "I:(crl-directory)"
115 "g:(crl-get-crl-uri)"
116 "X:(crl-proxy)"
117 "S:(crl-ignore-crl-sign)"
118 "D:(crl-ignore-crl-date)"
119 "z:(crl-none)"
120 "u:(keyusage)"
121 "Y:(keyusage-none)"
122 "E:(ekunames)"
123 "O:(ekuoids)"
124 "m:(mapper-name)"
125 "M:(mapper-directory)"
126 "Q:(mapper-pathname)"
127 "q:(mapper-options)"
128 "Z:(eku-none)")) != EOF) {
129 switch (opt) {
130 case 'i':
131 filename = get_string(optarg_av, &rv);
132 if (filename == NULL) {
133 (void) fprintf(stderr,
134 gettext("Error dbfile input.\n"));
136 break;
137 case 'p':
138 plc.name = get_string(optarg_av, &rv);
139 if (plc.name == NULL) {
140 (void) fprintf(stderr,
141 gettext("Error policy name.\n"));
143 break;
144 case 'd':
145 plc.ignore_date = get_boolean(optarg_av);
146 if (plc.ignore_date == -1) {
147 (void) fprintf(stderr,
148 gettext("Error boolean input.\n"));
149 rv = KC_ERR_USAGE;
150 } else {
151 flags |= KC_IGNORE_DATE;
153 break;
154 case 'e':
155 plc.ignore_unknown_ekus =
156 get_boolean(optarg_av);
157 if (plc.ignore_unknown_ekus == -1) {
158 (void) fprintf(stderr,
159 gettext("Error boolean input.\n"));
160 rv = KC_ERR_USAGE;
161 } else {
162 flags |= KC_IGNORE_UNKNOWN_EKUS;
164 break;
165 case 'a':
166 plc.ignore_trust_anchor =
167 get_boolean(optarg_av);
168 if (plc.ignore_trust_anchor == -1) {
169 (void) fprintf(stderr,
170 gettext("Error boolean input.\n"));
171 rv = KC_ERR_USAGE;
172 } else {
173 flags |= KC_IGNORE_TRUST_ANCHOR;
175 break;
176 case 'v':
177 plc.validity_adjusttime =
178 get_string(optarg_av, &rv);
179 if (plc.validity_adjusttime == NULL) {
180 (void) fprintf(stderr,
181 gettext("Error time input.\n"));
182 } else {
183 uint32_t adj;
184 /* for syntax checking */
185 if (str2lifetime(
186 plc.validity_adjusttime,
187 &adj) < 0) {
188 (void) fprintf(stderr,
189 gettext("Error time "
190 "input.\n"));
191 rv = KC_ERR_USAGE;
192 } else {
193 flags |= KC_VALIDITY_ADJUSTTIME;
196 break;
197 case 't':
198 plc.ta_name = get_string(optarg_av, &rv);
199 if (plc.ta_name == NULL) {
200 (void) fprintf(stderr,
201 gettext("Error name input.\n"));
202 } else if (strcasecmp(plc.ta_name, "search")) {
203 KMF_X509_NAME taDN;
204 /* for syntax checking */
205 if (kmf_dn_parser(plc.ta_name,
206 &taDN) != KMF_OK) {
207 (void) fprintf(stderr,
208 gettext("Error name "
209 "input.\n"));
210 rv = KC_ERR_USAGE;
211 } else {
212 kmf_free_dn(&taDN);
213 flags |= KC_TA_NAME;
215 } else {
216 flags |= KC_TA_NAME;
218 break;
219 case 's':
220 plc.ta_serial = get_string(optarg_av, &rv);
221 if (plc.ta_serial == NULL) {
222 (void) fprintf(stderr,
223 gettext("Error serial input.\n"));
224 } else {
225 uchar_t *bytes = NULL;
226 size_t bytelen;
228 ret = kmf_hexstr_to_bytes(
229 (uchar_t *)plc.ta_serial,
230 &bytes, &bytelen);
231 if (ret != KMF_OK || bytes == NULL) {
232 (void) fprintf(stderr,
233 gettext("serial number "
234 "must be specified as a "
235 "hex number "
236 "(ex: 0x0102030405"
237 "ffeeddee)\n"));
238 rv = KC_ERR_USAGE;
239 break;
241 free(bytes);
242 flags |= KC_TA_SERIAL;
244 break;
245 case 'o':
246 plc.VAL_OCSP_RESPONDER_URI =
247 get_string(optarg_av, &rv);
248 if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
249 (void) fprintf(stderr,
250 gettext("Error responder "
251 "input.\n"));
252 } else {
253 flags |= KC_OCSP_RESPONDER_URI;
254 ocsp_set_attr++;
256 break;
257 case 'P':
258 plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
259 if (plc.VAL_OCSP_PROXY == NULL) {
260 (void) fprintf(stderr,
261 gettext("Error proxy input.\n"));
262 } else {
263 flags |= KC_OCSP_PROXY;
264 ocsp_set_attr++;
266 break;
267 case 'r':
268 plc.VAL_OCSP_URI_FROM_CERT =
269 get_boolean(optarg_av);
270 if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
271 (void) fprintf(stderr,
272 gettext("Error boolean input.\n"));
273 rv = KC_ERR_USAGE;
274 } else {
275 flags |= KC_OCSP_URI_FROM_CERT;
276 ocsp_set_attr++;
278 break;
279 case 'T':
280 plc.VAL_OCSP_RESP_LIFETIME =
281 get_string(optarg_av, &rv);
282 if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
283 (void) fprintf(stderr,
284 gettext("Error time input.\n"));
285 } else {
286 uint32_t adj;
287 /* for syntax checking */
288 if (str2lifetime(
289 plc.VAL_OCSP_RESP_LIFETIME,
290 &adj) < 0) {
291 (void) fprintf(stderr,
292 gettext("Error time "
293 "input.\n"));
294 rv = KC_ERR_USAGE;
295 } else {
296 flags |= KC_OCSP_RESP_LIFETIME;
297 ocsp_set_attr++;
300 break;
301 case 'R':
302 plc.VAL_OCSP_IGNORE_RESP_SIGN =
303 get_boolean(optarg_av);
304 if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
305 (void) fprintf(stderr,
306 gettext("Error boolean input.\n"));
307 rv = KC_ERR_USAGE;
308 } else {
309 flags |= KC_OCSP_IGNORE_RESP_SIGN;
310 ocsp_set_attr++;
312 break;
313 case 'n':
314 plc.VAL_OCSP_RESP_CERT_NAME =
315 get_string(optarg_av, &rv);
316 if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
317 (void) fprintf(stderr,
318 gettext("Error name input.\n"));
319 } else {
320 KMF_X509_NAME respDN;
321 /* for syntax checking */
322 if (kmf_dn_parser(
323 plc.VAL_OCSP_RESP_CERT_NAME,
324 &respDN) != KMF_OK) {
325 (void) fprintf(stderr,
326 gettext("Error name "
327 "input.\n"));
328 rv = KC_ERR_USAGE;
329 } else {
330 kmf_free_dn(&respDN);
331 flags |= KC_OCSP_RESP_CERT_NAME;
332 ocsp_set_attr++;
335 break;
336 case 'A':
337 plc.VAL_OCSP_RESP_CERT_SERIAL =
338 get_string(optarg_av, &rv);
339 if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
340 (void) fprintf(stderr,
341 gettext("Error serial input.\n"));
342 } else {
343 uchar_t *bytes = NULL;
344 size_t bytelen;
346 ret = kmf_hexstr_to_bytes((uchar_t *)
347 plc.VAL_OCSP_RESP_CERT_SERIAL,
348 &bytes, &bytelen);
349 if (ret != KMF_OK || bytes == NULL) {
350 (void) fprintf(stderr,
351 gettext("serial number "
352 "must be specified as a "
353 "hex number "
354 "(ex: 0x0102030405"
355 "ffeeddee)\n"));
356 rv = KC_ERR_USAGE;
357 break;
359 free(bytes);
360 flags |= KC_OCSP_RESP_CERT_SERIAL;
361 ocsp_set_attr++;
363 break;
364 case 'y':
365 ocsp_none_opt = get_boolean(optarg_av);
366 if (ocsp_none_opt == -1) {
367 (void) fprintf(stderr,
368 gettext("Error boolean input.\n"));
369 rv = KC_ERR_USAGE;
370 } else {
371 flags |= KC_OCSP_NONE;
373 break;
374 case 'c':
375 plc.VAL_CRL_BASEFILENAME =
376 get_string(optarg_av, &rv);
377 if (plc.VAL_CRL_BASEFILENAME == NULL) {
378 (void) fprintf(stderr, gettext(
379 "Error basefilename input.\n"));
380 } else {
381 flags |= KC_CRL_BASEFILENAME;
382 crl_set_attr++;
384 break;
385 case 'I':
386 plc.VAL_CRL_DIRECTORY =
387 get_string(optarg_av, &rv);
388 if (plc.VAL_CRL_DIRECTORY == NULL) {
389 (void) fprintf(stderr,
390 gettext("Error boolean input.\n"));
391 } else {
392 flags |= KC_CRL_DIRECTORY;
393 crl_set_attr++;
395 break;
396 case 'g':
397 plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
398 if (plc.VAL_CRL_GET_URI == -1) {
399 (void) fprintf(stderr,
400 gettext("Error boolean input.\n"));
401 rv = KC_ERR_USAGE;
402 } else {
403 flags |= KC_CRL_GET_URI;
404 crl_set_attr++;
406 break;
407 case 'X':
408 plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
409 if (plc.VAL_CRL_PROXY == NULL) {
410 (void) fprintf(stderr,
411 gettext("Error proxy input.\n"));
412 } else {
413 flags |= KC_CRL_PROXY;
414 crl_set_attr++;
416 break;
417 case 'S':
418 plc.VAL_CRL_IGNORE_SIGN =
419 get_boolean(optarg_av);
420 if (plc.VAL_CRL_IGNORE_SIGN == -1) {
421 (void) fprintf(stderr,
422 gettext("Error boolean input.\n"));
423 rv = KC_ERR_USAGE;
424 } else {
425 flags |= KC_CRL_IGNORE_SIGN;
426 crl_set_attr++;
428 break;
429 case 'D':
430 plc.VAL_CRL_IGNORE_DATE =
431 get_boolean(optarg_av);
432 if (plc.VAL_CRL_IGNORE_DATE == -1) {
433 (void) fprintf(stderr,
434 gettext("Error boolean input.\n"));
435 rv = KC_ERR_USAGE;
436 } else {
437 flags |= KC_CRL_IGNORE_DATE;
438 crl_set_attr++;
440 break;
441 case 'z':
442 crl_none_opt = get_boolean(optarg_av);
443 if (crl_none_opt == -1) {
444 (void) fprintf(stderr,
445 gettext("Error boolean input.\n"));
446 rv = KC_ERR_USAGE;
447 } else {
448 flags |= KC_CRL_NONE;
450 break;
451 case 'u':
452 plc.ku_bits = parseKUlist(optarg_av);
453 if (plc.ku_bits == 0) {
454 (void) fprintf(stderr, gettext(
455 "Error keyusage input.\n"));
456 rv = KC_ERR_USAGE;
457 } else {
458 flags |= KC_KEYUSAGE;
460 break;
461 case 'Y':
462 ku_none_opt = get_boolean(optarg_av);
463 if (ku_none_opt == -1) {
464 (void) fprintf(stderr,
465 gettext("Error boolean input.\n"));
466 rv = KC_ERR_USAGE;
467 } else {
468 flags |= KC_KEYUSAGE_NONE;
470 break;
471 case 'E':
472 if (parseEKUNames(optarg_av, &plc) != 0) {
473 (void) fprintf(stderr,
474 gettext("Error EKU input.\n"));
475 rv = KC_ERR_USAGE;
476 } else {
477 flags |= KC_EKUS;
479 break;
480 case 'O':
481 if (parseEKUOIDs(optarg_av, &plc) != 0) {
482 (void) fprintf(stderr,
483 gettext("Error EKU OID input.\n"));
484 rv = KC_ERR_USAGE;
485 } else {
486 flags |= KC_EKUS;
488 break;
489 case 'Z':
490 eku_none_opt = get_boolean(optarg_av);
491 if (eku_none_opt == -1) {
492 (void) fprintf(stderr,
493 gettext("Error boolean input.\n"));
494 rv = KC_ERR_USAGE;
495 } else {
496 flags |= KC_EKUS_NONE;
498 break;
499 case 'm':
500 mapper_name = get_string(optarg_av, &rv);
501 if (mapper_name == NULL) {
502 (void) fprintf(stderr,
503 gettext("Error mapper-name "
504 "input.\n"));
506 break;
507 case 'M':
508 mapper_dir = get_string(optarg_av, &rv);
509 if (mapper_dir == NULL) {
510 (void) fprintf(stderr,
511 gettext("Error mapper-directory "
512 "input.\n"));
514 break;
515 case 'Q':
516 mapper_pathname = get_string(optarg_av, &rv);
517 if (mapper_pathname == NULL) {
518 (void) fprintf(stderr,
519 gettext("Error mapper-pathname "
520 "input.\n"));
522 break;
523 case 'q':
524 plc.mapper.options = get_string(optarg_av, &rv);
525 rv = 0; /* its ok for this to be NULL */
526 flags |= KC_MAPPER_OPTIONS;
527 break;
528 default:
529 (void) fprintf(stderr,
530 gettext("Error input option.\n"));
531 rv = KC_ERR_USAGE;
532 break;
534 if (rv != KC_OK)
535 goto out;
538 /* No additional args allowed. */
539 argc -= optind_av;
540 if (argc) {
541 (void) fprintf(stderr,
542 gettext("Error input option\n"));
543 rv = KC_ERR_USAGE;
544 goto out;
547 if (filename == NULL) {
548 filename = strdup(KMF_DEFAULT_POLICY_FILE);
549 if (filename == NULL) {
550 rv = KC_ERR_MEMORY;
551 goto out;
556 * Must have a policy name. The policy name can not be default
557 * if using the default policy file.
559 if (plc.name == NULL) {
560 (void) fprintf(stderr,
561 gettext("You must specify a policy name.\n"));
562 rv = KC_ERR_USAGE;
563 goto out;
564 } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
565 strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
566 (void) fprintf(stderr,
567 gettext("Can not modify the default policy in the default "
568 "policy file.\n"));
569 rv = KC_ERR_USAGE;
570 goto out;
573 /* Check the access permission of the policy DB */
574 if (access(filename, W_OK) < 0) {
575 int err = errno;
576 (void) fprintf(stderr,
577 gettext("Cannot access \"%s\" for modify - %s\n"),
578 filename, strerror(err));
579 rv = KC_ERR_ACCESS;
580 goto out;
583 /* Try to load the named policy from the DB */
584 ret = kmf_get_policy(filename, plc.name, &oplc);
585 if (ret != KMF_OK) {
586 (void) fprintf(stderr,
587 gettext("Error loading policy \"%s\" from %s\n"), filename,
588 plc.name);
589 return (KC_ERR_FIND_POLICY);
592 /* Update the general policy attributes. */
593 if (flags & KC_IGNORE_DATE)
594 oplc.ignore_date = plc.ignore_date;
596 if (flags & KC_IGNORE_UNKNOWN_EKUS)
597 oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
599 if (flags & KC_IGNORE_TRUST_ANCHOR)
600 oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
602 if (flags & KC_VALIDITY_ADJUSTTIME) {
603 free(oplc.validity_adjusttime);
604 oplc.validity_adjusttime =
605 plc.validity_adjusttime;
608 if (flags & KC_TA_NAME) {
609 free(oplc.ta_name);
610 oplc.ta_name = plc.ta_name;
612 if (flags & KC_TA_SERIAL) {
613 free(oplc.ta_serial);
614 oplc.ta_serial = plc.ta_serial;
618 * There are some combinations of attributes that are not valid.
620 * First, setting mapper-name (with optional mapper-directory) and
621 * mapper-pathname is mutually exclusive.
623 if ((mapper_name != NULL && mapper_pathname != NULL) ||
624 (mapper_name != NULL && oplc.mapper.pathname != NULL) ||
625 (mapper_pathname != NULL && oplc.mapper.mapname != NULL) ||
626 /* Mapper directory can be set only if mapper name is set. */
627 (mapper_dir != NULL && mapper_pathname != NULL) ||
628 (mapper_dir != NULL && mapper_name == NULL &&
629 oplc.mapper.mapname == NULL) ||
630 (mapper_dir != NULL && oplc.mapper.pathname != NULL) ||
631 /* Options can be set only if mapper name or pathname is set. */
632 ((plc.mapper.options != NULL || oplc.mapper.options != NULL) &&
633 (mapper_name == NULL && oplc.mapper.mapname == NULL &&
634 mapper_pathname == NULL && oplc.mapper.pathname == NULL))) {
635 (void) fprintf(stderr,
636 gettext("Error in mapper input options\n"));
637 free(mapper_name);
638 free(mapper_pathname);
639 free(mapper_dir);
640 if (flags & KC_MAPPER_OPTIONS)
641 free(plc.mapper.options);
642 rv = KC_ERR_USAGE;
643 goto out;
644 } else {
645 if (mapper_name != NULL)
646 plc.mapper.mapname = mapper_name;
647 if (mapper_pathname != NULL)
648 plc.mapper.pathname = mapper_pathname;
649 if (mapper_dir != NULL)
650 plc.mapper.dir = mapper_dir;
653 UPDATE_IF_DIFFERENT(oplc.mapper.mapname, plc.mapper.mapname);
654 UPDATE_IF_DIFFERENT(oplc.mapper.pathname, plc.mapper.pathname);
655 UPDATE_IF_DIFFERENT(oplc.mapper.dir, plc.mapper.dir);
657 if (flags & KC_MAPPER_OPTIONS) {
658 free(oplc.mapper.options);
659 oplc.mapper.options = plc.mapper.options;
662 /* Update the OCSP policy */
663 if (ocsp_none_opt == B_TRUE) {
664 if (ocsp_set_attr > 0) {
665 (void) fprintf(stderr,
666 gettext("Can not set ocsp-none=true and other "
667 "OCSP attributes at the same time.\n"));
668 rv = KC_ERR_USAGE;
669 goto out;
673 * If the original policy does not have OCSP checking,
674 * then we do not need to do anything. If the original
675 * policy has the OCSP checking, then we need to release the
676 * space of OCSP attributes and turn the OCSP checking off.
678 if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
679 if (oplc.VAL_OCSP_BASIC.responderURI) {
680 free(oplc.VAL_OCSP_BASIC.responderURI);
681 oplc.VAL_OCSP_BASIC.responderURI = NULL;
684 if (oplc.VAL_OCSP_BASIC.proxy) {
685 free(oplc.VAL_OCSP_BASIC.proxy);
686 oplc.VAL_OCSP_BASIC.proxy = NULL;
689 if (oplc.VAL_OCSP_BASIC.response_lifetime) {
690 free(oplc.VAL_OCSP_BASIC.response_lifetime);
691 oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
694 if (flags & KC_OCSP_RESP_CERT_NAME) {
695 free(oplc.VAL_OCSP_RESP_CERT.name);
696 oplc.VAL_OCSP_RESP_CERT.name = NULL;
699 if (flags & KC_OCSP_RESP_CERT_SERIAL) {
700 free(oplc.VAL_OCSP_RESP_CERT.serial);
701 oplc.VAL_OCSP_RESP_CERT.serial = NULL;
704 /* Turn off the OCSP checking */
705 oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
708 } else {
710 * If the "ocsp-none" option is not set or is set to false,
711 * then we only need to do the modification if there is at
712 * least one OCSP attribute is specified.
714 if (ocsp_set_attr > 0) {
715 if (flags & KC_OCSP_RESPONDER_URI) {
716 free(oplc.VAL_OCSP_RESPONDER_URI);
717 oplc.VAL_OCSP_RESPONDER_URI =
718 plc.VAL_OCSP_RESPONDER_URI;
721 if (flags & KC_OCSP_PROXY) {
722 free(oplc.VAL_OCSP_PROXY);
723 oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
726 if (flags & KC_OCSP_URI_FROM_CERT)
727 oplc.VAL_OCSP_URI_FROM_CERT =
728 plc.VAL_OCSP_URI_FROM_CERT;
730 if (flags & KC_OCSP_RESP_LIFETIME) {
731 free(oplc.VAL_OCSP_RESP_LIFETIME);
732 oplc.VAL_OCSP_RESP_LIFETIME =
733 plc.VAL_OCSP_RESP_LIFETIME;
736 if (flags & KC_OCSP_IGNORE_RESP_SIGN)
737 oplc.VAL_OCSP_IGNORE_RESP_SIGN =
738 plc.VAL_OCSP_IGNORE_RESP_SIGN;
740 if (flags & KC_OCSP_RESP_CERT_NAME) {
741 free(oplc.VAL_OCSP_RESP_CERT_NAME);
742 oplc.VAL_OCSP_RESP_CERT_NAME =
743 plc.VAL_OCSP_RESP_CERT_NAME;
746 if (flags & KC_OCSP_RESP_CERT_SERIAL) {
747 free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
748 oplc.VAL_OCSP_RESP_CERT_SERIAL =
749 plc.VAL_OCSP_RESP_CERT_SERIAL;
752 if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
753 oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
754 oplc.VAL_OCSP.has_resp_cert = B_TRUE;
755 else
756 oplc.VAL_OCSP.has_resp_cert = B_FALSE;
758 /* Turn on the OCSP checking */
759 oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
763 /* Update the CRL policy */
764 if (crl_none_opt == B_TRUE) {
765 if (crl_set_attr > 0) {
766 (void) fprintf(stderr,
767 gettext("Can not set crl-none=true and other CRL "
768 "attributes at the same time.\n"));
769 rv = KC_ERR_USAGE;
770 goto out;
774 * If the original policy does not have CRL checking,
775 * then we do not need to do anything. If the original
776 * policy has the CRL checking, then we need to release the
777 * space of CRL attributes and turn the CRL checking off.
779 if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
780 if (oplc.VAL_CRL_BASEFILENAME) {
781 free(oplc.VAL_CRL_BASEFILENAME);
782 oplc.VAL_CRL_BASEFILENAME = NULL;
785 if (oplc.VAL_CRL_DIRECTORY) {
786 free(oplc.VAL_CRL_DIRECTORY);
787 oplc.VAL_CRL_DIRECTORY = NULL;
790 if (oplc.VAL_CRL_PROXY) {
791 free(oplc.VAL_CRL_PROXY);
792 oplc.VAL_CRL_PROXY = NULL;
795 /* Turn off the CRL checking */
796 oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
798 } else {
800 * If the "ocsp-none" option is not set or is set to false,
801 * then we only need to do the modification if there is at
802 * least one CRL attribute is specified.
804 if (crl_set_attr > 0) {
805 if (flags & KC_CRL_BASEFILENAME) {
806 free(oplc.VAL_CRL_BASEFILENAME);
807 oplc.VAL_CRL_BASEFILENAME =
808 plc.VAL_CRL_BASEFILENAME;
811 if (flags & KC_CRL_DIRECTORY) {
812 free(oplc.VAL_CRL_DIRECTORY);
813 oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
816 if (flags & KC_CRL_GET_URI) {
817 oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
820 if (flags & KC_CRL_PROXY) {
821 free(oplc.VAL_CRL_PROXY);
822 oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
825 if (flags & KC_CRL_IGNORE_SIGN) {
826 oplc.VAL_CRL_IGNORE_SIGN =
827 plc.VAL_CRL_IGNORE_SIGN;
830 if (flags & KC_CRL_IGNORE_DATE) {
831 oplc.VAL_CRL_IGNORE_DATE =
832 plc.VAL_CRL_IGNORE_DATE;
835 /* Turn on the CRL checking */
836 oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
840 /* Update the Key Usage */
841 if (ku_none_opt == B_TRUE) {
842 if (flags & KC_KEYUSAGE) {
843 (void) fprintf(stderr,
844 gettext("Can not set keyusage-none=true and "
845 "modify the keyusage value at the same time.\n"));
846 rv = KC_ERR_USAGE;
847 goto out;
850 oplc.ku_bits = 0;
851 } else {
853 * If the "keyusage-none" option is not set or is set to
854 * false, then we only need to do the modification if
855 * the keyusage value is specified.
857 if (flags & KC_KEYUSAGE)
858 oplc.ku_bits = plc.ku_bits;
862 /* Update the Extended Key Usage */
863 if (eku_none_opt == B_TRUE) {
864 if (flags & KC_EKUS) {
865 (void) fprintf(stderr,
866 gettext("Can not set eku-none=true and modify "
867 "EKU values at the same time.\n"));
868 rv = KC_ERR_USAGE;
869 goto out;
872 /* Release current EKU list (if any) */
873 if (oplc.eku_set.eku_count > 0) {
874 kmf_free_eku_policy(&oplc.eku_set);
875 oplc.eku_set.eku_count = 0;
876 oplc.eku_set.ekulist = NULL;
878 } else {
880 * If the "eku-none" option is not set or is set to false,
881 * then we only need to do the modification if either
882 * "ekuname" or "ekuoids" is specified.
884 if (flags & KC_EKUS) {
885 /* Release current EKU list (if any) */
886 kmf_free_eku_policy(&oplc.eku_set);
887 oplc.eku_set = plc.eku_set;
891 /* Do a sanity check on the modified policy */
892 ret = kmf_verify_policy(&oplc);
893 if (ret != KMF_OK) {
894 print_sanity_error(ret);
895 rv = KC_ERR_VERIFY_POLICY;
896 goto out;
899 /* The modify operation is a delete followed by an add */
900 ret = kmf_delete_policy_from_db(oplc.name, filename);
901 if (ret != KMF_OK) {
902 rv = KC_ERR_DELETE_POLICY;
903 goto out;
907 * Now add the modified policy back to the DB.
909 ret = kmf_add_policy_to_db(&oplc, filename, B_FALSE);
910 if (ret != KMF_OK) {
911 (void) fprintf(stderr,
912 gettext("Error adding policy to database: 0x%04x\n"), ret);
913 rv = KC_ERR_ADD_POLICY;
914 goto out;
917 out:
918 free(filename);
920 kmf_free_policy_record(&oplc);
922 return (rv);
925 static int
926 kc_modify_plugin(int argc, char *argv[])
928 int rv = KC_OK;
929 int opt;
930 extern int optind_av;
931 extern char *optarg_av;
932 char *keystore_name = NULL;
933 char *option = NULL;
934 boolean_t modify_plugin = B_FALSE;
935 boolean_t has_option_arg = B_FALSE;
936 conf_entry_t *entry = NULL;
937 FILE *pfile = NULL;
938 FILE *pfile_tmp = NULL;
939 char tmpfile_name[MAXPATHLEN];
940 char buffer[MAXPATHLEN];
941 char buffer2[MAXPATHLEN];
943 while ((opt = getopt_av(argc, argv, "p(plugin)k:(keystore)o:(option)"))
944 != EOF) {
945 switch (opt) {
946 case 'p':
947 if (modify_plugin) {
948 (void) fprintf(stderr,
949 gettext("duplicate plugin input.\n"));
950 rv = KC_ERR_USAGE;
951 } else {
952 modify_plugin = B_TRUE;
954 break;
955 case 'k':
956 if (keystore_name != NULL)
957 rv = KC_ERR_USAGE;
958 else {
959 keystore_name = get_string(optarg_av, &rv);
960 if (keystore_name == NULL) {
961 (void) fprintf(stderr, gettext(
962 "Error keystore input.\n"));
963 rv = KC_ERR_USAGE;
966 break;
967 case 'o':
968 if (has_option_arg) {
969 (void) fprintf(stderr,
970 gettext("duplicate option input.\n"));
971 rv = KC_ERR_USAGE;
972 } else {
973 has_option_arg = B_TRUE;
974 option = get_string(optarg_av, NULL);
976 break;
977 default:
978 (void) fprintf(stderr,
979 gettext("Error input option.\n"));
980 rv = KC_ERR_USAGE;
981 break;
984 if (rv != KC_OK)
985 goto out;
988 /* No additional args allowed. */
989 argc -= optind_av;
990 if (argc) {
991 (void) fprintf(stderr,
992 gettext("Error input option\n"));
993 rv = KC_ERR_USAGE;
994 goto out;
997 if (keystore_name == NULL || has_option_arg == B_FALSE) {
998 (void) fprintf(stderr,
999 gettext("Error input option\n"));
1000 rv = KC_ERR_USAGE;
1001 goto out;
1004 if (strcasecmp(keystore_name, "nss") == 0 ||
1005 strcasecmp(keystore_name, "pkcs11") == 0 ||
1006 strcasecmp(keystore_name, "file") == 0) {
1007 (void) fprintf(stderr,
1008 gettext("Can not modify the built-in keystore %s\n"),
1009 keystore_name);
1010 rv = KC_ERR_USAGE;
1011 goto out;
1014 entry = get_keystore_entry(keystore_name);
1015 if (entry == NULL) {
1016 (void) fprintf(stderr, gettext("%s does not exist.\n"),
1017 keystore_name);
1018 rv = KC_ERR_USAGE;
1019 goto out;
1022 if ((entry->option == NULL && option == NULL) ||
1023 (entry->option != NULL && option != NULL &&
1024 strcmp(entry->option, option) == 0)) {
1025 (void) fprintf(stderr, gettext("No change - "
1026 "the new option is same as the old option.\n"));
1027 rv = KC_OK;
1028 goto out;
1031 if ((pfile = fopen(_PATH_KMF_CONF, "r+")) == NULL) {
1032 err = errno;
1033 (void) fprintf(stderr,
1034 gettext("failed to update the configuration - %s\n"),
1035 strerror(err));
1036 rv = KC_ERR_ACCESS;
1037 goto out;
1040 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
1041 err = errno;
1042 (void) fprintf(stderr,
1043 gettext("failed to lock the configuration - %s\n"),
1044 strerror(err));
1045 rv = KC_ERR_MODIFY_PLUGIN;
1046 goto out;
1050 * Create a temporary file in the /etc/crypto directory.
1052 (void) strlcpy(tmpfile_name, CONF_TEMPFILE, sizeof (tmpfile_name));
1053 if (mkstemp(tmpfile_name) == -1) {
1054 err = errno;
1055 (void) fprintf(stderr,
1056 gettext("failed to create a temporary file - %s\n"),
1057 strerror(err));
1058 rv = KC_ERR_MODIFY_PLUGIN;
1059 goto out;
1062 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
1063 err = errno;
1064 (void) fprintf(stderr,
1065 gettext("failed to open %s - %s\n"),
1066 tmpfile_name, strerror(err));
1067 rv = KC_ERR_MODIFY_PLUGIN;
1068 goto out;
1072 * Loop thru the config file and update the entry.
1074 while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
1075 char *name;
1076 int len;
1078 if (buffer[0] == '#') {
1079 if (fputs(buffer, pfile_tmp) == EOF) {
1080 rv = KC_ERR_MODIFY_PLUGIN;
1081 goto out;
1082 } else {
1083 continue;
1088 * make a copy of the original buffer to buffer2. Also get
1089 * rid of the trailing '\n' from buffer2.
1091 (void) strlcpy(buffer2, buffer, MAXPATHLEN);
1092 len = strlen(buffer2);
1093 if (buffer2[len-1] == '\n') {
1094 len--;
1096 buffer2[len] = '\0';
1098 if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
1099 rv = KC_ERR_UNINSTALL;
1100 goto out;
1103 if (strcmp(name, keystore_name) == 0) {
1104 /* found the entry */
1105 if (option == NULL)
1106 (void) snprintf(buffer, MAXPATHLEN,
1107 "%s:%s%s\n", keystore_name,
1108 CONF_MODULEPATH, entry->modulepath);
1109 else
1110 (void) snprintf(buffer, MAXPATHLEN,
1111 "%s:%s%s;%s%s\n", keystore_name,
1112 CONF_MODULEPATH, entry->modulepath,
1113 CONF_OPTION, option);
1115 if (fputs(buffer, pfile_tmp) == EOF) {
1116 err = errno;
1117 (void) fprintf(stderr, gettext(
1118 "failed to write to %s: %s\n"),
1119 tmpfile_name, strerror(err));
1120 rv = KC_ERR_MODIFY_PLUGIN;
1121 goto out;
1123 } else {
1125 if (fputs(buffer, pfile_tmp) == EOF) {
1126 rv = KC_ERR_UNINSTALL;
1127 goto out;
1132 if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) {
1133 err = errno;
1134 (void) fprintf(stderr, gettext(
1135 "failed to update the configuration - %s"), strerror(err));
1136 rv = KC_ERR_MODIFY_PLUGIN;
1137 goto out;
1140 if (chmod(_PATH_KMF_CONF,
1141 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1142 err = errno;
1143 (void) fprintf(stderr, gettext(
1144 "failed to update the configuration - %s\n"),
1145 strerror(err));
1146 rv = KC_ERR_MODIFY_PLUGIN;
1147 goto out;
1150 out:
1151 if (entry != NULL)
1152 free_entry(entry);
1154 if (pfile != NULL)
1155 (void) fclose(pfile);
1157 if (rv != KC_OK && pfile_tmp != NULL)
1158 (void) unlink(tmpfile_name);
1160 if (pfile_tmp != NULL)
1161 (void) fclose(pfile_tmp);
1163 return (rv);
1168 kc_modify(int argc, char *argv[])
1170 if (argc > 2 &&
1171 strcmp(argv[0], "modify") == 0 &&
1172 strcmp(argv[1], "plugin") == 0) {
1173 return (kc_modify_plugin(argc, argv));
1174 } else {
1175 return (kc_modify_policy(argc, argv));