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