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