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 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 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 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