1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
22 */
23
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"
35
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
62
63 static int err; /* To store errno which may be overwritten by gettext() */
64
65 #define UPDATE_IF_DIFFERENT(old, new) \
66 if ((old != NULL && new != NULL && strcmp(old, new) != 0) || \
67 (old == NULL && new != NULL)) { \
68 if (old != NULL) \
69 free(old); \
70 old = new; \
71 }
72
73 int
kc_modify_policy(int argc,char * argv[])74 kc_modify_policy(int argc, char *argv[])
75 {
76 KMF_RETURN ret;
77 int rv = KC_OK;
78 int opt;
79 extern int optind_av;
80 extern char *optarg_av;
81 char *filename = NULL;
82 char *mapper_name = NULL;
83 char *mapper_dir = NULL;
84 char *mapper_pathname = NULL;
85 uint32_t flags = 0;
86 boolean_t ocsp_none_opt = B_FALSE;
87 boolean_t crl_none_opt = B_FALSE;
88 boolean_t ku_none_opt = B_FALSE;
89 boolean_t eku_none_opt = B_FALSE;
90 int ocsp_set_attr = 0;
91 int crl_set_attr = 0;
92 KMF_POLICY_RECORD oplc, plc;
93
94 (void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
95 (void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD));
96
97 while ((opt = getopt_av(argc, argv,
98 "i:(dbfile)"
99 "p:(policy)"
100 "d:(ignore-date)"
101 "e:(ignore-unknown-eku)"
102 "a:(ignore-trust-anchor)"
103 "v:(validity-adjusttime)"
104 "t:(ta-name)"
105 "s:(ta-serial)"
106 "o:(ocsp-responder)"
107 "P:(ocsp-proxy)"
108 "r:(ocsp-use-cert-responder)"
109 "T:(ocsp-response-lifetime)"
110 "R:(ocsp-ignore-response-sign)"
111 "n:(ocsp-responder-cert-name)"
112 "A:(ocsp-responder-cert-serial)"
113 "y:(ocsp-none)"
114 "c:(crl-basefilename)"
115 "I:(crl-directory)"
116 "g:(crl-get-crl-uri)"
117 "X:(crl-proxy)"
118 "S:(crl-ignore-crl-sign)"
119 "D:(crl-ignore-crl-date)"
120 "z:(crl-none)"
121 "u:(keyusage)"
122 "Y:(keyusage-none)"
123 "E:(ekunames)"
124 "O:(ekuoids)"
125 "m:(mapper-name)"
126 "M:(mapper-directory)"
127 "Q:(mapper-pathname)"
128 "q:(mapper-options)"
129 "Z:(eku-none)")) != EOF) {
130 switch (opt) {
131 case 'i':
132 filename = get_string(optarg_av, &rv);
133 if (filename == NULL) {
134 (void) fprintf(stderr,
135 gettext("Error dbfile input.\n"));
136 }
137 break;
138 case 'p':
139 plc.name = get_string(optarg_av, &rv);
140 if (plc.name == NULL) {
141 (void) fprintf(stderr,
142 gettext("Error policy name.\n"));
143 }
144 break;
145 case 'd':
146 plc.ignore_date = get_boolean(optarg_av);
147 if (plc.ignore_date == -1) {
148 (void) fprintf(stderr,
149 gettext("Error boolean input.\n"));
150 rv = KC_ERR_USAGE;
151 } else {
152 flags |= KC_IGNORE_DATE;
153 }
154 break;
155 case 'e':
156 plc.ignore_unknown_ekus =
157 get_boolean(optarg_av);
158 if (plc.ignore_unknown_ekus == -1) {
159 (void) fprintf(stderr,
160 gettext("Error boolean input.\n"));
161 rv = KC_ERR_USAGE;
162 } else {
163 flags |= KC_IGNORE_UNKNOWN_EKUS;
164 }
165 break;
166 case 'a':
167 plc.ignore_trust_anchor =
168 get_boolean(optarg_av);
169 if (plc.ignore_trust_anchor == -1) {
170 (void) fprintf(stderr,
171 gettext("Error boolean input.\n"));
172 rv = KC_ERR_USAGE;
173 } else {
174 flags |= KC_IGNORE_TRUST_ANCHOR;
175 }
176 break;
177 case 'v':
178 plc.validity_adjusttime =
179 get_string(optarg_av, &rv);
180 if (plc.validity_adjusttime == NULL) {
181 (void) fprintf(stderr,
182 gettext("Error time input.\n"));
183 } else {
184 uint32_t adj;
185 /* for syntax checking */
186 if (str2lifetime(
187 plc.validity_adjusttime,
188 &adj) < 0) {
189 (void) fprintf(stderr,
190 gettext("Error time "
191 "input.\n"));
192 rv = KC_ERR_USAGE;
193 } else {
194 flags |= KC_VALIDITY_ADJUSTTIME;
195 }
196 }
197 break;
198 case 't':
199 plc.ta_name = get_string(optarg_av, &rv);
200 if (plc.ta_name == NULL) {
201 (void) fprintf(stderr,
202 gettext("Error name input.\n"));
203 } else if (strcasecmp(plc.ta_name, "search")) {
204 KMF_X509_NAME taDN;
205 /* for syntax checking */
206 if (kmf_dn_parser(plc.ta_name,
207 &taDN) != KMF_OK) {
208 (void) fprintf(stderr,
209 gettext("Error name "
210 "input.\n"));
211 rv = KC_ERR_USAGE;
212 } else {
213 kmf_free_dn(&taDN);
214 flags |= KC_TA_NAME;
215 }
216 } else {
217 flags |= KC_TA_NAME;
218 }
219 break;
220 case 's':
221 plc.ta_serial = get_string(optarg_av, &rv);
222 if (plc.ta_serial == NULL) {
223 (void) fprintf(stderr,
224 gettext("Error serial input.\n"));
225 } else {
226 uchar_t *bytes = NULL;
227 size_t bytelen;
228
229 ret = kmf_hexstr_to_bytes(
230 (uchar_t *)plc.ta_serial,
231 &bytes, &bytelen);
232 if (ret != KMF_OK || bytes == NULL) {
233 (void) fprintf(stderr,
234 gettext("serial number "
235 "must be specified as a "
236 "hex number "
237 "(ex: 0x0102030405"
238 "ffeeddee)\n"));
239 rv = KC_ERR_USAGE;
240 break;
241 }
242 if (bytes != NULL)
243 free(bytes);
244 flags |= KC_TA_SERIAL;
245 }
246 break;
247 case 'o':
248 plc.VAL_OCSP_RESPONDER_URI =
249 get_string(optarg_av, &rv);
250 if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
251 (void) fprintf(stderr,
252 gettext("Error responder "
253 "input.\n"));
254 } else {
255 flags |= KC_OCSP_RESPONDER_URI;
256 ocsp_set_attr++;
257 }
258 break;
259 case 'P':
260 plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
261 if (plc.VAL_OCSP_PROXY == NULL) {
262 (void) fprintf(stderr,
263 gettext("Error proxy input.\n"));
264 } else {
265 flags |= KC_OCSP_PROXY;
266 ocsp_set_attr++;
267 }
268 break;
269 case 'r':
270 plc.VAL_OCSP_URI_FROM_CERT =
271 get_boolean(optarg_av);
272 if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
273 (void) fprintf(stderr,
274 gettext("Error boolean input.\n"));
275 rv = KC_ERR_USAGE;
276 } else {
277 flags |= KC_OCSP_URI_FROM_CERT;
278 ocsp_set_attr++;
279 }
280 break;
281 case 'T':
282 plc.VAL_OCSP_RESP_LIFETIME =
283 get_string(optarg_av, &rv);
284 if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
285 (void) fprintf(stderr,
286 gettext("Error time input.\n"));
287 } else {
288 uint32_t adj;
289 /* for syntax checking */
290 if (str2lifetime(
291 plc.VAL_OCSP_RESP_LIFETIME,
292 &adj) < 0) {
293 (void) fprintf(stderr,
294 gettext("Error time "
295 "input.\n"));
296 rv = KC_ERR_USAGE;
297 } else {
298 flags |= KC_OCSP_RESP_LIFETIME;
299 ocsp_set_attr++;
300 }
301 }
302 break;
303 case 'R':
304 plc.VAL_OCSP_IGNORE_RESP_SIGN =
305 get_boolean(optarg_av);
306 if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
307 (void) fprintf(stderr,
308 gettext("Error boolean input.\n"));
309 rv = KC_ERR_USAGE;
310 } else {
311 flags |= KC_OCSP_IGNORE_RESP_SIGN;
312 ocsp_set_attr++;
313 }
314 break;
315 case 'n':
316 plc.VAL_OCSP_RESP_CERT_NAME =
317 get_string(optarg_av, &rv);
318 if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
319 (void) fprintf(stderr,
320 gettext("Error name input.\n"));
321 } else {
322 KMF_X509_NAME respDN;
323 /* for syntax checking */
324 if (kmf_dn_parser(
325 plc.VAL_OCSP_RESP_CERT_NAME,
326 &respDN) != KMF_OK) {
327 (void) fprintf(stderr,
328 gettext("Error name "
329 "input.\n"));
330 rv = KC_ERR_USAGE;
331 } else {
332 kmf_free_dn(&respDN);
333 flags |= KC_OCSP_RESP_CERT_NAME;
334 ocsp_set_attr++;
335 }
336 }
337 break;
338 case 'A':
339 plc.VAL_OCSP_RESP_CERT_SERIAL =
340 get_string(optarg_av, &rv);
341 if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
342 (void) fprintf(stderr,
343 gettext("Error serial input.\n"));
344 } else {
345 uchar_t *bytes = NULL;
346 size_t bytelen;
347
348 ret = kmf_hexstr_to_bytes((uchar_t *)
349 plc.VAL_OCSP_RESP_CERT_SERIAL,
350 &bytes, &bytelen);
351 if (ret != KMF_OK || bytes == NULL) {
352 (void) fprintf(stderr,
353 gettext("serial number "
354 "must be specified as a "
355 "hex number "
356 "(ex: 0x0102030405"
357 "ffeeddee)\n"));
358 rv = KC_ERR_USAGE;
359 break;
360 }
361 if (bytes != NULL)
362 free(bytes);
363 flags |= KC_OCSP_RESP_CERT_SERIAL;
364 ocsp_set_attr++;
365 }
366 break;
367 case 'y':
368 ocsp_none_opt = get_boolean(optarg_av);
369 if (ocsp_none_opt == -1) {
370 (void) fprintf(stderr,
371 gettext("Error boolean input.\n"));
372 rv = KC_ERR_USAGE;
373 } else {
374 flags |= KC_OCSP_NONE;
375 }
376 break;
377 case 'c':
378 plc.VAL_CRL_BASEFILENAME =
379 get_string(optarg_av, &rv);
380 if (plc.VAL_CRL_BASEFILENAME == NULL) {
381 (void) fprintf(stderr, gettext(
382 "Error basefilename input.\n"));
383 } else {
384 flags |= KC_CRL_BASEFILENAME;
385 crl_set_attr++;
386 }
387 break;
388 case 'I':
389 plc.VAL_CRL_DIRECTORY =
390 get_string(optarg_av, &rv);
391 if (plc.VAL_CRL_DIRECTORY == NULL) {
392 (void) fprintf(stderr,
393 gettext("Error boolean input.\n"));
394 } else {
395 flags |= KC_CRL_DIRECTORY;
396 crl_set_attr++;
397 }
398 break;
399 case 'g':
400 plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
401 if (plc.VAL_CRL_GET_URI == -1) {
402 (void) fprintf(stderr,
403 gettext("Error boolean input.\n"));
404 rv = KC_ERR_USAGE;
405 } else {
406 flags |= KC_CRL_GET_URI;
407 crl_set_attr++;
408 }
409 break;
410 case 'X':
411 plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
412 if (plc.VAL_CRL_PROXY == NULL) {
413 (void) fprintf(stderr,
414 gettext("Error proxy input.\n"));
415 } else {
416 flags |= KC_CRL_PROXY;
417 crl_set_attr++;
418 }
419 break;
420 case 'S':
421 plc.VAL_CRL_IGNORE_SIGN =
422 get_boolean(optarg_av);
423 if (plc.VAL_CRL_IGNORE_SIGN == -1) {
424 (void) fprintf(stderr,
425 gettext("Error boolean input.\n"));
426 rv = KC_ERR_USAGE;
427 } else {
428 flags |= KC_CRL_IGNORE_SIGN;
429 crl_set_attr++;
430 }
431 break;
432 case 'D':
433 plc.VAL_CRL_IGNORE_DATE =
434 get_boolean(optarg_av);
435 if (plc.VAL_CRL_IGNORE_DATE == -1) {
436 (void) fprintf(stderr,
437 gettext("Error boolean input.\n"));
438 rv = KC_ERR_USAGE;
439 } else {
440 flags |= KC_CRL_IGNORE_DATE;
441 crl_set_attr++;
442 }
443 break;
444 case 'z':
445 crl_none_opt = get_boolean(optarg_av);
446 if (crl_none_opt == -1) {
447 (void) fprintf(stderr,
448 gettext("Error boolean input.\n"));
449 rv = KC_ERR_USAGE;
450 } else {
451 flags |= KC_CRL_NONE;
452 }
453 break;
454 case 'u':
455 plc.ku_bits = parseKUlist(optarg_av);
456 if (plc.ku_bits == 0) {
457 (void) fprintf(stderr, gettext(
458 "Error keyusage input.\n"));
459 rv = KC_ERR_USAGE;
460 } else {
461 flags |= KC_KEYUSAGE;
462 }
463 break;
464 case 'Y':
465 ku_none_opt = get_boolean(optarg_av);
466 if (ku_none_opt == -1) {
467 (void) fprintf(stderr,
468 gettext("Error boolean input.\n"));
469 rv = KC_ERR_USAGE;
470 } else {
471 flags |= KC_KEYUSAGE_NONE;
472 }
473 break;
474 case 'E':
475 if (parseEKUNames(optarg_av, &plc) != 0) {
476 (void) fprintf(stderr,
477 gettext("Error EKU input.\n"));
478 rv = KC_ERR_USAGE;
479 } else {
480 flags |= KC_EKUS;
481 }
482 break;
483 case 'O':
484 if (parseEKUOIDs(optarg_av, &plc) != 0) {
485 (void) fprintf(stderr,
486 gettext("Error EKU OID input.\n"));
487 rv = KC_ERR_USAGE;
488 } else {
489 flags |= KC_EKUS;
490 }
491 break;
492 case 'Z':
493 eku_none_opt = get_boolean(optarg_av);
494 if (eku_none_opt == -1) {
495 (void) fprintf(stderr,
496 gettext("Error boolean input.\n"));
497 rv = KC_ERR_USAGE;
498 } else {
499 flags |= KC_EKUS_NONE;
500 }
501 break;
502 case 'm':
503 mapper_name = get_string(optarg_av, &rv);
504 if (mapper_name == NULL) {
505 (void) fprintf(stderr,
506 gettext("Error mapper-name "
507 "input.\n"));
508 }
509 break;
510 case 'M':
511 mapper_dir = get_string(optarg_av, &rv);
512 if (mapper_dir == NULL) {
513 (void) fprintf(stderr,
514 gettext("Error mapper-directory "
515 "input.\n"));
516 }
517 break;
518 case 'Q':
519 mapper_pathname = get_string(optarg_av, &rv);
520 if (mapper_pathname == NULL) {
521 (void) fprintf(stderr,
522 gettext("Error mapper-pathname "
523 "input.\n"));
524 }
525 break;
526 case 'q':
527 plc.mapper.options = get_string(optarg_av, &rv);
528 rv = 0; /* its ok for this to be NULL */
529 flags |= KC_MAPPER_OPTIONS;
530 break;
531 default:
532 (void) fprintf(stderr,
533 gettext("Error input option.\n"));
534 rv = KC_ERR_USAGE;
535 break;
536 }
537 if (rv != KC_OK)
538 goto out;
539 }
540
541 /* No additional args allowed. */
542 argc -= optind_av;
543 if (argc) {
544 (void) fprintf(stderr,
545 gettext("Error input option\n"));
546 rv = KC_ERR_USAGE;
547 goto out;
548 }
549
550 if (filename == NULL) {
551 filename = strdup(KMF_DEFAULT_POLICY_FILE);
552 if (filename == NULL) {
553 rv = KC_ERR_MEMORY;
554 goto out;
555 }
556 }
557
558 /*
559 * Must have a policy name. The policy name can not be default
560 * if using the default policy file.
561 */
562 if (plc.name == NULL) {
563 (void) fprintf(stderr,
564 gettext("You must specify a policy name.\n"));
565 rv = KC_ERR_USAGE;
566 goto out;
567 } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
568 strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
569 (void) fprintf(stderr,
570 gettext("Can not modify the default policy in the default "
571 "policy file.\n"));
572 rv = KC_ERR_USAGE;
573 goto out;
574 }
575
576 /* Check the access permission of the policy DB */
577 if (access(filename, W_OK) < 0) {
578 int err = errno;
579 (void) fprintf(stderr,
580 gettext("Cannot access \"%s\" for modify - %s\n"),
581 filename, strerror(err));
582 rv = KC_ERR_ACCESS;
583 goto out;
584 }
585
586 /* Try to load the named policy from the DB */
587 ret = kmf_get_policy(filename, plc.name, &oplc);
588 if (ret != KMF_OK) {
589 (void) fprintf(stderr,
590 gettext("Error loading policy \"%s\" from %s\n"), filename,
591 plc.name);
592 return (KC_ERR_FIND_POLICY);
593 }
594
595 /* Update the general policy attributes. */
596 if (flags & KC_IGNORE_DATE)
597 oplc.ignore_date = plc.ignore_date;
598
599 if (flags & KC_IGNORE_UNKNOWN_EKUS)
600 oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
601
602 if (flags & KC_IGNORE_TRUST_ANCHOR)
603 oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
604
605 if (flags & KC_VALIDITY_ADJUSTTIME) {
606 if (oplc.validity_adjusttime)
607 free(oplc.validity_adjusttime);
608 oplc.validity_adjusttime =
609 plc.validity_adjusttime;
610 }
611
612 if (flags & KC_TA_NAME) {
613 if (oplc.ta_name)
614 free(oplc.ta_name);
615 oplc.ta_name = plc.ta_name;
616 }
617 if (flags & KC_TA_SERIAL) {
618 if (oplc.ta_serial)
619 free(oplc.ta_serial);
620 oplc.ta_serial = plc.ta_serial;
621 }
622
623 /*
624 * There are some combinations of attributes that are not valid.
625 *
626 * First, setting mapper-name (with optional mapper-directory) and
627 * mapper-pathname is mutually exclusive.
628 */
629 if ((mapper_name != NULL && mapper_pathname != NULL) ||
630 (mapper_name != NULL && oplc.mapper.pathname != NULL) ||
631 (mapper_pathname != NULL && oplc.mapper.mapname != NULL) ||
632 /* Mapper directory can be set only if mapper name is set. */
633 (mapper_dir != NULL && mapper_pathname != NULL) ||
634 (mapper_dir != NULL && mapper_name == NULL &&
635 oplc.mapper.mapname == NULL) ||
636 (mapper_dir != NULL && oplc.mapper.pathname != NULL) ||
637 /* Options can be set only if mapper name or pathname is set. */
638 ((plc.mapper.options != NULL || oplc.mapper.options != NULL) &&
639 (mapper_name == NULL && oplc.mapper.mapname == NULL &&
640 mapper_pathname == NULL && oplc.mapper.pathname == NULL))) {
641 (void) fprintf(stderr,
642 gettext("Error in mapper input options\n"));
643 if (mapper_name != NULL)
644 free(mapper_name);
645 if (mapper_pathname != NULL)
646 free(mapper_pathname);
647 if (mapper_dir != NULL)
648 free(mapper_dir);
649 if (flags & KC_MAPPER_OPTIONS && plc.mapper.options != NULL)
650 free(plc.mapper.options);
651 rv = KC_ERR_USAGE;
652 goto out;
653 } else {
654 if (mapper_name != NULL)
655 plc.mapper.mapname = mapper_name;
656 if (mapper_pathname != NULL)
657 plc.mapper.pathname = mapper_pathname;
658 if (mapper_dir != NULL)
659 plc.mapper.dir = mapper_dir;
660 }
661
662 UPDATE_IF_DIFFERENT(oplc.mapper.mapname, plc.mapper.mapname);
663 UPDATE_IF_DIFFERENT(oplc.mapper.pathname, plc.mapper.pathname);
664 UPDATE_IF_DIFFERENT(oplc.mapper.dir, plc.mapper.dir);
665
666 if (flags & KC_MAPPER_OPTIONS) {
667 if (oplc.mapper.options != NULL)
668 free(oplc.mapper.options);
669 oplc.mapper.options = plc.mapper.options;
670 }
671
672 /* Update the OCSP policy */
673 if (ocsp_none_opt == B_TRUE) {
674 if (ocsp_set_attr > 0) {
675 (void) fprintf(stderr,
676 gettext("Can not set ocsp-none=true and other "
677 "OCSP attributes at the same time.\n"));
678 rv = KC_ERR_USAGE;
679 goto out;
680 }
681
682 /*
683 * If the original policy does not have OCSP checking,
684 * then we do not need to do anything. If the original
685 * policy has the OCSP checking, then we need to release the
686 * space of OCSP attributes and turn the OCSP checking off.
687 */
688 if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
689 if (oplc.VAL_OCSP_BASIC.responderURI) {
690 free(oplc.VAL_OCSP_BASIC.responderURI);
691 oplc.VAL_OCSP_BASIC.responderURI = NULL;
692 }
693
694 if (oplc.VAL_OCSP_BASIC.proxy) {
695 free(oplc.VAL_OCSP_BASIC.proxy);
696 oplc.VAL_OCSP_BASIC.proxy = NULL;
697 }
698
699 if (oplc.VAL_OCSP_BASIC.response_lifetime) {
700 free(oplc.VAL_OCSP_BASIC.response_lifetime);
701 oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
702 }
703
704 if (flags & KC_OCSP_RESP_CERT_NAME) {
705 free(oplc.VAL_OCSP_RESP_CERT.name);
706 oplc.VAL_OCSP_RESP_CERT.name = NULL;
707 }
708
709 if (flags & KC_OCSP_RESP_CERT_SERIAL) {
710 free(oplc.VAL_OCSP_RESP_CERT.serial);
711 oplc.VAL_OCSP_RESP_CERT.serial = NULL;
712 }
713
714 /* Turn off the OCSP checking */
715 oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
716 }
717
718 } else {
719 /*
720 * If the "ocsp-none" option is not set or is set to false,
721 * then we only need to do the modification if there is at
722 * least one OCSP attribute is specified.
723 */
724 if (ocsp_set_attr > 0) {
725 if (flags & KC_OCSP_RESPONDER_URI) {
726 if (oplc.VAL_OCSP_RESPONDER_URI)
727 free(oplc.VAL_OCSP_RESPONDER_URI);
728 oplc.VAL_OCSP_RESPONDER_URI =
729 plc.VAL_OCSP_RESPONDER_URI;
730 }
731
732 if (flags & KC_OCSP_PROXY) {
733 if (oplc.VAL_OCSP_PROXY)
734 free(oplc.VAL_OCSP_PROXY);
735 oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
736 }
737
738 if (flags & KC_OCSP_URI_FROM_CERT)
739 oplc.VAL_OCSP_URI_FROM_CERT =
740 plc.VAL_OCSP_URI_FROM_CERT;
741
742 if (flags & KC_OCSP_RESP_LIFETIME) {
743 if (oplc.VAL_OCSP_RESP_LIFETIME)
744 free(oplc.VAL_OCSP_RESP_LIFETIME);
745 oplc.VAL_OCSP_RESP_LIFETIME =
746 plc.VAL_OCSP_RESP_LIFETIME;
747 }
748
749 if (flags & KC_OCSP_IGNORE_RESP_SIGN)
750 oplc.VAL_OCSP_IGNORE_RESP_SIGN =
751 plc.VAL_OCSP_IGNORE_RESP_SIGN;
752
753 if (flags & KC_OCSP_RESP_CERT_NAME) {
754 if (oplc.VAL_OCSP_RESP_CERT_NAME)
755 free(oplc.VAL_OCSP_RESP_CERT_NAME);
756 oplc.VAL_OCSP_RESP_CERT_NAME =
757 plc.VAL_OCSP_RESP_CERT_NAME;
758 }
759
760 if (flags & KC_OCSP_RESP_CERT_SERIAL) {
761 if (oplc.VAL_OCSP_RESP_CERT_SERIAL)
762 free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
763 oplc.VAL_OCSP_RESP_CERT_SERIAL =
764 plc.VAL_OCSP_RESP_CERT_SERIAL;
765 }
766
767 if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
768 oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
769 oplc.VAL_OCSP.has_resp_cert = B_TRUE;
770 else
771 oplc.VAL_OCSP.has_resp_cert = B_FALSE;
772
773 /* Turn on the OCSP checking */
774 oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
775 }
776 }
777
778 /* Update the CRL policy */
779 if (crl_none_opt == B_TRUE) {
780 if (crl_set_attr > 0) {
781 (void) fprintf(stderr,
782 gettext("Can not set crl-none=true and other CRL "
783 "attributes at the same time.\n"));
784 rv = KC_ERR_USAGE;
785 goto out;
786 }
787
788 /*
789 * If the original policy does not have CRL checking,
790 * then we do not need to do anything. If the original
791 * policy has the CRL checking, then we need to release the
792 * space of CRL attributes and turn the CRL checking off.
793 */
794 if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
795 if (oplc.VAL_CRL_BASEFILENAME) {
796 free(oplc.VAL_CRL_BASEFILENAME);
797 oplc.VAL_CRL_BASEFILENAME = NULL;
798 }
799
800 if (oplc.VAL_CRL_DIRECTORY) {
801 free(oplc.VAL_CRL_DIRECTORY);
802 oplc.VAL_CRL_DIRECTORY = NULL;
803 }
804
805 if (oplc.VAL_CRL_PROXY) {
806 free(oplc.VAL_CRL_PROXY);
807 oplc.VAL_CRL_PROXY = NULL;
808 }
809
810 /* Turn off the CRL checking */
811 oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
812 }
813 } else {
814 /*
815 * If the "ocsp-none" option is not set or is set to false,
816 * then we only need to do the modification if there is at
817 * least one CRL attribute is specified.
818 */
819 if (crl_set_attr > 0) {
820 if (flags & KC_CRL_BASEFILENAME) {
821 if (oplc.VAL_CRL_BASEFILENAME)
822 free(oplc.VAL_CRL_BASEFILENAME);
823 oplc.VAL_CRL_BASEFILENAME =
824 plc.VAL_CRL_BASEFILENAME;
825 }
826
827 if (flags & KC_CRL_DIRECTORY) {
828 if (oplc.VAL_CRL_DIRECTORY)
829 free(oplc.VAL_CRL_DIRECTORY);
830 oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
831 }
832
833 if (flags & KC_CRL_GET_URI) {
834 oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
835 }
836
837 if (flags & KC_CRL_PROXY) {
838 if (oplc.VAL_CRL_PROXY)
839 free(oplc.VAL_CRL_PROXY);
840 oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
841 }
842
843 if (flags & KC_CRL_IGNORE_SIGN) {
844 oplc.VAL_CRL_IGNORE_SIGN =
845 plc.VAL_CRL_IGNORE_SIGN;
846 }
847
848 if (flags & KC_CRL_IGNORE_DATE) {
849 oplc.VAL_CRL_IGNORE_DATE =
850 plc.VAL_CRL_IGNORE_DATE;
851 }
852
853 /* Turn on the CRL checking */
854 oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
855 }
856 }
857
858 /* Update the Key Usage */
859 if (ku_none_opt == B_TRUE) {
860 if (flags & KC_KEYUSAGE) {
861 (void) fprintf(stderr,
862 gettext("Can not set keyusage-none=true and "
863 "modify the keyusage value at the same time.\n"));
864 rv = KC_ERR_USAGE;
865 goto out;
866 }
867
868 oplc.ku_bits = 0;
869 } else {
870 /*
871 * If the "keyusage-none" option is not set or is set to
872 * false, then we only need to do the modification if
873 * the keyusage value is specified.
874 */
875 if (flags & KC_KEYUSAGE)
876 oplc.ku_bits = plc.ku_bits;
877 }
878
879
880 /* Update the Extended Key Usage */
881 if (eku_none_opt == B_TRUE) {
882 if (flags & KC_EKUS) {
883 (void) fprintf(stderr,
884 gettext("Can not set eku-none=true and modify "
885 "EKU values at the same time.\n"));
886 rv = KC_ERR_USAGE;
887 goto out;
888 }
889
890 /* Release current EKU list (if any) */
891 if (oplc.eku_set.eku_count > 0) {
892 kmf_free_eku_policy(&oplc.eku_set);
893 oplc.eku_set.eku_count = 0;
894 oplc.eku_set.ekulist = NULL;
895 }
896 } else {
897 /*
898 * If the "eku-none" option is not set or is set to false,
899 * then we only need to do the modification if either
900 * "ekuname" or "ekuoids" is specified.
901 */
902 if (flags & KC_EKUS) {
903 /* Release current EKU list (if any) */
904 kmf_free_eku_policy(&oplc.eku_set);
905 oplc.eku_set = plc.eku_set;
906 }
907 }
908
909 /* Do a sanity check on the modified policy */
910 ret = kmf_verify_policy(&oplc);
911 if (ret != KMF_OK) {
912 print_sanity_error(ret);
913 rv = KC_ERR_VERIFY_POLICY;
914 goto out;
915 }
916
917 /* The modify operation is a delete followed by an add */
918 ret = kmf_delete_policy_from_db(oplc.name, filename);
919 if (ret != KMF_OK) {
920 rv = KC_ERR_DELETE_POLICY;
921 goto out;
922 }
923
924 /*
925 * Now add the modified policy back to the DB.
926 */
927 ret = kmf_add_policy_to_db(&oplc, filename, B_FALSE);
928 if (ret != KMF_OK) {
929 (void) fprintf(stderr,
930 gettext("Error adding policy to database: 0x%04x\n"), ret);
931 rv = KC_ERR_ADD_POLICY;
932 goto out;
933 }
934
935 out:
936 if (filename != NULL)
937 free(filename);
938
939 kmf_free_policy_record(&oplc);
940
941 return (rv);
942 }
943
944 static int
kc_modify_plugin(int argc,char * argv[])945 kc_modify_plugin(int argc, char *argv[])
946 {
947 int rv = KC_OK;
948 int opt;
949 extern int optind_av;
950 extern char *optarg_av;
951 char *keystore_name = NULL;
952 char *option = NULL;
953 boolean_t modify_plugin = B_FALSE;
954 boolean_t has_option_arg = B_FALSE;
955 conf_entry_t *entry = NULL;
956 FILE *pfile = NULL;
957 FILE *pfile_tmp = NULL;
958 char tmpfile_name[MAXPATHLEN];
959 char buffer[MAXPATHLEN];
960 char buffer2[MAXPATHLEN];
961
962 while ((opt = getopt_av(argc, argv, "p(plugin)k:(keystore)o:(option)"))
963 != EOF) {
964 switch (opt) {
965 case 'p':
966 if (modify_plugin) {
967 (void) fprintf(stderr,
968 gettext("duplicate plugin input.\n"));
969 rv = KC_ERR_USAGE;
970 } else {
971 modify_plugin = B_TRUE;
972 }
973 break;
974 case 'k':
975 if (keystore_name != NULL)
976 rv = KC_ERR_USAGE;
977 else {
978 keystore_name = get_string(optarg_av, &rv);
979 if (keystore_name == NULL) {
980 (void) fprintf(stderr, gettext(
981 "Error keystore input.\n"));
982 rv = KC_ERR_USAGE;
983 }
984 }
985 break;
986 case 'o':
987 if (has_option_arg) {
988 (void) fprintf(stderr,
989 gettext("duplicate option input.\n"));
990 rv = KC_ERR_USAGE;
991 } else {
992 has_option_arg = B_TRUE;
993 option = get_string(optarg_av, NULL);
994 }
995 break;
996 default:
997 (void) fprintf(stderr,
998 gettext("Error input option.\n"));
999 rv = KC_ERR_USAGE;
1000 break;
1001 }
1002
1003 if (rv != KC_OK)
1004 goto out;
1005 }
1006
1007 /* No additional args allowed. */
1008 argc -= optind_av;
1009 if (argc) {
1010 (void) fprintf(stderr,
1011 gettext("Error input option\n"));
1012 rv = KC_ERR_USAGE;
1013 goto out;
1014 }
1015
1016 if (keystore_name == NULL || has_option_arg == B_FALSE) {
1017 (void) fprintf(stderr,
1018 gettext("Error input option\n"));
1019 rv = KC_ERR_USAGE;
1020 goto out;
1021 }
1022
1023 if (strcasecmp(keystore_name, "nss") == 0 ||
1024 strcasecmp(keystore_name, "pkcs11") == 0 ||
1025 strcasecmp(keystore_name, "file") == 0) {
1026 (void) fprintf(stderr,
1027 gettext("Can not modify the built-in keystore %s\n"),
1028 keystore_name);
1029 rv = KC_ERR_USAGE;
1030 goto out;
1031 }
1032
1033 entry = get_keystore_entry(keystore_name);
1034 if (entry == NULL) {
1035 (void) fprintf(stderr, gettext("%s does not exist.\n"),
1036 keystore_name);
1037 rv = KC_ERR_USAGE;
1038 goto out;
1039 }
1040
1041 if ((entry->option == NULL && option == NULL) ||
1042 (entry->option != NULL && option != NULL &&
1043 strcmp(entry->option, option) == 0)) {
1044 (void) fprintf(stderr, gettext("No change - "
1045 "the new option is same as the old option.\n"));
1046 rv = KC_OK;
1047 goto out;
1048 }
1049
1050 if ((pfile = fopen(_PATH_KMF_CONF, "r+")) == NULL) {
1051 err = errno;
1052 (void) fprintf(stderr,
1053 gettext("failed to update the configuration - %s\n"),
1054 strerror(err));
1055 rv = KC_ERR_ACCESS;
1056 goto out;
1057 }
1058
1059 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
1060 err = errno;
1061 (void) fprintf(stderr,
1062 gettext("failed to lock the configuration - %s\n"),
1063 strerror(err));
1064 rv = KC_ERR_MODIFY_PLUGIN;
1065 goto out;
1066 }
1067
1068 /*
1069 * Create a temporary file in the /etc/crypto directory.
1070 */
1071 (void) strlcpy(tmpfile_name, CONF_TEMPFILE, sizeof (tmpfile_name));
1072 if (mkstemp(tmpfile_name) == -1) {
1073 err = errno;
1074 (void) fprintf(stderr,
1075 gettext("failed to create a temporary file - %s\n"),
1076 strerror(err));
1077 rv = KC_ERR_MODIFY_PLUGIN;
1078 goto out;
1079 }
1080
1081 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
1082 err = errno;
1083 (void) fprintf(stderr,
1084 gettext("failed to open %s - %s\n"),
1085 tmpfile_name, strerror(err));
1086 rv = KC_ERR_MODIFY_PLUGIN;
1087 goto out;
1088 }
1089
1090 /*
1091 * Loop thru the config file and update the entry.
1092 */
1093 while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
1094 char *name;
1095 int len;
1096
1097 if (buffer[0] == '#') {
1098 if (fputs(buffer, pfile_tmp) == EOF) {
1099 rv = KC_ERR_MODIFY_PLUGIN;
1100 goto out;
1101 } else {
1102 continue;
1103 }
1104 }
1105
1106 /*
1107 * make a copy of the original buffer to buffer2. Also get
1108 * rid of the trailing '\n' from buffer2.
1109 */
1110 (void) strlcpy(buffer2, buffer, MAXPATHLEN);
1111 len = strlen(buffer2);
1112 if (buffer2[len-1] == '\n') {
1113 len--;
1114 }
1115 buffer2[len] = '\0';
1116
1117 if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
1118 rv = KC_ERR_UNINSTALL;
1119 goto out;
1120 }
1121
1122 if (strcmp(name, keystore_name) == 0) {
1123 /* found the entry */
1124 if (option == NULL)
1125 (void) snprintf(buffer, MAXPATHLEN,
1126 "%s:%s%s\n", keystore_name,
1127 CONF_MODULEPATH, entry->modulepath);
1128 else
1129 (void) snprintf(buffer, MAXPATHLEN,
1130 "%s:%s%s;%s%s\n", keystore_name,
1131 CONF_MODULEPATH, entry->modulepath,
1132 CONF_OPTION, option);
1133
1134 if (fputs(buffer, pfile_tmp) == EOF) {
1135 err = errno;
1136 (void) fprintf(stderr, gettext(
1137 "failed to write to %s: %s\n"),
1138 tmpfile_name, strerror(err));
1139 rv = KC_ERR_MODIFY_PLUGIN;
1140 goto out;
1141 }
1142 } else {
1143
1144 if (fputs(buffer, pfile_tmp) == EOF) {
1145 rv = KC_ERR_UNINSTALL;
1146 goto out;
1147 }
1148 }
1149 }
1150
1151 if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) {
1152 err = errno;
1153 (void) fprintf(stderr, gettext(
1154 "failed to update the configuration - %s"), strerror(err));
1155 rv = KC_ERR_MODIFY_PLUGIN;
1156 goto out;
1157 }
1158
1159 if (chmod(_PATH_KMF_CONF,
1160 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1161 err = errno;
1162 (void) fprintf(stderr, gettext(
1163 "failed to update the configuration - %s\n"),
1164 strerror(err));
1165 rv = KC_ERR_MODIFY_PLUGIN;
1166 goto out;
1167 }
1168
1169 out:
1170 if (entry != NULL)
1171 free_entry(entry);
1172
1173 if (pfile != NULL)
1174 (void) fclose(pfile);
1175
1176 if (rv != KC_OK && pfile_tmp != NULL)
1177 (void) unlink(tmpfile_name);
1178
1179 if (pfile_tmp != NULL)
1180 (void) fclose(pfile_tmp);
1181
1182 return (rv);
1183 }
1184
1185
1186 int
kc_modify(int argc,char * argv[])1187 kc_modify(int argc, char *argv[])
1188 {
1189 if (argc > 2 &&
1190 strcmp(argv[0], "modify") == 0 &&
1191 strcmp(argv[1], "plugin") == 0) {
1192 return (kc_modify_plugin(argc, argv));
1193 } else {
1194 return (kc_modify_policy(argc, argv));
1195 }
1196 }
1197