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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <cryptoutil.h> 27 #include <fcntl.h> 28 #include <libintl.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <strings.h> 32 #include <unistd.h> 33 #include <errno.h> 34 #include <dlfcn.h> 35 #include <link.h> 36 #include <sys/types.h> 37 #include <sys/stat.h> 38 #include <security/cryptoki.h> 39 #include "cryptoadm.h" 40 41 #define HDR1 " P\n" 42 #define HDR2 " S V K a U D\n" 43 #define HDR3 " i e e i n e\n" 44 #define HDR4 " S g V r y r W w r\n" 45 #define HDR5 " E D D i n e i G G r r i\n" 46 #define HDR6 " H n e i g + r + e e a a v E\n" 47 #define HDR7 "min max W c c g n R i R n n p p e C\n" 48 49 50 static int err; /* To store errno which may be overwritten by gettext() */ 51 static boolean_t is_in_policylist(midstr_t, umechlist_t *); 52 static char *uent2str(uentry_t *); 53 static boolean_t check_random(CK_SLOT_ID, CK_FUNCTION_LIST_PTR); 54 55 static void display_slot_flags(CK_FLAGS flags) 56 { 57 (void) printf(gettext("Slot Flags: ")); 58 if (flags & CKF_TOKEN_PRESENT) 59 (void) printf("CKF_TOKEN_PRESENT "); 60 if (flags & CKF_REMOVABLE_DEVICE) 61 (void) printf("CKF_REMOVABLE_DEVICE "); 62 if (flags & CKF_HW_SLOT) 63 (void) printf("CKF_HW_SLOT "); 64 (void) printf("\n"); 65 } 66 67 void 68 display_token_flags(CK_FLAGS flags) 69 { 70 (void) printf(gettext("Flags: ")); 71 if (flags & CKF_RNG) 72 (void) printf("CKF_RNG "); 73 if (flags & CKF_WRITE_PROTECTED) 74 (void) printf("CKF_WRITE_PROTECTED "); 75 if (flags & CKF_LOGIN_REQUIRED) 76 (void) printf("CKF_LOGIN_REQUIRED "); 77 if (flags & CKF_USER_PIN_INITIALIZED) 78 (void) printf("CKF_USER_PIN_INITIALIZED "); 79 if (flags & CKF_RESTORE_KEY_NOT_NEEDED) 80 (void) printf("CKF_RESTORE_KEY_NOT_NEEDED "); 81 if (flags & CKF_CLOCK_ON_TOKEN) 82 (void) printf("CKF_CLOCK_ON_TOKEN "); 83 if (flags & CKF_PROTECTED_AUTHENTICATION_PATH) 84 (void) printf("CKF_PROTECTED_AUTHENTICATION_PATH "); 85 if (flags & CKF_DUAL_CRYPTO_OPERATIONS) 86 (void) printf("CKF_DUAL_CRYPTO_OPERATIONS "); 87 if (flags & CKF_TOKEN_INITIALIZED) 88 (void) printf("CKF_TOKEN_INITIALIZED "); 89 if (flags & CKF_SECONDARY_AUTHENTICATION) 90 (void) printf("CKF_SECONDARY_AUTHENTICATION "); 91 if (flags & CKF_USER_PIN_COUNT_LOW) 92 (void) printf("CKF_USER_PIN_COUNT_LOW "); 93 if (flags & CKF_USER_PIN_FINAL_TRY) 94 (void) printf("CKF_USER_PIN_FINAL_TRY "); 95 if (flags & CKF_USER_PIN_LOCKED) 96 (void) printf("CKF_USER_PIN_LOCKED "); 97 if (flags & CKF_USER_PIN_TO_BE_CHANGED) 98 (void) printf("CKF_USER_PIN_TO_BE_CHANGED "); 99 if (flags & CKF_SO_PIN_COUNT_LOW) 100 (void) printf("CKF_SO_PIN_COUNT_LOW "); 101 if (flags & CKF_SO_PIN_FINAL_TRY) 102 (void) printf("CKF_SO_PIN_FINAL_TRY "); 103 if (flags & CKF_SO_PIN_LOCKED) 104 (void) printf("CKF_SO_PIN_LOCKED "); 105 if (flags & CKF_SO_PIN_TO_BE_CHANGED) 106 (void) printf("CKF_SO_PIN_TO_BE_CHANGED "); 107 if (flags & CKF_SO_PIN_TO_BE_CHANGED) 108 (void) printf("CKF_SO_PIN_TO_BE_CHANGED "); 109 (void) printf("\n"); 110 } 111 112 void 113 display_mech_info(CK_MECHANISM_INFO *mechInfo) 114 { 115 CK_FLAGS ec_flags = CKF_EC_F_P | CKF_EC_F_2M | CKF_EC_ECPARAMETERS | 116 CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS | CKF_EC_COMPRESS; 117 118 (void) printf("%-4ld %-4ld ", mechInfo->ulMinKeySize, 119 mechInfo->ulMaxKeySize); 120 (void) printf("%s %s %s %s %s %s %s %s %s %s %s %s " 121 "%s %s", 122 (mechInfo->flags & CKF_HW) ? "X" : ".", 123 (mechInfo->flags & CKF_ENCRYPT) ? "X" : ".", 124 (mechInfo->flags & CKF_DECRYPT) ? "X" : ".", 125 (mechInfo->flags & CKF_DIGEST) ? "X" : ".", 126 (mechInfo->flags & CKF_SIGN) ? "X" : ".", 127 (mechInfo->flags & CKF_SIGN_RECOVER) ? "X" : ".", 128 (mechInfo->flags & CKF_VERIFY) ? "X" : ".", 129 (mechInfo->flags & CKF_VERIFY_RECOVER) ? "X" : ".", 130 (mechInfo->flags & CKF_GENERATE) ? "X" : ".", 131 (mechInfo->flags & CKF_GENERATE_KEY_PAIR) ? "X" : ".", 132 (mechInfo->flags & CKF_WRAP) ? "X" : ".", 133 (mechInfo->flags & CKF_UNWRAP) ? "X" : ".", 134 (mechInfo->flags & CKF_DERIVE) ? "X" : ".", 135 (mechInfo->flags & ec_flags) ? "X" : "."); 136 } 137 138 /* 139 * Converts the provided list of mechanism names in their string format to 140 * their corresponding PKCS#11 mechanism IDs. 141 * 142 * The list of mechanism names to be converted is provided in the 143 * "mlist" argument. The list of converted mechanism IDs is returned 144 * in the "pmech_list" argument. 145 * 146 * This function is called by list_metaslot_info() and 147 * list_mechlist_for_lib() functions. 148 */ 149 int 150 convert_mechlist(CK_MECHANISM_TYPE **pmech_list, CK_ULONG *mech_count, 151 mechlist_t *mlist) 152 { 153 int i, n = 0; 154 mechlist_t *p = mlist; 155 156 while (p != NULL) { 157 p = p->next; 158 n++; 159 } 160 161 *pmech_list = malloc(n * sizeof (CK_MECHANISM_TYPE)); 162 if (pmech_list == NULL) { 163 cryptodebug("out of memory"); 164 return (FAILURE); 165 } 166 p = mlist; 167 for (i = 0; i < n; i++) { 168 if (pkcs11_str2mech(p->name, &(*pmech_list[i])) != CKR_OK) { 169 free(*pmech_list); 170 return (FAILURE); 171 } 172 p = p->next; 173 } 174 *mech_count = n; 175 return (SUCCESS); 176 } 177 178 /* 179 * Display the mechanism list for a user-level library 180 */ 181 int 182 list_mechlist_for_lib(char *libname, mechlist_t *mlist, 183 flag_val_t *rng_flag, boolean_t no_warn, 184 boolean_t verbose, boolean_t show_mechs) 185 { 186 CK_RV rv = CKR_OK; 187 CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR); 188 CK_FUNCTION_LIST_PTR prov_funcs; /* Provider's function list */ 189 CK_SLOT_ID_PTR prov_slots = NULL; /* Provider's slot list */ 190 CK_MECHANISM_TYPE_PTR pmech_list; /* mechanism list for a slot */ 191 CK_SLOT_INFO slotinfo; 192 CK_ULONG slot_count; 193 CK_ULONG mech_count; 194 uentry_t *puent = NULL; 195 boolean_t lib_initialized = B_FALSE; 196 void *dldesc = NULL; 197 char *dl_error; 198 const char *mech_name; 199 char *isa; 200 char libpath[MAXPATHLEN]; 201 char buf[MAXPATHLEN]; 202 int i, j; 203 int rc = SUCCESS; 204 205 if (libname == NULL) { 206 /* should not happen */ 207 cryptoerror(LOG_STDERR, gettext("internal error.")); 208 cryptodebug("list_mechlist_for_lib() - libname is NULL."); 209 return (FAILURE); 210 } 211 212 /* Check if the library is in the pkcs11.conf file */ 213 if ((puent = getent_uef(libname)) == NULL) { 214 cryptoerror(LOG_STDERR, 215 gettext("%s does not exist."), libname); 216 return (FAILURE); 217 } 218 free_uentry(puent); 219 220 /* Remove $ISA from the library name */ 221 if (strlcpy(buf, libname, sizeof (buf)) >= sizeof (buf)) { 222 (void) printf(gettext("%s: the provider name is too long."), 223 libname); 224 return (FAILURE); 225 } 226 227 if ((isa = strstr(buf, PKCS11_ISA)) != NULL) { 228 *isa = '\000'; 229 isa += strlen(PKCS11_ISA); 230 (void) snprintf(libpath, MAXPATHLEN, "%s%s%s", buf, "/", isa); 231 } else { 232 (void) strlcpy(libpath, libname, sizeof (libpath)); 233 } 234 235 /* Open the provider */ 236 dldesc = dlopen(libpath, RTLD_NOW); 237 if (dldesc == NULL) { 238 dl_error = dlerror(); 239 cryptodebug("Cannot load PKCS#11 library %s. dlerror: %s", 240 libname, dl_error != NULL ? dl_error : "Unknown"); 241 rc = FAILURE; 242 goto clean_exit; 243 } 244 245 /* Get the pointer to provider's C_GetFunctionList() */ 246 Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList"); 247 if (Tmp_C_GetFunctionList == NULL) { 248 cryptodebug("Cannot get the address of the C_GetFunctionList " 249 "from %s", libname); 250 rc = FAILURE; 251 goto clean_exit; 252 } 253 254 /* Get the provider's function list */ 255 rv = Tmp_C_GetFunctionList(&prov_funcs); 256 if (rv != CKR_OK) { 257 cryptodebug("failed to call C_GetFunctionList from %s", 258 libname); 259 rc = FAILURE; 260 goto clean_exit; 261 } 262 263 /* Initialize this provider */ 264 rv = prov_funcs->C_Initialize(NULL_PTR); 265 if (rv != CKR_OK) { 266 cryptodebug("failed to call C_Initialize from %s, " 267 "return code = %d", libname, rv); 268 rc = FAILURE; 269 goto clean_exit; 270 } else { 271 lib_initialized = B_TRUE; 272 } 273 274 /* 275 * Find out how many slots this provider has, call with tokenPresent 276 * set to FALSE so all potential slots are returned. 277 */ 278 rv = prov_funcs->C_GetSlotList(FALSE, NULL_PTR, &slot_count); 279 if (rv != CKR_OK) { 280 cryptodebug("failed to get the slotlist from %s.", libname); 281 rc = FAILURE; 282 goto clean_exit; 283 } else if (slot_count == 0) { 284 if (!no_warn) 285 (void) printf(gettext("%s: no slots presented.\n"), 286 libname); 287 rc = SUCCESS; 288 goto clean_exit; 289 } 290 291 /* Allocate memory for the slot list */ 292 prov_slots = malloc(slot_count * sizeof (CK_SLOT_ID)); 293 if (prov_slots == NULL) { 294 cryptodebug("out of memory."); 295 rc = FAILURE; 296 goto clean_exit; 297 } 298 299 /* Get the slot list from provider */ 300 rv = prov_funcs->C_GetSlotList(FALSE, prov_slots, &slot_count); 301 if (rv != CKR_OK) { 302 cryptodebug("failed to call C_GetSlotList() from %s.", 303 libname); 304 rc = FAILURE; 305 goto clean_exit; 306 } 307 308 if (verbose) { 309 (void) printf(gettext("Number of slots: %d\n"), slot_count); 310 } 311 312 /* Get the mechanism list for each slot */ 313 for (i = 0; i < slot_count; i++) { 314 if (verbose) 315 /* 316 * TRANSLATION_NOTE 317 * In some languages, the # symbol should be 318 * converted to "no", an "n" followed by a 319 * superscript "o".. 320 */ 321 (void) printf(gettext("\nSlot #%d\n"), i+1); 322 323 if ((rng_flag != NULL) && (*rng_flag == NO_RNG)) { 324 if (check_random(prov_slots[i], prov_funcs)) { 325 *rng_flag = HAS_RNG; 326 rc = SUCCESS; 327 goto clean_exit; 328 } else 329 continue; 330 } 331 332 rv = prov_funcs->C_GetSlotInfo(prov_slots[i], &slotinfo); 333 if (rv != CKR_OK) { 334 cryptodebug("failed to get slotinfo from %s", libname); 335 rc = FAILURE; 336 break; 337 } 338 if (verbose) { 339 CK_TOKEN_INFO tokeninfo; 340 341 (void) printf(gettext("Description: %.64s\n" 342 "Manufacturer: %.32s\n" 343 "PKCS#11 Version: %d.%d\n"), 344 slotinfo.slotDescription, 345 slotinfo.manufacturerID, 346 prov_funcs->version.major, 347 prov_funcs->version.minor); 348 349 (void) printf(gettext("Hardware Version: %d.%d\n" 350 "Firmware Version: %d.%d\n"), 351 slotinfo.hardwareVersion.major, 352 slotinfo.hardwareVersion.minor, 353 slotinfo.firmwareVersion.major, 354 slotinfo.firmwareVersion.minor); 355 356 (void) printf(gettext("Token Present: %s\n"), 357 (slotinfo.flags & CKF_TOKEN_PRESENT ? 358 gettext("True") : gettext("False"))); 359 360 display_slot_flags(slotinfo.flags); 361 362 rv = prov_funcs->C_GetTokenInfo(prov_slots[i], 363 &tokeninfo); 364 if (rv != CKR_OK) { 365 cryptodebug("Failed to get " 366 "token info from %s", libname); 367 rc = FAILURE; 368 break; 369 } 370 371 (void) printf(gettext("Token Label: %.32s\n" 372 "Manufacturer ID: %.32s\n" 373 "Model: %.16s\n" 374 "Serial Number: %.16s\n" 375 "Hardware Version: %d.%d\n" 376 "Firmware Version: %d.%d\n" 377 "UTC Time: %.16s\n" 378 "PIN Min Length: %d\n" 379 "PIN Max Length: %d\n"), 380 tokeninfo.label, 381 tokeninfo.manufacturerID, 382 tokeninfo.model, 383 tokeninfo.serialNumber, 384 tokeninfo.hardwareVersion.major, 385 tokeninfo.hardwareVersion.minor, 386 tokeninfo.firmwareVersion.major, 387 tokeninfo.firmwareVersion.minor, 388 tokeninfo.utcTime, 389 tokeninfo.ulMinPinLen, 390 tokeninfo.ulMaxPinLen); 391 392 display_token_flags(tokeninfo.flags); 393 } 394 395 if (mlist == NULL) { 396 rv = prov_funcs->C_GetMechanismList(prov_slots[i], 397 NULL_PTR, &mech_count); 398 if (rv != CKR_OK) { 399 cryptodebug( 400 "failed to call C_GetMechanismList() " 401 "from %s.", libname); 402 rc = FAILURE; 403 break; 404 } 405 406 if (mech_count == 0) { 407 /* no mechanisms in this slot */ 408 continue; 409 } 410 411 pmech_list = malloc(mech_count * 412 sizeof (CK_MECHANISM_TYPE)); 413 if (pmech_list == NULL) { 414 cryptodebug("out of memory"); 415 rc = FAILURE; 416 break; 417 } 418 419 /* Get the actual mechanism list */ 420 rv = prov_funcs->C_GetMechanismList(prov_slots[i], 421 pmech_list, &mech_count); 422 if (rv != CKR_OK) { 423 cryptodebug( 424 "failed to call C_GetMechanismList() " 425 "from %s.", libname); 426 (void) free(pmech_list); 427 rc = FAILURE; 428 break; 429 } 430 } else { 431 /* use the mechanism list passed in */ 432 rc = convert_mechlist(&pmech_list, &mech_count, mlist); 433 if (rc != SUCCESS) { 434 goto clean_exit; 435 } 436 } 437 if (show_mechs) 438 (void) printf(gettext("Mechanisms:\n")); 439 440 if (verbose && show_mechs) { 441 display_verbose_mech_header(); 442 } 443 /* 444 * Merge the current mechanism list into the returning 445 * mechanism list. 446 */ 447 for (j = 0; show_mechs && j < mech_count; j++) { 448 CK_MECHANISM_TYPE mech = pmech_list[j]; 449 450 if (mech >= CKM_VENDOR_DEFINED) { 451 (void) printf("%#lx", mech); 452 } else { 453 mech_name = pkcs11_mech2str(mech); 454 (void) printf("%-29s", mech_name); 455 } 456 457 if (verbose) { 458 CK_MECHANISM_INFO mech_info; 459 rv = prov_funcs->C_GetMechanismInfo( 460 prov_slots[i], mech, &mech_info); 461 if (rv != CKR_OK) { 462 cryptodebug( 463 "failed to call " 464 "C_GetMechanismInfo() from %s.", 465 libname); 466 (void) free(pmech_list); 467 rc = FAILURE; 468 break; 469 } 470 display_mech_info(&mech_info); 471 } 472 (void) printf("\n"); 473 } 474 (void) free(pmech_list); 475 if (rc == FAILURE) { 476 break; 477 } 478 } 479 480 if (rng_flag != NULL || rc == FAILURE) { 481 goto clean_exit; 482 } 483 484 clean_exit: 485 486 if (rc == FAILURE) { 487 (void) printf(gettext( 488 "%s: failed to retrieve the mechanism list.\n"), libname); 489 } 490 491 if (lib_initialized) { 492 (void) prov_funcs->C_Finalize(NULL_PTR); 493 } 494 495 if (dldesc != NULL) { 496 (void) dlclose(dldesc); 497 } 498 499 if (prov_slots != NULL) { 500 (void) free(prov_slots); 501 } 502 503 return (rc); 504 } 505 506 507 /* 508 * Display the mechanism policy for a user-level library 509 */ 510 int 511 list_policy_for_lib(char *libname) 512 { 513 uentry_t *puent = NULL; 514 int rc; 515 516 if (libname == NULL) { 517 /* should not happen */ 518 cryptoerror(LOG_STDERR, gettext("internal error.")); 519 cryptodebug("list_policy_for_lib() - libname is NULL."); 520 return (FAILURE); 521 } 522 523 /* Get the library entry from the pkcs11.conf file */ 524 if ((puent = getent_uef(libname)) == NULL) { 525 cryptoerror(LOG_STDERR, 526 gettext("%s does not exist."), libname); 527 return (FAILURE); 528 } 529 530 /* Print the policy for this library */ 531 rc = print_uef_policy(puent); 532 free_uentry(puent); 533 534 return (rc); 535 } 536 537 538 /* 539 * Disable mechanisms for a user-level library 540 */ 541 int 542 disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag, 543 mechlist_t *marglist) 544 { 545 uentry_t *puent; 546 int rc; 547 548 if (libname == NULL) { 549 /* should not happen */ 550 cryptoerror(LOG_STDERR, gettext("internal error.")); 551 cryptodebug("disable_uef_lib() - libname is NULL."); 552 return (FAILURE); 553 } 554 555 /* Get the provider entry from the pkcs11.conf file */ 556 if ((puent = getent_uef(libname)) == NULL) { 557 cryptoerror(LOG_STDERR, 558 gettext("%s does not exist."), libname); 559 return (FAILURE); 560 } 561 562 /* 563 * Update the mechanism policy of this library entry, based on 564 * the current policy mode of the library and the mechanisms specified 565 * in CLI. 566 */ 567 if (allflag) { 568 /* 569 * If disabling all, just need to clean up the policylist and 570 * set the flag_enabledlist flag to be B_TRUE. 571 */ 572 free_umechlist(puent->policylist); 573 puent->policylist = NULL; 574 puent->count = 0; 575 puent->flag_enabledlist = B_TRUE; 576 rc = SUCCESS; 577 } else if (marglist != NULL) { 578 if (puent->flag_enabledlist == B_TRUE) { 579 /* 580 * The current default policy mode of this library 581 * is "all are disabled, except ...", so if a 582 * specified mechanism is in the exception list 583 * (the policylist), delete it from the policylist. 584 */ 585 rc = update_policylist(puent, marglist, DELETE_MODE); 586 } else { 587 /* 588 * The current default policy mode of this library 589 * is "all are enabled", so if a specified mechanism 590 * is not in the exception list (policylist), add 591 * it into the policylist. 592 */ 593 rc = update_policylist(puent, marglist, ADD_MODE); 594 } 595 } else if (!rndflag) { 596 /* should not happen */ 597 cryptoerror(LOG_STDERR, gettext("internal error.")); 598 cryptodebug("disable_uef_lib() - wrong arguments."); 599 return (FAILURE); 600 } 601 602 if (rndflag) 603 puent->flag_norandom = B_TRUE; 604 605 if (rc == FAILURE) { 606 free_uentry(puent); 607 return (FAILURE); 608 } 609 610 /* Update the pkcs11.conf file with the updated entry */ 611 rc = update_pkcs11conf(puent); 612 free_uentry(puent); 613 return (rc); 614 } 615 616 617 /* 618 * Enable disabled mechanisms for a user-level library. 619 */ 620 int 621 enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag, 622 mechlist_t *marglist) 623 { 624 uentry_t *puent; 625 int rc = SUCCESS; 626 627 if (libname == NULL) { 628 /* should not happen */ 629 cryptoerror(LOG_STDERR, gettext("internal error.")); 630 cryptodebug("enable_uef_lib() - libname is NULL."); 631 return (FAILURE); 632 } 633 634 /* Get the provider entry from the pkcs11.conf file */ 635 if ((puent = getent_uef(libname)) == NULL) { 636 cryptoerror(LOG_STDERR, 637 gettext("%s does not exist."), libname); 638 return (FAILURE); 639 } 640 641 /* 642 * Update the mechanism policy of this library entry, based on 643 * the current policy mode of the library and the mechanisms 644 * specified in CLI. 645 */ 646 if (allflag) { 647 /* 648 * If enabling all, what needs to be done are cleaning up the 649 * policylist and setting the "flag_enabledlist" flag to 650 * B_FALSE. 651 */ 652 free_umechlist(puent->policylist); 653 puent->policylist = NULL; 654 puent->count = 0; 655 puent->flag_enabledlist = B_FALSE; 656 rc = SUCCESS; 657 } else if (marglist != NULL) { 658 if (puent->flag_enabledlist == B_TRUE) { 659 /* 660 * The current default policy mode of this library 661 * is "all are disabled, except ...", so if a 662 * specified mechanism is not in the exception list 663 * (policylist), add it. 664 */ 665 rc = update_policylist(puent, marglist, ADD_MODE); 666 } else { 667 /* 668 * The current default policy mode of this library 669 * is "all are enabled, except", so if a specified 670 * mechanism is in the exception list (policylist), 671 * delete it. 672 */ 673 rc = update_policylist(puent, marglist, DELETE_MODE); 674 } 675 } else if (!rndflag) { 676 /* should not come here */ 677 cryptoerror(LOG_STDERR, gettext("internal error.")); 678 cryptodebug("enable_uef_lib() - wrong arguments."); 679 return (FAILURE); 680 } 681 682 if (rndflag) 683 puent->flag_norandom = B_FALSE; 684 685 if (rc == FAILURE) { 686 free_uentry(puent); 687 return (FAILURE); 688 } 689 690 /* Update the pkcs11.conf file with the updated entry */ 691 rc = update_pkcs11conf(puent); 692 free_uentry(puent); 693 return (rc); 694 } 695 696 697 /* 698 * Install a user-level library. 699 */ 700 int 701 install_uef_lib(char *libname) 702 { 703 uentry_t *puent; 704 struct stat statbuf; 705 boolean_t found; 706 FILE *pfile; 707 FILE *pfile_tmp; 708 char tmpfile_name[MAXPATHLEN]; 709 char libpath[MAXPATHLEN]; 710 char libbuf[MAXPATHLEN]; 711 char *isa; 712 char buffer[BUFSIZ]; 713 char *ptr; 714 int found_count; 715 int rc = SUCCESS; 716 717 718 if (libname == NULL) { 719 /* should not happen */ 720 cryptoerror(LOG_STDERR, gettext("internal error.")); 721 cryptodebug("install_uef_lib() - libname is NULL."); 722 return (FAILURE); 723 } 724 725 /* Check if the provider already exists in the framework */ 726 if ((puent = getent_uef(libname)) != NULL) { 727 cryptoerror(LOG_STDERR, gettext("%s exists already."), 728 libname); 729 free_uentry(puent); 730 return (FAILURE); 731 } 732 733 /* 734 * Check if the library exists in the system. if $ISA is in the 735 * path, only check the 32bit version. 736 */ 737 if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) { 738 cryptoerror(LOG_STDERR, 739 gettext("the provider name is too long - %s"), libname); 740 return (FAILURE); 741 } 742 743 if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) { 744 *isa = '\000'; 745 isa += strlen(PKCS11_ISA); 746 (void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf, 747 "/", isa); 748 } else { 749 (void) strlcpy(libpath, libname, sizeof (libpath)); 750 } 751 752 /* Check if it is same as the framework library */ 753 if (strcmp(libpath, UEF_FRAME_LIB) == 0) { 754 cryptoerror(LOG_STDERR, gettext( 755 "The framework library %s can not be installed."), 756 libname); 757 return (FAILURE); 758 } 759 760 if (stat(libpath, &statbuf) != 0) { 761 cryptoerror(LOG_STDERR, gettext("%s not found"), libname); 762 return (FAILURE); 763 } 764 765 /* Need to add "\n" to libname for adding into the config file */ 766 if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) { 767 cryptoerror(LOG_STDERR, gettext( 768 "can not install %s; the name is too long."), libname); 769 return (FAILURE); 770 } 771 772 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 773 err = errno; 774 cryptoerror(LOG_STDERR, 775 gettext("failed to update the configuration - %s"), 776 strerror(err)); 777 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 778 return (FAILURE); 779 } 780 781 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 782 err = errno; 783 cryptoerror(LOG_STDERR, 784 gettext("failed to lock the configuration - %s"), 785 strerror(err)); 786 (void) fclose(pfile); 787 return (FAILURE); 788 } 789 790 /* 791 * Create a temporary file in the /etc/crypto directory. 792 */ 793 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 794 if (mkstemp(tmpfile_name) == -1) { 795 err = errno; 796 cryptoerror(LOG_STDERR, 797 gettext("failed to create a temporary file - %s"), 798 strerror(err)); 799 (void) fclose(pfile); 800 return (FAILURE); 801 } 802 803 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 804 err = errno; 805 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 806 tmpfile_name, strerror(err)); 807 (void) fclose(pfile); 808 return (FAILURE); 809 } 810 811 /* 812 * Loop thru the config file. If the file was reserved within a 813 * package bracket, just uncomment it. Other wise, append it at 814 * the end. The resulting file will be saved in the temp file first. 815 */ 816 found_count = 0; 817 rc = SUCCESS; 818 while (fgets(buffer, BUFSIZ, pfile) != NULL) { 819 found = B_FALSE; 820 if (buffer[0] == '#') { 821 ptr = buffer; 822 ptr++; 823 if (strcmp(libname, ptr) == 0) { 824 found = B_TRUE; 825 found_count++; 826 } 827 } 828 829 if (found == B_FALSE) { 830 if (fputs(buffer, pfile_tmp) == EOF) { 831 rc = FAILURE; 832 } 833 } else { 834 if (found_count == 1) { 835 if (fputs(ptr, pfile_tmp) == EOF) { 836 rc = FAILURE; 837 } 838 } else { 839 /* 840 * Found a second entry with #libname. 841 * Should not happen. The pkcs11.conf file 842 * is corrupted. Give a warning and skip 843 * this entry. 844 */ 845 cryptoerror(LOG_STDERR, gettext( 846 "(Warning) Found an additional reserved " 847 "entry for %s."), libname); 848 } 849 } 850 851 if (rc == FAILURE) { 852 break; 853 } 854 } 855 856 if (rc == FAILURE) { 857 cryptoerror(LOG_STDERR, gettext("write error.")); 858 (void) fclose(pfile); 859 (void) fclose(pfile_tmp); 860 if (unlink(tmpfile_name) != 0) { 861 err = errno; 862 cryptoerror(LOG_STDERR, gettext( 863 "(Warning) failed to remove %s: %s"), tmpfile_name, 864 strerror(err)); 865 } 866 return (FAILURE); 867 } 868 869 if (found_count == 0) { 870 /* 871 * This libname was not in package before, append it to the 872 * end of the temp file. 873 */ 874 if (fputs(libname, pfile_tmp) == EOF) { 875 err = errno; 876 cryptoerror(LOG_STDERR, gettext( 877 "failed to write to %s: %s"), tmpfile_name, 878 strerror(err)); 879 (void) fclose(pfile); 880 (void) fclose(pfile_tmp); 881 if (unlink(tmpfile_name) != 0) { 882 err = errno; 883 cryptoerror(LOG_STDERR, gettext( 884 "(Warning) failed to remove %s: %s"), 885 tmpfile_name, strerror(err)); 886 } 887 return (FAILURE); 888 } 889 } 890 891 (void) fclose(pfile); 892 if (fclose(pfile_tmp) != 0) { 893 err = errno; 894 cryptoerror(LOG_STDERR, 895 gettext("failed to close %s: %s"), tmpfile_name, 896 strerror(err)); 897 return (FAILURE); 898 } 899 900 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 901 err = errno; 902 cryptoerror(LOG_STDERR, 903 gettext("failed to update the configuration - %s"), 904 strerror(err)); 905 cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 906 _PATH_PKCS11_CONF, strerror(err)); 907 rc = FAILURE; 908 } else if (chmod(_PATH_PKCS11_CONF, 909 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 910 err = errno; 911 cryptoerror(LOG_STDERR, 912 gettext("failed to update the configuration - %s"), 913 strerror(err)); 914 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 915 strerror(err)); 916 rc = FAILURE; 917 } else { 918 rc = SUCCESS; 919 } 920 921 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 922 err = errno; 923 cryptoerror(LOG_STDERR, gettext( 924 "(Warning) failed to remove %s: %s"), tmpfile_name, 925 strerror(err)); 926 } 927 928 return (rc); 929 } 930 931 932 /* 933 * Uninstall a user-level library. 934 */ 935 int 936 uninstall_uef_lib(char *libname) 937 { 938 uentry_t *puent; 939 FILE *pfile; 940 FILE *pfile_tmp; 941 char buffer[BUFSIZ]; 942 char buffer2[BUFSIZ]; 943 char tmpfile_name[MAXPATHLEN]; 944 char *name; 945 boolean_t found; 946 boolean_t in_package; 947 int len; 948 int rc = SUCCESS; 949 950 if (libname == NULL) { 951 /* should not happen */ 952 cryptoerror(LOG_STDERR, gettext("internal error.")); 953 cryptodebug("uninstall_uef_lib() - libname is NULL."); 954 return (FAILURE); 955 } 956 957 /* Check if the provider exists */ 958 if ((puent = getent_uef(libname)) == NULL) { 959 cryptoerror(LOG_STDERR, 960 gettext("%s does not exist."), libname); 961 return (FAILURE); 962 } 963 free_uentry(puent); 964 965 /* Open the pkcs11.conf file and lock it */ 966 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 967 err = errno; 968 cryptoerror(LOG_STDERR, 969 gettext("failed to update the configuration - %s"), 970 strerror(err)); 971 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 972 return (FAILURE); 973 } 974 975 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 976 err = errno; 977 cryptoerror(LOG_STDERR, 978 gettext("failed to lock the configuration - %s"), 979 strerror(err)); 980 (void) fclose(pfile); 981 return (FAILURE); 982 } 983 984 /* 985 * Create a temporary file in the /etc/crypto directory to save 986 * the new configuration file first. 987 */ 988 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 989 if (mkstemp(tmpfile_name) == -1) { 990 err = errno; 991 cryptoerror(LOG_STDERR, 992 gettext("failed to create a temporary file - %s"), 993 strerror(err)); 994 (void) fclose(pfile); 995 return (FAILURE); 996 } 997 998 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 999 err = errno; 1000 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 1001 tmpfile_name, strerror(err)); 1002 if (unlink(tmpfile_name) != 0) { 1003 err = errno; 1004 cryptoerror(LOG_STDERR, gettext( 1005 "(Warning) failed to remove %s: %s"), 1006 tmpfile_name, strerror(err)); 1007 } 1008 (void) fclose(pfile); 1009 return (FAILURE); 1010 } 1011 1012 1013 /* 1014 * Loop thru the config file. If the library to be uninstalled 1015 * is in a package, just comment it off. 1016 */ 1017 in_package = B_FALSE; 1018 while (fgets(buffer, BUFSIZ, pfile) != NULL) { 1019 found = B_FALSE; 1020 if (!(buffer[0] == ' ' || buffer[0] == '\n' || 1021 buffer[0] == '\t')) { 1022 if (strstr(buffer, " Start ") != NULL) { 1023 in_package = B_TRUE; 1024 } else if (strstr(buffer, " End ") != NULL) { 1025 in_package = B_FALSE; 1026 } else if (buffer[0] != '#') { 1027 (void) strlcpy(buffer2, buffer, BUFSIZ); 1028 1029 /* get rid of trailing '\n' */ 1030 len = strlen(buffer2); 1031 if (buffer2[len-1] == '\n') { 1032 len--; 1033 } 1034 buffer2[len] = '\0'; 1035 1036 if ((name = strtok(buffer2, SEP_COLON)) 1037 == NULL) { 1038 rc = FAILURE; 1039 break; 1040 } else if (strcmp(libname, name) == 0) { 1041 found = B_TRUE; 1042 } 1043 } 1044 } 1045 1046 if (found) { 1047 if (in_package) { 1048 (void) snprintf(buffer2, sizeof (buffer2), 1049 "%s%s%s", "#", libname, "\n"); 1050 if (fputs(buffer2, pfile_tmp) == EOF) { 1051 rc = FAILURE; 1052 } 1053 } 1054 } else { 1055 if (fputs(buffer, pfile_tmp) == EOF) { 1056 rc = FAILURE; 1057 } 1058 } 1059 1060 if (rc == FAILURE) { 1061 break; 1062 } 1063 } 1064 1065 if (rc == FAILURE) { 1066 cryptoerror(LOG_STDERR, gettext("write error.")); 1067 (void) fclose(pfile); 1068 (void) fclose(pfile_tmp); 1069 if (unlink(tmpfile_name) != 0) { 1070 err = errno; 1071 cryptoerror(LOG_STDERR, gettext( 1072 "(Warning) failed to remove %s: %s"), 1073 tmpfile_name, strerror(err)); 1074 } 1075 return (FAILURE); 1076 } 1077 1078 (void) fclose(pfile); 1079 if (fclose(pfile_tmp) != 0) { 1080 err = errno; 1081 cryptoerror(LOG_STDERR, 1082 gettext("failed to close a temporary file - %s"), 1083 strerror(err)); 1084 return (FAILURE); 1085 } 1086 1087 /* Now update the real config file */ 1088 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 1089 err = errno; 1090 cryptoerror(LOG_STDERR, 1091 gettext("failed to update the configuration - %s"), 1092 strerror(err)); 1093 cryptodebug("failed to rename %s to %s: %s", tmpfile, 1094 _PATH_PKCS11_CONF, strerror(err)); 1095 rc = FAILURE; 1096 } else if (chmod(_PATH_PKCS11_CONF, 1097 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 1098 err = errno; 1099 cryptoerror(LOG_STDERR, 1100 gettext("failed to update the configuration - %s"), 1101 strerror(err)); 1102 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 1103 strerror(err)); 1104 rc = FAILURE; 1105 } else { 1106 rc = SUCCESS; 1107 } 1108 1109 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 1110 err = errno; 1111 cryptoerror(LOG_STDERR, gettext( 1112 "(Warning) failed to remove %s: %s"), 1113 tmpfile_name, strerror(err)); 1114 } 1115 1116 return (rc); 1117 } 1118 1119 1120 int 1121 display_policy(uentry_t *puent) 1122 { 1123 CK_MECHANISM_TYPE mech_id; 1124 const char *mech_name; 1125 umechlist_t *ptr; 1126 1127 if (puent == NULL) { 1128 return (SUCCESS); 1129 } 1130 1131 if (puent->flag_enabledlist == B_FALSE) { 1132 (void) printf(gettext("%s: all mechanisms are enabled"), 1133 puent->name); 1134 ptr = puent->policylist; 1135 if (ptr == NULL) { 1136 (void) printf("."); 1137 } else { 1138 (void) printf(gettext(", except ")); 1139 while (ptr != NULL) { 1140 mech_id = strtoul(ptr->name, NULL, 0); 1141 if (mech_id & CKO_VENDOR_DEFINED) { 1142 /* vendor defined mechanism */ 1143 (void) printf("%s", ptr->name); 1144 } else { 1145 if (mech_id >= CKM_VENDOR_DEFINED) { 1146 (void) printf("%#lx", mech_id); 1147 } else { 1148 mech_name = pkcs11_mech2str( 1149 mech_id); 1150 if (mech_name == NULL) { 1151 return (FAILURE); 1152 } 1153 (void) printf("%s", mech_name); 1154 } 1155 } 1156 1157 ptr = ptr->next; 1158 if (ptr == NULL) { 1159 (void) printf("."); 1160 } else { 1161 (void) printf(","); 1162 } 1163 } 1164 } 1165 } else { /* puent->flag_enabledlist == B_TRUE */ 1166 (void) printf(gettext("%s: all mechanisms are disabled"), 1167 puent->name); 1168 ptr = puent->policylist; 1169 if (ptr == NULL) { 1170 (void) printf("."); 1171 } else { 1172 (void) printf(gettext(", except ")); 1173 while (ptr != NULL) { 1174 mech_id = strtoul(ptr->name, NULL, 0); 1175 if (mech_id & CKO_VENDOR_DEFINED) { 1176 /* vendor defined mechanism */ 1177 (void) printf("%s", ptr->name); 1178 } else { 1179 mech_name = pkcs11_mech2str(mech_id); 1180 if (mech_name == NULL) { 1181 return (FAILURE); 1182 } 1183 (void) printf("%s", mech_name); 1184 } 1185 ptr = ptr->next; 1186 if (ptr == NULL) { 1187 (void) printf("."); 1188 } else { 1189 (void) printf(","); 1190 } 1191 } 1192 } 1193 } 1194 return (SUCCESS); 1195 } 1196 1197 1198 1199 /* 1200 * Print out the mechanism policy for a user-level provider pointed by puent. 1201 */ 1202 int 1203 print_uef_policy(uentry_t *puent) 1204 { 1205 flag_val_t rng_flag; 1206 1207 if (puent == NULL) { 1208 return (FAILURE); 1209 } 1210 1211 rng_flag = NO_RNG; 1212 if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE, 1213 B_FALSE, B_FALSE) != SUCCESS) { 1214 cryptoerror(LOG_STDERR, 1215 gettext("%s internal error."), puent->name); 1216 return (FAILURE); 1217 } 1218 1219 if (display_policy(puent) != SUCCESS) { 1220 goto failed_exit; 1221 } 1222 1223 1224 if (puent->flag_norandom == B_TRUE) 1225 /* 1226 * TRANSLATION_NOTE 1227 * "random" is a keyword and not to be translated. 1228 */ 1229 (void) printf(gettext(" %s is disabled."), "random"); 1230 else { 1231 if (rng_flag == HAS_RNG) 1232 /* 1233 * TRANSLATION_NOTE 1234 * "random" is a keyword and not to be translated. 1235 */ 1236 (void) printf(gettext(" %s is enabled."), "random"); 1237 } 1238 (void) printf("\n"); 1239 1240 return (SUCCESS); 1241 1242 failed_exit: 1243 1244 (void) printf(gettext("\nout of memory.\n")); 1245 return (FAILURE); 1246 } 1247 1248 1249 /* 1250 * Check if the mechanism is in the mechanism list. 1251 */ 1252 static boolean_t 1253 is_in_policylist(midstr_t mechname, umechlist_t *plist) 1254 { 1255 boolean_t found = B_FALSE; 1256 1257 if (mechname == NULL) { 1258 return (B_FALSE); 1259 } 1260 1261 while (plist != NULL) { 1262 if (strcmp(plist->name, mechname) == 0) { 1263 found = B_TRUE; 1264 break; 1265 } 1266 plist = plist->next; 1267 } 1268 1269 return (found); 1270 } 1271 1272 1273 /* 1274 * Update the pkcs11.conf file with the updated entry. 1275 */ 1276 int 1277 update_pkcs11conf(uentry_t *puent) 1278 { 1279 FILE *pfile; 1280 FILE *pfile_tmp; 1281 char buffer[BUFSIZ]; 1282 char buffer2[BUFSIZ]; 1283 char tmpfile_name[MAXPATHLEN]; 1284 char *name; 1285 char *str; 1286 int len; 1287 int rc = SUCCESS; 1288 boolean_t found; 1289 1290 if (puent == NULL) { 1291 cryptoerror(LOG_STDERR, gettext("internal error.")); 1292 return (FAILURE); 1293 } 1294 1295 /* Open the pkcs11.conf file */ 1296 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 1297 err = errno; 1298 cryptoerror(LOG_STDERR, 1299 gettext("failed to update the configuration - %s"), 1300 strerror(err)); 1301 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 1302 return (FAILURE); 1303 } 1304 1305 /* Lock the pkcs11.conf file */ 1306 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 1307 err = errno; 1308 cryptoerror(LOG_STDERR, 1309 gettext("failed to update the configuration - %s"), 1310 strerror(err)); 1311 (void) fclose(pfile); 1312 return (FAILURE); 1313 } 1314 1315 /* 1316 * Create a temporary file in the /etc/crypto directory to save 1317 * updated configuration file first. 1318 */ 1319 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 1320 if (mkstemp(tmpfile_name) == -1) { 1321 err = errno; 1322 cryptoerror(LOG_STDERR, 1323 gettext("failed to create a temporary file - %s"), 1324 strerror(err)); 1325 (void) fclose(pfile); 1326 return (FAILURE); 1327 } 1328 1329 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 1330 err = errno; 1331 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 1332 tmpfile_name, strerror(err)); 1333 if (unlink(tmpfile_name) != 0) { 1334 err = errno; 1335 cryptoerror(LOG_STDERR, gettext( 1336 "(Warning) failed to remove %s: %s"), 1337 tmpfile_name, strerror(err)); 1338 } 1339 (void) fclose(pfile); 1340 return (FAILURE); 1341 } 1342 1343 1344 /* 1345 * Loop thru entire pkcs11.conf file, update the entry to be 1346 * updated and save the updated file to the temporary file first. 1347 */ 1348 while (fgets(buffer, BUFSIZ, pfile) != NULL) { 1349 found = B_FALSE; 1350 if (!(buffer[0] == '#' || buffer[0] == ' ' || 1351 buffer[0] == '\n'|| buffer[0] == '\t')) { 1352 /* 1353 * Get the provider name from this line and check if 1354 * this is the entry to be updated. Note: can not use 1355 * "buffer" directly because strtok will change its 1356 * value. 1357 */ 1358 (void) strlcpy(buffer2, buffer, BUFSIZ); 1359 1360 /* get rid of trailing '\n' */ 1361 len = strlen(buffer2); 1362 if (buffer2[len-1] == '\n') { 1363 len--; 1364 } 1365 buffer2[len] = '\0'; 1366 1367 if ((name = strtok(buffer2, SEP_COLON)) == NULL) { 1368 rc = FAILURE; 1369 break; 1370 } else if (strcmp(puent->name, name) == 0) { 1371 found = B_TRUE; 1372 } 1373 } 1374 1375 if (found) { 1376 /* 1377 * This is the entry to be modified, get the updated 1378 * string. 1379 */ 1380 if ((str = uent2str(puent)) == NULL) { 1381 rc = FAILURE; 1382 break; 1383 } else { 1384 (void) strlcpy(buffer, str, BUFSIZ); 1385 free(str); 1386 } 1387 } 1388 1389 if (fputs(buffer, pfile_tmp) == EOF) { 1390 err = errno; 1391 cryptoerror(LOG_STDERR, gettext( 1392 "failed to write to a temp file: %s."), 1393 strerror(err)); 1394 rc = FAILURE; 1395 break; 1396 } 1397 } 1398 1399 if (rc == FAILURE) { 1400 (void) fclose(pfile); 1401 (void) fclose(pfile_tmp); 1402 if (unlink(tmpfile_name) != 0) { 1403 err = errno; 1404 cryptoerror(LOG_STDERR, gettext( 1405 "(Warning) failed to remove %s: %s"), 1406 tmpfile_name, strerror(err)); 1407 } 1408 return (FAILURE); 1409 } 1410 1411 (void) fclose(pfile); 1412 if (fclose(pfile_tmp) != 0) { 1413 err = errno; 1414 cryptoerror(LOG_STDERR, 1415 gettext("failed to close %s: %s"), tmpfile_name, 1416 strerror(err)); 1417 return (FAILURE); 1418 } 1419 1420 /* Copy the temporary file to the pkcs11.conf file */ 1421 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 1422 err = errno; 1423 cryptoerror(LOG_STDERR, 1424 gettext("failed to update the configuration - %s"), 1425 strerror(err)); 1426 cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 1427 _PATH_PKCS11_CONF, strerror(err)); 1428 rc = FAILURE; 1429 } else if (chmod(_PATH_PKCS11_CONF, 1430 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 1431 err = errno; 1432 cryptoerror(LOG_STDERR, 1433 gettext("failed to update the configuration - %s"), 1434 strerror(err)); 1435 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 1436 strerror(err)); 1437 rc = FAILURE; 1438 } else { 1439 rc = SUCCESS; 1440 } 1441 1442 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 1443 err = errno; 1444 cryptoerror(LOG_STDERR, gettext( 1445 "(Warning) failed to remove %s: %s"), 1446 tmpfile_name, strerror(err)); 1447 } 1448 1449 return (rc); 1450 } 1451 1452 1453 /* 1454 * Convert an uentry to a character string 1455 */ 1456 static char * 1457 uent2str(uentry_t *puent) 1458 { 1459 umechlist_t *phead; 1460 boolean_t tok1_present = B_FALSE; 1461 char *buf; 1462 char blank_buf[128]; 1463 1464 if (puent == NULL) { 1465 cryptoerror(LOG_STDERR, gettext("internal error.")); 1466 return (NULL); 1467 } 1468 1469 buf = malloc(BUFSIZ); 1470 if (buf == NULL) { 1471 cryptoerror(LOG_STDERR, gettext("out of memory.")); 1472 return (NULL); 1473 } 1474 1475 /* convert the library name */ 1476 if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) { 1477 free(buf); 1478 return (NULL); 1479 } 1480 1481 1482 /* convert the enabledlist or the disabledlist */ 1483 if (puent->flag_enabledlist == B_TRUE) { 1484 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) { 1485 free(buf); 1486 return (NULL); 1487 } 1488 1489 if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) { 1490 free(buf); 1491 return (NULL); 1492 } 1493 1494 phead = puent->policylist; 1495 while (phead != NULL) { 1496 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) { 1497 free(buf); 1498 return (NULL); 1499 } 1500 1501 phead = phead->next; 1502 if (phead != NULL) { 1503 if (strlcat(buf, SEP_COMMA, BUFSIZ) 1504 >= BUFSIZ) { 1505 free(buf); 1506 return (NULL); 1507 } 1508 } 1509 } 1510 tok1_present = B_TRUE; 1511 } else if (puent->policylist != NULL) { 1512 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) { 1513 free(buf); 1514 return (NULL); 1515 } 1516 1517 if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) { 1518 free(buf); 1519 return (NULL); 1520 } 1521 phead = puent->policylist; 1522 while (phead != NULL) { 1523 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) { 1524 free(buf); 1525 return (NULL); 1526 } 1527 1528 phead = phead->next; 1529 if (phead != NULL) { 1530 if (strlcat(buf, SEP_COMMA, BUFSIZ) 1531 >= BUFSIZ) { 1532 free(buf); 1533 return (NULL); 1534 } 1535 } 1536 } 1537 tok1_present = B_TRUE; 1538 } 1539 1540 if (puent->flag_norandom == B_TRUE) { 1541 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON), 1542 BUFSIZ) >= BUFSIZ) { 1543 free(buf); 1544 return (NULL); 1545 } 1546 1547 if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) { 1548 free(buf); 1549 return (NULL); 1550 } 1551 } 1552 1553 if (strcmp(puent->name, METASLOT_KEYWORD) == 0) { 1554 1555 /* write the metaslot_status= value */ 1556 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON), 1557 BUFSIZ) >= BUFSIZ) { 1558 free(buf); 1559 return (NULL); 1560 } 1561 1562 if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) { 1563 free(buf); 1564 return (NULL); 1565 } 1566 1567 if (puent->flag_metaslot_enabled) { 1568 if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) { 1569 free(buf); 1570 return (NULL); 1571 } 1572 } else { 1573 if (strlcat(buf, METASLOT_DISABLED, BUFSIZ) 1574 >= BUFSIZ) { 1575 free(buf); 1576 return (NULL); 1577 } 1578 } 1579 1580 if (!tok1_present) { 1581 tok1_present = B_TRUE; 1582 } 1583 1584 if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) { 1585 free(buf); 1586 return (NULL); 1587 } 1588 1589 if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) { 1590 free(buf); 1591 return (NULL); 1592 } 1593 1594 if (puent->flag_metaslot_auto_key_migrate) { 1595 if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) { 1596 free(buf); 1597 return (NULL); 1598 } 1599 } else { 1600 if (strlcat(buf, METASLOT_DISABLED, BUFSIZ) >= BUFSIZ) { 1601 free(buf); 1602 return (NULL); 1603 } 1604 } 1605 1606 bzero(blank_buf, sizeof (blank_buf)); 1607 1608 /* write metaslot_token= if specified */ 1609 if (memcmp(puent->metaslot_ks_token, blank_buf, 1610 TOKEN_LABEL_SIZE) != 0) { 1611 /* write the metaslot_status= value */ 1612 if (strlcat(buf, (tok1_present ? 1613 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) { 1614 free(buf); 1615 return (NULL); 1616 } 1617 1618 if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) { 1619 free(buf); 1620 return (NULL); 1621 } 1622 1623 if (strlcat(buf, 1624 (const char *)puent->metaslot_ks_token, BUFSIZ) 1625 >= BUFSIZ) { 1626 free(buf); 1627 return (NULL); 1628 } 1629 } 1630 1631 /* write metaslot_slot= if specified */ 1632 if (memcmp(puent->metaslot_ks_slot, blank_buf, 1633 SLOT_DESCRIPTION_SIZE) != 0) { 1634 /* write the metaslot_status= value */ 1635 if (strlcat(buf, (tok1_present ? 1636 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) { 1637 free(buf); 1638 return (NULL); 1639 } 1640 1641 if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) { 1642 free(buf); 1643 return (NULL); 1644 } 1645 1646 if (strlcat(buf, 1647 (const char *)puent->metaslot_ks_slot, BUFSIZ) 1648 >= BUFSIZ) { 1649 free(buf); 1650 return (NULL); 1651 } 1652 } 1653 } 1654 1655 if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) { 1656 free(buf); 1657 return (NULL); 1658 } 1659 1660 return (buf); 1661 } 1662 1663 1664 /* 1665 * This function updates the default policy mode and the policy exception list 1666 * for a user-level provider based on the mechanism specified in the disable 1667 * or enable subcommand and the update mode. This function is called by the 1668 * enable_uef_lib() or disable_uef_lib(). 1669 */ 1670 int 1671 update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode) 1672 { 1673 CK_MECHANISM_TYPE mech_type; 1674 midstr_t midname; 1675 umechlist_t *phead; 1676 umechlist_t *pcur; 1677 umechlist_t *pumech; 1678 boolean_t found; 1679 int rc = SUCCESS; 1680 1681 if ((puent == NULL) || (marglist == NULL)) { 1682 /* should not happen */ 1683 cryptoerror(LOG_STDERR, gettext("internal error.")); 1684 cryptodebug("update_policylist()- puent or marglist is NULL."); 1685 return (FAILURE); 1686 } 1687 1688 if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) { 1689 /* should not happen */ 1690 cryptoerror(LOG_STDERR, gettext("internal error.")); 1691 cryptodebug("update_policylist() - update_mode is incorrect."); 1692 return (FAILURE); 1693 } 1694 1695 /* 1696 * For each mechanism operand, get its mechanism type first. 1697 * If fails to get the mechanism type, the mechanism operand must be 1698 * invalid, gives an warning and ignore it. Otherwise, 1699 * - convert the mechanism type to the internal representation (hex) 1700 * in the pkcs11.conf file 1701 * - If update_mode == DELETE_MODE, 1702 * If the mechanism is in the policy list, delete it. 1703 * If the mechanism is not in the policy list, do nothing. 1704 * - If update_mode == ADD_MODE, 1705 * If the mechanism is not in the policy list, add it. 1706 * If the mechanism is in the policy list already, do nothing. 1707 */ 1708 while (marglist) { 1709 if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) { 1710 /* 1711 * This mechanism is not a valid PKCS11 mechanism, 1712 * give warning and ignore it. 1713 */ 1714 cryptoerror(LOG_STDERR, gettext( 1715 "(Warning) %s is not a valid PKCS#11 mechanism."), 1716 marglist->name); 1717 rc = FAILURE; 1718 } else { 1719 (void) snprintf(midname, sizeof (midname), "%#010x", 1720 (int)mech_type); 1721 if (update_mode == DELETE_MODE) { 1722 found = B_FALSE; 1723 phead = pcur = puent->policylist; 1724 while (!found && pcur) { 1725 if (strcmp(pcur->name, midname) == 0) { 1726 found = B_TRUE; 1727 } else { 1728 phead = pcur; 1729 pcur = pcur->next; 1730 } 1731 } 1732 1733 if (found) { 1734 if (phead == pcur) { 1735 puent->policylist = 1736 puent->policylist->next; 1737 free(pcur); 1738 } else { 1739 phead->next = pcur->next; 1740 free(pcur); 1741 } 1742 puent->count--; 1743 if (puent->count == 0) { 1744 puent->policylist = NULL; 1745 } 1746 } 1747 } else if (update_mode == ADD_MODE) { 1748 if (!is_in_policylist(midname, 1749 puent->policylist)) { 1750 pumech = create_umech(midname); 1751 if (pumech == NULL) { 1752 rc = FAILURE; 1753 break; 1754 } 1755 phead = puent->policylist; 1756 puent->policylist = pumech; 1757 pumech->next = phead; 1758 puent->count++; 1759 } 1760 } 1761 } 1762 marglist = marglist->next; 1763 } 1764 1765 return (rc); 1766 } 1767 1768 /* 1769 * Open a session to the given slot and check if we can do 1770 * random numbers by asking for one byte. 1771 */ 1772 static boolean_t 1773 check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs) 1774 { 1775 CK_RV rv; 1776 CK_SESSION_HANDLE hSession; 1777 CK_BYTE test_byte; 1778 CK_BYTE_PTR test_byte_ptr = &test_byte; 1779 1780 rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION, 1781 NULL_PTR, NULL, &hSession); 1782 if (rv != CKR_OK) 1783 return (B_FALSE); 1784 1785 /* We care only about the return value */ 1786 rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr, 1787 sizeof (test_byte)); 1788 (void) prov_funcs->C_CloseSession(hSession); 1789 1790 /* 1791 * These checks are purely to determine whether the slot can do 1792 * random numbers. So, we don't check whether the routine 1793 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that 1794 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED. 1795 */ 1796 if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG) 1797 return (B_TRUE); 1798 else 1799 return (B_FALSE); 1800 } 1801 1802 void 1803 display_verbose_mech_header() 1804 { 1805 (void) printf("%28s %s", " ", HDR1); 1806 (void) printf("%28s %s", " ", HDR2); 1807 (void) printf("%28s %s", " ", HDR3); 1808 (void) printf("%28s %s", " ", HDR4); 1809 (void) printf("%28s %s", " ", HDR5); 1810 (void) printf("%28s %s", " ", HDR6); 1811 (void) printf("%-28.28s %s", gettext("mechanism name"), HDR7); 1812 /* 1813 * TRANSLATION_NOTE 1814 * Strictly for appearance's sake, the first header line should be 1815 * as long as the length of the translated text above. The format 1816 * lengths should all match too. 1817 */ 1818 (void) printf("%28s ---- ---- " 1819 "- - - - - - - - - - - - - -\n", 1820 gettext("----------------------------")); 1821 } 1822