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 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 { 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 } 217 break; 218 case 's': 219 plc.ta_serial = get_string(optarg_av, &rv); 220 if (plc.ta_serial == NULL) { 221 (void) fprintf(stderr, 222 gettext("Error serial input.\n")); 223 } else { 224 uchar_t *bytes = NULL; 225 size_t bytelen; 226 227 ret = kmf_hexstr_to_bytes( 228 (uchar_t *)plc.ta_serial, 229 &bytes, &bytelen); 230 if (ret != KMF_OK || bytes == NULL) { 231 (void) fprintf(stderr, 232 gettext("serial number " 233 "must be specified as a " 234 "hex number " 235 "(ex: 0x0102030405" 236 "ffeeddee)\n")); 237 rv = KC_ERR_USAGE; 238 break; 239 } 240 if (bytes != NULL) 241 free(bytes); 242 flags |= KC_TA_SERIAL; 243 } 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++; 255 } 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++; 265 } 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++; 277 } 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++; 298 } 299 } 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++; 311 } 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++; 333 } 334 } 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; 345 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; 358 } 359 if (bytes != NULL) 360 free(bytes); 361 flags |= KC_OCSP_RESP_CERT_SERIAL; 362 ocsp_set_attr++; 363 } 364 break; 365 case 'y': 366 ocsp_none_opt = get_boolean(optarg_av); 367 if (ocsp_none_opt == -1) { 368 (void) fprintf(stderr, 369 gettext("Error boolean input.\n")); 370 rv = KC_ERR_USAGE; 371 } else { 372 flags |= KC_OCSP_NONE; 373 } 374 break; 375 case 'c': 376 plc.VAL_CRL_BASEFILENAME = 377 get_string(optarg_av, &rv); 378 if (plc.VAL_CRL_BASEFILENAME == NULL) { 379 (void) fprintf(stderr, gettext( 380 "Error basefilename input.\n")); 381 } else { 382 flags |= KC_CRL_BASEFILENAME; 383 crl_set_attr++; 384 } 385 break; 386 case 'I': 387 plc.VAL_CRL_DIRECTORY = 388 get_string(optarg_av, &rv); 389 if (plc.VAL_CRL_DIRECTORY == NULL) { 390 (void) fprintf(stderr, 391 gettext("Error boolean input.\n")); 392 } else { 393 flags |= KC_CRL_DIRECTORY; 394 crl_set_attr++; 395 } 396 break; 397 case 'g': 398 plc.VAL_CRL_GET_URI = get_boolean(optarg_av); 399 if (plc.VAL_CRL_GET_URI == -1) { 400 (void) fprintf(stderr, 401 gettext("Error boolean input.\n")); 402 rv = KC_ERR_USAGE; 403 } else { 404 flags |= KC_CRL_GET_URI; 405 crl_set_attr++; 406 } 407 break; 408 case 'X': 409 plc.VAL_CRL_PROXY = get_string(optarg_av, &rv); 410 if (plc.VAL_CRL_PROXY == NULL) { 411 (void) fprintf(stderr, 412 gettext("Error proxy input.\n")); 413 } else { 414 flags |= KC_CRL_PROXY; 415 crl_set_attr++; 416 } 417 break; 418 case 'S': 419 plc.VAL_CRL_IGNORE_SIGN = 420 get_boolean(optarg_av); 421 if (plc.VAL_CRL_IGNORE_SIGN == -1) { 422 (void) fprintf(stderr, 423 gettext("Error boolean input.\n")); 424 rv = KC_ERR_USAGE; 425 } else { 426 flags |= KC_CRL_IGNORE_SIGN; 427 crl_set_attr++; 428 } 429 break; 430 case 'D': 431 plc.VAL_CRL_IGNORE_DATE = 432 get_boolean(optarg_av); 433 if (plc.VAL_CRL_IGNORE_DATE == -1) { 434 (void) fprintf(stderr, 435 gettext("Error boolean input.\n")); 436 rv = KC_ERR_USAGE; 437 } else { 438 flags |= KC_CRL_IGNORE_DATE; 439 crl_set_attr++; 440 } 441 break; 442 case 'z': 443 crl_none_opt = get_boolean(optarg_av); 444 if (crl_none_opt == -1) { 445 (void) fprintf(stderr, 446 gettext("Error boolean input.\n")); 447 rv = KC_ERR_USAGE; 448 } else { 449 flags |= KC_CRL_NONE; 450 } 451 break; 452 case 'u': 453 plc.ku_bits = parseKUlist(optarg_av); 454 if (plc.ku_bits == 0) { 455 (void) fprintf(stderr, gettext( 456 "Error keyusage input.\n")); 457 rv = KC_ERR_USAGE; 458 } else { 459 flags |= KC_KEYUSAGE; 460 } 461 break; 462 case 'Y': 463 ku_none_opt = get_boolean(optarg_av); 464 if (ku_none_opt == -1) { 465 (void) fprintf(stderr, 466 gettext("Error boolean input.\n")); 467 rv = KC_ERR_USAGE; 468 } else { 469 flags |= KC_KEYUSAGE_NONE; 470 } 471 break; 472 case 'E': 473 if (parseEKUNames(optarg_av, &plc) != 0) { 474 (void) fprintf(stderr, 475 gettext("Error EKU input.\n")); 476 rv = KC_ERR_USAGE; 477 } else { 478 flags |= KC_EKUS; 479 } 480 break; 481 case 'O': 482 if (parseEKUOIDs(optarg_av, &plc) != 0) { 483 (void) fprintf(stderr, 484 gettext("Error EKU OID input.\n")); 485 rv = KC_ERR_USAGE; 486 } else { 487 flags |= KC_EKUS; 488 } 489 break; 490 case 'Z': 491 eku_none_opt = get_boolean(optarg_av); 492 if (eku_none_opt == -1) { 493 (void) fprintf(stderr, 494 gettext("Error boolean input.\n")); 495 rv = KC_ERR_USAGE; 496 } else { 497 flags |= KC_EKUS_NONE; 498 } 499 break; 500 case 'm': 501 mapper_name = get_string(optarg_av, &rv); 502 if (mapper_name == NULL) { 503 (void) fprintf(stderr, 504 gettext("Error mapper-name " 505 "input.\n")); 506 } 507 break; 508 case 'M': 509 mapper_dir = get_string(optarg_av, &rv); 510 if (mapper_dir == NULL) { 511 (void) fprintf(stderr, 512 gettext("Error mapper-directory " 513 "input.\n")); 514 } 515 break; 516 case 'Q': 517 mapper_pathname = get_string(optarg_av, &rv); 518 if (mapper_pathname == NULL) { 519 (void) fprintf(stderr, 520 gettext("Error mapper-pathname " 521 "input.\n")); 522 } 523 break; 524 case 'q': 525 plc.mapper.options = get_string(optarg_av, &rv); 526 rv = 0; /* its ok for this to be NULL */ 527 flags |= KC_MAPPER_OPTIONS; 528 break; 529 default: 530 (void) fprintf(stderr, 531 gettext("Error input option.\n")); 532 rv = KC_ERR_USAGE; 533 break; 534 } 535 if (rv != KC_OK) 536 goto out; 537 } 538 539 /* No additional args allowed. */ 540 argc -= optind_av; 541 if (argc) { 542 (void) fprintf(stderr, 543 gettext("Error input option\n")); 544 rv = KC_ERR_USAGE; 545 goto out; 546 } 547 548 if (filename == NULL) { 549 filename = strdup(KMF_DEFAULT_POLICY_FILE); 550 if (filename == NULL) { 551 rv = KC_ERR_MEMORY; 552 goto out; 553 } 554 } 555 556 /* 557 * Must have a policy name. The policy name can not be default 558 * if using the default policy file. 559 */ 560 if (plc.name == NULL) { 561 (void) fprintf(stderr, 562 gettext("You must specify a policy name.\n")); 563 rv = KC_ERR_USAGE; 564 goto out; 565 } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 && 566 strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) { 567 (void) fprintf(stderr, 568 gettext("Can not modify the default policy in the default " 569 "policy file.\n")); 570 rv = KC_ERR_USAGE; 571 goto out; 572 } 573 574 /* Check the access permission of the policy DB */ 575 if (access(filename, W_OK) < 0) { 576 int err = errno; 577 (void) fprintf(stderr, 578 gettext("Cannot access \"%s\" for modify - %s\n"), 579 filename, strerror(err)); 580 rv = KC_ERR_ACCESS; 581 goto out; 582 } 583 584 /* Try to load the named policy from the DB */ 585 ret = kmf_get_policy(filename, plc.name, &oplc); 586 if (ret != KMF_OK) { 587 (void) fprintf(stderr, 588 gettext("Error loading policy \"%s\" from %s\n"), filename, 589 plc.name); 590 return (KC_ERR_FIND_POLICY); 591 } 592 593 /* Update the general policy attributes. */ 594 if (flags & KC_IGNORE_DATE) 595 oplc.ignore_date = plc.ignore_date; 596 597 if (flags & KC_IGNORE_UNKNOWN_EKUS) 598 oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus; 599 600 if (flags & KC_IGNORE_TRUST_ANCHOR) 601 oplc.ignore_trust_anchor = plc.ignore_trust_anchor; 602 603 if (flags & KC_VALIDITY_ADJUSTTIME) { 604 if (oplc.validity_adjusttime) 605 free(oplc.validity_adjusttime); 606 oplc.validity_adjusttime = 607 plc.validity_adjusttime; 608 } 609 610 if (flags & KC_TA_NAME) { 611 if (oplc.ta_name) 612 free(oplc.ta_name); 613 oplc.ta_name = plc.ta_name; 614 } 615 if (flags & KC_TA_SERIAL) { 616 if (oplc.ta_serial) 617 free(oplc.ta_serial); 618 oplc.ta_serial = plc.ta_serial; 619 } 620 621 /* 622 * There are some combinations of attributes that are not valid. 623 * 624 * First, setting mapper-name (with optional mapper-directory) and 625 * mapper-pathname is mutually exclusive. 626 */ 627 if ((mapper_name != NULL && mapper_pathname != NULL) || 628 (mapper_name != NULL && oplc.mapper.pathname != NULL) || 629 (mapper_pathname != NULL && oplc.mapper.mapname != NULL) || 630 /* Mapper directory can be set only if mapper name is set. */ 631 (mapper_dir != NULL && mapper_pathname != NULL) || 632 (mapper_dir != NULL && mapper_name == NULL && 633 oplc.mapper.mapname == NULL) || 634 (mapper_dir != NULL && oplc.mapper.pathname != NULL) || 635 /* Options can be set only if mapper name or pathname is set. */ 636 ((plc.mapper.options != NULL || oplc.mapper.options != NULL) && 637 (mapper_name == NULL && oplc.mapper.mapname == NULL && 638 mapper_pathname == NULL && oplc.mapper.pathname == NULL))) { 639 (void) fprintf(stderr, 640 gettext("Error in mapper input options\n")); 641 if (mapper_name != NULL) 642 free(mapper_name); 643 if (mapper_pathname != NULL) 644 free(mapper_pathname); 645 if (mapper_dir != NULL) 646 free(mapper_dir); 647 if (flags & KC_MAPPER_OPTIONS && plc.mapper.options != NULL) 648 free(plc.mapper.options); 649 rv = KC_ERR_USAGE; 650 goto out; 651 } else { 652 if (mapper_name != NULL) 653 plc.mapper.mapname = mapper_name; 654 if (mapper_pathname != NULL) 655 plc.mapper.pathname = mapper_pathname; 656 if (mapper_dir != NULL) 657 plc.mapper.dir = mapper_dir; 658 } 659 660 UPDATE_IF_DIFFERENT(oplc.mapper.mapname, plc.mapper.mapname); 661 UPDATE_IF_DIFFERENT(oplc.mapper.pathname, plc.mapper.pathname); 662 UPDATE_IF_DIFFERENT(oplc.mapper.dir, plc.mapper.dir); 663 664 if (flags & KC_MAPPER_OPTIONS) { 665 if (oplc.mapper.options != NULL) 666 free(oplc.mapper.options); 667 oplc.mapper.options = plc.mapper.options; 668 } 669 670 /* Update the OCSP policy */ 671 if (ocsp_none_opt == B_TRUE) { 672 if (ocsp_set_attr > 0) { 673 (void) fprintf(stderr, 674 gettext("Can not set ocsp-none=true and other " 675 "OCSP attributes at the same time.\n")); 676 rv = KC_ERR_USAGE; 677 goto out; 678 } 679 680 /* 681 * If the original policy does not have OCSP checking, 682 * then we do not need to do anything. If the original 683 * policy has the OCSP checking, then we need to release the 684 * space of OCSP attributes and turn the OCSP checking off. 685 */ 686 if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) { 687 if (oplc.VAL_OCSP_BASIC.responderURI) { 688 free(oplc.VAL_OCSP_BASIC.responderURI); 689 oplc.VAL_OCSP_BASIC.responderURI = NULL; 690 } 691 692 if (oplc.VAL_OCSP_BASIC.proxy) { 693 free(oplc.VAL_OCSP_BASIC.proxy); 694 oplc.VAL_OCSP_BASIC.proxy = NULL; 695 } 696 697 if (oplc.VAL_OCSP_BASIC.response_lifetime) { 698 free(oplc.VAL_OCSP_BASIC.response_lifetime); 699 oplc.VAL_OCSP_BASIC.response_lifetime = NULL; 700 } 701 702 if (flags & KC_OCSP_RESP_CERT_NAME) { 703 free(oplc.VAL_OCSP_RESP_CERT.name); 704 oplc.VAL_OCSP_RESP_CERT.name = NULL; 705 } 706 707 if (flags & KC_OCSP_RESP_CERT_SERIAL) { 708 free(oplc.VAL_OCSP_RESP_CERT.serial); 709 oplc.VAL_OCSP_RESP_CERT.serial = NULL; 710 } 711 712 /* Turn off the OCSP checking */ 713 oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP; 714 } 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 OCSP attribute is specified. 721 */ 722 if (ocsp_set_attr > 0) { 723 if (flags & KC_OCSP_RESPONDER_URI) { 724 if (oplc.VAL_OCSP_RESPONDER_URI) 725 free(oplc.VAL_OCSP_RESPONDER_URI); 726 oplc.VAL_OCSP_RESPONDER_URI = 727 plc.VAL_OCSP_RESPONDER_URI; 728 } 729 730 if (flags & KC_OCSP_PROXY) { 731 if (oplc.VAL_OCSP_PROXY) 732 free(oplc.VAL_OCSP_PROXY); 733 oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY; 734 } 735 736 if (flags & KC_OCSP_URI_FROM_CERT) 737 oplc.VAL_OCSP_URI_FROM_CERT = 738 plc.VAL_OCSP_URI_FROM_CERT; 739 740 if (flags & KC_OCSP_RESP_LIFETIME) { 741 if (oplc.VAL_OCSP_RESP_LIFETIME) 742 free(oplc.VAL_OCSP_RESP_LIFETIME); 743 oplc.VAL_OCSP_RESP_LIFETIME = 744 plc.VAL_OCSP_RESP_LIFETIME; 745 } 746 747 if (flags & KC_OCSP_IGNORE_RESP_SIGN) 748 oplc.VAL_OCSP_IGNORE_RESP_SIGN = 749 plc.VAL_OCSP_IGNORE_RESP_SIGN; 750 751 if (flags & KC_OCSP_RESP_CERT_NAME) { 752 if (oplc.VAL_OCSP_RESP_CERT_NAME) 753 free(oplc.VAL_OCSP_RESP_CERT_NAME); 754 oplc.VAL_OCSP_RESP_CERT_NAME = 755 plc.VAL_OCSP_RESP_CERT_NAME; 756 } 757 758 if (flags & KC_OCSP_RESP_CERT_SERIAL) { 759 if (oplc.VAL_OCSP_RESP_CERT_SERIAL) 760 free(oplc.VAL_OCSP_RESP_CERT_SERIAL); 761 oplc.VAL_OCSP_RESP_CERT_SERIAL = 762 plc.VAL_OCSP_RESP_CERT_SERIAL; 763 } 764 765 if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL && 766 oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL) 767 oplc.VAL_OCSP.has_resp_cert = B_TRUE; 768 else 769 oplc.VAL_OCSP.has_resp_cert = B_FALSE; 770 771 /* Turn on the OCSP checking */ 772 oplc.revocation |= KMF_REVOCATION_METHOD_OCSP; 773 } 774 } 775 776 /* Update the CRL policy */ 777 if (crl_none_opt == B_TRUE) { 778 if (crl_set_attr > 0) { 779 (void) fprintf(stderr, 780 gettext("Can not set crl-none=true and other CRL " 781 "attributes at the same time.\n")); 782 rv = KC_ERR_USAGE; 783 goto out; 784 } 785 786 /* 787 * If the original policy does not have CRL checking, 788 * then we do not need to do anything. If the original 789 * policy has the CRL checking, then we need to release the 790 * space of CRL attributes and turn the CRL checking off. 791 */ 792 if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) { 793 if (oplc.VAL_CRL_BASEFILENAME) { 794 free(oplc.VAL_CRL_BASEFILENAME); 795 oplc.VAL_CRL_BASEFILENAME = NULL; 796 } 797 798 if (oplc.VAL_CRL_DIRECTORY) { 799 free(oplc.VAL_CRL_DIRECTORY); 800 oplc.VAL_CRL_DIRECTORY = NULL; 801 } 802 803 if (oplc.VAL_CRL_PROXY) { 804 free(oplc.VAL_CRL_PROXY); 805 oplc.VAL_CRL_PROXY = NULL; 806 } 807 808 /* Turn off the CRL checking */ 809 oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL; 810 } 811 } else { 812 /* 813 * If the "ocsp-none" option is not set or is set to false, 814 * then we only need to do the modification if there is at 815 * least one CRL attribute is specified. 816 */ 817 if (crl_set_attr > 0) { 818 if (flags & KC_CRL_BASEFILENAME) { 819 if (oplc.VAL_CRL_BASEFILENAME) 820 free(oplc.VAL_CRL_BASEFILENAME); 821 oplc.VAL_CRL_BASEFILENAME = 822 plc.VAL_CRL_BASEFILENAME; 823 } 824 825 if (flags & KC_CRL_DIRECTORY) { 826 if (oplc.VAL_CRL_DIRECTORY) 827 free(oplc.VAL_CRL_DIRECTORY); 828 oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY; 829 } 830 831 if (flags & KC_CRL_GET_URI) { 832 oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI; 833 } 834 835 if (flags & KC_CRL_PROXY) { 836 if (oplc.VAL_CRL_PROXY) 837 free(oplc.VAL_CRL_PROXY); 838 oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY; 839 } 840 841 if (flags & KC_CRL_IGNORE_SIGN) { 842 oplc.VAL_CRL_IGNORE_SIGN = 843 plc.VAL_CRL_IGNORE_SIGN; 844 } 845 846 if (flags & KC_CRL_IGNORE_DATE) { 847 oplc.VAL_CRL_IGNORE_DATE = 848 plc.VAL_CRL_IGNORE_DATE; 849 } 850 851 /* Turn on the CRL checking */ 852 oplc.revocation |= KMF_REVOCATION_METHOD_CRL; 853 } 854 } 855 856 /* Update the Key Usage */ 857 if (ku_none_opt == B_TRUE) { 858 if (flags & KC_KEYUSAGE) { 859 (void) fprintf(stderr, 860 gettext("Can not set keyusage-none=true and " 861 "modify the keyusage value at the same time.\n")); 862 rv = KC_ERR_USAGE; 863 goto out; 864 } 865 866 oplc.ku_bits = 0; 867 } else { 868 /* 869 * If the "keyusage-none" option is not set or is set to 870 * false, then we only need to do the modification if 871 * the keyusage value is specified. 872 */ 873 if (flags & KC_KEYUSAGE) 874 oplc.ku_bits = plc.ku_bits; 875 } 876 877 878 /* Update the Extended Key Usage */ 879 if (eku_none_opt == B_TRUE) { 880 if (flags & KC_EKUS) { 881 (void) fprintf(stderr, 882 gettext("Can not set eku-none=true and modify " 883 "EKU values at the same time.\n")); 884 rv = KC_ERR_USAGE; 885 goto out; 886 } 887 888 /* Release current EKU list (if any) */ 889 if (oplc.eku_set.eku_count > 0) { 890 kmf_free_eku_policy(&oplc.eku_set); 891 oplc.eku_set.eku_count = 0; 892 oplc.eku_set.ekulist = NULL; 893 } 894 } else { 895 /* 896 * If the "eku-none" option is not set or is set to false, 897 * then we only need to do the modification if either 898 * "ekuname" or "ekuoids" is specified. 899 */ 900 if (flags & KC_EKUS) { 901 /* Release current EKU list (if any) */ 902 kmf_free_eku_policy(&oplc.eku_set); 903 oplc.eku_set = plc.eku_set; 904 } 905 } 906 907 /* Do a sanity check on the modified policy */ 908 ret = kmf_verify_policy(&oplc); 909 if (ret != KMF_OK) { 910 print_sanity_error(ret); 911 rv = KC_ERR_VERIFY_POLICY; 912 goto out; 913 } 914 915 /* The modify operation is a delete followed by an add */ 916 ret = kmf_delete_policy_from_db(oplc.name, filename); 917 if (ret != KMF_OK) { 918 rv = KC_ERR_DELETE_POLICY; 919 goto out; 920 } 921 922 /* 923 * Now add the modified policy back to the DB. 924 */ 925 ret = kmf_add_policy_to_db(&oplc, filename, B_FALSE); 926 if (ret != KMF_OK) { 927 (void) fprintf(stderr, 928 gettext("Error adding policy to database: 0x%04x\n"), ret); 929 rv = KC_ERR_ADD_POLICY; 930 goto out; 931 } 932 933 out: 934 if (filename != NULL) 935 free(filename); 936 937 kmf_free_policy_record(&oplc); 938 939 return (rv); 940 } 941 942 static int 943 kc_modify_plugin(int argc, char *argv[]) 944 { 945 int rv = KC_OK; 946 int opt; 947 extern int optind_av; 948 extern char *optarg_av; 949 char *keystore_name = NULL; 950 char *option = NULL; 951 boolean_t modify_plugin = B_FALSE; 952 boolean_t has_option_arg = B_FALSE; 953 conf_entry_t *entry = NULL; 954 FILE *pfile = NULL; 955 FILE *pfile_tmp = NULL; 956 char tmpfile_name[MAXPATHLEN]; 957 char buffer[MAXPATHLEN]; 958 char buffer2[MAXPATHLEN]; 959 960 while ((opt = getopt_av(argc, argv, "p(plugin)k:(keystore)o:(option)")) 961 != EOF) { 962 switch (opt) { 963 case 'p': 964 if (modify_plugin) { 965 (void) fprintf(stderr, 966 gettext("duplicate plugin input.\n")); 967 rv = KC_ERR_USAGE; 968 } else { 969 modify_plugin = B_TRUE; 970 } 971 break; 972 case 'k': 973 if (keystore_name != NULL) 974 rv = KC_ERR_USAGE; 975 else { 976 keystore_name = get_string(optarg_av, &rv); 977 if (keystore_name == NULL) { 978 (void) fprintf(stderr, gettext( 979 "Error keystore input.\n")); 980 rv = KC_ERR_USAGE; 981 } 982 } 983 break; 984 case 'o': 985 if (has_option_arg) { 986 (void) fprintf(stderr, 987 gettext("duplicate option input.\n")); 988 rv = KC_ERR_USAGE; 989 } else { 990 has_option_arg = B_TRUE; 991 option = get_string(optarg_av, NULL); 992 } 993 break; 994 default: 995 (void) fprintf(stderr, 996 gettext("Error input option.\n")); 997 rv = KC_ERR_USAGE; 998 break; 999 } 1000 1001 if (rv != KC_OK) 1002 goto out; 1003 } 1004 1005 /* No additional args allowed. */ 1006 argc -= optind_av; 1007 if (argc) { 1008 (void) fprintf(stderr, 1009 gettext("Error input option\n")); 1010 rv = KC_ERR_USAGE; 1011 goto out; 1012 } 1013 1014 if (keystore_name == NULL || has_option_arg == B_FALSE) { 1015 (void) fprintf(stderr, 1016 gettext("Error input option\n")); 1017 rv = KC_ERR_USAGE; 1018 goto out; 1019 } 1020 1021 if (strcasecmp(keystore_name, "nss") == 0 || 1022 strcasecmp(keystore_name, "pkcs11") == 0 || 1023 strcasecmp(keystore_name, "file") == 0) { 1024 (void) fprintf(stderr, 1025 gettext("Can not modify the built-in keystore %s\n"), 1026 keystore_name); 1027 rv = KC_ERR_USAGE; 1028 goto out; 1029 } 1030 1031 entry = get_keystore_entry(keystore_name); 1032 if (entry == NULL) { 1033 (void) fprintf(stderr, gettext("%s does not exist.\n"), 1034 keystore_name); 1035 rv = KC_ERR_USAGE; 1036 goto out; 1037 } 1038 1039 if ((entry->option == NULL && option == NULL) || 1040 (entry->option != NULL && option != NULL && 1041 strcmp(entry->option, option) == 0)) { 1042 (void) fprintf(stderr, gettext("No change - " 1043 "the new option is same as the old option.\n")); 1044 rv = KC_OK; 1045 goto out; 1046 } 1047 1048 if ((pfile = fopen(_PATH_KMF_CONF, "r+")) == NULL) { 1049 err = errno; 1050 (void) fprintf(stderr, 1051 gettext("failed to update the configuration - %s\n"), 1052 strerror(err)); 1053 rv = KC_ERR_ACCESS; 1054 goto out; 1055 } 1056 1057 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 1058 err = errno; 1059 (void) fprintf(stderr, 1060 gettext("failed to lock the configuration - %s\n"), 1061 strerror(err)); 1062 rv = KC_ERR_MODIFY_PLUGIN; 1063 goto out; 1064 } 1065 1066 /* 1067 * Create a temporary file in the /etc/crypto directory. 1068 */ 1069 (void) strlcpy(tmpfile_name, CONF_TEMPFILE, sizeof (tmpfile_name)); 1070 if (mkstemp(tmpfile_name) == -1) { 1071 err = errno; 1072 (void) fprintf(stderr, 1073 gettext("failed to create a temporary file - %s\n"), 1074 strerror(err)); 1075 rv = KC_ERR_MODIFY_PLUGIN; 1076 goto out; 1077 } 1078 1079 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 1080 err = errno; 1081 (void) fprintf(stderr, 1082 gettext("failed to open %s - %s\n"), 1083 tmpfile_name, strerror(err)); 1084 rv = KC_ERR_MODIFY_PLUGIN; 1085 goto out; 1086 } 1087 1088 /* 1089 * Loop thru the config file and update the entry. 1090 */ 1091 while (fgets(buffer, MAXPATHLEN, pfile) != NULL) { 1092 char *name; 1093 int len; 1094 1095 if (buffer[0] == '#') { 1096 if (fputs(buffer, pfile_tmp) == EOF) { 1097 rv = KC_ERR_MODIFY_PLUGIN; 1098 goto out; 1099 } else { 1100 continue; 1101 } 1102 } 1103 1104 /* 1105 * make a copy of the original buffer to buffer2. Also get 1106 * rid of the trailing '\n' from buffer2. 1107 */ 1108 (void) strlcpy(buffer2, buffer, MAXPATHLEN); 1109 len = strlen(buffer2); 1110 if (buffer2[len-1] == '\n') { 1111 len--; 1112 } 1113 buffer2[len] = '\0'; 1114 1115 if ((name = strtok(buffer2, SEP_COLON)) == NULL) { 1116 rv = KC_ERR_UNINSTALL; 1117 goto out; 1118 } 1119 1120 if (strcmp(name, keystore_name) == 0) { 1121 /* found the entry */ 1122 if (option == NULL) 1123 (void) snprintf(buffer, MAXPATHLEN, 1124 "%s:%s%s\n", keystore_name, 1125 CONF_MODULEPATH, entry->modulepath); 1126 else 1127 (void) snprintf(buffer, MAXPATHLEN, 1128 "%s:%s%s;%s%s\n", keystore_name, 1129 CONF_MODULEPATH, entry->modulepath, 1130 CONF_OPTION, option); 1131 1132 if (fputs(buffer, pfile_tmp) == EOF) { 1133 err = errno; 1134 (void) fprintf(stderr, gettext( 1135 "failed to write to %s: %s\n"), 1136 tmpfile_name, strerror(err)); 1137 rv = KC_ERR_MODIFY_PLUGIN; 1138 goto out; 1139 } 1140 } else { 1141 1142 if (fputs(buffer, pfile_tmp) == EOF) { 1143 rv = KC_ERR_UNINSTALL; 1144 goto out; 1145 } 1146 } 1147 } 1148 1149 if (rename(tmpfile_name, _PATH_KMF_CONF) == -1) { 1150 err = errno; 1151 (void) fprintf(stderr, gettext( 1152 "failed to update the configuration - %s"), strerror(err)); 1153 rv = KC_ERR_MODIFY_PLUGIN; 1154 goto out; 1155 } 1156 1157 if (chmod(_PATH_KMF_CONF, 1158 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 1159 err = errno; 1160 (void) fprintf(stderr, gettext( 1161 "failed to update the configuration - %s\n"), 1162 strerror(err)); 1163 rv = KC_ERR_MODIFY_PLUGIN; 1164 goto out; 1165 } 1166 1167 out: 1168 if (entry != NULL) 1169 free_entry(entry); 1170 1171 if (pfile != NULL) 1172 (void) fclose(pfile); 1173 1174 if (rv != KC_OK && pfile_tmp != NULL) 1175 (void) unlink(tmpfile_name); 1176 1177 if (pfile_tmp != NULL) 1178 (void) fclose(pfile_tmp); 1179 1180 return (rv); 1181 } 1182 1183 1184 int 1185 kc_modify(int argc, char *argv[]) 1186 { 1187 if (argc > 2 && 1188 strcmp(argv[0], "modify") == 0 && 1189 strcmp(argv[1], "plugin") == 0) { 1190 return (kc_modify_plugin(argc, argv)); 1191 } else { 1192 return (kc_modify_policy(argc, argv)); 1193 } 1194 } 1195