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 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Module: keystore.c 29 * Description: This module contains the structure definitions for processing 30 * package keystore files. 31 */ 32 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <unistd.h> 36 #include <strings.h> 37 #include <libintl.h> 38 #include <time.h> 39 #include <ctype.h> 40 #include <sys/types.h> 41 #include <sys/stat.h> 42 #include <openssl/evp.h> 43 #include <openssl/x509.h> 44 #include <openssl/pkcs12.h> 45 #include <openssl/asn1.h> 46 #include <openssl/pem.h> 47 #include <openssl/err.h> 48 #include <openssl/safestack.h> 49 #include <openssl/stack.h> 50 #include "p12lib.h" 51 #include "pkgerr.h" 52 #include "keystore.h" 53 #include "pkglib.h" 54 #include "pkglibmsgs.h" 55 56 typedef struct keystore_t { 57 boolean_t dirty; 58 boolean_t new; 59 char *path; 60 char *passphrase; 61 /* truststore handles */ 62 int cafd; 63 STACK_OF(X509) *cacerts; 64 char *capath; 65 66 /* user certificate handles */ 67 STACK_OF(X509) *clcerts; 68 char *clpath; 69 70 /* private key handles */ 71 STACK_OF(EVP_PKEY) *pkeys; 72 char *keypath; 73 } keystore_t; 74 75 /* local routines */ 76 static keystore_t *new_keystore(void); 77 static void free_keystore(keystore_t *); 78 static boolean_t verify_keystore_integrity(PKG_ERR *, keystore_t *); 79 static boolean_t check_password(PKCS12 *, char *); 80 static boolean_t resolve_paths(PKG_ERR *, char *, char *, 81 long, keystore_t *); 82 static boolean_t lock_keystore(PKG_ERR *, long, keystore_t *); 83 84 static boolean_t unlock_keystore(PKG_ERR *, keystore_t *); 85 static boolean_t read_keystore(PKG_ERR *, keystore_t *, 86 keystore_passphrase_cb); 87 static boolean_t write_keystore(PKG_ERR *, keystore_t *, 88 keystore_passphrase_cb); 89 static boolean_t write_keystore_file(PKG_ERR *, char *, PKCS12 *); 90 static boolean_t clear_keystore_file(PKG_ERR *, char *); 91 static PKCS12 *read_keystore_file(PKG_ERR *, char *); 92 static char *get_time_string(ASN1_TIME *); 93 94 /* locking routines */ 95 static boolean_t restore_keystore_file(PKG_ERR *, char *); 96 static int file_lock(int, int, int); 97 static int file_unlock(int); 98 static boolean_t file_lock_test(int, int); 99 static boolean_t file_empty(char *); 100 static boolean_t get_keystore_passwd(PKG_ERR *err, PKCS12 *p12, 101 keystore_passphrase_cb cb, keystore_t *keystore); 102 static boolean_t wait_restore(int, char *, char *, char *); 103 104 #define KEYSTORE_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) 105 106 /* wait on other keystore access for 1 minute before giving up */ 107 #define LOCK_TIMEOUT 60 108 109 /* 110 * print_certs - prints certificates out of a keystore, to a file. 111 * 112 * Arguments: 113 * err - Error object to append errors to 114 * keystore - Keystore on which to operate 115 * alias - Name of certificate to print, NULL means print all 116 * format - Format in which to print certificates 117 * outfile - Where to print certificates 118 * 119 * Returns: 120 * 0 - Success 121 * non-zero - Failure, errors added to err 122 */ 123 int 124 print_certs(PKG_ERR *err, keystore_handle_t keystore_h, char *alias, 125 keystore_encoding_format_t format, FILE *outfile) 126 { 127 int i; 128 X509 *cert; 129 char *fname = NULL; 130 boolean_t found = B_FALSE; 131 keystore_t *keystore = keystore_h; 132 133 if (keystore->clcerts != NULL) { 134 /* print out each client cert */ 135 for (i = 0; i < sk_X509_num(keystore->clcerts); i++) { 136 cert = sk_X509_value(keystore->clcerts, i); 137 (void) sunw_get_cert_fname(GETDO_COPY, cert, 138 &fname); 139 140 if (fname == NULL) { 141 /* no name recorded, keystore is corrupt */ 142 pkgerr_add(err, PKGERR_CORRUPT, 143 gettext(ERR_KEYSTORE_NO_ALIAS), 144 get_subject_display_name(cert)); 145 return (1); 146 } 147 148 if ((alias != NULL) && (!streq(alias, fname))) { 149 /* name does not match, skip it */ 150 (void) OPENSSL_free(fname); 151 fname = NULL; 152 continue; 153 } else { 154 found = B_TRUE; 155 (void) print_cert(err, cert, format, 156 fname, B_FALSE, outfile); 157 (void) OPENSSL_free(fname); 158 fname = NULL; 159 } 160 } 161 } 162 163 if (fname != NULL) { 164 (void) OPENSSL_free(fname); 165 fname = NULL; 166 } 167 168 if (keystore->cacerts != NULL) { 169 /* print out each trusted cert */ 170 for (i = 0; i < sk_X509_num(keystore->cacerts); i++) { 171 cert = sk_X509_value(keystore->cacerts, i); 172 (void) sunw_get_cert_fname(GETDO_COPY, 173 cert, &fname); 174 175 if (fname == NULL) { 176 /* no name recorded, keystore is corrupt */ 177 pkgerr_add(err, PKGERR_CORRUPT, 178 gettext(ERR_KEYSTORE_NO_ALIAS), 179 get_subject_display_name(cert)); 180 return (1); 181 } 182 183 if ((alias != NULL) && (!streq(alias, fname))) { 184 /* name does not match, skip it */ 185 (void) OPENSSL_free(fname); 186 fname = NULL; 187 continue; 188 } else { 189 found = B_TRUE; 190 (void) print_cert(err, cert, format, 191 fname, B_TRUE, outfile); 192 (void) OPENSSL_free(fname); 193 fname = NULL; 194 } 195 } 196 } 197 198 if (fname != NULL) { 199 (void) OPENSSL_free(fname); 200 fname = NULL; 201 } 202 203 if (found) { 204 return (0); 205 } else { 206 /* no certs printed */ 207 if (alias != NULL) { 208 pkgerr_add(err, PKGERR_NOALIASMATCH, 209 gettext(ERR_KEYSTORE_NOCERT), 210 alias, keystore->path); 211 } else { 212 pkgerr_add(err, PKGERR_NOPUBKEY, 213 gettext(ERR_KEYSTORE_NOPUBCERTS), 214 keystore->path); 215 pkgerr_add(err, PKGERR_NOCACERT, 216 gettext(ERR_KEYSTORE_NOCACERTS), 217 keystore->path); 218 } 219 return (1); 220 } 221 } 222 223 /* 224 * print_cert - prints a single certificate, to a file 225 * 226 * Arguments: 227 * err - Error object to append errors to 228 * x - The certificate to print 229 * alias - Name of certificate to print 230 * format - Format in which to print certificate 231 * outfile - Where to print certificate 232 * 233 * Returns: 234 * 0 - Success 235 * non-zero - Failure, errors added to err 236 */ 237 int print_cert(PKG_ERR *err, X509 *x, 238 keystore_encoding_format_t format, char *alias, boolean_t is_trusted, 239 FILE *outfile) 240 { 241 242 char *vdb_str; 243 char *vda_str; 244 char vd_str[ATTR_MAX]; 245 int ret = 0; 246 char *cn_str, *icn_str, *typ_str; 247 char *tmp; 248 char *md5_fp; 249 char *sha1_fp; 250 int len; 251 252 /* need to localize the word "Fingerprint", hence these pointers */ 253 char md5_label[ATTR_MAX]; 254 char sha1_label[ATTR_MAX]; 255 256 if (is_trusted) { 257 typ_str = gettext(MSG_KEYSTORE_TRUSTED); 258 } else { 259 typ_str = gettext(MSG_KEYSTORE_UNTRUSTED); 260 } 261 262 if ((cn_str = get_subject_display_name(x)) == NULL) { 263 cn_str = gettext(MSG_KEYSTORE_UNKNOWN); 264 } 265 266 if ((icn_str = get_issuer_display_name(x)) == NULL) { 267 icn_str = gettext(MSG_KEYSTORE_UNKNOWN); 268 } 269 270 vdb_str = xstrdup(get_time_string(X509_get_notBefore(x))); 271 vda_str = xstrdup(get_time_string(X509_get_notAfter(x))); 272 if (((len = snprintf(vd_str, ATTR_MAX, "<%s> - <%s>", 273 vdb_str, vda_str)) < 0) || (len >= ATTR_MAX)) { 274 pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), vdb_str); 275 ret = 1; 276 goto cleanup; 277 } 278 279 if ((tmp = get_fingerprint(x, EVP_md5())) == NULL) { 280 md5_fp = gettext(MSG_KEYSTORE_UNKNOWN); 281 } else { 282 /* 283 * make a copy, otherwise the next call to get_fingerprint 284 * will overwrite this one 285 */ 286 md5_fp = xstrdup(tmp); 287 } 288 289 if ((tmp = get_fingerprint(x, EVP_sha1())) == NULL) { 290 sha1_fp = gettext(MSG_KEYSTORE_UNKNOWN); 291 } else { 292 sha1_fp = xstrdup(tmp); 293 } 294 295 (void) snprintf(md5_label, ATTR_MAX, "%s %s", 296 OBJ_nid2sn(EVP_MD_type(EVP_md5())), 297 /* i18n: 14 characters max */ 298 gettext(MSG_KEYSTORE_FP)); 299 300 (void) snprintf(sha1_label, ATTR_MAX, "%s %s", 301 OBJ_nid2sn(EVP_MD_type(EVP_sha1())), 302 /* i18n: 14 characters max */ 303 gettext(MSG_KEYSTORE_FP)); 304 305 switch (format) { 306 case KEYSTORE_FORMAT_PEM: 307 (void) PEM_write_X509(outfile, x); 308 break; 309 case KEYSTORE_FORMAT_DER: 310 (void) i2d_X509_fp(outfile, x); 311 break; 312 case KEYSTORE_FORMAT_TEXT: 313 (void) fprintf(outfile, "%18s: %s\n", 314 /* i18n: 18 characters max */ 315 gettext(MSG_KEYSTORE_AL), alias); 316 (void) fprintf(outfile, "%18s: %s\n", 317 /* i18n: 18 characters max */ 318 gettext(MSG_KEYSTORE_CN), cn_str); 319 (void) fprintf(outfile, "%18s: %s\n", 320 /* i18n: 18 characters max */ 321 gettext(MSG_KEYSTORE_TY), typ_str); 322 (void) fprintf(outfile, "%18s: %s\n", 323 /* i18n: 18 characters max */ 324 gettext(MSG_KEYSTORE_IN), icn_str); 325 (void) fprintf(outfile, "%18s: %s\n", 326 /* i18n: 18 characters max */ 327 gettext(MSG_KEYSTORE_VD), vd_str); 328 (void) fprintf(outfile, "%18s: %s\n", md5_label, md5_fp); 329 (void) fprintf(outfile, "%18s: %s\n", sha1_label, sha1_fp); 330 (void) fprintf(outfile, "\n"); 331 break; 332 default: 333 pkgerr_add(err, PKGERR_INTERNAL, 334 gettext(ERR_KEYSTORE_INTERNAL), 335 __FILE__, __LINE__); 336 ret = 1; 337 goto cleanup; 338 } 339 340 cleanup: 341 if (md5_fp != NULL) 342 free(md5_fp); 343 if (sha1_fp != NULL) 344 free(sha1_fp); 345 if (vda_str != NULL) 346 free(vda_str); 347 if (vdb_str != NULL) 348 free(vdb_str); 349 return (ret); 350 } 351 352 /* 353 * open_keystore - Initialize new keystore object for 354 * impending access. 355 * 356 * Arguments: 357 * err - Error object to append errors to 358 * keystore_file - Base filename or directory of keystore 359 * app - Application making request 360 * passwd - Password used to decrypt keystore 361 * flags - Control flags used to control access mode and behavior 362 * result - Resulting keystore object stored here on success 363 * 364 * Returns: 365 * 0 - Success - result contains a pointer to the opened keystore 366 * non-zero - Failure, errors added to err 367 */ 368 int 369 open_keystore(PKG_ERR *err, char *keystore_file, char *app, 370 keystore_passphrase_cb cb, long flags, keystore_handle_t *result) 371 { 372 int ret = 0; 373 keystore_t *tmpstore; 374 375 tmpstore = new_keystore(); 376 377 tmpstore->dirty = B_FALSE; 378 tmpstore->new = B_FALSE; 379 tmpstore->path = xstrdup(keystore_file); 380 381 if (!resolve_paths(err, keystore_file, app, flags, tmpstore)) { 382 /* unable to determine keystore paths */ 383 pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR), 384 keystore_file); 385 ret = 1; 386 goto cleanup; 387 } 388 389 if (!verify_keystore_integrity(err, tmpstore)) { 390 /* unable to repair keystore */ 391 pkgerr_add(err, PKGERR_CORRUPT, gettext(ERR_KEYSTORE_REPAIR), 392 keystore_file); 393 ret = 1; 394 goto cleanup; 395 } 396 397 if (!lock_keystore(err, flags, tmpstore)) { 398 pkgerr_add(err, PKGERR_LOCKED, gettext(ERR_KEYSTORE_LOCKED), 399 keystore_file); 400 ret = 1; 401 goto cleanup; 402 } 403 404 /* now that we have locked the keystore, go ahead and read it */ 405 if (!read_keystore(err, tmpstore, cb)) { 406 pkgerr_add(err, PKGERR_READ, gettext(ERR_PARSE), 407 keystore_file); 408 ret = 1; 409 goto cleanup; 410 } 411 412 *result = tmpstore; 413 tmpstore = NULL; 414 415 cleanup: 416 if (tmpstore != NULL) 417 free_keystore(tmpstore); 418 return (ret); 419 } 420 421 /* 422 * new_keystore - Allocates and initializes a Keystore object 423 * 424 * Arguments: 425 * NONE 426 * 427 * Returns: 428 * NULL - out of memory 429 * otherwise, returns a pointer to the newly allocated object, 430 * which should be freed with free_keystore() when no longer 431 * needed. 432 */ 433 static keystore_t 434 *new_keystore(void) 435 { 436 keystore_t *tmpstore; 437 438 if ((tmpstore = (keystore_t *)malloc(sizeof (keystore_t))) == NULL) { 439 return (NULL); 440 } 441 tmpstore->dirty = B_FALSE; 442 tmpstore->new = B_FALSE; 443 tmpstore->path = NULL; 444 tmpstore->passphrase = NULL; 445 tmpstore->cafd = -1; 446 tmpstore->cacerts = NULL; 447 tmpstore->capath = NULL; 448 tmpstore->clcerts = NULL; 449 tmpstore->clpath = NULL; 450 tmpstore->pkeys = NULL; 451 tmpstore->keypath = NULL; 452 453 return (tmpstore); 454 } 455 456 /* 457 * free_keystore - Deallocates a Keystore object 458 * 459 * Arguments: 460 * keystore - The keystore to deallocate 461 * 462 * Returns: 463 * NONE 464 */ 465 static void 466 free_keystore(keystore_t *keystore) 467 { 468 if (keystore->path != NULL) 469 free(keystore->path); 470 if (keystore->capath != NULL) 471 free(keystore->capath); 472 if (keystore->passphrase != NULL) 473 free(keystore->passphrase); 474 if (keystore->clpath != NULL) 475 free(keystore->clpath); 476 if (keystore->keypath != NULL) 477 free(keystore->keypath); 478 479 if (keystore->pkeys != NULL) { 480 sk_EVP_PKEY_pop_free(keystore->pkeys, 481 sunw_evp_pkey_free); 482 } 483 if (keystore->clcerts != NULL) 484 sk_X509_free(keystore->clcerts); 485 if (keystore->cacerts != NULL) 486 sk_X509_free(keystore->cacerts); 487 free(keystore); 488 } 489 490 /* 491 * close_keystore - Writes keystore to disk if needed, then 492 * unlocks and closes keystore. 493 * 494 * Arguments: 495 * err - Error object to append errors to 496 * keystore - Keystore which should be closed 497 * passwd - Password used to encrypt keystore 498 * 499 * Returns: 500 * 0 - Success - keystore is committed to disk, and unlocked 501 * non-zero - Failure, errors added to err 502 */ 503 int 504 close_keystore(PKG_ERR *err, keystore_handle_t keystore_h, 505 keystore_passphrase_cb cb) 506 { 507 int ret = 0; 508 keystore_t *keystore = keystore_h; 509 510 if (keystore->dirty) { 511 /* write out the keystore first */ 512 if (!write_keystore(err, keystore, cb)) { 513 pkgerr_add(err, PKGERR_WRITE, 514 gettext(ERR_KEYSTORE_WRITE), 515 keystore->path); 516 ret = 1; 517 goto cleanup; 518 } 519 } 520 521 if (!unlock_keystore(err, keystore)) { 522 pkgerr_add(err, PKGERR_UNLOCK, gettext(ERR_KEYSTORE_UNLOCK), 523 keystore->path); 524 ret = 1; 525 goto cleanup; 526 } 527 528 free_keystore(keystore); 529 cleanup: 530 return (ret); 531 } 532 533 /* 534 * merge_ca_cert - Adds a trusted certificate (trust anchor) to a keystore. 535 * certificate checked for validity dates and non-duplicity. 536 * 537 * Arguments: 538 * err - Error object to add errors to 539 * cacert - Certificate which to merge into keystore 540 * keystore - The keystore into which the certificate is merged 541 * 542 * Returns: 543 * 0 - Success - Certificate passes validity, and 544 * is merged into keystore 545 * non-zero - Failure, errors recorded in err 546 */ 547 int 548 merge_ca_cert(PKG_ERR *err, X509 *cacert, keystore_handle_t keystore_h) 549 { 550 551 int ret = 0; 552 X509 *existing = NULL; 553 char *fname; 554 keystore_t *keystore = keystore_h; 555 556 /* check validity dates */ 557 if (check_cert(err, cacert) != 0) { 558 ret = 1; 559 goto cleanup; 560 } 561 562 /* create the certificate's friendlyName */ 563 fname = get_subject_display_name(cacert); 564 565 if (sunw_set_fname(fname, NULL, cacert) != 0) { 566 pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM)); 567 ret = 1; 568 goto cleanup; 569 } 570 571 /* merge certificate into the keystore */ 572 if (keystore->cacerts == NULL) { 573 /* no existing truststore, so make a new one */ 574 if ((keystore->cacerts = sk_X509_new_null()) == NULL) { 575 pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM)); 576 ret = 1; 577 goto cleanup; 578 } 579 } else { 580 /* existing truststore, make sure there's no duplicate */ 581 if (sunw_find_fname(fname, NULL, keystore->cacerts, 582 NULL, &existing) < 0) { 583 pkgerr_add(err, PKGERR_INTERNAL, 584 gettext(ERR_KEYSTORE_INTERNAL), 585 __FILE__, __LINE__); 586 ERR_print_errors_fp(stderr); 587 ret = 1; 588 goto cleanup; 589 /* could not search properly! */ 590 } 591 if (existing != NULL) { 592 /* whoops, found one already */ 593 pkgerr_add(err, PKGERR_DUPLICATE, 594 gettext(ERR_KEYSTORE_DUPLICATECERT), fname); 595 ret = 1; 596 goto cleanup; 597 } 598 } 599 600 (void) sk_X509_push(keystore->cacerts, cacert); 601 keystore->dirty = B_TRUE; 602 cleanup: 603 if (existing != NULL) 604 X509_free(existing); 605 return (ret); 606 } 607 608 /* 609 * find_key_cert_pair - Searches a keystore for a matching 610 * public key certificate and private key, given an alias. 611 * 612 * Arguments: 613 * err - Error object to add errors to 614 * ks - Keystore to search 615 * alias - Name to used to match certificate's alias 616 * key - Resulting key is placed here 617 * cert - Resulting cert is placed here 618 * 619 * Returns: 620 * 0 - Success - Matching cert/key pair placed in key and cert. 621 * non-zero - Failure, errors recorded in err 622 */ 623 int 624 find_key_cert_pair(PKG_ERR *err, keystore_handle_t ks_h, char *alias, 625 EVP_PKEY **key, X509 **cert) 626 { 627 X509 *tmpcert = NULL; 628 EVP_PKEY *tmpkey = NULL; 629 int ret = 0; 630 int items_found; 631 keystore_t *ks = ks_h; 632 633 if (key == NULL || cert == NULL) { 634 pkgerr_add(err, PKGERR_NOPUBKEY, 635 gettext(ERR_KEYSTORE_NOPUBCERTS), ks->path); 636 ret = 1; 637 goto cleanup; 638 } 639 640 if (ks->clcerts == NULL) { 641 /* no public certs */ 642 pkgerr_add(err, PKGERR_NOPUBKEY, 643 gettext(ERR_KEYSTORE_NOCERTS), ks->path); 644 ret = 1; 645 goto cleanup; 646 } 647 if (ks->pkeys == NULL) { 648 /* no private keys */ 649 pkgerr_add(err, PKGERR_NOPRIVKEY, 650 gettext(ERR_KEYSTORE_NOKEYS), ks->path); 651 ret = 1; 652 goto cleanup; 653 } 654 655 /* try the easy case first */ 656 if ((sk_EVP_PKEY_num(ks->pkeys) == 1) && 657 (sk_X509_num(ks->clcerts) == 1)) { 658 tmpkey = sk_EVP_PKEY_value(ks->pkeys, 0); 659 tmpcert = sk_X509_value(ks->clcerts, 0); 660 if (sunw_check_keys(tmpcert, tmpkey)) { 661 /* 662 * only one private key and public key cert, and they 663 * match, so use them 664 */ 665 *key = tmpkey; 666 tmpkey = NULL; 667 *cert = tmpcert; 668 tmpcert = NULL; 669 goto cleanup; 670 } 671 } 672 673 /* Attempt to find the right pair given the alias */ 674 items_found = sunw_find_fname(alias, ks->pkeys, ks->clcerts, 675 &tmpkey, &tmpcert); 676 677 if ((items_found < 0) || 678 (items_found & (FOUND_PKEY | FOUND_CERT)) == 0) { 679 /* no key/cert pair found. bail. */ 680 pkgerr_add(err, PKGERR_BADALIAS, 681 gettext(ERR_KEYSTORE_NOMATCH), alias); 682 ret = 1; 683 goto cleanup; 684 } 685 686 /* success */ 687 *key = tmpkey; 688 tmpkey = NULL; 689 *cert = tmpcert; 690 tmpcert = NULL; 691 692 cleanup: 693 694 if (tmpcert != NULL) 695 (void) X509_free(tmpcert); 696 697 if (tmpkey != NULL) 698 sunw_evp_pkey_free(tmpkey); 699 700 return (ret); 701 } 702 703 /* 704 * find_ca_certs - Searches a keystore for trusted certificates 705 * 706 * Arguments: 707 * err - Error object to add errors to 708 * ks - Keystore to search 709 * cacerts - resulting set of trusted certs are placed here 710 * 711 * Returns: 712 * 0 - Success - trusted cert list returned in cacerts 713 * non-zero - Failure, errors recorded in err 714 */ 715 int 716 find_ca_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **cacerts) 717 { 718 719 keystore_t *ks = ks_h; 720 721 /* easy */ 722 if (cacerts == NULL) { 723 pkgerr_add(err, PKGERR_INTERNAL, 724 gettext(ERR_KEYSTORE_INTERNAL), __FILE__, __LINE__); 725 return (1); 726 } 727 728 *cacerts = ks->cacerts; 729 return (0); 730 } 731 732 /* 733 * find_cl_certs - Searches a keystore for user certificates 734 * 735 * Arguments: 736 * err - Error object to add errors to 737 * ks - Keystore to search 738 * cacerts - resulting set of user certs are placed here 739 * 740 * No matching of any kind is performed. 741 * Returns: 742 * 0 - Success - trusted cert list returned in cacerts 743 * non-zero - Failure, errors recorded in err 744 */ 745 /* ARGSUSED */ 746 int 747 find_cl_certs(PKG_ERR *err, keystore_handle_t ks_h, STACK_OF(X509) **clcerts) 748 { 749 keystore_t *ks = ks_h; 750 751 /* easy */ 752 *clcerts = ks->clcerts; 753 return (0); 754 } 755 756 757 /* 758 * merge_cert_and_key - Adds a user certificate and matching 759 * private key to a keystore. 760 * certificate checked for validity dates and non-duplicity. 761 * 762 * Arguments: 763 * err - Error object to add errors to 764 * cert - Certificate which to merge into keystore 765 * key - matching private key to 'cert' 766 * alias - Name which to store the cert and key under 767 * keystore - The keystore into which the certificate is merged 768 * 769 * Returns: 770 * 0 - Success - Certificate passes validity, and 771 * is merged into keystore, along with key 772 * non-zero - Failure, errors recorded in err 773 */ 774 int 775 merge_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key, char *alias, 776 keystore_handle_t keystore_h) 777 { 778 X509 *existingcert = NULL; 779 EVP_PKEY *existingkey = NULL; 780 int ret = 0; 781 keystore_t *keystore = keystore_h; 782 783 /* check validity dates */ 784 if (check_cert(err, cert) != 0) { 785 ret = 1; 786 goto cleanup; 787 } 788 789 /* set the friendlyName of the key and cert to the supplied alias */ 790 if (sunw_set_fname(alias, key, cert) != 0) { 791 pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM)); 792 ret = 1; 793 goto cleanup; 794 } 795 796 /* merge certificate and key into the keystore */ 797 if (keystore->clcerts == NULL) { 798 /* no existing truststore, so make a new one */ 799 if ((keystore->clcerts = sk_X509_new_null()) == NULL) { 800 pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM)); 801 ret = 1; 802 goto cleanup; 803 } 804 } else { 805 /* existing certstore, make sure there's no duplicate */ 806 if (sunw_find_fname(alias, NULL, keystore->clcerts, 807 NULL, &existingcert) < 0) { 808 pkgerr_add(err, PKGERR_INTERNAL, 809 gettext(ERR_KEYSTORE_INTERNAL), 810 __FILE__, __LINE__); 811 ERR_print_errors_fp(stderr); 812 ret = 1; 813 goto cleanup; 814 /* could not search properly! */ 815 } 816 if (existingcert != NULL) { 817 /* whoops, found one already */ 818 pkgerr_add(err, PKGERR_DUPLICATE, 819 gettext(ERR_KEYSTORE_DUPLICATECERT), alias); 820 ret = 1; 821 goto cleanup; 822 } 823 } 824 825 if (keystore->pkeys == NULL) { 826 /* no existing keystore, so make a new one */ 827 if ((keystore->pkeys = sk_EVP_PKEY_new_null()) == NULL) { 828 pkgerr_add(err, PKGERR_NOMEM, gettext(ERR_MEM)); 829 ret = 1; 830 goto cleanup; 831 } 832 } else { 833 /* existing keystore, so make sure there's no duplicate entry */ 834 if (sunw_find_fname(alias, keystore->pkeys, NULL, 835 &existingkey, NULL) < 0) { 836 pkgerr_add(err, PKGERR_INTERNAL, 837 gettext(ERR_KEYSTORE_INTERNAL), 838 __FILE__, __LINE__); 839 ERR_print_errors_fp(stderr); 840 ret = 1; 841 goto cleanup; 842 /* could not search properly! */ 843 } 844 if (existingkey != NULL) { 845 /* whoops, found one already */ 846 pkgerr_add(err, PKGERR_DUPLICATE, 847 gettext(ERR_KEYSTORE_DUPLICATEKEY), alias); 848 ret = 1; 849 goto cleanup; 850 } 851 } 852 853 (void) sk_X509_push(keystore->clcerts, cert); 854 (void) sk_EVP_PKEY_push(keystore->pkeys, key); 855 keystore->dirty = B_TRUE; 856 cleanup: 857 if (existingcert != NULL) 858 (void) X509_free(existingcert); 859 if (existingkey != NULL) 860 (void) sunw_evp_pkey_free(existingkey); 861 return (ret); 862 } 863 864 /* 865 * delete_cert_and_keys - Deletes one or more certificates 866 * and matching private keys from a keystore. 867 * 868 * Arguments: 869 * err - Error object to add errors to 870 * ks - The keystore from which certs and keys are deleted 871 * alias - Name which to search for certificates and keys 872 * to delete 873 * 874 * Returns: 875 * 0 - Success - All trusted certs which match 'alias' 876 * are deleted. All user certificates 877 * which match 'alias' are deleted, along 878 * with the matching private key. 879 * non-zero - Failure, errors recorded in err 880 */ 881 int 882 delete_cert_and_keys(PKG_ERR *err, keystore_handle_t ks_h, char *alias) 883 { 884 X509 *existingcert; 885 EVP_PKEY *existingkey; 886 int i; 887 char *fname = NULL; 888 boolean_t found = B_FALSE; 889 keystore_t *ks = ks_h; 890 891 /* delete any and all client certs with the supplied name */ 892 if (ks->clcerts != NULL) { 893 for (i = 0; i < sk_X509_num(ks->clcerts); i++) { 894 existingcert = sk_X509_value(ks->clcerts, i); 895 if (sunw_get_cert_fname(GETDO_COPY, 896 existingcert, &fname) >= 0) { 897 if (streq(fname, alias)) { 898 /* match, so nuke it */ 899 existingcert = 900 sk_X509_delete(ks->clcerts, i); 901 X509_free(existingcert); 902 existingcert = NULL; 903 found = B_TRUE; 904 } 905 (void) OPENSSL_free(fname); 906 fname = NULL; 907 } 908 } 909 if (sk_X509_num(ks->clcerts) <= 0) { 910 /* we deleted all the client certs */ 911 sk_X509_free(ks->clcerts); 912 ks->clcerts = NULL; 913 } 914 } 915 916 /* and now the private keys */ 917 if (ks->pkeys != NULL) { 918 for (i = 0; i < sk_EVP_PKEY_num(ks->pkeys); i++) { 919 existingkey = sk_EVP_PKEY_value(ks->pkeys, i); 920 if (sunw_get_pkey_fname(GETDO_COPY, 921 existingkey, &fname) >= 0) { 922 if (streq(fname, alias)) { 923 /* match, so nuke it */ 924 existingkey = 925 sk_EVP_PKEY_delete(ks->pkeys, i); 926 sunw_evp_pkey_free(existingkey); 927 existingkey = NULL; 928 found = B_TRUE; 929 } 930 (void) OPENSSL_free(fname); 931 fname = NULL; 932 } 933 } 934 if (sk_EVP_PKEY_num(ks->pkeys) <= 0) { 935 /* we deleted all the private keys */ 936 sk_EVP_PKEY_free(ks->pkeys); 937 ks->pkeys = NULL; 938 } 939 } 940 941 /* finally, remove any trust anchors that match */ 942 943 if (ks->cacerts != NULL) { 944 for (i = 0; i < sk_X509_num(ks->cacerts); i++) { 945 existingcert = sk_X509_value(ks->cacerts, i); 946 if (sunw_get_cert_fname(GETDO_COPY, 947 existingcert, &fname) >= 0) { 948 if (streq(fname, alias)) { 949 /* match, so nuke it */ 950 existingcert = 951 sk_X509_delete(ks->cacerts, i); 952 X509_free(existingcert); 953 existingcert = NULL; 954 found = B_TRUE; 955 } 956 (void) OPENSSL_free(fname); 957 fname = NULL; 958 } 959 } 960 if (sk_X509_num(ks->cacerts) <= 0) { 961 /* we deleted all the CA certs */ 962 sk_X509_free(ks->cacerts); 963 ks->cacerts = NULL; 964 } 965 } 966 967 if (found) { 968 ks->dirty = B_TRUE; 969 return (0); 970 } else { 971 /* no certs or keys deleted */ 972 pkgerr_add(err, PKGERR_NOALIASMATCH, 973 gettext(ERR_KEYSTORE_NOCERTKEY), 974 alias, ks->path); 975 return (1); 976 } 977 } 978 979 /* 980 * check_cert - Checks certificate validity. This routine 981 * checks that the current time falls within the period 982 * of validity for the cert. 983 * 984 * Arguments: 985 * err - Error object to add errors to 986 * cert - The certificate to check 987 * 988 * Returns: 989 * 0 - Success - Certificate checks out 990 * non-zero - Failure, errors and reasons recorded in err 991 */ 992 int 993 check_cert(PKG_ERR *err, X509 *cert) 994 { 995 char currtimestr[ATTR_MAX]; 996 time_t currtime; 997 char *r, *before_str, *after_str; 998 /* get current time */ 999 if ((currtime = time(NULL)) == (time_t)-1) { 1000 pkgerr_add(err, PKGERR_TIME, gettext(ERR_CURR_TIME)); 1001 return (1); 1002 } 1003 1004 (void) strlcpy(currtimestr, ctime(&currtime), ATTR_MAX); 1005 1006 /* trim whitespace from end of time string */ 1007 for (r = (currtimestr + strlen(currtimestr) - 1); isspace(*r); r--) { 1008 *r = '\0'; 1009 } 1010 /* check validity of cert */ 1011 switch (sunw_check_cert_times(CHK_BOTH, cert)) { 1012 case CHKERR_TIME_OK: 1013 /* Current time meets requested checks */ 1014 break; 1015 case CHKERR_TIME_BEFORE_BAD: 1016 /* 'not before' field is invalid */ 1017 case CHKERR_TIME_AFTER_BAD: 1018 /* 'not after' field is invalid */ 1019 pkgerr_add(err, PKGERR_TIME, gettext(ERR_CERT_TIME_BAD)); 1020 return (1); 1021 case CHKERR_TIME_IS_BEFORE: 1022 /* Current time is before 'not before' */ 1023 case CHKERR_TIME_HAS_EXPIRED: 1024 /* 1025 * Ignore expiration time since the trust cert used to 1026 * verify the certs used to sign Sun patches is already 1027 * expired. Once the patches get resigned with the new 1028 * cert we will check expiration against the time the 1029 * patch was signed and not the time it is installed. 1030 */ 1031 return (0); 1032 default: 1033 pkgerr_add(err, PKGERR_INTERNAL, 1034 gettext(ERR_KEYSTORE_INTERNAL), 1035 __FILE__, __LINE__); 1036 return (1); 1037 } 1038 1039 /* all checks ok */ 1040 return (0); 1041 } 1042 1043 /* 1044 * check_cert - Checks certificate validity. This routine 1045 * checks everything that check_cert checks, and additionally 1046 * verifies that the private key and corresponding public 1047 * key are indeed a pair. 1048 * 1049 * Arguments: 1050 * err - Error object to add errors to 1051 * cert - The certificate to check 1052 * key - the key to check 1053 * Returns: 1054 * 0 - Success - Certificate checks out 1055 * non-zero - Failure, errors and reasons recorded in err 1056 */ 1057 int 1058 check_cert_and_key(PKG_ERR *err, X509 *cert, EVP_PKEY *key) 1059 { 1060 1061 /* check validity dates */ 1062 if (check_cert(err, cert) != 0) { 1063 return (1); 1064 } 1065 1066 /* check key pair match */ 1067 if (sunw_check_keys(cert, key) == 0) { 1068 pkgerr_add(err, PKGERR_VERIFY, gettext(ERR_MISMATCHED_KEYS), 1069 get_subject_display_name(cert)); 1070 return (1); 1071 } 1072 1073 /* all checks OK */ 1074 return (0); 1075 } 1076 1077 /* ------------------ private functions ---------------------- */ 1078 1079 /* 1080 * verify_keystore_integrity - Searches for the remnants 1081 * of a failed or aborted keystore modification, and 1082 * cleans up the files, retstores the keystore to a known 1083 * state. 1084 * 1085 * Arguments: 1086 * err - Error object to add errors to 1087 * keystore_file - Base directory or filename of keystore 1088 * app - Application making request 1089 * 1090 * Returns: 1091 * 0 - Success - Keystore is restored, or untouched in the 1092 * case that cleanup was unnecessary 1093 * non-zero - Failure, errors and reasons recorded in err 1094 */ 1095 static boolean_t 1096 verify_keystore_integrity(PKG_ERR *err, keystore_t *keystore) 1097 { 1098 if (keystore->capath != NULL) { 1099 if (!restore_keystore_file(err, keystore->capath)) { 1100 return (B_FALSE); 1101 } 1102 } 1103 if (keystore->clpath != NULL) { 1104 if (!restore_keystore_file(err, keystore->clpath)) { 1105 return (B_FALSE); 1106 } 1107 } 1108 if (keystore->keypath != NULL) { 1109 if (!restore_keystore_file(err, keystore->keypath)) { 1110 return (B_FALSE); 1111 } 1112 } 1113 return (B_TRUE); 1114 } 1115 1116 /* 1117 * restore_keystore_file - restores a keystore file to 1118 * a known state. 1119 * 1120 * Keystore files can possibly be corrupted by a variety 1121 * of error conditions during reading/writing. This 1122 * routine, along with write_keystore_file, tries to 1123 * maintain keystore integrity by writing the files 1124 * out in a particular order, minimizing the time period 1125 * that the keystore is in an indeterminate state. 1126 * 1127 * With the current implementation, there are some failures 1128 * that are wholly unrecoverable, such as disk corruption. 1129 * These routines attempt to minimize the risk, but not 1130 * eliminate it. When better, atomic operations are available 1131 * (such as a trued atabase with commit, rollback, and 1132 * guaranteed atomicity), this implementation should use that. 1133 * 1134 * Arguments: 1135 * err - Error object to add errors to 1136 * keystore_file - keystore file path to restore. 1137 * 1138 * Returns: 1139 * 0 - Success - Keystore file is restored, or untouched in the 1140 * case that cleanup was unnecessary 1141 * non-zero - Failure, errors and reasons recorded in err 1142 */ 1143 /* ARGSUSED */ 1144 static boolean_t 1145 restore_keystore_file(PKG_ERR *err, char *keystore_file) 1146 { 1147 char newpath[MAXPATHLEN]; 1148 char backuppath[MAXPATHLEN]; 1149 int newfd; 1150 struct stat buf; 1151 int len; 1152 1153 if (((len = snprintf(newpath, MAXPATHLEN, "%s.new", 1154 keystore_file)) < 0) || 1155 (len >= ATTR_MAX)) { 1156 pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file); 1157 return (B_FALSE); 1158 } 1159 1160 if (((len = snprintf(backuppath, MAXPATHLEN, "%s.bak", 1161 keystore_file)) < 0) || 1162 (len >= ATTR_MAX)) { 1163 pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), keystore_file); 1164 return (B_FALSE); 1165 } 1166 1167 if ((newfd = open(newpath, O_RDWR|O_NONBLOCK, 0)) != -1) { 1168 if (fstat(newfd, &buf) != -1) { 1169 if (S_ISREG(buf.st_mode)) { 1170 /* 1171 * restore the file, waiting on it 1172 * to be free for locking, or for 1173 * it to disappear 1174 */ 1175 if (!wait_restore(newfd, keystore_file, 1176 newpath, backuppath)) { 1177 pkgerr_add(err, PKGERR_WRITE, 1178 gettext(ERR_WRITE), 1179 newpath, strerror(errno)); 1180 (void) close(newfd); 1181 return (B_FALSE); 1182 } else { 1183 return (B_TRUE); 1184 } 1185 } else { 1186 /* "new" file is not a regular file */ 1187 pkgerr_add(err, PKGERR_WRITE, 1188 gettext(ERR_NOT_REG), newpath); 1189 (void) close(newfd); 1190 return (B_FALSE); 1191 } 1192 } else { 1193 /* couldn't stat "new" file */ 1194 pkgerr_add(err, PKGERR_WRITE, 1195 gettext(ERR_WRITE), newpath, 1196 strerror(errno)); 1197 (void) close(newfd); 1198 return (B_FALSE); 1199 } 1200 } else { 1201 /* "new" file doesn't exist */ 1202 return (B_TRUE); 1203 } 1204 } 1205 1206 static boolean_t 1207 wait_restore(int newfd, char *keystore_file, 1208 char *origpath, char *backuppath) 1209 { 1210 struct stat buf; 1211 FILE *newstream; 1212 PKCS12 *p12; 1213 1214 (void) alarm(LOCK_TIMEOUT); 1215 if (file_lock(newfd, F_WRLCK, 1) == -1) { 1216 /* could not lock file */ 1217 (void) alarm(0); 1218 return (B_FALSE); 1219 } 1220 (void) alarm(0); 1221 1222 if (fstat(newfd, &buf) != -1) { 1223 if (S_ISREG(buf.st_mode)) { 1224 /* 1225 * The new file still 1226 * exists, with no 1227 * owner. It must be 1228 * the result of an 1229 * aborted update. 1230 */ 1231 newstream = fdopen(newfd, "r"); 1232 if ((p12 = 1233 d2i_PKCS12_fp(newstream, 1234 NULL)) != NULL) { 1235 /* 1236 * The file 1237 * appears 1238 * complete. 1239 * Replace the 1240 * exsisting 1241 * keystore 1242 * file with 1243 * this one 1244 */ 1245 (void) rename(keystore_file, backuppath); 1246 (void) rename(origpath, keystore_file); 1247 PKCS12_free(p12); 1248 } else { 1249 /* The file is not complete. Remove it */ 1250 (void) remove(origpath); 1251 } 1252 /* remove backup file */ 1253 (void) remove(backuppath); 1254 (void) fclose(newstream); 1255 (void) close(newfd); 1256 return (B_TRUE); 1257 } else { 1258 /* 1259 * new file exists, but is not a 1260 * regular file 1261 */ 1262 (void) close(newfd); 1263 return (B_FALSE); 1264 } 1265 } else { 1266 /* 1267 * could not stat file. Unless 1268 * the reason was that the file 1269 * is now gone, this is an error 1270 */ 1271 if (errno != ENOENT) { 1272 (void) close(newfd); 1273 return (B_FALSE); 1274 } 1275 /* 1276 * otherwise, file is gone. The process 1277 * that held the lock must have 1278 * successfully cleaned up and 1279 * exited with a valid keystore 1280 * state 1281 */ 1282 (void) close(newfd); 1283 return (B_TRUE); 1284 } 1285 } 1286 1287 /* 1288 * resolve_paths - figure out if we are dealing with a single-file 1289 * or multi-file keystore 1290 * 1291 * The flags tell resolve_paths how to behave: 1292 * 1293 * KEYSTORE_PATH_SOFT 1294 * If the keystore file does not exist at <base>/<app> then 1295 * use <base> as the path to the keystore. This can be used, 1296 * for example, to access an app-specific keystore iff it 1297 * exists, otherwise revert back to an app-generic keystore. 1298 * 1299 * KEYSTORE_PATH_HARD 1300 * Always use the keystore located at <keystore_path>/<app>. 1301 * In read/write mode, if the files do not exist, then 1302 * they will be created. This is used to avoid falling 1303 * back to an app-generic keystore path when the app-specific 1304 * one does not exist. 1305 * 1306 * Arguments: 1307 * err - Error object to add errors to 1308 * keystore_file - base keystore file path to lock 1309 * app - Application making requests 1310 * flags - Control flags (see above description) 1311 * keystore - object which is being locked 1312 * 1313 * Returns: 1314 * B_TRUE - Success - Keystore file is locked, paths to 1315 * appropriate files placed in keystore. 1316 * B_FALSE - Failure, errors and reasons recorded in err 1317 */ 1318 static boolean_t 1319 resolve_paths(PKG_ERR *err, char *keystore_file, char *app, 1320 long flags, keystore_t *keystore) 1321 { 1322 char storepath[PATH_MAX]; 1323 struct stat buf; 1324 boolean_t multi = B_FALSE; 1325 int fd1, fd2, len; 1326 1327 /* 1328 * figure out whether we are dealing with a single-file keystore 1329 * or a multi-file keystore 1330 */ 1331 if (app != NULL) { 1332 if (((len = snprintf(storepath, PATH_MAX, "%s/%s", 1333 keystore_file, app)) < 0) || 1334 (len >= ATTR_MAX)) { 1335 pkgerr_add(err, PKGERR_WEB, gettext(ERR_LEN), 1336 keystore_file); 1337 return (B_FALSE); 1338 } 1339 1340 if (((fd1 = open(storepath, O_NONBLOCK|O_RDONLY)) == -1) || 1341 (fstat(fd1, &buf) == -1) || 1342 !S_ISDIR(buf.st_mode)) { 1343 /* 1344 * app-specific does not exist 1345 * fallback to app-generic, if flags say we can 1346 */ 1347 if ((flags & KEYSTORE_PATH_MASK) == 1348 KEYSTORE_PATH_SOFT) { 1349 1350 if (((fd2 = open(keystore_file, 1351 O_NONBLOCK|O_RDONLY)) != -1) && 1352 (fstat(fd2, &buf) != -1)) { 1353 if (S_ISDIR(buf.st_mode)) { 1354 /* 1355 * app-generic dir 1356 * exists, so use it 1357 * as a multi-file 1358 * keystore 1359 */ 1360 multi = B_TRUE; 1361 app = NULL; 1362 } else if (S_ISREG(buf.st_mode)) { 1363 /* 1364 * app-generic file exists, so 1365 * use it as a single file ks 1366 */ 1367 multi = B_FALSE; 1368 app = NULL; 1369 } 1370 } 1371 } 1372 } 1373 if (fd1 != -1) 1374 (void) close(fd1); 1375 if (fd2 != -1) 1376 (void) close(fd2); 1377 } else { 1378 if (((fd1 = open(keystore_file, 1379 O_NONBLOCK|O_RDONLY)) != -1) && 1380 (fstat(fd1, &buf) != -1) && 1381 S_ISDIR(buf.st_mode)) { 1382 /* 1383 * app-generic dir exists, so use 1384 * it as a multi-file keystore 1385 */ 1386 multi = B_TRUE; 1387 } 1388 if (fd1 != -1) 1389 (void) close(fd1); 1390 } 1391 1392 if (app != NULL) { 1393 /* app-specific keystore */ 1394 (void) snprintf(storepath, PATH_MAX, "%s/%s/%s", 1395 keystore_file, app, TRUSTSTORE); 1396 keystore->capath = xstrdup(storepath); 1397 (void) snprintf(storepath, PATH_MAX, "%s/%s/%s", 1398 keystore_file, app, CERTSTORE); 1399 keystore->clpath = xstrdup(storepath); 1400 (void) snprintf(storepath, PATH_MAX, "%s/%s/%s", 1401 keystore_file, app, KEYSTORE); 1402 keystore->keypath = xstrdup(storepath); 1403 } else { 1404 /* app-generic keystore */ 1405 if (!multi) { 1406 /* single-file app-generic keystore */ 1407 keystore->capath = xstrdup(keystore_file); 1408 keystore->keypath = NULL; 1409 keystore->clpath = NULL; 1410 } else { 1411 /* multi-file app-generic keystore */ 1412 (void) snprintf(storepath, PATH_MAX, "%s/%s", 1413 keystore_file, TRUSTSTORE); 1414 keystore->capath = xstrdup(storepath); 1415 (void) snprintf(storepath, PATH_MAX, "%s/%s", 1416 keystore_file, CERTSTORE); 1417 keystore->clpath = xstrdup(storepath); 1418 (void) snprintf(storepath, PATH_MAX, "%s/%s", 1419 keystore_file, KEYSTORE); 1420 keystore->keypath = xstrdup(storepath); 1421 } 1422 } 1423 1424 return (B_TRUE); 1425 } 1426 1427 /* 1428 * lock_keystore - Locks a keystore for shared (read-only) 1429 * or exclusive (read-write) access. 1430 * 1431 * The flags tell lock_keystore how to behave: 1432 * 1433 * KEYSTORE_ACCESS_READONLY 1434 * opens keystore read-only. Attempts to modify results in an error 1435 * 1436 * KEYSTORE_ACCESS_READWRITE 1437 * opens keystore read-write 1438 * 1439 * KEYSTORE_PATH_SOFT 1440 * If the keystore file does not exist at <base>/<app> then 1441 * use <base> as the path to the keystore. This can be used, 1442 * for example, to access an app-specific keystore iff it 1443 * exists, otherwise revert back to an app-generic keystore. 1444 * 1445 * KEYSTORE_PATH_HARD 1446 * Always use the keystore located at <keystore_path>/<app>. 1447 * In read/write mode, if the files do not exist, then 1448 * they will be created. This is used to avoid falling 1449 * back to an app-generic keystore path when the app-specific 1450 * one does not exist. 1451 * 1452 * Arguments: 1453 * err - Error object to add errors to 1454 * flags - Control flags (see above description) 1455 * keystore - object which is being locked 1456 * 1457 * Returns: 1458 * 0 - Success - Keystore file is locked, paths to 1459 * appropriate files placed in keystore. 1460 * non-zero - Failure, errors and reasons recorded in err 1461 */ 1462 static boolean_t 1463 lock_keystore(PKG_ERR *err, long flags, keystore_t *keystore) 1464 { 1465 boolean_t ret = B_TRUE; 1466 struct stat buf; 1467 1468 switch (flags & KEYSTORE_ACCESS_MASK) { 1469 case KEYSTORE_ACCESS_READONLY: 1470 if ((keystore->cafd = 1471 open(keystore->capath, O_NONBLOCK|O_RDONLY)) == -1) { 1472 if (errno == ENOENT) { 1473 /* 1474 * no keystore. try to create an 1475 * empty one so we can lock on it and 1476 * prevent others from gaining 1477 * exclusive access. It will be 1478 * deleted when the keystore is closed. 1479 */ 1480 if ((keystore->cafd = 1481 open(keystore->capath, 1482 O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL, 1483 S_IRUSR|S_IWUSR)) == -1) { 1484 pkgerr_add(err, PKGERR_READ, 1485 gettext(ERR_NO_KEYSTORE), 1486 keystore->capath); 1487 ret = B_FALSE; 1488 goto cleanup; 1489 } 1490 } else { 1491 pkgerr_add(err, PKGERR_READ, 1492 gettext(ERR_KEYSTORE_OPEN), 1493 keystore->capath, strerror(errno)); 1494 ret = B_FALSE; 1495 goto cleanup; 1496 } 1497 } 1498 if (fstat(keystore->cafd, &buf) != -1) { 1499 if (S_ISREG(buf.st_mode)) { 1500 if (file_lock(keystore->cafd, F_RDLCK, 1501 0) == -1) { 1502 pkgerr_add(err, PKGERR_LOCKED, 1503 gettext(ERR_KEYSTORE_LOCKED_READ), 1504 keystore->capath); 1505 ret = B_FALSE; 1506 goto cleanup; 1507 } 1508 } else { 1509 /* ca file not a regular file! */ 1510 pkgerr_add(err, PKGERR_READ, 1511 gettext(ERR_NOT_REG), 1512 keystore->capath); 1513 ret = B_FALSE; 1514 goto cleanup; 1515 } 1516 } else { 1517 pkgerr_add(err, PKGERR_READ, 1518 gettext(ERR_KEYSTORE_OPEN), 1519 keystore->capath, strerror(errno)); 1520 ret = B_FALSE; 1521 goto cleanup; 1522 } 1523 break; 1524 case KEYSTORE_ACCESS_READWRITE: 1525 1526 if ((keystore->cafd = open(keystore->capath, 1527 O_RDWR|O_NONBLOCK)) == -1) { 1528 /* does not exist. try to create an empty one */ 1529 if (errno == ENOENT) { 1530 if ((keystore->cafd = 1531 open(keystore->capath, 1532 O_NONBLOCK|O_RDWR|O_CREAT|O_EXCL, 1533 S_IRUSR|S_IWUSR)) == -1) { 1534 pkgerr_add(err, PKGERR_READ, 1535 gettext(ERR_KEYSTORE_WRITE), 1536 keystore->capath); 1537 ret = B_FALSE; 1538 goto cleanup; 1539 } 1540 } else { 1541 pkgerr_add(err, PKGERR_READ, 1542 gettext(ERR_KEYSTORE_OPEN), 1543 keystore->capath, strerror(errno)); 1544 ret = B_FALSE; 1545 goto cleanup; 1546 } 1547 } 1548 if (fstat(keystore->cafd, &buf) != -1) { 1549 if (S_ISREG(buf.st_mode)) { 1550 if (file_lock(keystore->cafd, F_WRLCK, 1551 0) == -1) { 1552 pkgerr_add(err, PKGERR_LOCKED, 1553 gettext(ERR_KEYSTORE_LOCKED), 1554 keystore->capath); 1555 ret = B_FALSE; 1556 goto cleanup; 1557 } 1558 } else { 1559 /* ca file not a regular file! */ 1560 pkgerr_add(err, PKGERR_READ, 1561 gettext(ERR_NOT_REG), 1562 keystore->capath); 1563 ret = B_FALSE; 1564 goto cleanup; 1565 } 1566 } else { 1567 pkgerr_add(err, PKGERR_READ, 1568 gettext(ERR_KEYSTORE_OPEN), 1569 keystore->capath, strerror(errno)); 1570 ret = B_FALSE; 1571 goto cleanup; 1572 } 1573 1574 break; 1575 default: 1576 pkgerr_add(err, PKGERR_INTERNAL, 1577 gettext(ERR_KEYSTORE_INTERNAL), 1578 __FILE__, __LINE__); 1579 ret = B_FALSE; 1580 goto cleanup; 1581 } 1582 1583 cleanup: 1584 if (!ret) { 1585 if (keystore->cafd > 0) { 1586 (void) file_unlock(keystore->cafd); 1587 (void) close(keystore->cafd); 1588 keystore->cafd = -1; 1589 } 1590 1591 if (keystore->capath != NULL) 1592 free(keystore->capath); 1593 if (keystore->clpath != NULL) 1594 free(keystore->clpath); 1595 if (keystore->keypath != NULL) 1596 free(keystore->keypath); 1597 keystore->capath = NULL; 1598 keystore->clpath = NULL; 1599 keystore->keypath = NULL; 1600 } 1601 1602 return (ret); 1603 } 1604 1605 /* 1606 * unlock_keystore - Unocks a keystore 1607 * 1608 * Arguments: 1609 * err - Error object to add errors to 1610 * keystore - keystore object to unlock 1611 * Returns: 1612 * 0 - Success - Keystore files are unlocked, files are closed, 1613 * non-zero - Failure, errors and reasons recorded in err 1614 */ 1615 /* ARGSUSED */ 1616 static boolean_t 1617 unlock_keystore(PKG_ERR *err, keystore_t *keystore) 1618 { 1619 1620 /* 1621 * Release lock on the CA file. 1622 * Delete file if it is empty 1623 */ 1624 if (file_empty(keystore->capath)) { 1625 (void) remove(keystore->capath); 1626 } 1627 1628 (void) file_unlock(keystore->cafd); 1629 (void) close(keystore->cafd); 1630 return (B_TRUE); 1631 } 1632 1633 /* 1634 * read_keystore - Reads keystore files of disk, parses 1635 * into internal structures. 1636 * 1637 * Arguments: 1638 * err - Error object to add errors to 1639 * keystore - keystore object to read into 1640 * cb - callback to get password, if required 1641 * Returns: 1642 * 0 - Success - Keystore files are read, and placed 1643 * into keystore structure. 1644 * non-zero - Failure, errors and reasons recorded in err 1645 */ 1646 static boolean_t 1647 read_keystore(PKG_ERR *err, keystore_t *keystore, keystore_passphrase_cb cb) 1648 { 1649 boolean_t ret = B_TRUE; 1650 PKCS12 *p12 = NULL; 1651 boolean_t ca_empty; 1652 boolean_t have_passwd = B_FALSE; 1653 boolean_t cl_empty = B_TRUE; 1654 boolean_t key_empty = B_TRUE; 1655 1656 ca_empty = file_empty(keystore->capath); 1657 1658 if (keystore->clpath != NULL) 1659 cl_empty = file_empty(keystore->clpath); 1660 if (keystore->keypath != NULL) 1661 key_empty = file_empty(keystore->keypath); 1662 1663 if (ca_empty && cl_empty && key_empty) { 1664 keystore->new = B_TRUE; 1665 } 1666 1667 if (!ca_empty) { 1668 /* first read the ca file */ 1669 if ((p12 = read_keystore_file(err, 1670 keystore->capath)) == NULL) { 1671 pkgerr_add(err, PKGERR_CORRUPT, 1672 gettext(ERR_KEYSTORE_CORRUPT), keystore->capath); 1673 ret = B_FALSE; 1674 goto cleanup; 1675 } 1676 1677 /* Get password, using callback if necessary */ 1678 if (!have_passwd) { 1679 if (!get_keystore_passwd(err, p12, cb, keystore)) { 1680 ret = B_FALSE; 1681 goto cleanup; 1682 } 1683 have_passwd = B_TRUE; 1684 } 1685 1686 /* decrypt and parse keystore file */ 1687 if (sunw_PKCS12_contents(p12, keystore->passphrase, 1688 &keystore->pkeys, &keystore->cacerts) < 0) { 1689 /* could not parse the contents */ 1690 pkgerr_add(err, PKGERR_CORRUPT, 1691 gettext(ERR_KEYSTORE_CORRUPT), keystore->capath); 1692 ret = B_FALSE; 1693 goto cleanup; 1694 } 1695 1696 PKCS12_free(p12); 1697 p12 = NULL; 1698 } else { 1699 1700 /* 1701 * truststore is empty, so we don't have any trusted 1702 * certs 1703 */ 1704 keystore->cacerts = NULL; 1705 } 1706 1707 /* 1708 * if there is no cl file or key file, use the cl's and key's found 1709 * in the ca file 1710 */ 1711 if (keystore->clpath == NULL && !ca_empty) { 1712 if (sunw_split_certs(keystore->pkeys, keystore->cacerts, 1713 &keystore->clcerts, NULL) < 0) { 1714 pkgerr_add(err, PKGERR_CORRUPT, 1715 gettext(ERR_KEYSTORE_CORRUPT), keystore->capath); 1716 ret = B_FALSE; 1717 goto cleanup; 1718 } 1719 } else { 1720 /* 1721 * files are in separate files. read keys out of the keystore 1722 * certs out of the certstore, if they are not empty 1723 */ 1724 if (!cl_empty) { 1725 if ((p12 = read_keystore_file(err, 1726 keystore->clpath)) == NULL) { 1727 pkgerr_add(err, PKGERR_CORRUPT, 1728 gettext(ERR_KEYSTORE_CORRUPT), 1729 keystore->clpath); 1730 ret = B_FALSE; 1731 goto cleanup; 1732 } 1733 1734 /* Get password, using callback if necessary */ 1735 if (!have_passwd) { 1736 if (!get_keystore_passwd(err, p12, cb, 1737 keystore)) { 1738 ret = B_FALSE; 1739 goto cleanup; 1740 } 1741 have_passwd = B_TRUE; 1742 } 1743 1744 if (check_password(p12, 1745 keystore->passphrase) == B_FALSE) { 1746 /* 1747 * password in client cert file 1748 * is different than 1749 * the one in the other files! 1750 */ 1751 pkgerr_add(err, PKGERR_BADPASS, 1752 gettext(ERR_MISMATCHPASS), 1753 keystore->clpath, 1754 keystore->capath, keystore->path); 1755 ret = B_FALSE; 1756 goto cleanup; 1757 } 1758 1759 if (sunw_PKCS12_contents(p12, keystore->passphrase, 1760 NULL, &keystore->clcerts) < 0) { 1761 /* could not parse the contents */ 1762 pkgerr_add(err, PKGERR_CORRUPT, 1763 gettext(ERR_KEYSTORE_CORRUPT), 1764 keystore->clpath); 1765 ret = B_FALSE; 1766 goto cleanup; 1767 } 1768 1769 PKCS12_free(p12); 1770 p12 = NULL; 1771 } else { 1772 keystore->clcerts = NULL; 1773 } 1774 1775 if (!key_empty) { 1776 if ((p12 = read_keystore_file(err, 1777 keystore->keypath)) == NULL) { 1778 pkgerr_add(err, PKGERR_CORRUPT, 1779 gettext(ERR_KEYSTORE_CORRUPT), 1780 keystore->keypath); 1781 ret = B_FALSE; 1782 goto cleanup; 1783 } 1784 1785 /* Get password, using callback if necessary */ 1786 if (!have_passwd) { 1787 if (!get_keystore_passwd(err, p12, cb, 1788 keystore)) { 1789 ret = B_FALSE; 1790 goto cleanup; 1791 } 1792 have_passwd = B_TRUE; 1793 } 1794 1795 if (check_password(p12, 1796 keystore->passphrase) == B_FALSE) { 1797 pkgerr_add(err, PKGERR_BADPASS, 1798 gettext(ERR_MISMATCHPASS), 1799 keystore->keypath, 1800 keystore->capath, keystore->path); 1801 ret = B_FALSE; 1802 goto cleanup; 1803 } 1804 1805 if (sunw_PKCS12_contents(p12, keystore->passphrase, 1806 &keystore->pkeys, NULL) < 0) { 1807 /* could not parse the contents */ 1808 pkgerr_add(err, PKGERR_CORRUPT, 1809 gettext(ERR_KEYSTORE_CORRUPT), 1810 keystore->keypath); 1811 ret = B_FALSE; 1812 goto cleanup; 1813 } 1814 1815 PKCS12_free(p12); 1816 p12 = NULL; 1817 } else { 1818 keystore->pkeys = NULL; 1819 } 1820 } 1821 1822 cleanup: 1823 if (p12 != NULL) 1824 PKCS12_free(p12); 1825 return (ret); 1826 } 1827 1828 /* 1829 * get_keystore_password - retrieves pasword used to 1830 * decrypt PKCS12 structure. 1831 * 1832 * Arguments: 1833 * err - Error object to add errors to 1834 * p12 - PKCS12 structure which returned password should 1835 * decrypt 1836 * cb - callback to collect password. 1837 * keystore - The keystore in which the PKCS12 structure 1838 * will eventually populate. 1839 * Returns: 1840 * B_TRUE - success. 1841 * keystore password is set in keystore->passphrase. 1842 * B_FALSE - failure, errors logged 1843 */ 1844 static boolean_t 1845 get_keystore_passwd(PKG_ERR *err, PKCS12 *p12, keystore_passphrase_cb cb, 1846 keystore_t *keystore) 1847 { 1848 char *passwd; 1849 char passbuf[KEYSTORE_PASS_MAX + 1]; 1850 keystore_passphrase_data data; 1851 1852 /* see if no password is the right password */ 1853 if (check_password(p12, "") == B_TRUE) { 1854 passwd = ""; 1855 } else if (check_password(p12, NULL) == B_TRUE) { 1856 passwd = NULL; 1857 } else { 1858 /* oops, it's encrypted. get password */ 1859 data.err = err; 1860 if (cb(passbuf, KEYSTORE_PASS_MAX, 0, 1861 &data) == -1) { 1862 /* could not get password */ 1863 return (B_FALSE); 1864 } 1865 1866 if (check_password(p12, passbuf) == B_FALSE) { 1867 /* wrong password */ 1868 pkgerr_add(err, PKGERR_BADPASS, 1869 gettext(ERR_BADPASS)); 1870 return (B_FALSE); 1871 } 1872 1873 /* 1874 * make copy of password buffer, since it 1875 * goes away upon return 1876 */ 1877 passwd = xstrdup(passbuf); 1878 } 1879 keystore->passphrase = passwd; 1880 return (B_TRUE); 1881 } 1882 1883 /* 1884 * write_keystore - Writes keystore files to disk 1885 * 1886 * Arguments: 1887 * err - Error object to add errors to 1888 * keystore - keystore object to write from 1889 * passwd - password used to encrypt keystore 1890 * Returns: 1891 * 0 - Success - Keystore contents are written out to 1892 * the same locations as read from 1893 * non-zero - Failure, errors and reasons recorded in err 1894 */ 1895 static boolean_t 1896 write_keystore(PKG_ERR *err, keystore_t *keystore, 1897 keystore_passphrase_cb cb) 1898 { 1899 PKCS12 *p12 = NULL; 1900 boolean_t ret = B_TRUE; 1901 keystore_passphrase_data data; 1902 char passbuf[KEYSTORE_PASS_MAX + 1]; 1903 1904 if (keystore->capath != NULL && keystore->clpath == NULL && 1905 keystore->keypath == NULL) { 1906 1907 /* 1908 * keystore is a file. 1909 * just write out a single file 1910 */ 1911 if ((keystore->pkeys == NULL) && 1912 (keystore->clcerts == NULL) && 1913 (keystore->cacerts == NULL)) { 1914 if (!clear_keystore_file(err, keystore->capath)) { 1915 /* 1916 * no keys or certs to write out, so 1917 * blank the ca file. we do not 1918 * delete it since it is used as a 1919 * lock by lock_keystore() in 1920 * subsequent invocations 1921 */ 1922 pkgerr_add(err, PKGERR_WRITE, 1923 gettext(ERR_KEYSTORE_WRITE), 1924 keystore->capath); 1925 ret = B_FALSE; 1926 goto cleanup; 1927 } 1928 } else { 1929 /* 1930 * if the keystore is being created for the first time, 1931 * prompt for a passphrase for encryption 1932 */ 1933 if (keystore->new) { 1934 data.err = err; 1935 if (cb(passbuf, KEYSTORE_PASS_MAX, 1936 1, &data) == -1) { 1937 ret = B_FALSE; 1938 goto cleanup; 1939 } 1940 } else { 1941 /* 1942 * use the one used when the keystore 1943 * was read 1944 */ 1945 strlcpy(passbuf, keystore->passphrase, 1946 KEYSTORE_PASS_MAX); 1947 } 1948 1949 p12 = sunw_PKCS12_create(passbuf, keystore->pkeys, 1950 keystore->clcerts, keystore->cacerts); 1951 1952 if (p12 == NULL) { 1953 pkgerr_add(err, PKGERR_WRITE, 1954 gettext(ERR_KEYSTORE_FORM), 1955 keystore->capath); 1956 ret = B_FALSE; 1957 goto cleanup; 1958 } 1959 1960 if (!write_keystore_file(err, keystore->capath, p12)) { 1961 pkgerr_add(err, PKGERR_WRITE, 1962 gettext(ERR_KEYSTORE_WRITE), 1963 keystore->capath); 1964 ret = B_FALSE; 1965 goto cleanup; 1966 } 1967 } 1968 1969 } else { 1970 /* files are seprate. Do one at a time */ 1971 1972 /* 1973 * if the keystore is being created for the first time, 1974 * prompt for a passphrase for encryption 1975 */ 1976 if (keystore->new && ((keystore->pkeys != NULL) || 1977 (keystore->clcerts != NULL) || 1978 (keystore->cacerts != NULL))) { 1979 data.err = err; 1980 if (cb(passbuf, KEYSTORE_PASS_MAX, 1981 1, &data) == -1) { 1982 ret = B_FALSE; 1983 goto cleanup; 1984 } 1985 } else { 1986 /* use the one used when the keystore was read */ 1987 strlcpy(passbuf, keystore->passphrase, 1988 KEYSTORE_PASS_MAX); 1989 } 1990 1991 /* do private keys first */ 1992 if (keystore->pkeys != NULL) { 1993 p12 = sunw_PKCS12_create(passbuf, keystore->pkeys, 1994 NULL, NULL); 1995 1996 if (p12 == NULL) { 1997 pkgerr_add(err, PKGERR_WRITE, 1998 gettext(ERR_KEYSTORE_FORM), 1999 keystore->keypath); 2000 ret = B_FALSE; 2001 goto cleanup; 2002 } 2003 2004 if (!write_keystore_file(err, keystore->keypath, 2005 p12)) { 2006 pkgerr_add(err, PKGERR_WRITE, 2007 gettext(ERR_KEYSTORE_WRITE), 2008 keystore->keypath); 2009 ret = B_FALSE; 2010 goto cleanup; 2011 } 2012 2013 PKCS12_free(p12); 2014 } else { 2015 if ((remove(keystore->keypath) != 0) && 2016 (errno != ENOENT)) { 2017 pkgerr_add(err, PKGERR_WRITE, 2018 gettext(ERR_KEYSTORE_REMOVE), 2019 keystore->keypath); 2020 ret = B_FALSE; 2021 goto cleanup; 2022 } 2023 } 2024 2025 /* do user certs next */ 2026 if (keystore->clcerts != NULL) { 2027 p12 = sunw_PKCS12_create(passbuf, NULL, 2028 keystore->clcerts, NULL); 2029 2030 if (p12 == NULL) { 2031 pkgerr_add(err, PKGERR_WRITE, 2032 gettext(ERR_KEYSTORE_FORM), 2033 keystore->clpath); 2034 ret = B_FALSE; 2035 goto cleanup; 2036 } 2037 2038 if (!write_keystore_file(err, keystore->clpath, p12)) { 2039 pkgerr_add(err, PKGERR_WRITE, 2040 gettext(ERR_KEYSTORE_WRITE), 2041 keystore->clpath); 2042 ret = B_FALSE; 2043 goto cleanup; 2044 } 2045 2046 PKCS12_free(p12); 2047 } else { 2048 if ((remove(keystore->clpath) != 0) && 2049 (errno != ENOENT)) { 2050 pkgerr_add(err, PKGERR_WRITE, 2051 gettext(ERR_KEYSTORE_REMOVE), 2052 keystore->clpath); 2053 ret = B_FALSE; 2054 goto cleanup; 2055 } 2056 } 2057 2058 2059 /* finally do CA cert file */ 2060 if (keystore->cacerts != NULL) { 2061 p12 = sunw_PKCS12_create(passbuf, NULL, 2062 NULL, keystore->cacerts); 2063 2064 if (p12 == NULL) { 2065 pkgerr_add(err, PKGERR_WRITE, 2066 gettext(ERR_KEYSTORE_FORM), 2067 keystore->capath); 2068 ret = B_FALSE; 2069 goto cleanup; 2070 } 2071 2072 if (!write_keystore_file(err, keystore->capath, p12)) { 2073 pkgerr_add(err, PKGERR_WRITE, 2074 gettext(ERR_KEYSTORE_WRITE), 2075 keystore->capath); 2076 ret = B_FALSE; 2077 goto cleanup; 2078 } 2079 2080 PKCS12_free(p12); 2081 p12 = NULL; 2082 } else { 2083 /* 2084 * nothing to write out, so truncate the file 2085 * (it will be deleted during close_keystore) 2086 */ 2087 if (!clear_keystore_file(err, keystore->capath)) { 2088 pkgerr_add(err, PKGERR_WRITE, 2089 gettext(ERR_KEYSTORE_WRITE), 2090 keystore->capath); 2091 ret = B_FALSE; 2092 goto cleanup; 2093 } 2094 } 2095 } 2096 2097 cleanup: 2098 if (p12 != NULL) 2099 PKCS12_free(p12); 2100 2101 return (ret); 2102 } 2103 2104 /* 2105 * clear_keystore_file - Clears (zeros out) a keystore file. 2106 * 2107 * Arguments: 2108 * err - Error object to add errors to 2109 * dest - Path of keystore file to zero out. 2110 * Returns: 2111 * 0 - Success - Keystore file is truncated to zero length 2112 * non-zero - Failure, errors and reasons recorded in err 2113 */ 2114 static boolean_t 2115 clear_keystore_file(PKG_ERR *err, char *dest) 2116 { 2117 int fd; 2118 struct stat buf; 2119 2120 fd = open(dest, O_RDWR|O_NONBLOCK); 2121 if (fd == -1) { 2122 /* can't open for writing */ 2123 pkgerr_add(err, PKGERR_WRITE, gettext(MSG_OPEN), 2124 errno); 2125 return (B_FALSE); 2126 } 2127 2128 if ((fstat(fd, &buf) == -1) || !S_ISREG(buf.st_mode)) { 2129 /* not a regular file */ 2130 (void) close(fd); 2131 pkgerr_add(err, PKGERR_WRITE, gettext(ERR_NOT_REG), 2132 dest); 2133 return (B_FALSE); 2134 } 2135 2136 if (ftruncate(fd, 0) == -1) { 2137 (void) close(fd); 2138 pkgerr_add(err, PKGERR_WRITE, gettext(ERR_WRITE), 2139 dest, strerror(errno)); 2140 return (B_FALSE); 2141 } 2142 2143 (void) close(fd); 2144 return (B_TRUE); 2145 } 2146 2147 /* 2148 * write_keystore_file - Writes keystore file to disk. 2149 * 2150 * Keystore files can possibly be corrupted by a variety 2151 * of error conditions during reading/writing. This 2152 * routine, along with restore_keystore_file, tries to 2153 * maintain keystore integity by writing the files 2154 * out in a particular order, minimizing the time period 2155 * that the keystore is in an indeterminate state. 2156 * 2157 * With the current implementation, there are some failures 2158 * that are wholly unrecoverable, such as disk corruption. 2159 * These routines attempt to minimize the risk, but not 2160 * eliminate it. When better, atomic operations are available 2161 * (such as a true database with commit, rollback, and 2162 * guaranteed atomicity), this implementation should use that. 2163 * 2164 * 2165 * Arguments: 2166 * err - Error object to add errors to 2167 * dest - Destination filename 2168 * contents - Contents to write to the file 2169 * Returns: 2170 * 0 - Success - Keystore contents are written out to 2171 * the destination. 2172 * non-zero - Failure, errors and reasons recorded in err 2173 */ 2174 static boolean_t 2175 write_keystore_file(PKG_ERR *err, char *dest, PKCS12 *contents) 2176 { 2177 FILE *newfile = NULL; 2178 boolean_t ret = B_TRUE; 2179 char newpath[MAXPATHLEN]; 2180 char backuppath[MAXPATHLEN]; 2181 struct stat buf; 2182 int fd; 2183 2184 (void) snprintf(newpath, MAXPATHLEN, "%s.new", dest); 2185 (void) snprintf(backuppath, MAXPATHLEN, "%s.bak", dest); 2186 2187 if ((fd = open(newpath, O_CREAT|O_EXCL|O_WRONLY|O_NONBLOCK, 2188 S_IRUSR|S_IWUSR)) == -1) { 2189 pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN), 2190 newpath, strerror(errno)); 2191 ret = B_FALSE; 2192 goto cleanup; 2193 } 2194 2195 if (fstat(fd, &buf) == -1) { 2196 pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN), 2197 newpath, strerror(errno)); 2198 ret = B_FALSE; 2199 goto cleanup; 2200 } 2201 2202 if (!S_ISREG(buf.st_mode)) { 2203 pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG), 2204 newpath); 2205 ret = B_FALSE; 2206 goto cleanup; 2207 } 2208 2209 if ((newfile = fdopen(fd, "w")) == NULL) { 2210 pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN), 2211 newpath, strerror(errno)); 2212 ret = B_FALSE; 2213 goto cleanup; 2214 } 2215 2216 if (i2d_PKCS12_fp(newfile, contents) == 0) { 2217 pkgerr_add(err, PKGERR_WRITE, gettext(ERR_KEYSTORE_WRITE), 2218 newpath); 2219 ret = B_FALSE; 2220 goto cleanup; 2221 } 2222 2223 /* flush, then close */ 2224 (void) fflush(newfile); 2225 (void) fclose(newfile); 2226 newfile = NULL; 2227 2228 /* now back up the original file */ 2229 (void) rename(dest, backuppath); 2230 2231 /* put new one in its place */ 2232 (void) rename(newpath, dest); 2233 2234 /* remove backup */ 2235 (void) remove(backuppath); 2236 2237 cleanup: 2238 if (newfile != NULL) 2239 (void) fclose(newfile); 2240 if (fd != -1) 2241 (void) close(fd); 2242 2243 return (ret); 2244 } 2245 2246 /* 2247 * read_keystore_file - Reads single keystore file 2248 * off disk in PKCS12 format. 2249 * 2250 * Arguments: 2251 * err - Error object to add errors to 2252 * file - File path to read 2253 * Returns: 2254 * PKCS12 contents of file, or NULL if an error occurred. 2255 * errors recorded in 'err'. 2256 */ 2257 static PKCS12 2258 *read_keystore_file(PKG_ERR *err, char *file) 2259 { 2260 int fd; 2261 struct stat buf; 2262 FILE *newfile; 2263 PKCS12 *p12 = NULL; 2264 2265 if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) { 2266 pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN), 2267 file, strerror(errno)); 2268 goto cleanup; 2269 } 2270 2271 if (fstat(fd, &buf) == -1) { 2272 pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN), 2273 file, strerror(errno)); 2274 goto cleanup; 2275 } 2276 2277 if (!S_ISREG(buf.st_mode)) { 2278 pkgerr_add(err, PKGERR_READ, gettext(ERR_NOT_REG), 2279 file); 2280 goto cleanup; 2281 } 2282 2283 if ((newfile = fdopen(fd, "r")) == NULL) { 2284 pkgerr_add(err, PKGERR_READ, gettext(ERR_KEYSTORE_OPEN), 2285 file, strerror(errno)); 2286 goto cleanup; 2287 } 2288 2289 if ((p12 = d2i_PKCS12_fp(newfile, NULL)) == NULL) { 2290 pkgerr_add(err, PKGERR_CORRUPT, 2291 gettext(ERR_KEYSTORE_CORRUPT), file); 2292 goto cleanup; 2293 } 2294 2295 cleanup: 2296 if (newfile != NULL) 2297 (void) fclose(newfile); 2298 if (fd != -1) 2299 (void) close(fd); 2300 2301 return (p12); 2302 } 2303 2304 2305 /* 2306 * Locks the specified file. 2307 */ 2308 static int 2309 file_lock(int fd, int type, int wait) 2310 { 2311 struct flock lock; 2312 2313 lock.l_type = type; 2314 lock.l_start = 0; 2315 lock.l_whence = SEEK_SET; 2316 lock.l_len = 0; 2317 2318 if (!wait) { 2319 if (file_lock_test(fd, type)) { 2320 /* 2321 * The caller would have to wait to get the 2322 * lock on this file. 2323 */ 2324 return (-1); 2325 } 2326 } 2327 2328 return (fcntl(fd, F_SETLKW, &lock)); 2329 } 2330 2331 /* 2332 * Returns FALSE if the file is not locked; TRUE 2333 * otherwise. 2334 */ 2335 static boolean_t 2336 file_lock_test(int fd, int type) 2337 { 2338 struct flock lock; 2339 2340 lock.l_type = type; 2341 lock.l_start = 0; 2342 lock.l_whence = SEEK_SET; 2343 lock.l_len = 0; 2344 2345 if (fcntl(fd, F_GETLK, &lock) != -1) { 2346 if (lock.l_type != F_UNLCK) { 2347 /* 2348 * The caller would have to wait to get the 2349 * lock on this file. 2350 */ 2351 return (B_TRUE); 2352 } 2353 } 2354 2355 /* 2356 * The file is not locked. 2357 */ 2358 return (B_FALSE); 2359 } 2360 2361 /* 2362 * Unlocks the specified file. 2363 */ 2364 static int 2365 file_unlock(int fd) 2366 { 2367 struct flock lock; 2368 2369 lock.l_type = F_UNLCK; 2370 lock.l_start = 0; 2371 lock.l_whence = SEEK_SET; 2372 lock.l_len = 0; 2373 2374 return (fcntl(fd, F_SETLK, &lock)); 2375 } 2376 2377 /* 2378 * Determines if file has a length of 0 or not 2379 */ 2380 static boolean_t 2381 file_empty(char *path) 2382 { 2383 struct stat buf; 2384 2385 /* file is empty if size = 0 or it doesn't exist */ 2386 if (lstat(path, &buf) == 0) { 2387 if (buf.st_size == 0) { 2388 return (B_TRUE); 2389 } 2390 } else { 2391 if (errno == ENOENT) { 2392 return (B_TRUE); 2393 } 2394 } 2395 2396 return (B_FALSE); 2397 } 2398 2399 /* 2400 * Name: get_time_string 2401 * Description: Generates a human-readable string from an ASN1_TIME 2402 * 2403 * Arguments: intime - The time to convert 2404 * 2405 * Returns : A pointer to a static string representing the passed-in time. 2406 */ 2407 static char 2408 *get_time_string(ASN1_TIME *intime) 2409 { 2410 2411 static char time[ATTR_MAX]; 2412 BIO *mem; 2413 char *p; 2414 2415 if (intime == NULL) { 2416 return (NULL); 2417 } 2418 if ((mem = BIO_new(BIO_s_mem())) == NULL) { 2419 return (NULL); 2420 } 2421 2422 if (ASN1_TIME_print(mem, intime) == 0) { 2423 (void) BIO_free(mem); 2424 return (NULL); 2425 } 2426 2427 if (BIO_gets(mem, time, ATTR_MAX) <= 0) { 2428 (void) BIO_free(mem); 2429 return (NULL); 2430 } 2431 2432 (void) BIO_free(mem); 2433 2434 /* trim the end of the string */ 2435 for (p = time + strlen(time) - 1; isspace(*p); p--) { 2436 *p = '\0'; 2437 } 2438 2439 return (time); 2440 } 2441 2442 /* 2443 * check_password - do various password checks to see if the current password 2444 * will work or we need to prompt for a new one. 2445 * 2446 * Arguments: 2447 * pass - password to check 2448 * 2449 * Returns: 2450 * B_TRUE - Password is OK. 2451 * B_FALSE - Password not valid. 2452 */ 2453 static boolean_t 2454 check_password(PKCS12 *p12, char *pass) 2455 { 2456 boolean_t ret = B_TRUE; 2457 2458 /* 2459 * If password is zero length or NULL then try verifying both cases 2460 * to determine which password is correct. The reason for this is that 2461 * under PKCS#12 password based encryption no password and a zero 2462 * length password are two different things... 2463 */ 2464 2465 /* Check the mac */ 2466 if (pass == NULL || *pass == '\0') { 2467 if (PKCS12_verify_mac(p12, NULL, 0) == 0 && 2468 PKCS12_verify_mac(p12, "", 0) == 0) 2469 ret = B_FALSE; 2470 } else if (PKCS12_verify_mac(p12, pass, -1) == 0) { 2471 ret = B_FALSE; 2472 } 2473 return (ret); 2474 } 2475