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 2006 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 corrsponding 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 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 mech_name = pkcs11_mech2str(pmech_list[j]); 450 (void) printf("%-29s", mech_name); 451 if (verbose) { 452 CK_MECHANISM_INFO mech_info; 453 rv = prov_funcs->C_GetMechanismInfo( 454 prov_slots[i], pmech_list[j], &mech_info); 455 if (rv != CKR_OK) { 456 cryptodebug( 457 "failed to call " 458 "C_GetMechanismInfo() from %s.", 459 libname); 460 (void) free(pmech_list); 461 rc = FAILURE; 462 break; 463 } 464 display_mech_info(&mech_info); 465 } 466 (void) printf("\n"); 467 } 468 (void) free(pmech_list); 469 if (rc == FAILURE) { 470 break; 471 } 472 } 473 474 if (rng_flag != NULL || rc == FAILURE) { 475 goto clean_exit; 476 } 477 478 clean_exit: 479 480 if (rc == FAILURE) { 481 (void) printf(gettext( 482 "%s: failed to retrieve the mechanism list.\n"), libname); 483 } 484 485 if (lib_initialized) { 486 (void) prov_funcs->C_Finalize(NULL_PTR); 487 } 488 489 if (dldesc != NULL) { 490 (void) dlclose(dldesc); 491 } 492 493 if (prov_slots != NULL) { 494 (void) free(prov_slots); 495 } 496 497 return (rc); 498 } 499 500 501 /* 502 * Display the mechanism policy for a user-level library 503 */ 504 int 505 list_policy_for_lib(char *libname) 506 { 507 uentry_t *puent = NULL; 508 int rc; 509 510 if (libname == NULL) { 511 /* should not happen */ 512 cryptoerror(LOG_STDERR, gettext("internal error.")); 513 cryptodebug("list_policy_for_lib() - libname is NULL."); 514 return (FAILURE); 515 } 516 517 /* Get the library entry from the pkcs11.conf file */ 518 if ((puent = getent_uef(libname)) == NULL) { 519 cryptoerror(LOG_STDERR, 520 gettext("%s does not exist."), libname); 521 return (FAILURE); 522 } 523 524 /* Print the policy for this library */ 525 rc = print_uef_policy(puent); 526 free_uentry(puent); 527 528 return (rc); 529 } 530 531 532 /* 533 * Disable mechanisms for a user-level library 534 */ 535 int 536 disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag, 537 mechlist_t *marglist) 538 { 539 uentry_t *puent; 540 int rc; 541 542 if (libname == NULL) { 543 /* should not happen */ 544 cryptoerror(LOG_STDERR, gettext("internal error.")); 545 cryptodebug("disable_uef_lib() - libname is NULL."); 546 return (FAILURE); 547 } 548 549 /* Get the provider entry from the pkcs11.conf file */ 550 if ((puent = getent_uef(libname)) == NULL) { 551 cryptoerror(LOG_STDERR, 552 gettext("%s does not exist."), libname); 553 return (FAILURE); 554 } 555 556 /* 557 * Update the mechanism policy of this library entry, based on 558 * the current policy mode of the library and the mechanisms specified 559 * in CLI. 560 */ 561 if (allflag) { 562 /* 563 * If disabling all, just need to clean up the policylist and 564 * set the flag_enabledlist flag to be B_TRUE. 565 */ 566 free_umechlist(puent->policylist); 567 puent->policylist = NULL; 568 puent->count = 0; 569 puent->flag_enabledlist = B_TRUE; 570 rc = SUCCESS; 571 } else if (marglist != NULL) { 572 if (puent->flag_enabledlist == B_TRUE) { 573 /* 574 * The current default policy mode of this library 575 * is "all are disabled, except ...", so if a 576 * specified mechanism is in the exception list 577 * (the policylist), delete it from the policylist. 578 */ 579 rc = update_policylist(puent, marglist, DELETE_MODE); 580 } else { 581 /* 582 * The current default policy mode of this library 583 * is "all are enabled", so if a specified mechanism 584 * is not in the exception list (policylist), add 585 * it into the policylist. 586 */ 587 rc = update_policylist(puent, marglist, ADD_MODE); 588 } 589 } else if (!rndflag) { 590 /* should not happen */ 591 cryptoerror(LOG_STDERR, gettext("internal error.")); 592 cryptodebug("disable_uef_lib() - wrong arguments."); 593 return (FAILURE); 594 } 595 596 if (rndflag) 597 puent->flag_norandom = B_TRUE; 598 599 if (rc == FAILURE) { 600 free_uentry(puent); 601 return (FAILURE); 602 } 603 604 /* Update the pkcs11.conf file with the updated entry */ 605 rc = update_pkcs11conf(puent); 606 free_uentry(puent); 607 return (rc); 608 } 609 610 611 /* 612 * Enable disabled mechanisms for a user-level library. 613 */ 614 int 615 enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag, 616 mechlist_t *marglist) 617 { 618 uentry_t *puent; 619 int rc = SUCCESS; 620 621 if (libname == NULL) { 622 /* should not happen */ 623 cryptoerror(LOG_STDERR, gettext("internal error.")); 624 cryptodebug("enable_uef_lib() - libname is NULL."); 625 return (FAILURE); 626 } 627 628 /* Get the provider entry from the pkcs11.conf file */ 629 if ((puent = getent_uef(libname)) == NULL) { 630 cryptoerror(LOG_STDERR, 631 gettext("%s does not exist."), libname); 632 return (FAILURE); 633 } 634 635 /* 636 * Update the mechanism policy of this library entry, based on 637 * the current policy mode of the library and the mechanisms 638 * specified in CLI. 639 */ 640 if (allflag) { 641 /* 642 * If enabling all, what needs to be done are cleaning up the 643 * policylist and setting the "flag_enabledlist" flag to 644 * B_FALSE. 645 */ 646 free_umechlist(puent->policylist); 647 puent->policylist = NULL; 648 puent->count = 0; 649 puent->flag_enabledlist = B_FALSE; 650 rc = SUCCESS; 651 } else if (marglist != NULL) { 652 if (puent->flag_enabledlist == B_TRUE) { 653 /* 654 * The current default policy mode of this library 655 * is "all are disabled, except ...", so if a 656 * specified mechanism is not in the exception list 657 * (policylist), add it. 658 */ 659 rc = update_policylist(puent, marglist, ADD_MODE); 660 } else { 661 /* 662 * The current default policy mode of this library 663 * is "all are enabled, except", so if a specified 664 * mechanism is in the exception list (policylist), 665 * delete it. 666 */ 667 rc = update_policylist(puent, marglist, DELETE_MODE); 668 } 669 } else if (!rndflag) { 670 /* should not come here */ 671 cryptoerror(LOG_STDERR, gettext("internal error.")); 672 cryptodebug("enable_uef_lib() - wrong arguments."); 673 return (FAILURE); 674 } 675 676 if (rndflag) 677 puent->flag_norandom = B_FALSE; 678 679 if (rc == FAILURE) { 680 free_uentry(puent); 681 return (FAILURE); 682 } 683 684 /* Update the pkcs11.conf file with the updated entry */ 685 rc = update_pkcs11conf(puent); 686 free_uentry(puent); 687 return (rc); 688 } 689 690 691 /* 692 * Install a user-level library. 693 */ 694 int 695 install_uef_lib(char *libname) 696 { 697 uentry_t *puent; 698 struct stat statbuf; 699 boolean_t found; 700 FILE *pfile; 701 FILE *pfile_tmp; 702 char tmpfile_name[MAXPATHLEN]; 703 char libpath[MAXPATHLEN]; 704 char libbuf[MAXPATHLEN]; 705 char *isa; 706 char buffer[BUFSIZ]; 707 char *ptr; 708 int found_count; 709 int rc = SUCCESS; 710 711 712 if (libname == NULL) { 713 /* should not happen */ 714 cryptoerror(LOG_STDERR, gettext("internal error.")); 715 cryptodebug("install_uef_lib() - libname is NULL."); 716 return (FAILURE); 717 } 718 719 /* Check if the provider already exists in the framework */ 720 if ((puent = getent_uef(libname)) != NULL) { 721 cryptoerror(LOG_STDERR, gettext("%s exists already."), 722 libname); 723 free_uentry(puent); 724 return (FAILURE); 725 } 726 727 /* 728 * Check if the library exists in the system. if $ISA is in the 729 * path, only check the 32bit version. 730 */ 731 if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) { 732 cryptoerror(LOG_STDERR, 733 gettext("the provider name is too long - %s"), libname); 734 return (FAILURE); 735 } 736 737 if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) { 738 *isa = '\000'; 739 isa += strlen(PKCS11_ISA); 740 (void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf, 741 "/", isa); 742 } else { 743 (void) strlcpy(libpath, libname, sizeof (libpath)); 744 } 745 746 /* Check if it is same as the framework library */ 747 if (strcmp(libpath, UEF_FRAME_LIB) == 0) { 748 cryptoerror(LOG_STDERR, gettext( 749 "The framework library %s can not be installed."), 750 libname); 751 return (FAILURE); 752 } 753 754 if (stat(libpath, &statbuf) != 0) { 755 cryptoerror(LOG_STDERR, gettext("%s not found"), libname); 756 return (FAILURE); 757 } 758 759 /* Need to add "\n" to libname for adding into the config file */ 760 if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) { 761 cryptoerror(LOG_STDERR, gettext( 762 "can not install %s; the name is too long."), libname); 763 return (FAILURE); 764 } 765 766 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 767 err = errno; 768 cryptoerror(LOG_STDERR, 769 gettext("failed to update the configuration - %s"), 770 strerror(err)); 771 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 772 return (FAILURE); 773 } 774 775 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 776 err = errno; 777 cryptoerror(LOG_STDERR, 778 gettext("failed to lock the configuration - %s"), 779 strerror(err)); 780 (void) fclose(pfile); 781 return (FAILURE); 782 } 783 784 /* 785 * Create a temporary file in the /etc/crypto directory. 786 */ 787 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 788 if (mkstemp(tmpfile_name) == -1) { 789 err = errno; 790 cryptoerror(LOG_STDERR, 791 gettext("failed to create a temporary file - %s"), 792 strerror(err)); 793 (void) fclose(pfile); 794 return (FAILURE); 795 } 796 797 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 798 err = errno; 799 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 800 tmpfile_name, strerror(err)); 801 (void) fclose(pfile); 802 return (FAILURE); 803 } 804 805 /* 806 * Loop thru the config file. If the file was reserved within a 807 * package bracket, just uncomment it. Other wise, append it at 808 * the end. The resulting file will be saved in the temp file first. 809 */ 810 found_count = 0; 811 rc = SUCCESS; 812 while (fgets(buffer, BUFSIZ, pfile) != NULL) { 813 found = B_FALSE; 814 if (buffer[0] == '#') { 815 ptr = buffer; 816 ptr++; 817 if (strcmp(libname, ptr) == 0) { 818 found = B_TRUE; 819 found_count++; 820 } 821 } 822 823 if (found == B_FALSE) { 824 if (fputs(buffer, pfile_tmp) == EOF) { 825 rc = FAILURE; 826 } 827 } else { 828 if (found_count == 1) { 829 if (fputs(ptr, pfile_tmp) == EOF) { 830 rc = FAILURE; 831 } 832 } else { 833 /* 834 * Found a second entry with #libname. 835 * Should not happen. The pkcs11.conf file 836 * is corrupted. Give a warning and skip 837 * this entry. 838 */ 839 cryptoerror(LOG_STDERR, gettext( 840 "(Warning) Found an additional reserved " 841 "entry for %s."), libname); 842 } 843 } 844 845 if (rc == FAILURE) { 846 break; 847 } 848 } 849 850 if (rc == FAILURE) { 851 cryptoerror(LOG_STDERR, gettext("write error.")); 852 (void) fclose(pfile); 853 (void) fclose(pfile_tmp); 854 if (unlink(tmpfile_name) != 0) { 855 err = errno; 856 cryptoerror(LOG_STDERR, gettext( 857 "(Warning) failed to remove %s: %s"), tmpfile_name, 858 strerror(err)); 859 } 860 return (FAILURE); 861 } 862 863 if (found_count == 0) { 864 /* 865 * This libname was not in package before, append it to the 866 * end of the temp file. 867 */ 868 if (fputs(libname, pfile_tmp) == EOF) { 869 err = errno; 870 cryptoerror(LOG_STDERR, gettext( 871 "failed to write to %s: %s"), tmpfile_name, 872 strerror(err)); 873 (void) fclose(pfile); 874 (void) fclose(pfile_tmp); 875 if (unlink(tmpfile_name) != 0) { 876 err = errno; 877 cryptoerror(LOG_STDERR, gettext( 878 "(Warning) failed to remove %s: %s"), 879 tmpfile_name, strerror(err)); 880 } 881 return (FAILURE); 882 } 883 } 884 885 (void) fclose(pfile); 886 if (fclose(pfile_tmp) != 0) { 887 err = errno; 888 cryptoerror(LOG_STDERR, 889 gettext("failed to close %s: %s"), tmpfile_name, 890 strerror(err)); 891 return (FAILURE); 892 } 893 894 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 895 err = errno; 896 cryptoerror(LOG_STDERR, 897 gettext("failed to update the configuration - %s"), 898 strerror(err)); 899 cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 900 _PATH_PKCS11_CONF, strerror(err)); 901 rc = FAILURE; 902 } else if (chmod(_PATH_PKCS11_CONF, 903 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 904 err = errno; 905 cryptoerror(LOG_STDERR, 906 gettext("failed to update the configuration - %s"), 907 strerror(err)); 908 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 909 strerror(err)); 910 rc = FAILURE; 911 } else { 912 rc = SUCCESS; 913 } 914 915 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 916 err = errno; 917 cryptoerror(LOG_STDERR, gettext( 918 "(Warning) failed to remove %s: %s"), tmpfile_name, 919 strerror(err)); 920 } 921 922 return (rc); 923 } 924 925 926 /* 927 * Uninstall a user-level library. 928 */ 929 int 930 uninstall_uef_lib(char *libname) 931 { 932 uentry_t *puent; 933 FILE *pfile; 934 FILE *pfile_tmp; 935 char buffer[BUFSIZ]; 936 char buffer2[BUFSIZ]; 937 char tmpfile_name[MAXPATHLEN]; 938 char *name; 939 boolean_t found; 940 boolean_t in_package; 941 int len; 942 int rc = SUCCESS; 943 944 if (libname == NULL) { 945 /* should not happen */ 946 cryptoerror(LOG_STDERR, gettext("internal error.")); 947 cryptodebug("uninstall_uef_lib() - libname is NULL."); 948 return (FAILURE); 949 } 950 951 /* Check if the provider exists */ 952 if ((puent = getent_uef(libname)) == NULL) { 953 cryptoerror(LOG_STDERR, 954 gettext("%s does not exist."), libname); 955 return (FAILURE); 956 } 957 free_uentry(puent); 958 959 /* Open the pkcs11.conf file and lock it */ 960 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 961 err = errno; 962 cryptoerror(LOG_STDERR, 963 gettext("failed to update the configuration - %s"), 964 strerror(err)); 965 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 966 return (FAILURE); 967 } 968 969 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 970 err = errno; 971 cryptoerror(LOG_STDERR, 972 gettext("failed to lock the configuration - %s"), 973 strerror(err)); 974 (void) fclose(pfile); 975 return (FAILURE); 976 } 977 978 /* 979 * Create a temporary file in the /etc/crypto directory to save 980 * the new configuration file first. 981 */ 982 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 983 if (mkstemp(tmpfile_name) == -1) { 984 err = errno; 985 cryptoerror(LOG_STDERR, 986 gettext("failed to create a temporary file - %s"), 987 strerror(err)); 988 (void) fclose(pfile); 989 return (FAILURE); 990 } 991 992 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 993 err = errno; 994 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 995 tmpfile_name, strerror(err)); 996 if (unlink(tmpfile_name) != 0) { 997 err = errno; 998 cryptoerror(LOG_STDERR, gettext( 999 "(Warning) failed to remove %s: %s"), 1000 tmpfile_name, strerror(err)); 1001 } 1002 (void) fclose(pfile); 1003 return (FAILURE); 1004 } 1005 1006 1007 /* 1008 * Loop thru the config file. If the library to be uninstalled 1009 * is in a package, just comment it off. 1010 */ 1011 in_package = B_FALSE; 1012 while (fgets(buffer, BUFSIZ, pfile) != NULL) { 1013 found = B_FALSE; 1014 if (!(buffer[0] == ' ' || buffer[0] == '\n' || 1015 buffer[0] == '\t')) { 1016 if (strstr(buffer, " Start ") != NULL) { 1017 in_package = B_TRUE; 1018 } else if (strstr(buffer, " End ") != NULL) { 1019 in_package = B_FALSE; 1020 } else if (buffer[0] != '#') { 1021 (void) strlcpy(buffer2, buffer, BUFSIZ); 1022 1023 /* get rid of trailing '\n' */ 1024 len = strlen(buffer2); 1025 if (buffer2[len-1] == '\n') { 1026 len--; 1027 } 1028 buffer2[len] = '\0'; 1029 1030 if ((name = strtok(buffer2, SEP_COLON)) 1031 == NULL) { 1032 rc = FAILURE; 1033 break; 1034 } else if (strcmp(libname, name) == 0) { 1035 found = B_TRUE; 1036 } 1037 } 1038 } 1039 1040 if (found) { 1041 if (in_package) { 1042 (void) snprintf(buffer2, sizeof (buffer2), 1043 "%s%s%s", "#", libname, "\n"); 1044 if (fputs(buffer2, pfile_tmp) == EOF) { 1045 rc = FAILURE; 1046 } 1047 } 1048 } else { 1049 if (fputs(buffer, pfile_tmp) == EOF) { 1050 rc = FAILURE; 1051 } 1052 } 1053 1054 if (rc == FAILURE) { 1055 break; 1056 } 1057 } 1058 1059 if (rc == FAILURE) { 1060 cryptoerror(LOG_STDERR, gettext("write error.")); 1061 (void) fclose(pfile); 1062 (void) fclose(pfile_tmp); 1063 if (unlink(tmpfile_name) != 0) { 1064 err = errno; 1065 cryptoerror(LOG_STDERR, gettext( 1066 "(Warning) failed to remove %s: %s"), 1067 tmpfile_name, strerror(err)); 1068 } 1069 return (FAILURE); 1070 } 1071 1072 (void) fclose(pfile); 1073 if (fclose(pfile_tmp) != 0) { 1074 err = errno; 1075 cryptoerror(LOG_STDERR, 1076 gettext("failed to close a temporary file - %s"), 1077 strerror(err)); 1078 return (FAILURE); 1079 } 1080 1081 /* Now update the real config file */ 1082 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 1083 err = errno; 1084 cryptoerror(LOG_STDERR, 1085 gettext("failed to update the configuration - %s"), 1086 strerror(err)); 1087 cryptodebug("failed to rename %s to %s: %s", tmpfile, 1088 _PATH_PKCS11_CONF, strerror(err)); 1089 rc = FAILURE; 1090 } else if (chmod(_PATH_PKCS11_CONF, 1091 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 1092 err = errno; 1093 cryptoerror(LOG_STDERR, 1094 gettext("failed to update the configuration - %s"), 1095 strerror(err)); 1096 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 1097 strerror(err)); 1098 rc = FAILURE; 1099 } else { 1100 rc = SUCCESS; 1101 } 1102 1103 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 1104 err = errno; 1105 cryptoerror(LOG_STDERR, gettext( 1106 "(Warning) failed to remove %s: %s"), 1107 tmpfile_name, strerror(err)); 1108 } 1109 1110 return (rc); 1111 } 1112 1113 1114 int 1115 display_policy(uentry_t *puent) 1116 { 1117 CK_MECHANISM_TYPE mech_id; 1118 char *mech_name; 1119 umechlist_t *ptr; 1120 1121 if (puent == NULL) { 1122 return (SUCCESS); 1123 } 1124 1125 if (puent->flag_enabledlist == B_FALSE) { 1126 (void) printf(gettext("%s: all mechanisms are enabled"), 1127 puent->name); 1128 ptr = puent->policylist; 1129 if (ptr == NULL) { 1130 (void) printf("."); 1131 } else { 1132 (void) printf(gettext(", except ")); 1133 while (ptr != NULL) { 1134 mech_id = strtoul(ptr->name, NULL, 0); 1135 if (mech_id & CKO_VENDOR_DEFINED) { 1136 /* vendor defined mechanism */ 1137 (void) printf("%s", ptr->name); 1138 } else { 1139 mech_name = pkcs11_mech2str(mech_id); 1140 if (mech_name == NULL) { 1141 return (FAILURE); 1142 } 1143 (void) printf("%s", mech_name); 1144 free(mech_name); 1145 } 1146 1147 ptr = ptr->next; 1148 if (ptr == NULL) { 1149 (void) printf("."); 1150 } else { 1151 (void) printf(","); 1152 } 1153 } 1154 } 1155 } else { /* puent->flag_enabledlist == B_TRUE */ 1156 (void) printf(gettext("%s: all mechanisms are disabled"), 1157 puent->name); 1158 ptr = puent->policylist; 1159 if (ptr == NULL) { 1160 (void) printf("."); 1161 } else { 1162 (void) printf(gettext(", except ")); 1163 while (ptr != NULL) { 1164 mech_id = strtoul(ptr->name, NULL, 0); 1165 if (mech_id & CKO_VENDOR_DEFINED) { 1166 /* vendor defined mechanism */ 1167 (void) printf("%s", ptr->name); 1168 } else { 1169 mech_name = pkcs11_mech2str(mech_id); 1170 if (mech_name == NULL) { 1171 return (FAILURE); 1172 } 1173 (void) printf("%s", mech_name); 1174 free(mech_name); 1175 } 1176 ptr = ptr->next; 1177 if (ptr == NULL) { 1178 (void) printf("."); 1179 } else { 1180 (void) printf(","); 1181 } 1182 } 1183 } 1184 } 1185 return (SUCCESS); 1186 } 1187 1188 1189 1190 /* 1191 * Print out the mechanism policy for a user-level provider pointed by puent. 1192 */ 1193 int 1194 print_uef_policy(uentry_t *puent) 1195 { 1196 flag_val_t rng_flag; 1197 1198 if (puent == NULL) { 1199 return (FAILURE); 1200 } 1201 1202 rng_flag = NO_RNG; 1203 if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE, 1204 B_FALSE, B_FALSE) != SUCCESS) { 1205 cryptoerror(LOG_STDERR, 1206 gettext("%s internal error."), puent->name); 1207 return (FAILURE); 1208 } 1209 1210 if (display_policy(puent) != SUCCESS) { 1211 goto failed_exit; 1212 } 1213 1214 1215 if (puent->flag_norandom == B_TRUE) 1216 /* 1217 * TRANSLATION_NOTE: 1218 * "random" is a keyword and not to be translated. 1219 */ 1220 (void) printf(gettext(" %s is disabled."), "random"); 1221 else { 1222 if (rng_flag == HAS_RNG) 1223 /* 1224 * TRANSLATION_NOTE: 1225 * "random" is a keyword and not to be translated. 1226 */ 1227 (void) printf(gettext(" %s is enabled."), "random"); 1228 } 1229 (void) printf("\n"); 1230 1231 return (SUCCESS); 1232 1233 failed_exit: 1234 1235 (void) printf(gettext("\nout of memory.\n")); 1236 return (FAILURE); 1237 } 1238 1239 1240 /* 1241 * Check if the mechanism is in the mechanism list. 1242 */ 1243 static boolean_t 1244 is_in_policylist(midstr_t mechname, umechlist_t *plist) 1245 { 1246 boolean_t found = B_FALSE; 1247 1248 if (mechname == NULL) { 1249 return (B_FALSE); 1250 } 1251 1252 while (plist != NULL) { 1253 if (strcmp(plist->name, mechname) == 0) { 1254 found = B_TRUE; 1255 break; 1256 } 1257 plist = plist->next; 1258 } 1259 1260 return (found); 1261 } 1262 1263 1264 /* 1265 * Update the pkcs11.conf file with the updated entry. 1266 */ 1267 int 1268 update_pkcs11conf(uentry_t *puent) 1269 { 1270 FILE *pfile; 1271 FILE *pfile_tmp; 1272 char buffer[BUFSIZ]; 1273 char buffer2[BUFSIZ]; 1274 char tmpfile_name[MAXPATHLEN]; 1275 char *name; 1276 char *str; 1277 int len; 1278 int rc = SUCCESS; 1279 boolean_t found; 1280 1281 if (puent == NULL) { 1282 cryptoerror(LOG_STDERR, gettext("internal error.")); 1283 return (FAILURE); 1284 } 1285 1286 /* Open the pkcs11.conf file */ 1287 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 1288 err = errno; 1289 cryptoerror(LOG_STDERR, 1290 gettext("failed to update the configuration - %s"), 1291 strerror(err)); 1292 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 1293 return (FAILURE); 1294 } 1295 1296 /* Lock the pkcs11.conf file */ 1297 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 1298 err = errno; 1299 cryptoerror(LOG_STDERR, 1300 gettext("failed to update the configuration - %s"), 1301 strerror(err)); 1302 (void) fclose(pfile); 1303 return (FAILURE); 1304 } 1305 1306 /* 1307 * Create a temporary file in the /etc/crypto directory to save 1308 * updated configuration file first. 1309 */ 1310 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 1311 if (mkstemp(tmpfile_name) == -1) { 1312 err = errno; 1313 cryptoerror(LOG_STDERR, 1314 gettext("failed to create a temporary file - %s"), 1315 strerror(err)); 1316 (void) fclose(pfile); 1317 return (FAILURE); 1318 } 1319 1320 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 1321 err = errno; 1322 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 1323 tmpfile_name, strerror(err)); 1324 if (unlink(tmpfile_name) != 0) { 1325 err = errno; 1326 cryptoerror(LOG_STDERR, gettext( 1327 "(Warning) failed to remove %s: %s"), 1328 tmpfile_name, strerror(err)); 1329 } 1330 (void) fclose(pfile); 1331 return (FAILURE); 1332 } 1333 1334 1335 /* 1336 * Loop thru entire pkcs11.conf file, update the entry to be 1337 * updated and save the updated file to the temporary file first. 1338 */ 1339 while (fgets(buffer, BUFSIZ, pfile) != NULL) { 1340 found = B_FALSE; 1341 if (!(buffer[0] == '#' || buffer[0] == ' ' || 1342 buffer[0] == '\n'|| buffer[0] == '\t')) { 1343 /* 1344 * Get the provider name from this line and check if 1345 * this is the entry to be updated. Note: can not use 1346 * "buffer" directly because strtok will change its 1347 * value. 1348 */ 1349 (void) strlcpy(buffer2, buffer, BUFSIZ); 1350 1351 /* get rid of trailing '\n' */ 1352 len = strlen(buffer2); 1353 if (buffer2[len-1] == '\n') { 1354 len--; 1355 } 1356 buffer2[len] = '\0'; 1357 1358 if ((name = strtok(buffer2, SEP_COLON)) == NULL) { 1359 rc = FAILURE; 1360 break; 1361 } else if (strcmp(puent->name, name) == 0) { 1362 found = B_TRUE; 1363 } 1364 } 1365 1366 if (found) { 1367 /* 1368 * This is the entry to be modified, get the updated 1369 * string. 1370 */ 1371 if ((str = uent2str(puent)) == NULL) { 1372 rc = FAILURE; 1373 break; 1374 } else { 1375 (void) strlcpy(buffer, str, BUFSIZ); 1376 free(str); 1377 } 1378 } 1379 1380 if (fputs(buffer, pfile_tmp) == EOF) { 1381 err = errno; 1382 cryptoerror(LOG_STDERR, gettext( 1383 "failed to write to a temp file: %s."), 1384 strerror(err)); 1385 rc = FAILURE; 1386 break; 1387 } 1388 } 1389 1390 if (rc == FAILURE) { 1391 (void) fclose(pfile); 1392 (void) fclose(pfile_tmp); 1393 if (unlink(tmpfile_name) != 0) { 1394 err = errno; 1395 cryptoerror(LOG_STDERR, gettext( 1396 "(Warning) failed to remove %s: %s"), 1397 tmpfile_name, strerror(err)); 1398 } 1399 return (FAILURE); 1400 } 1401 1402 (void) fclose(pfile); 1403 if (fclose(pfile_tmp) != 0) { 1404 err = errno; 1405 cryptoerror(LOG_STDERR, 1406 gettext("failed to close %s: %s"), tmpfile_name, 1407 strerror(err)); 1408 return (FAILURE); 1409 } 1410 1411 /* Copy the temporary file to the pkcs11.conf file */ 1412 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 1413 err = errno; 1414 cryptoerror(LOG_STDERR, 1415 gettext("failed to update the configuration - %s"), 1416 strerror(err)); 1417 cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 1418 _PATH_PKCS11_CONF, strerror(err)); 1419 rc = FAILURE; 1420 } else if (chmod(_PATH_PKCS11_CONF, 1421 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 1422 err = errno; 1423 cryptoerror(LOG_STDERR, 1424 gettext("failed to update the configuration - %s"), 1425 strerror(err)); 1426 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 1427 strerror(err)); 1428 rc = FAILURE; 1429 } else { 1430 rc = SUCCESS; 1431 } 1432 1433 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 1434 err = errno; 1435 cryptoerror(LOG_STDERR, gettext( 1436 "(Warning) failed to remove %s: %s"), 1437 tmpfile_name, strerror(err)); 1438 } 1439 1440 return (rc); 1441 } 1442 1443 1444 /* 1445 * Convert an uentry to a character string 1446 */ 1447 static char * 1448 uent2str(uentry_t *puent) 1449 { 1450 umechlist_t *phead; 1451 boolean_t tok1_present = B_FALSE; 1452 char *buf; 1453 char blank_buf[128]; 1454 1455 if (puent == NULL) { 1456 cryptoerror(LOG_STDERR, gettext("internal error.")); 1457 return (NULL); 1458 } 1459 1460 buf = malloc(BUFSIZ); 1461 if (buf == NULL) { 1462 cryptoerror(LOG_STDERR, gettext("out of memory.")); 1463 return (NULL); 1464 } 1465 1466 /* convert the library name */ 1467 if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) { 1468 free(buf); 1469 return (NULL); 1470 } 1471 1472 1473 /* convert the enabledlist or the disabledlist */ 1474 if (puent->flag_enabledlist == B_TRUE) { 1475 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) { 1476 free(buf); 1477 return (NULL); 1478 } 1479 1480 if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) { 1481 free(buf); 1482 return (NULL); 1483 } 1484 1485 phead = puent->policylist; 1486 while (phead != NULL) { 1487 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) { 1488 free(buf); 1489 return (NULL); 1490 } 1491 1492 phead = phead->next; 1493 if (phead != NULL) { 1494 if (strlcat(buf, SEP_COMMA, BUFSIZ) 1495 >= BUFSIZ) { 1496 free(buf); 1497 return (NULL); 1498 } 1499 } 1500 } 1501 tok1_present = B_TRUE; 1502 } else if (puent->policylist != NULL) { 1503 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) { 1504 free(buf); 1505 return (NULL); 1506 } 1507 1508 if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) { 1509 free(buf); 1510 return (NULL); 1511 } 1512 phead = puent->policylist; 1513 while (phead != NULL) { 1514 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) { 1515 free(buf); 1516 return (NULL); 1517 } 1518 1519 phead = phead->next; 1520 if (phead != NULL) { 1521 if (strlcat(buf, SEP_COMMA, BUFSIZ) 1522 >= BUFSIZ) { 1523 free(buf); 1524 return (NULL); 1525 } 1526 } 1527 } 1528 tok1_present = B_TRUE; 1529 } 1530 1531 if (puent->flag_norandom == B_TRUE) { 1532 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON), 1533 BUFSIZ) >= BUFSIZ) { 1534 free(buf); 1535 return (NULL); 1536 } 1537 1538 if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) { 1539 free(buf); 1540 return (NULL); 1541 } 1542 } 1543 1544 if (strcmp(puent->name, METASLOT_KEYWORD) == 0) { 1545 1546 /* write the metaslot_status= value */ 1547 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON), 1548 BUFSIZ) >= BUFSIZ) { 1549 free(buf); 1550 return (NULL); 1551 } 1552 1553 if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) { 1554 free(buf); 1555 return (NULL); 1556 } 1557 1558 if (puent->flag_metaslot_enabled) { 1559 if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) { 1560 free(buf); 1561 return (NULL); 1562 } 1563 } else { 1564 if (strlcat(buf, METASLOT_DISABLED, BUFSIZ) 1565 >= BUFSIZ) { 1566 free(buf); 1567 return (NULL); 1568 } 1569 } 1570 1571 if (!tok1_present) { 1572 tok1_present = B_TRUE; 1573 } 1574 1575 if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) { 1576 free(buf); 1577 return (NULL); 1578 } 1579 1580 if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) { 1581 free(buf); 1582 return (NULL); 1583 } 1584 1585 if (puent->flag_metaslot_auto_key_migrate) { 1586 if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) { 1587 free(buf); 1588 return (NULL); 1589 } 1590 } else { 1591 if (strlcat(buf, METASLOT_DISABLED, BUFSIZ) >= BUFSIZ) { 1592 free(buf); 1593 return (NULL); 1594 } 1595 } 1596 1597 bzero(blank_buf, sizeof (blank_buf)); 1598 1599 /* write metaslot_token= if specified */ 1600 if (memcmp(puent->metaslot_ks_token, blank_buf, 1601 TOKEN_LABEL_SIZE) != 0) { 1602 /* write the metaslot_status= value */ 1603 if (strlcat(buf, (tok1_present ? 1604 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) { 1605 free(buf); 1606 return (NULL); 1607 } 1608 1609 if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) { 1610 free(buf); 1611 return (NULL); 1612 } 1613 1614 if (strlcat(buf, 1615 (const char *)puent->metaslot_ks_token, BUFSIZ) 1616 >= BUFSIZ) { 1617 free(buf); 1618 return (NULL); 1619 } 1620 } 1621 1622 /* write metaslot_slot= if specified */ 1623 if (memcmp(puent->metaslot_ks_slot, blank_buf, 1624 SLOT_DESCRIPTION_SIZE) != 0) { 1625 /* write the metaslot_status= value */ 1626 if (strlcat(buf, (tok1_present ? 1627 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) { 1628 free(buf); 1629 return (NULL); 1630 } 1631 1632 if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) { 1633 free(buf); 1634 return (NULL); 1635 } 1636 1637 if (strlcat(buf, 1638 (const char *)puent->metaslot_ks_slot, BUFSIZ) 1639 >= BUFSIZ) { 1640 free(buf); 1641 return (NULL); 1642 } 1643 } 1644 } 1645 1646 if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) { 1647 free(buf); 1648 return (NULL); 1649 } 1650 1651 return (buf); 1652 } 1653 1654 1655 /* 1656 * This function updates the default policy mode and the policy exception list 1657 * for a user-level provider based on the mechanism specified in the disable 1658 * or enable subcommand and the update mode. This function is called by the 1659 * enable_uef_lib() or disable_uef_lib(). 1660 */ 1661 int 1662 update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode) 1663 { 1664 CK_MECHANISM_TYPE mech_type; 1665 midstr_t midname; 1666 umechlist_t *phead; 1667 umechlist_t *pcur; 1668 umechlist_t *pumech; 1669 boolean_t found; 1670 int rc = SUCCESS; 1671 1672 if ((puent == NULL) || (marglist == NULL)) { 1673 /* should not happen */ 1674 cryptoerror(LOG_STDERR, gettext("internal error.")); 1675 cryptodebug("update_policylist()- puent or marglist is NULL."); 1676 return (FAILURE); 1677 } 1678 1679 if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) { 1680 /* should not happen */ 1681 cryptoerror(LOG_STDERR, gettext("internal error.")); 1682 cryptodebug("update_policylist() - update_mode is incorrect."); 1683 return (FAILURE); 1684 } 1685 1686 /* 1687 * For each mechanism operand, get its mechanism type first. 1688 * If fails to get the mechanism type, the mechanism operand must be 1689 * invalid, gives an warning and ignore it. Otherwise, 1690 * - convert the mechanism type to the internal representation (hex) 1691 * in the pkcs11.conf file 1692 * - If update_mode == DELETE_MODE, 1693 * If the mechanism is in the policy list, delete it. 1694 * If the mechanism is not in the policy list, do nothing. 1695 * - If update_mode == ADD_MODE, 1696 * If the mechanism is not in the policy list, add it. 1697 * If the mechanism is in the policy list already, do nothing. 1698 */ 1699 while (marglist) { 1700 if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) { 1701 /* 1702 * This mechanism is not a valid PKCS11 mechanism, 1703 * give warning and ignore it. 1704 */ 1705 cryptoerror(LOG_STDERR, gettext( 1706 "(Warning) %s is not a valid PKCS#11 mechanism."), 1707 marglist->name); 1708 rc = FAILURE; 1709 } else { 1710 (void) snprintf(midname, sizeof (midname), "%#010x", 1711 (int)mech_type); 1712 if (update_mode == DELETE_MODE) { 1713 found = B_FALSE; 1714 phead = pcur = puent->policylist; 1715 while (!found && pcur) { 1716 if (strcmp(pcur->name, midname) == 0) { 1717 found = B_TRUE; 1718 } else { 1719 phead = pcur; 1720 pcur = pcur->next; 1721 } 1722 } 1723 1724 if (found) { 1725 if (phead == pcur) { 1726 puent->policylist = 1727 puent->policylist->next; 1728 free(pcur); 1729 } else { 1730 phead->next = pcur->next; 1731 free(pcur); 1732 } 1733 puent->count--; 1734 if (puent->count == 0) { 1735 puent->policylist = NULL; 1736 } 1737 } 1738 } else if (update_mode == ADD_MODE) { 1739 if (!is_in_policylist(midname, 1740 puent->policylist)) { 1741 pumech = create_umech(midname); 1742 if (pumech == NULL) { 1743 rc = FAILURE; 1744 break; 1745 } 1746 phead = puent->policylist; 1747 puent->policylist = pumech; 1748 pumech->next = phead; 1749 puent->count++; 1750 } 1751 } 1752 } 1753 marglist = marglist->next; 1754 } 1755 1756 return (rc); 1757 } 1758 1759 /* 1760 * Open a session to the given slot and check if we can do 1761 * random numbers by asking for one byte. 1762 */ 1763 static boolean_t 1764 check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs) 1765 { 1766 CK_RV rv; 1767 CK_SESSION_HANDLE hSession; 1768 CK_BYTE test_byte; 1769 CK_BYTE_PTR test_byte_ptr = &test_byte; 1770 1771 rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION, 1772 NULL_PTR, NULL, &hSession); 1773 if (rv != CKR_OK) 1774 return (B_FALSE); 1775 1776 /* We care only about the return value */ 1777 rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr, 1778 sizeof (test_byte)); 1779 (void) prov_funcs->C_CloseSession(hSession); 1780 1781 /* 1782 * These checks are purely to determine whether the slot can do 1783 * random numbers. So, we don't check whether the routine 1784 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that 1785 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED. 1786 */ 1787 if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG) 1788 return (B_TRUE); 1789 else 1790 return (B_FALSE); 1791 } 1792 1793 void 1794 display_verbose_mech_header() 1795 { 1796 (void) printf("%28s %s", " ", HDR1); 1797 (void) printf("%28s %s", " ", HDR2); 1798 (void) printf("%28s %s", " ", HDR3); 1799 (void) printf("%28s %s", " ", HDR4); 1800 (void) printf("%28s %s", " ", HDR5); 1801 (void) printf("%28s %s", " ", HDR6); 1802 (void) printf("%-28.28s %s", gettext("mechanism name"), HDR7); 1803 /* 1804 * TRANSLATION_NOTE: 1805 * Strictly for appearance's sake, the first header line should be 1806 * as long as the length of the translated text above. The format 1807 * lengths should all match too. 1808 */ 1809 (void) printf("%28s ---- ---- " 1810 "- - - - - - - - - - - - - -\n", 1811 gettext("----------------------------")); 1812 } 1813