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