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