17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 599ebb4caSwyllys * Common Development and Distribution License (the "License"). 699ebb4caSwyllys * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 2212240b1dSDarren J Moffat * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 24*6ea3c060SGarrett D'Amore /* 25*6ea3c060SGarrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights resrved. 26*6ea3c060SGarrett D'Amore */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <cryptoutil.h> 297c478bd9Sstevel@tonic-gate #include <fcntl.h> 307c478bd9Sstevel@tonic-gate #include <libintl.h> 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <strings.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate #include <dlfcn.h> 377c478bd9Sstevel@tonic-gate #include <link.h> 387c478bd9Sstevel@tonic-gate #include <sys/types.h> 397c478bd9Sstevel@tonic-gate #include <sys/stat.h> 407c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 417c478bd9Sstevel@tonic-gate #include "cryptoadm.h" 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #define HDR1 " P\n" 447c478bd9Sstevel@tonic-gate #define HDR2 " S V K a U D\n" 457c478bd9Sstevel@tonic-gate #define HDR3 " i e e i n e\n" 467c478bd9Sstevel@tonic-gate #define HDR4 " S g V r y r W w r\n" 477c478bd9Sstevel@tonic-gate #define HDR5 " E D D i n e i G G r r i\n" 487c478bd9Sstevel@tonic-gate #define HDR6 " H n e i g + r + e e a a v E\n" 497c478bd9Sstevel@tonic-gate #define HDR7 "min max W c c g n R i R n n p p e C\n" 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate static int err; /* To store errno which may be overwritten by gettext() */ 537c478bd9Sstevel@tonic-gate static boolean_t is_in_policylist(midstr_t, umechlist_t *); 547c478bd9Sstevel@tonic-gate static char *uent2str(uentry_t *); 557c478bd9Sstevel@tonic-gate static boolean_t check_random(CK_SLOT_ID, CK_FUNCTION_LIST_PTR); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate static void display_slot_flags(CK_FLAGS flags) 587c478bd9Sstevel@tonic-gate { 597c478bd9Sstevel@tonic-gate (void) printf(gettext("Slot Flags: ")); 607c478bd9Sstevel@tonic-gate if (flags & CKF_TOKEN_PRESENT) 617c478bd9Sstevel@tonic-gate (void) printf("CKF_TOKEN_PRESENT "); 627c478bd9Sstevel@tonic-gate if (flags & CKF_REMOVABLE_DEVICE) 637c478bd9Sstevel@tonic-gate (void) printf("CKF_REMOVABLE_DEVICE "); 647c478bd9Sstevel@tonic-gate if (flags & CKF_HW_SLOT) 657c478bd9Sstevel@tonic-gate (void) printf("CKF_HW_SLOT "); 667c478bd9Sstevel@tonic-gate (void) printf("\n"); 677c478bd9Sstevel@tonic-gate } 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate void 707c478bd9Sstevel@tonic-gate display_token_flags(CK_FLAGS flags) 717c478bd9Sstevel@tonic-gate { 727c478bd9Sstevel@tonic-gate (void) printf(gettext("Flags: ")); 737c478bd9Sstevel@tonic-gate if (flags & CKF_RNG) 747c478bd9Sstevel@tonic-gate (void) printf("CKF_RNG "); 757c478bd9Sstevel@tonic-gate if (flags & CKF_WRITE_PROTECTED) 767c478bd9Sstevel@tonic-gate (void) printf("CKF_WRITE_PROTECTED "); 777c478bd9Sstevel@tonic-gate if (flags & CKF_LOGIN_REQUIRED) 787c478bd9Sstevel@tonic-gate (void) printf("CKF_LOGIN_REQUIRED "); 797c478bd9Sstevel@tonic-gate if (flags & CKF_USER_PIN_INITIALIZED) 807c478bd9Sstevel@tonic-gate (void) printf("CKF_USER_PIN_INITIALIZED "); 817c478bd9Sstevel@tonic-gate if (flags & CKF_RESTORE_KEY_NOT_NEEDED) 827c478bd9Sstevel@tonic-gate (void) printf("CKF_RESTORE_KEY_NOT_NEEDED "); 837c478bd9Sstevel@tonic-gate if (flags & CKF_CLOCK_ON_TOKEN) 847c478bd9Sstevel@tonic-gate (void) printf("CKF_CLOCK_ON_TOKEN "); 857c478bd9Sstevel@tonic-gate if (flags & CKF_PROTECTED_AUTHENTICATION_PATH) 867c478bd9Sstevel@tonic-gate (void) printf("CKF_PROTECTED_AUTHENTICATION_PATH "); 877c478bd9Sstevel@tonic-gate if (flags & CKF_DUAL_CRYPTO_OPERATIONS) 887c478bd9Sstevel@tonic-gate (void) printf("CKF_DUAL_CRYPTO_OPERATIONS "); 897c478bd9Sstevel@tonic-gate if (flags & CKF_TOKEN_INITIALIZED) 907c478bd9Sstevel@tonic-gate (void) printf("CKF_TOKEN_INITIALIZED "); 917c478bd9Sstevel@tonic-gate if (flags & CKF_SECONDARY_AUTHENTICATION) 927c478bd9Sstevel@tonic-gate (void) printf("CKF_SECONDARY_AUTHENTICATION "); 937c478bd9Sstevel@tonic-gate if (flags & CKF_USER_PIN_COUNT_LOW) 947c478bd9Sstevel@tonic-gate (void) printf("CKF_USER_PIN_COUNT_LOW "); 957c478bd9Sstevel@tonic-gate if (flags & CKF_USER_PIN_FINAL_TRY) 967c478bd9Sstevel@tonic-gate (void) printf("CKF_USER_PIN_FINAL_TRY "); 977c478bd9Sstevel@tonic-gate if (flags & CKF_USER_PIN_LOCKED) 987c478bd9Sstevel@tonic-gate (void) printf("CKF_USER_PIN_LOCKED "); 997c478bd9Sstevel@tonic-gate if (flags & CKF_USER_PIN_TO_BE_CHANGED) 1007c478bd9Sstevel@tonic-gate (void) printf("CKF_USER_PIN_TO_BE_CHANGED "); 1017c478bd9Sstevel@tonic-gate if (flags & CKF_SO_PIN_COUNT_LOW) 1027c478bd9Sstevel@tonic-gate (void) printf("CKF_SO_PIN_COUNT_LOW "); 1037c478bd9Sstevel@tonic-gate if (flags & CKF_SO_PIN_FINAL_TRY) 1047c478bd9Sstevel@tonic-gate (void) printf("CKF_SO_PIN_FINAL_TRY "); 1057c478bd9Sstevel@tonic-gate if (flags & CKF_SO_PIN_LOCKED) 1067c478bd9Sstevel@tonic-gate (void) printf("CKF_SO_PIN_LOCKED "); 1077c478bd9Sstevel@tonic-gate if (flags & CKF_SO_PIN_TO_BE_CHANGED) 1087c478bd9Sstevel@tonic-gate (void) printf("CKF_SO_PIN_TO_BE_CHANGED "); 1097c478bd9Sstevel@tonic-gate if (flags & CKF_SO_PIN_TO_BE_CHANGED) 1107c478bd9Sstevel@tonic-gate (void) printf("CKF_SO_PIN_TO_BE_CHANGED "); 1117c478bd9Sstevel@tonic-gate (void) printf("\n"); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate void 1157c478bd9Sstevel@tonic-gate display_mech_info(CK_MECHANISM_INFO *mechInfo) 1167c478bd9Sstevel@tonic-gate { 1177c478bd9Sstevel@tonic-gate CK_FLAGS ec_flags = CKF_EC_F_P | CKF_EC_F_2M | CKF_EC_ECPARAMETERS | 1187c478bd9Sstevel@tonic-gate CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS | CKF_EC_COMPRESS; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate (void) printf("%-4ld %-4ld ", mechInfo->ulMinKeySize, 1217c478bd9Sstevel@tonic-gate mechInfo->ulMaxKeySize); 1227c478bd9Sstevel@tonic-gate (void) printf("%s %s %s %s %s %s %s %s %s %s %s %s " 1237c478bd9Sstevel@tonic-gate "%s %s", 1247c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_HW) ? "X" : ".", 1257c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_ENCRYPT) ? "X" : ".", 1267c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_DECRYPT) ? "X" : ".", 1277c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_DIGEST) ? "X" : ".", 1287c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_SIGN) ? "X" : ".", 1297c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_SIGN_RECOVER) ? "X" : ".", 1307c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_VERIFY) ? "X" : ".", 1317c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_VERIFY_RECOVER) ? "X" : ".", 1327c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_GENERATE) ? "X" : ".", 1337c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_GENERATE_KEY_PAIR) ? "X" : ".", 1347c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_WRAP) ? "X" : ".", 1357c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_UNWRAP) ? "X" : ".", 1367c478bd9Sstevel@tonic-gate (mechInfo->flags & CKF_DERIVE) ? "X" : ".", 1377c478bd9Sstevel@tonic-gate (mechInfo->flags & ec_flags) ? "X" : "."); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* 1417c478bd9Sstevel@tonic-gate * Converts the provided list of mechanism names in their string format to 1422321aa36Sda73024 * their corresponding PKCS#11 mechanism IDs. 1437c478bd9Sstevel@tonic-gate * 1447c478bd9Sstevel@tonic-gate * The list of mechanism names to be converted is provided in the 1457c478bd9Sstevel@tonic-gate * "mlist" argument. The list of converted mechanism IDs is returned 1467c478bd9Sstevel@tonic-gate * in the "pmech_list" argument. 1477c478bd9Sstevel@tonic-gate * 1487c478bd9Sstevel@tonic-gate * This function is called by list_metaslot_info() and 1497c478bd9Sstevel@tonic-gate * list_mechlist_for_lib() functions. 1507c478bd9Sstevel@tonic-gate */ 1517c478bd9Sstevel@tonic-gate int 1527c478bd9Sstevel@tonic-gate convert_mechlist(CK_MECHANISM_TYPE **pmech_list, CK_ULONG *mech_count, 1537c478bd9Sstevel@tonic-gate mechlist_t *mlist) 1547c478bd9Sstevel@tonic-gate { 1557c478bd9Sstevel@tonic-gate int i, n = 0; 1567c478bd9Sstevel@tonic-gate mechlist_t *p = mlist; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate while (p != NULL) { 1597c478bd9Sstevel@tonic-gate p = p->next; 1607c478bd9Sstevel@tonic-gate n++; 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate *pmech_list = malloc(n * sizeof (CK_MECHANISM_TYPE)); 1647c478bd9Sstevel@tonic-gate if (pmech_list == NULL) { 1657c478bd9Sstevel@tonic-gate cryptodebug("out of memory"); 1667c478bd9Sstevel@tonic-gate return (FAILURE); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate p = mlist; 1697c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 1707c478bd9Sstevel@tonic-gate if (pkcs11_str2mech(p->name, &(*pmech_list[i])) != CKR_OK) { 1717c478bd9Sstevel@tonic-gate free(*pmech_list); 1727c478bd9Sstevel@tonic-gate return (FAILURE); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate p = p->next; 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate *mech_count = n; 1777c478bd9Sstevel@tonic-gate return (SUCCESS); 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /* 1817c478bd9Sstevel@tonic-gate * Display the mechanism list for a user-level library 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate int 1847c478bd9Sstevel@tonic-gate list_mechlist_for_lib(char *libname, mechlist_t *mlist, 1857c478bd9Sstevel@tonic-gate flag_val_t *rng_flag, boolean_t no_warn, 1867c478bd9Sstevel@tonic-gate boolean_t verbose, boolean_t show_mechs) 1877c478bd9Sstevel@tonic-gate { 1887c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK; 1897c478bd9Sstevel@tonic-gate CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR); 1907c478bd9Sstevel@tonic-gate CK_FUNCTION_LIST_PTR prov_funcs; /* Provider's function list */ 1917c478bd9Sstevel@tonic-gate CK_SLOT_ID_PTR prov_slots = NULL; /* Provider's slot list */ 19212240b1dSDarren J Moffat CK_MECHANISM_TYPE_PTR pmech_list = NULL; /* mech list for a slot */ 1937c478bd9Sstevel@tonic-gate CK_SLOT_INFO slotinfo; 1947c478bd9Sstevel@tonic-gate CK_ULONG slot_count; 1957c478bd9Sstevel@tonic-gate CK_ULONG mech_count; 1967c478bd9Sstevel@tonic-gate uentry_t *puent = NULL; 1977c478bd9Sstevel@tonic-gate boolean_t lib_initialized = B_FALSE; 1987c478bd9Sstevel@tonic-gate void *dldesc = NULL; 1997c478bd9Sstevel@tonic-gate char *dl_error; 2002321aa36Sda73024 const char *mech_name; 2017c478bd9Sstevel@tonic-gate char *isa; 2027c478bd9Sstevel@tonic-gate char libpath[MAXPATHLEN]; 2037c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 2047c478bd9Sstevel@tonic-gate int i, j; 2057c478bd9Sstevel@tonic-gate int rc = SUCCESS; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if (libname == NULL) { 2087c478bd9Sstevel@tonic-gate /* should not happen */ 2097c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 2107c478bd9Sstevel@tonic-gate cryptodebug("list_mechlist_for_lib() - libname is NULL."); 2117c478bd9Sstevel@tonic-gate return (FAILURE); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* Check if the library is in the pkcs11.conf file */ 2157c478bd9Sstevel@tonic-gate if ((puent = getent_uef(libname)) == NULL) { 2167c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 2177c478bd9Sstevel@tonic-gate gettext("%s does not exist."), libname); 2187c478bd9Sstevel@tonic-gate return (FAILURE); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate free_uentry(puent); 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* Remove $ISA from the library name */ 2237c478bd9Sstevel@tonic-gate if (strlcpy(buf, libname, sizeof (buf)) >= sizeof (buf)) { 2247c478bd9Sstevel@tonic-gate (void) printf(gettext("%s: the provider name is too long."), 2257c478bd9Sstevel@tonic-gate libname); 2267c478bd9Sstevel@tonic-gate return (FAILURE); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate if ((isa = strstr(buf, PKCS11_ISA)) != NULL) { 2307c478bd9Sstevel@tonic-gate *isa = '\000'; 2317c478bd9Sstevel@tonic-gate isa += strlen(PKCS11_ISA); 2327c478bd9Sstevel@tonic-gate (void) snprintf(libpath, MAXPATHLEN, "%s%s%s", buf, "/", isa); 2337c478bd9Sstevel@tonic-gate } else { 2347c478bd9Sstevel@tonic-gate (void) strlcpy(libpath, libname, sizeof (libpath)); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 237699ea13aSValerie Bubb Fenwick /* 238699ea13aSValerie Bubb Fenwick * Open the provider. Use RTLD_NOW here, as a way to 239699ea13aSValerie Bubb Fenwick * catch any providers with incomplete symbols that 240699ea13aSValerie Bubb Fenwick * might otherwise cause problems during libpkcs11's 241699ea13aSValerie Bubb Fenwick * execution. 242699ea13aSValerie Bubb Fenwick */ 2437c478bd9Sstevel@tonic-gate dldesc = dlopen(libpath, RTLD_NOW); 2447c478bd9Sstevel@tonic-gate if (dldesc == NULL) { 2457c478bd9Sstevel@tonic-gate dl_error = dlerror(); 2467c478bd9Sstevel@tonic-gate cryptodebug("Cannot load PKCS#11 library %s. dlerror: %s", 2477c478bd9Sstevel@tonic-gate libname, dl_error != NULL ? dl_error : "Unknown"); 2487c478bd9Sstevel@tonic-gate rc = FAILURE; 2497c478bd9Sstevel@tonic-gate goto clean_exit; 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate /* Get the pointer to provider's C_GetFunctionList() */ 2537c478bd9Sstevel@tonic-gate Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList"); 2547c478bd9Sstevel@tonic-gate if (Tmp_C_GetFunctionList == NULL) { 2557c478bd9Sstevel@tonic-gate cryptodebug("Cannot get the address of the C_GetFunctionList " 2567c478bd9Sstevel@tonic-gate "from %s", libname); 2577c478bd9Sstevel@tonic-gate rc = FAILURE; 2587c478bd9Sstevel@tonic-gate goto clean_exit; 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* Get the provider's function list */ 2627c478bd9Sstevel@tonic-gate rv = Tmp_C_GetFunctionList(&prov_funcs); 2637c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2647c478bd9Sstevel@tonic-gate cryptodebug("failed to call C_GetFunctionList from %s", 2657c478bd9Sstevel@tonic-gate libname); 2667c478bd9Sstevel@tonic-gate rc = FAILURE; 2677c478bd9Sstevel@tonic-gate goto clean_exit; 2687c478bd9Sstevel@tonic-gate } 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* Initialize this provider */ 2717c478bd9Sstevel@tonic-gate rv = prov_funcs->C_Initialize(NULL_PTR); 2727c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2737c478bd9Sstevel@tonic-gate cryptodebug("failed to call C_Initialize from %s, " 2747c478bd9Sstevel@tonic-gate "return code = %d", libname, rv); 2757c478bd9Sstevel@tonic-gate rc = FAILURE; 2767c478bd9Sstevel@tonic-gate goto clean_exit; 2777c478bd9Sstevel@tonic-gate } else { 2787c478bd9Sstevel@tonic-gate lib_initialized = B_TRUE; 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * Find out how many slots this provider has, call with tokenPresent 2837c478bd9Sstevel@tonic-gate * set to FALSE so all potential slots are returned. 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate rv = prov_funcs->C_GetSlotList(FALSE, NULL_PTR, &slot_count); 2867c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 2877c478bd9Sstevel@tonic-gate cryptodebug("failed to get the slotlist from %s.", libname); 2887c478bd9Sstevel@tonic-gate rc = FAILURE; 2897c478bd9Sstevel@tonic-gate goto clean_exit; 2907c478bd9Sstevel@tonic-gate } else if (slot_count == 0) { 2917c478bd9Sstevel@tonic-gate if (!no_warn) 2927c478bd9Sstevel@tonic-gate (void) printf(gettext("%s: no slots presented.\n"), 2937c478bd9Sstevel@tonic-gate libname); 2947c478bd9Sstevel@tonic-gate rc = SUCCESS; 2957c478bd9Sstevel@tonic-gate goto clean_exit; 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate /* Allocate memory for the slot list */ 2997c478bd9Sstevel@tonic-gate prov_slots = malloc(slot_count * sizeof (CK_SLOT_ID)); 3007c478bd9Sstevel@tonic-gate if (prov_slots == NULL) { 3017c478bd9Sstevel@tonic-gate cryptodebug("out of memory."); 3027c478bd9Sstevel@tonic-gate rc = FAILURE; 3037c478bd9Sstevel@tonic-gate goto clean_exit; 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* Get the slot list from provider */ 3077c478bd9Sstevel@tonic-gate rv = prov_funcs->C_GetSlotList(FALSE, prov_slots, &slot_count); 3087c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3097c478bd9Sstevel@tonic-gate cryptodebug("failed to call C_GetSlotList() from %s.", 3107c478bd9Sstevel@tonic-gate libname); 3117c478bd9Sstevel@tonic-gate rc = FAILURE; 3127c478bd9Sstevel@tonic-gate goto clean_exit; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate if (verbose) { 3167c478bd9Sstevel@tonic-gate (void) printf(gettext("Number of slots: %d\n"), slot_count); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate /* Get the mechanism list for each slot */ 3207c478bd9Sstevel@tonic-gate for (i = 0; i < slot_count; i++) { 3217c478bd9Sstevel@tonic-gate if (verbose) 3227c478bd9Sstevel@tonic-gate /* 3230a85b835SDaniel Anderson * TRANSLATION_NOTE 3247c478bd9Sstevel@tonic-gate * In some languages, the # symbol should be 3257c478bd9Sstevel@tonic-gate * converted to "no", an "n" followed by a 3267c478bd9Sstevel@tonic-gate * superscript "o".. 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate (void) printf(gettext("\nSlot #%d\n"), i+1); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate if ((rng_flag != NULL) && (*rng_flag == NO_RNG)) { 3317c478bd9Sstevel@tonic-gate if (check_random(prov_slots[i], prov_funcs)) { 3327c478bd9Sstevel@tonic-gate *rng_flag = HAS_RNG; 3337c478bd9Sstevel@tonic-gate rc = SUCCESS; 3347c478bd9Sstevel@tonic-gate goto clean_exit; 3357c478bd9Sstevel@tonic-gate } else 3367c478bd9Sstevel@tonic-gate continue; 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate rv = prov_funcs->C_GetSlotInfo(prov_slots[i], &slotinfo); 3407c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3417c478bd9Sstevel@tonic-gate cryptodebug("failed to get slotinfo from %s", libname); 3427c478bd9Sstevel@tonic-gate rc = FAILURE; 3437c478bd9Sstevel@tonic-gate break; 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate if (verbose) { 3467c478bd9Sstevel@tonic-gate CK_TOKEN_INFO tokeninfo; 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate (void) printf(gettext("Description: %.64s\n" 3497c478bd9Sstevel@tonic-gate "Manufacturer: %.32s\n" 3507c478bd9Sstevel@tonic-gate "PKCS#11 Version: %d.%d\n"), 3517c478bd9Sstevel@tonic-gate slotinfo.slotDescription, 3527c478bd9Sstevel@tonic-gate slotinfo.manufacturerID, 3537c478bd9Sstevel@tonic-gate prov_funcs->version.major, 3547c478bd9Sstevel@tonic-gate prov_funcs->version.minor); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate (void) printf(gettext("Hardware Version: %d.%d\n" 3577c478bd9Sstevel@tonic-gate "Firmware Version: %d.%d\n"), 3587c478bd9Sstevel@tonic-gate slotinfo.hardwareVersion.major, 3597c478bd9Sstevel@tonic-gate slotinfo.hardwareVersion.minor, 3607c478bd9Sstevel@tonic-gate slotinfo.firmwareVersion.major, 3617c478bd9Sstevel@tonic-gate slotinfo.firmwareVersion.minor); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate (void) printf(gettext("Token Present: %s\n"), 3647c478bd9Sstevel@tonic-gate (slotinfo.flags & CKF_TOKEN_PRESENT ? 3657c478bd9Sstevel@tonic-gate gettext("True") : gettext("False"))); 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate display_slot_flags(slotinfo.flags); 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate rv = prov_funcs->C_GetTokenInfo(prov_slots[i], 3707c478bd9Sstevel@tonic-gate &tokeninfo); 3717c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 3727c478bd9Sstevel@tonic-gate cryptodebug("Failed to get " 3737c478bd9Sstevel@tonic-gate "token info from %s", libname); 3747c478bd9Sstevel@tonic-gate rc = FAILURE; 3757c478bd9Sstevel@tonic-gate break; 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate (void) printf(gettext("Token Label: %.32s\n" 3797c478bd9Sstevel@tonic-gate "Manufacturer ID: %.32s\n" 3807c478bd9Sstevel@tonic-gate "Model: %.16s\n" 3817c478bd9Sstevel@tonic-gate "Serial Number: %.16s\n" 3827c478bd9Sstevel@tonic-gate "Hardware Version: %d.%d\n" 3837c478bd9Sstevel@tonic-gate "Firmware Version: %d.%d\n" 3847c478bd9Sstevel@tonic-gate "UTC Time: %.16s\n" 3857f3340f0SDarren Moffat "PIN Min Length: %d\n" 3867f3340f0SDarren Moffat "PIN Max Length: %d\n"), 3877c478bd9Sstevel@tonic-gate tokeninfo.label, 3887c478bd9Sstevel@tonic-gate tokeninfo.manufacturerID, 3897c478bd9Sstevel@tonic-gate tokeninfo.model, 3907c478bd9Sstevel@tonic-gate tokeninfo.serialNumber, 3917c478bd9Sstevel@tonic-gate tokeninfo.hardwareVersion.major, 3927c478bd9Sstevel@tonic-gate tokeninfo.hardwareVersion.minor, 3937c478bd9Sstevel@tonic-gate tokeninfo.firmwareVersion.major, 3947c478bd9Sstevel@tonic-gate tokeninfo.firmwareVersion.minor, 3957c478bd9Sstevel@tonic-gate tokeninfo.utcTime, 3967c478bd9Sstevel@tonic-gate tokeninfo.ulMinPinLen, 3977c478bd9Sstevel@tonic-gate tokeninfo.ulMaxPinLen); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate display_token_flags(tokeninfo.flags); 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate if (mlist == NULL) { 4037c478bd9Sstevel@tonic-gate rv = prov_funcs->C_GetMechanismList(prov_slots[i], 4047c478bd9Sstevel@tonic-gate NULL_PTR, &mech_count); 4057c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4067c478bd9Sstevel@tonic-gate cryptodebug( 4077c478bd9Sstevel@tonic-gate "failed to call C_GetMechanismList() " 4087c478bd9Sstevel@tonic-gate "from %s.", libname); 4097c478bd9Sstevel@tonic-gate rc = FAILURE; 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate if (mech_count == 0) { 4147c478bd9Sstevel@tonic-gate /* no mechanisms in this slot */ 4157c478bd9Sstevel@tonic-gate continue; 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate pmech_list = malloc(mech_count * 4197c478bd9Sstevel@tonic-gate sizeof (CK_MECHANISM_TYPE)); 4207c478bd9Sstevel@tonic-gate if (pmech_list == NULL) { 4217c478bd9Sstevel@tonic-gate cryptodebug("out of memory"); 4227c478bd9Sstevel@tonic-gate rc = FAILURE; 4237c478bd9Sstevel@tonic-gate break; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* Get the actual mechanism list */ 4277c478bd9Sstevel@tonic-gate rv = prov_funcs->C_GetMechanismList(prov_slots[i], 4287c478bd9Sstevel@tonic-gate pmech_list, &mech_count); 4297c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 4307c478bd9Sstevel@tonic-gate cryptodebug( 4317c478bd9Sstevel@tonic-gate "failed to call C_GetMechanismList() " 4327c478bd9Sstevel@tonic-gate "from %s.", libname); 43312240b1dSDarren J Moffat free(pmech_list); 4347c478bd9Sstevel@tonic-gate rc = FAILURE; 4357c478bd9Sstevel@tonic-gate break; 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate } else { 4387c478bd9Sstevel@tonic-gate /* use the mechanism list passed in */ 4397c478bd9Sstevel@tonic-gate rc = convert_mechlist(&pmech_list, &mech_count, mlist); 4407c478bd9Sstevel@tonic-gate if (rc != SUCCESS) { 4417c478bd9Sstevel@tonic-gate goto clean_exit; 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate if (show_mechs) 4457c478bd9Sstevel@tonic-gate (void) printf(gettext("Mechanisms:\n")); 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate if (verbose && show_mechs) { 4487c478bd9Sstevel@tonic-gate display_verbose_mech_header(); 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate /* 4517c478bd9Sstevel@tonic-gate * Merge the current mechanism list into the returning 4527c478bd9Sstevel@tonic-gate * mechanism list. 4537c478bd9Sstevel@tonic-gate */ 4547c478bd9Sstevel@tonic-gate for (j = 0; show_mechs && j < mech_count; j++) { 4552321aa36Sda73024 CK_MECHANISM_TYPE mech = pmech_list[j]; 45612240b1dSDarren J Moffat CK_MECHANISM_INFO mech_info; 4572321aa36Sda73024 45812240b1dSDarren J Moffat rv = prov_funcs->C_GetMechanismInfo( 45912240b1dSDarren J Moffat prov_slots[i], mech, &mech_info); 46012240b1dSDarren J Moffat if (rv != CKR_OK) { 46112240b1dSDarren J Moffat cryptodebug( 46212240b1dSDarren J Moffat "failed to call " 46312240b1dSDarren J Moffat "C_GetMechanismInfo() from %s.", 46412240b1dSDarren J Moffat libname); 46512240b1dSDarren J Moffat free(pmech_list); 46612240b1dSDarren J Moffat pmech_list = NULL; 46712240b1dSDarren J Moffat rc = FAILURE; 46812240b1dSDarren J Moffat break; 46912240b1dSDarren J Moffat } 47076d1b5a9Sda73024 if (mech >= CKM_VENDOR_DEFINED) { 4712321aa36Sda73024 (void) printf("%#lx", mech); 4722321aa36Sda73024 } else { 4732321aa36Sda73024 mech_name = pkcs11_mech2str(mech); 4747c478bd9Sstevel@tonic-gate (void) printf("%-29s", mech_name); 4752321aa36Sda73024 } 4762321aa36Sda73024 4777c478bd9Sstevel@tonic-gate if (verbose) { 4787c478bd9Sstevel@tonic-gate display_mech_info(&mech_info); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate (void) printf("\n"); 4817c478bd9Sstevel@tonic-gate } 48212240b1dSDarren J Moffat if (pmech_list) 48312240b1dSDarren J Moffat free(pmech_list); 4847c478bd9Sstevel@tonic-gate if (rc == FAILURE) { 4857c478bd9Sstevel@tonic-gate break; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate if (rng_flag != NULL || rc == FAILURE) { 4907c478bd9Sstevel@tonic-gate goto clean_exit; 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate clean_exit: 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate if (rc == FAILURE) { 4967c478bd9Sstevel@tonic-gate (void) printf(gettext( 4977c478bd9Sstevel@tonic-gate "%s: failed to retrieve the mechanism list.\n"), libname); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate if (lib_initialized) { 5017c478bd9Sstevel@tonic-gate (void) prov_funcs->C_Finalize(NULL_PTR); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate if (dldesc != NULL) { 5057c478bd9Sstevel@tonic-gate (void) dlclose(dldesc); 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate if (prov_slots != NULL) { 50912240b1dSDarren J Moffat free(prov_slots); 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate return (rc); 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* 5177c478bd9Sstevel@tonic-gate * Display the mechanism policy for a user-level library 5187c478bd9Sstevel@tonic-gate */ 5197c478bd9Sstevel@tonic-gate int 5207c478bd9Sstevel@tonic-gate list_policy_for_lib(char *libname) 5217c478bd9Sstevel@tonic-gate { 5227c478bd9Sstevel@tonic-gate uentry_t *puent = NULL; 5237c478bd9Sstevel@tonic-gate int rc; 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate if (libname == NULL) { 5267c478bd9Sstevel@tonic-gate /* should not happen */ 5277c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 5287c478bd9Sstevel@tonic-gate cryptodebug("list_policy_for_lib() - libname is NULL."); 5297c478bd9Sstevel@tonic-gate return (FAILURE); 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* Get the library entry from the pkcs11.conf file */ 5337c478bd9Sstevel@tonic-gate if ((puent = getent_uef(libname)) == NULL) { 5347c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 5357c478bd9Sstevel@tonic-gate gettext("%s does not exist."), libname); 5367c478bd9Sstevel@tonic-gate return (FAILURE); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate /* Print the policy for this library */ 5407c478bd9Sstevel@tonic-gate rc = print_uef_policy(puent); 5417c478bd9Sstevel@tonic-gate free_uentry(puent); 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate return (rc); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate /* 5487c478bd9Sstevel@tonic-gate * Disable mechanisms for a user-level library 5497c478bd9Sstevel@tonic-gate */ 5507c478bd9Sstevel@tonic-gate int 5517c478bd9Sstevel@tonic-gate disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag, 5527c478bd9Sstevel@tonic-gate mechlist_t *marglist) 5537c478bd9Sstevel@tonic-gate { 5547c478bd9Sstevel@tonic-gate uentry_t *puent; 5557c478bd9Sstevel@tonic-gate int rc; 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate if (libname == NULL) { 5587c478bd9Sstevel@tonic-gate /* should not happen */ 5597c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 5607c478bd9Sstevel@tonic-gate cryptodebug("disable_uef_lib() - libname is NULL."); 5617c478bd9Sstevel@tonic-gate return (FAILURE); 5627c478bd9Sstevel@tonic-gate } 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate /* Get the provider entry from the pkcs11.conf file */ 5657c478bd9Sstevel@tonic-gate if ((puent = getent_uef(libname)) == NULL) { 5667c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 5677c478bd9Sstevel@tonic-gate gettext("%s does not exist."), libname); 5687c478bd9Sstevel@tonic-gate return (FAILURE); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate /* 5727c478bd9Sstevel@tonic-gate * Update the mechanism policy of this library entry, based on 5737c478bd9Sstevel@tonic-gate * the current policy mode of the library and the mechanisms specified 5747c478bd9Sstevel@tonic-gate * in CLI. 5757c478bd9Sstevel@tonic-gate */ 5767c478bd9Sstevel@tonic-gate if (allflag) { 5777c478bd9Sstevel@tonic-gate /* 5787c478bd9Sstevel@tonic-gate * If disabling all, just need to clean up the policylist and 5797c478bd9Sstevel@tonic-gate * set the flag_enabledlist flag to be B_TRUE. 5807c478bd9Sstevel@tonic-gate */ 5817c478bd9Sstevel@tonic-gate free_umechlist(puent->policylist); 5827c478bd9Sstevel@tonic-gate puent->policylist = NULL; 5837c478bd9Sstevel@tonic-gate puent->count = 0; 5847c478bd9Sstevel@tonic-gate puent->flag_enabledlist = B_TRUE; 5857c478bd9Sstevel@tonic-gate rc = SUCCESS; 5867c478bd9Sstevel@tonic-gate } else if (marglist != NULL) { 5877c478bd9Sstevel@tonic-gate if (puent->flag_enabledlist == B_TRUE) { 5887c478bd9Sstevel@tonic-gate /* 5897c478bd9Sstevel@tonic-gate * The current default policy mode of this library 5907c478bd9Sstevel@tonic-gate * is "all are disabled, except ...", so if a 5917c478bd9Sstevel@tonic-gate * specified mechanism is in the exception list 5927c478bd9Sstevel@tonic-gate * (the policylist), delete it from the policylist. 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate rc = update_policylist(puent, marglist, DELETE_MODE); 5957c478bd9Sstevel@tonic-gate } else { 5967c478bd9Sstevel@tonic-gate /* 5977c478bd9Sstevel@tonic-gate * The current default policy mode of this library 5987c478bd9Sstevel@tonic-gate * is "all are enabled", so if a specified mechanism 5997c478bd9Sstevel@tonic-gate * is not in the exception list (policylist), add 6007c478bd9Sstevel@tonic-gate * it into the policylist. 6017c478bd9Sstevel@tonic-gate */ 6027c478bd9Sstevel@tonic-gate rc = update_policylist(puent, marglist, ADD_MODE); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate } else if (!rndflag) { 6057c478bd9Sstevel@tonic-gate /* should not happen */ 6067c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 6077c478bd9Sstevel@tonic-gate cryptodebug("disable_uef_lib() - wrong arguments."); 6087c478bd9Sstevel@tonic-gate return (FAILURE); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate if (rndflag) 6127c478bd9Sstevel@tonic-gate puent->flag_norandom = B_TRUE; 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate if (rc == FAILURE) { 6157c478bd9Sstevel@tonic-gate free_uentry(puent); 6167c478bd9Sstevel@tonic-gate return (FAILURE); 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate /* Update the pkcs11.conf file with the updated entry */ 6207c478bd9Sstevel@tonic-gate rc = update_pkcs11conf(puent); 6217c478bd9Sstevel@tonic-gate free_uentry(puent); 6227c478bd9Sstevel@tonic-gate return (rc); 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate /* 6277c478bd9Sstevel@tonic-gate * Enable disabled mechanisms for a user-level library. 6287c478bd9Sstevel@tonic-gate */ 6297c478bd9Sstevel@tonic-gate int 6307c478bd9Sstevel@tonic-gate enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag, 6317c478bd9Sstevel@tonic-gate mechlist_t *marglist) 6327c478bd9Sstevel@tonic-gate { 6337c478bd9Sstevel@tonic-gate uentry_t *puent; 6347c478bd9Sstevel@tonic-gate int rc = SUCCESS; 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate if (libname == NULL) { 6377c478bd9Sstevel@tonic-gate /* should not happen */ 6387c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 6397c478bd9Sstevel@tonic-gate cryptodebug("enable_uef_lib() - libname is NULL."); 6407c478bd9Sstevel@tonic-gate return (FAILURE); 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate /* Get the provider entry from the pkcs11.conf file */ 6447c478bd9Sstevel@tonic-gate if ((puent = getent_uef(libname)) == NULL) { 6457c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 6467c478bd9Sstevel@tonic-gate gettext("%s does not exist."), libname); 6477c478bd9Sstevel@tonic-gate return (FAILURE); 6487c478bd9Sstevel@tonic-gate } 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate /* 6517c478bd9Sstevel@tonic-gate * Update the mechanism policy of this library entry, based on 6527c478bd9Sstevel@tonic-gate * the current policy mode of the library and the mechanisms 6537c478bd9Sstevel@tonic-gate * specified in CLI. 6547c478bd9Sstevel@tonic-gate */ 6557c478bd9Sstevel@tonic-gate if (allflag) { 6567c478bd9Sstevel@tonic-gate /* 6577c478bd9Sstevel@tonic-gate * If enabling all, what needs to be done are cleaning up the 6587c478bd9Sstevel@tonic-gate * policylist and setting the "flag_enabledlist" flag to 6597c478bd9Sstevel@tonic-gate * B_FALSE. 6607c478bd9Sstevel@tonic-gate */ 6617c478bd9Sstevel@tonic-gate free_umechlist(puent->policylist); 6627c478bd9Sstevel@tonic-gate puent->policylist = NULL; 6637c478bd9Sstevel@tonic-gate puent->count = 0; 6647c478bd9Sstevel@tonic-gate puent->flag_enabledlist = B_FALSE; 6657c478bd9Sstevel@tonic-gate rc = SUCCESS; 6667c478bd9Sstevel@tonic-gate } else if (marglist != NULL) { 6677c478bd9Sstevel@tonic-gate if (puent->flag_enabledlist == B_TRUE) { 6687c478bd9Sstevel@tonic-gate /* 6697c478bd9Sstevel@tonic-gate * The current default policy mode of this library 6707c478bd9Sstevel@tonic-gate * is "all are disabled, except ...", so if a 6717c478bd9Sstevel@tonic-gate * specified mechanism is not in the exception list 6727c478bd9Sstevel@tonic-gate * (policylist), add it. 6737c478bd9Sstevel@tonic-gate */ 6747c478bd9Sstevel@tonic-gate rc = update_policylist(puent, marglist, ADD_MODE); 6757c478bd9Sstevel@tonic-gate } else { 6767c478bd9Sstevel@tonic-gate /* 6777c478bd9Sstevel@tonic-gate * The current default policy mode of this library 6787c478bd9Sstevel@tonic-gate * is "all are enabled, except", so if a specified 6797c478bd9Sstevel@tonic-gate * mechanism is in the exception list (policylist), 6807c478bd9Sstevel@tonic-gate * delete it. 6817c478bd9Sstevel@tonic-gate */ 6827c478bd9Sstevel@tonic-gate rc = update_policylist(puent, marglist, DELETE_MODE); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate } else if (!rndflag) { 6857c478bd9Sstevel@tonic-gate /* should not come here */ 6867c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 6877c478bd9Sstevel@tonic-gate cryptodebug("enable_uef_lib() - wrong arguments."); 6887c478bd9Sstevel@tonic-gate return (FAILURE); 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate if (rndflag) 6927c478bd9Sstevel@tonic-gate puent->flag_norandom = B_FALSE; 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate if (rc == FAILURE) { 6957c478bd9Sstevel@tonic-gate free_uentry(puent); 6967c478bd9Sstevel@tonic-gate return (FAILURE); 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate /* Update the pkcs11.conf file with the updated entry */ 7007c478bd9Sstevel@tonic-gate rc = update_pkcs11conf(puent); 7017c478bd9Sstevel@tonic-gate free_uentry(puent); 7027c478bd9Sstevel@tonic-gate return (rc); 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* 7077c478bd9Sstevel@tonic-gate * Install a user-level library. 7087c478bd9Sstevel@tonic-gate */ 7097c478bd9Sstevel@tonic-gate int 7107c478bd9Sstevel@tonic-gate install_uef_lib(char *libname) 7117c478bd9Sstevel@tonic-gate { 7127c478bd9Sstevel@tonic-gate uentry_t *puent; 7137c478bd9Sstevel@tonic-gate struct stat statbuf; 7147c478bd9Sstevel@tonic-gate char libpath[MAXPATHLEN]; 7157c478bd9Sstevel@tonic-gate char libbuf[MAXPATHLEN]; 7167c478bd9Sstevel@tonic-gate char *isa; 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate if (libname == NULL) { 7197c478bd9Sstevel@tonic-gate /* should not happen */ 7207c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 7217c478bd9Sstevel@tonic-gate cryptodebug("install_uef_lib() - libname is NULL."); 7227c478bd9Sstevel@tonic-gate return (FAILURE); 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate /* Check if the provider already exists in the framework */ 7267c478bd9Sstevel@tonic-gate if ((puent = getent_uef(libname)) != NULL) { 7277c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s exists already."), 7287c478bd9Sstevel@tonic-gate libname); 7297c478bd9Sstevel@tonic-gate free_uentry(puent); 7307c478bd9Sstevel@tonic-gate return (FAILURE); 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate /* 7347c478bd9Sstevel@tonic-gate * Check if the library exists in the system. if $ISA is in the 7357c478bd9Sstevel@tonic-gate * path, only check the 32bit version. 7367c478bd9Sstevel@tonic-gate */ 7377c478bd9Sstevel@tonic-gate if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) { 7387c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 7397c478bd9Sstevel@tonic-gate gettext("the provider name is too long - %s"), libname); 7407c478bd9Sstevel@tonic-gate return (FAILURE); 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) { 7447c478bd9Sstevel@tonic-gate *isa = '\000'; 7457c478bd9Sstevel@tonic-gate isa += strlen(PKCS11_ISA); 7467c478bd9Sstevel@tonic-gate (void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf, 7477c478bd9Sstevel@tonic-gate "/", isa); 7487c478bd9Sstevel@tonic-gate } else { 7497c478bd9Sstevel@tonic-gate (void) strlcpy(libpath, libname, sizeof (libpath)); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* Check if it is same as the framework library */ 7537c478bd9Sstevel@tonic-gate if (strcmp(libpath, UEF_FRAME_LIB) == 0) { 7547c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 7557c478bd9Sstevel@tonic-gate "The framework library %s can not be installed."), 7567c478bd9Sstevel@tonic-gate libname); 7577c478bd9Sstevel@tonic-gate return (FAILURE); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate if (stat(libpath, &statbuf) != 0) { 7617c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("%s not found"), libname); 7627c478bd9Sstevel@tonic-gate return (FAILURE); 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate 7657c478bd9Sstevel@tonic-gate /* Need to add "\n" to libname for adding into the config file */ 7667c478bd9Sstevel@tonic-gate if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) { 7677c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 7687c478bd9Sstevel@tonic-gate "can not install %s; the name is too long."), libname); 7697c478bd9Sstevel@tonic-gate return (FAILURE); 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 772b5a2d845SHai-May Chao return (update_conf(_PATH_PKCS11_CONF, libname)); 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * Uninstall a user-level library. 7797c478bd9Sstevel@tonic-gate */ 7807c478bd9Sstevel@tonic-gate int 7817c478bd9Sstevel@tonic-gate uninstall_uef_lib(char *libname) 7827c478bd9Sstevel@tonic-gate { 7837c478bd9Sstevel@tonic-gate uentry_t *puent; 7847c478bd9Sstevel@tonic-gate FILE *pfile; 7857c478bd9Sstevel@tonic-gate FILE *pfile_tmp; 7867c478bd9Sstevel@tonic-gate char buffer[BUFSIZ]; 7877c478bd9Sstevel@tonic-gate char buffer2[BUFSIZ]; 7887c478bd9Sstevel@tonic-gate char tmpfile_name[MAXPATHLEN]; 7897c478bd9Sstevel@tonic-gate char *name; 7907c478bd9Sstevel@tonic-gate boolean_t found; 7917c478bd9Sstevel@tonic-gate boolean_t in_package; 7927c478bd9Sstevel@tonic-gate int len; 7937c478bd9Sstevel@tonic-gate int rc = SUCCESS; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate if (libname == NULL) { 7967c478bd9Sstevel@tonic-gate /* should not happen */ 7977c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 7987c478bd9Sstevel@tonic-gate cryptodebug("uninstall_uef_lib() - libname is NULL."); 7997c478bd9Sstevel@tonic-gate return (FAILURE); 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate /* Check if the provider exists */ 8037c478bd9Sstevel@tonic-gate if ((puent = getent_uef(libname)) == NULL) { 8047c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8057c478bd9Sstevel@tonic-gate gettext("%s does not exist."), libname); 8067c478bd9Sstevel@tonic-gate return (FAILURE); 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate free_uentry(puent); 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate /* Open the pkcs11.conf file and lock it */ 8117c478bd9Sstevel@tonic-gate if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 8127c478bd9Sstevel@tonic-gate err = errno; 8137c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8147c478bd9Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 8157c478bd9Sstevel@tonic-gate strerror(err)); 8167c478bd9Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 8177c478bd9Sstevel@tonic-gate return (FAILURE); 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 8217c478bd9Sstevel@tonic-gate err = errno; 8227c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8237c478bd9Sstevel@tonic-gate gettext("failed to lock the configuration - %s"), 8247c478bd9Sstevel@tonic-gate strerror(err)); 8257c478bd9Sstevel@tonic-gate (void) fclose(pfile); 8267c478bd9Sstevel@tonic-gate return (FAILURE); 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate /* 8307c478bd9Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory to save 8317c478bd9Sstevel@tonic-gate * the new configuration file first. 8327c478bd9Sstevel@tonic-gate */ 8337c478bd9Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 8347c478bd9Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 8357c478bd9Sstevel@tonic-gate err = errno; 8367c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 8377c478bd9Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 8387c478bd9Sstevel@tonic-gate strerror(err)); 8397c478bd9Sstevel@tonic-gate (void) fclose(pfile); 8407c478bd9Sstevel@tonic-gate return (FAILURE); 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 8447c478bd9Sstevel@tonic-gate err = errno; 8457c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 8467c478bd9Sstevel@tonic-gate tmpfile_name, strerror(err)); 8477c478bd9Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 8487c478bd9Sstevel@tonic-gate err = errno; 8497c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 8507c478bd9Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 8517c478bd9Sstevel@tonic-gate tmpfile_name, strerror(err)); 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate (void) fclose(pfile); 8547c478bd9Sstevel@tonic-gate return (FAILURE); 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* 8597c478bd9Sstevel@tonic-gate * Loop thru the config file. If the library to be uninstalled 8607c478bd9Sstevel@tonic-gate * is in a package, just comment it off. 8617c478bd9Sstevel@tonic-gate */ 8627c478bd9Sstevel@tonic-gate in_package = B_FALSE; 8637c478bd9Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 8647c478bd9Sstevel@tonic-gate found = B_FALSE; 8657c478bd9Sstevel@tonic-gate if (!(buffer[0] == ' ' || buffer[0] == '\n' || 8667c478bd9Sstevel@tonic-gate buffer[0] == '\t')) { 8677c478bd9Sstevel@tonic-gate if (strstr(buffer, " Start ") != NULL) { 8687c478bd9Sstevel@tonic-gate in_package = B_TRUE; 8697c478bd9Sstevel@tonic-gate } else if (strstr(buffer, " End ") != NULL) { 8707c478bd9Sstevel@tonic-gate in_package = B_FALSE; 8717c478bd9Sstevel@tonic-gate } else if (buffer[0] != '#') { 8727c478bd9Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 8737c478bd9Sstevel@tonic-gate 8747c478bd9Sstevel@tonic-gate /* get rid of trailing '\n' */ 8757c478bd9Sstevel@tonic-gate len = strlen(buffer2); 8767c478bd9Sstevel@tonic-gate if (buffer2[len-1] == '\n') { 8777c478bd9Sstevel@tonic-gate len--; 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate buffer2[len] = '\0'; 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate if ((name = strtok(buffer2, SEP_COLON)) 8827c478bd9Sstevel@tonic-gate == NULL) { 8837c478bd9Sstevel@tonic-gate rc = FAILURE; 8847c478bd9Sstevel@tonic-gate break; 8857c478bd9Sstevel@tonic-gate } else if (strcmp(libname, name) == 0) { 8867c478bd9Sstevel@tonic-gate found = B_TRUE; 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate if (found) { 8927c478bd9Sstevel@tonic-gate if (in_package) { 8937c478bd9Sstevel@tonic-gate (void) snprintf(buffer2, sizeof (buffer2), 8947c478bd9Sstevel@tonic-gate "%s%s%s", "#", libname, "\n"); 8957c478bd9Sstevel@tonic-gate if (fputs(buffer2, pfile_tmp) == EOF) { 8967c478bd9Sstevel@tonic-gate rc = FAILURE; 8977c478bd9Sstevel@tonic-gate } 8987c478bd9Sstevel@tonic-gate } 8997c478bd9Sstevel@tonic-gate } else { 9007c478bd9Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 9017c478bd9Sstevel@tonic-gate rc = FAILURE; 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate if (rc == FAILURE) { 9067c478bd9Sstevel@tonic-gate break; 9077c478bd9Sstevel@tonic-gate } 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate if (rc == FAILURE) { 9117c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("write error.")); 9127c478bd9Sstevel@tonic-gate (void) fclose(pfile); 9137c478bd9Sstevel@tonic-gate (void) fclose(pfile_tmp); 9147c478bd9Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 9157c478bd9Sstevel@tonic-gate err = errno; 9167c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 9177c478bd9Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 9187c478bd9Sstevel@tonic-gate tmpfile_name, strerror(err)); 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate return (FAILURE); 9217c478bd9Sstevel@tonic-gate } 9227c478bd9Sstevel@tonic-gate 9237c478bd9Sstevel@tonic-gate (void) fclose(pfile); 9247c478bd9Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 9257c478bd9Sstevel@tonic-gate err = errno; 9267c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 9277c478bd9Sstevel@tonic-gate gettext("failed to close a temporary file - %s"), 9287c478bd9Sstevel@tonic-gate strerror(err)); 9297c478bd9Sstevel@tonic-gate return (FAILURE); 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate /* Now update the real config file */ 9337c478bd9Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 9347c478bd9Sstevel@tonic-gate err = errno; 9357c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 9367c478bd9Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 9377c478bd9Sstevel@tonic-gate strerror(err)); 9387c478bd9Sstevel@tonic-gate cryptodebug("failed to rename %s to %s: %s", tmpfile, 9397c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF, strerror(err)); 9407c478bd9Sstevel@tonic-gate rc = FAILURE; 9417c478bd9Sstevel@tonic-gate } else if (chmod(_PATH_PKCS11_CONF, 9427c478bd9Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 9437c478bd9Sstevel@tonic-gate err = errno; 9447c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 9457c478bd9Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 9467c478bd9Sstevel@tonic-gate strerror(err)); 9477c478bd9Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 9487c478bd9Sstevel@tonic-gate strerror(err)); 9497c478bd9Sstevel@tonic-gate rc = FAILURE; 9507c478bd9Sstevel@tonic-gate } else { 9517c478bd9Sstevel@tonic-gate rc = SUCCESS; 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 9557c478bd9Sstevel@tonic-gate err = errno; 9567c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 9577c478bd9Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 9587c478bd9Sstevel@tonic-gate tmpfile_name, strerror(err)); 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate return (rc); 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate int 9667c478bd9Sstevel@tonic-gate display_policy(uentry_t *puent) 9677c478bd9Sstevel@tonic-gate { 9687c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mech_id; 9692321aa36Sda73024 const char *mech_name; 9707c478bd9Sstevel@tonic-gate umechlist_t *ptr; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate if (puent == NULL) { 9737c478bd9Sstevel@tonic-gate return (SUCCESS); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate if (puent->flag_enabledlist == B_FALSE) { 9777c478bd9Sstevel@tonic-gate (void) printf(gettext("%s: all mechanisms are enabled"), 9787c478bd9Sstevel@tonic-gate puent->name); 9797c478bd9Sstevel@tonic-gate ptr = puent->policylist; 9807c478bd9Sstevel@tonic-gate if (ptr == NULL) { 9817c478bd9Sstevel@tonic-gate (void) printf("."); 9827c478bd9Sstevel@tonic-gate } else { 9837c478bd9Sstevel@tonic-gate (void) printf(gettext(", except ")); 9847c478bd9Sstevel@tonic-gate while (ptr != NULL) { 9857c478bd9Sstevel@tonic-gate mech_id = strtoul(ptr->name, NULL, 0); 9867c478bd9Sstevel@tonic-gate if (mech_id & CKO_VENDOR_DEFINED) { 9877c478bd9Sstevel@tonic-gate /* vendor defined mechanism */ 9887c478bd9Sstevel@tonic-gate (void) printf("%s", ptr->name); 9897c478bd9Sstevel@tonic-gate } else { 99076d1b5a9Sda73024 if (mech_id >= CKM_VENDOR_DEFINED) { 9912321aa36Sda73024 (void) printf("%#lx", mech_id); 9922321aa36Sda73024 } else { 9932321aa36Sda73024 mech_name = pkcs11_mech2str( 9942321aa36Sda73024 mech_id); 9957c478bd9Sstevel@tonic-gate if (mech_name == NULL) { 9967c478bd9Sstevel@tonic-gate return (FAILURE); 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate (void) printf("%s", mech_name); 9992321aa36Sda73024 } 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate ptr = ptr->next; 10037c478bd9Sstevel@tonic-gate if (ptr == NULL) { 10047c478bd9Sstevel@tonic-gate (void) printf("."); 10057c478bd9Sstevel@tonic-gate } else { 10067c478bd9Sstevel@tonic-gate (void) printf(","); 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate } else { /* puent->flag_enabledlist == B_TRUE */ 10117c478bd9Sstevel@tonic-gate (void) printf(gettext("%s: all mechanisms are disabled"), 10127c478bd9Sstevel@tonic-gate puent->name); 10137c478bd9Sstevel@tonic-gate ptr = puent->policylist; 10147c478bd9Sstevel@tonic-gate if (ptr == NULL) { 10157c478bd9Sstevel@tonic-gate (void) printf("."); 10167c478bd9Sstevel@tonic-gate } else { 10177c478bd9Sstevel@tonic-gate (void) printf(gettext(", except ")); 10187c478bd9Sstevel@tonic-gate while (ptr != NULL) { 10197c478bd9Sstevel@tonic-gate mech_id = strtoul(ptr->name, NULL, 0); 10207c478bd9Sstevel@tonic-gate if (mech_id & CKO_VENDOR_DEFINED) { 10217c478bd9Sstevel@tonic-gate /* vendor defined mechanism */ 10227c478bd9Sstevel@tonic-gate (void) printf("%s", ptr->name); 10237c478bd9Sstevel@tonic-gate } else { 10247c478bd9Sstevel@tonic-gate mech_name = pkcs11_mech2str(mech_id); 10257c478bd9Sstevel@tonic-gate if (mech_name == NULL) { 10267c478bd9Sstevel@tonic-gate return (FAILURE); 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate (void) printf("%s", mech_name); 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate ptr = ptr->next; 10317c478bd9Sstevel@tonic-gate if (ptr == NULL) { 10327c478bd9Sstevel@tonic-gate (void) printf("."); 10337c478bd9Sstevel@tonic-gate } else { 10347c478bd9Sstevel@tonic-gate (void) printf(","); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate } 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate return (SUCCESS); 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate /* 10457c478bd9Sstevel@tonic-gate * Print out the mechanism policy for a user-level provider pointed by puent. 10467c478bd9Sstevel@tonic-gate */ 10477c478bd9Sstevel@tonic-gate int 10487c478bd9Sstevel@tonic-gate print_uef_policy(uentry_t *puent) 10497c478bd9Sstevel@tonic-gate { 10507c478bd9Sstevel@tonic-gate flag_val_t rng_flag; 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate if (puent == NULL) { 10537c478bd9Sstevel@tonic-gate return (FAILURE); 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate rng_flag = NO_RNG; 10577c478bd9Sstevel@tonic-gate if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE, 10587c478bd9Sstevel@tonic-gate B_FALSE, B_FALSE) != SUCCESS) { 10597c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 10607c478bd9Sstevel@tonic-gate gettext("%s internal error."), puent->name); 10617c478bd9Sstevel@tonic-gate return (FAILURE); 10627c478bd9Sstevel@tonic-gate } 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate if (display_policy(puent) != SUCCESS) { 10657c478bd9Sstevel@tonic-gate goto failed_exit; 10667c478bd9Sstevel@tonic-gate } 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate if (puent->flag_norandom == B_TRUE) 10707c478bd9Sstevel@tonic-gate /* 10710a85b835SDaniel Anderson * TRANSLATION_NOTE 10727c478bd9Sstevel@tonic-gate * "random" is a keyword and not to be translated. 10737c478bd9Sstevel@tonic-gate */ 10747c478bd9Sstevel@tonic-gate (void) printf(gettext(" %s is disabled."), "random"); 10757c478bd9Sstevel@tonic-gate else { 10767c478bd9Sstevel@tonic-gate if (rng_flag == HAS_RNG) 10777c478bd9Sstevel@tonic-gate /* 10780a85b835SDaniel Anderson * TRANSLATION_NOTE 10797c478bd9Sstevel@tonic-gate * "random" is a keyword and not to be translated. 10807c478bd9Sstevel@tonic-gate */ 10817c478bd9Sstevel@tonic-gate (void) printf(gettext(" %s is enabled."), "random"); 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate (void) printf("\n"); 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate return (SUCCESS); 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate failed_exit: 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate (void) printf(gettext("\nout of memory.\n")); 10907c478bd9Sstevel@tonic-gate return (FAILURE); 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate /* 10957c478bd9Sstevel@tonic-gate * Check if the mechanism is in the mechanism list. 10967c478bd9Sstevel@tonic-gate */ 10977c478bd9Sstevel@tonic-gate static boolean_t 10987c478bd9Sstevel@tonic-gate is_in_policylist(midstr_t mechname, umechlist_t *plist) 10997c478bd9Sstevel@tonic-gate { 11007c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE; 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate if (mechname == NULL) { 11037c478bd9Sstevel@tonic-gate return (B_FALSE); 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate while (plist != NULL) { 11077c478bd9Sstevel@tonic-gate if (strcmp(plist->name, mechname) == 0) { 11087c478bd9Sstevel@tonic-gate found = B_TRUE; 11097c478bd9Sstevel@tonic-gate break; 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate plist = plist->next; 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate return (found); 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate 11177c478bd9Sstevel@tonic-gate 11187c478bd9Sstevel@tonic-gate /* 11197c478bd9Sstevel@tonic-gate * Update the pkcs11.conf file with the updated entry. 11207c478bd9Sstevel@tonic-gate */ 11217c478bd9Sstevel@tonic-gate int 11227c478bd9Sstevel@tonic-gate update_pkcs11conf(uentry_t *puent) 11237c478bd9Sstevel@tonic-gate { 11247c478bd9Sstevel@tonic-gate FILE *pfile; 11257c478bd9Sstevel@tonic-gate FILE *pfile_tmp; 11267c478bd9Sstevel@tonic-gate char buffer[BUFSIZ]; 11277c478bd9Sstevel@tonic-gate char buffer2[BUFSIZ]; 11287c478bd9Sstevel@tonic-gate char tmpfile_name[MAXPATHLEN]; 11297c478bd9Sstevel@tonic-gate char *name; 11307c478bd9Sstevel@tonic-gate char *str; 11317c478bd9Sstevel@tonic-gate int len; 11327c478bd9Sstevel@tonic-gate int rc = SUCCESS; 11337c478bd9Sstevel@tonic-gate boolean_t found; 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate if (puent == NULL) { 11367c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 11377c478bd9Sstevel@tonic-gate return (FAILURE); 11387c478bd9Sstevel@tonic-gate } 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate /* Open the pkcs11.conf file */ 11417c478bd9Sstevel@tonic-gate if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) { 11427c478bd9Sstevel@tonic-gate err = errno; 11437c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 11447c478bd9Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 11457c478bd9Sstevel@tonic-gate strerror(err)); 11467c478bd9Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF); 11477c478bd9Sstevel@tonic-gate return (FAILURE); 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate /* Lock the pkcs11.conf file */ 11517c478bd9Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 11527c478bd9Sstevel@tonic-gate err = errno; 11537c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 11547c478bd9Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 11557c478bd9Sstevel@tonic-gate strerror(err)); 11567c478bd9Sstevel@tonic-gate (void) fclose(pfile); 11577c478bd9Sstevel@tonic-gate return (FAILURE); 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate /* 11617c478bd9Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory to save 11627c478bd9Sstevel@tonic-gate * updated configuration file first. 11637c478bd9Sstevel@tonic-gate */ 11647c478bd9Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 11657c478bd9Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 11667c478bd9Sstevel@tonic-gate err = errno; 11677c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 11687c478bd9Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 11697c478bd9Sstevel@tonic-gate strerror(err)); 11707c478bd9Sstevel@tonic-gate (void) fclose(pfile); 11717c478bd9Sstevel@tonic-gate return (FAILURE); 11727c478bd9Sstevel@tonic-gate } 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 11757c478bd9Sstevel@tonic-gate err = errno; 11767c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 11777c478bd9Sstevel@tonic-gate tmpfile_name, strerror(err)); 11787c478bd9Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 11797c478bd9Sstevel@tonic-gate err = errno; 11807c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 11817c478bd9Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 11827c478bd9Sstevel@tonic-gate tmpfile_name, strerror(err)); 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate (void) fclose(pfile); 11857c478bd9Sstevel@tonic-gate return (FAILURE); 11867c478bd9Sstevel@tonic-gate } 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate /* 11907c478bd9Sstevel@tonic-gate * Loop thru entire pkcs11.conf file, update the entry to be 11917c478bd9Sstevel@tonic-gate * updated and save the updated file to the temporary file first. 11927c478bd9Sstevel@tonic-gate */ 11937c478bd9Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 11947c478bd9Sstevel@tonic-gate found = B_FALSE; 11957c478bd9Sstevel@tonic-gate if (!(buffer[0] == '#' || buffer[0] == ' ' || 11967c478bd9Sstevel@tonic-gate buffer[0] == '\n'|| buffer[0] == '\t')) { 11977c478bd9Sstevel@tonic-gate /* 11987c478bd9Sstevel@tonic-gate * Get the provider name from this line and check if 11997c478bd9Sstevel@tonic-gate * this is the entry to be updated. Note: can not use 12007c478bd9Sstevel@tonic-gate * "buffer" directly because strtok will change its 12017c478bd9Sstevel@tonic-gate * value. 12027c478bd9Sstevel@tonic-gate */ 12037c478bd9Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate /* get rid of trailing '\n' */ 12067c478bd9Sstevel@tonic-gate len = strlen(buffer2); 12077c478bd9Sstevel@tonic-gate if (buffer2[len-1] == '\n') { 12087c478bd9Sstevel@tonic-gate len--; 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate buffer2[len] = '\0'; 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate if ((name = strtok(buffer2, SEP_COLON)) == NULL) { 12137c478bd9Sstevel@tonic-gate rc = FAILURE; 12147c478bd9Sstevel@tonic-gate break; 12157c478bd9Sstevel@tonic-gate } else if (strcmp(puent->name, name) == 0) { 12167c478bd9Sstevel@tonic-gate found = B_TRUE; 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate } 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate if (found) { 12217c478bd9Sstevel@tonic-gate /* 12227c478bd9Sstevel@tonic-gate * This is the entry to be modified, get the updated 12237c478bd9Sstevel@tonic-gate * string. 12247c478bd9Sstevel@tonic-gate */ 12257c478bd9Sstevel@tonic-gate if ((str = uent2str(puent)) == NULL) { 12267c478bd9Sstevel@tonic-gate rc = FAILURE; 12277c478bd9Sstevel@tonic-gate break; 12287c478bd9Sstevel@tonic-gate } else { 12297c478bd9Sstevel@tonic-gate (void) strlcpy(buffer, str, BUFSIZ); 12307c478bd9Sstevel@tonic-gate free(str); 12317c478bd9Sstevel@tonic-gate } 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 12357c478bd9Sstevel@tonic-gate err = errno; 12367c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 12377c478bd9Sstevel@tonic-gate "failed to write to a temp file: %s."), 12387c478bd9Sstevel@tonic-gate strerror(err)); 12397c478bd9Sstevel@tonic-gate rc = FAILURE; 12407c478bd9Sstevel@tonic-gate break; 12417c478bd9Sstevel@tonic-gate } 12427c478bd9Sstevel@tonic-gate } 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate if (rc == FAILURE) { 12457c478bd9Sstevel@tonic-gate (void) fclose(pfile); 12467c478bd9Sstevel@tonic-gate (void) fclose(pfile_tmp); 12477c478bd9Sstevel@tonic-gate if (unlink(tmpfile_name) != 0) { 12487c478bd9Sstevel@tonic-gate err = errno; 12497c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 12507c478bd9Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 12517c478bd9Sstevel@tonic-gate tmpfile_name, strerror(err)); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate return (FAILURE); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate (void) fclose(pfile); 12577c478bd9Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 12587c478bd9Sstevel@tonic-gate err = errno; 12597c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 12607c478bd9Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name, 12617c478bd9Sstevel@tonic-gate strerror(err)); 12627c478bd9Sstevel@tonic-gate return (FAILURE); 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate /* Copy the temporary file to the pkcs11.conf file */ 12667c478bd9Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) { 12677c478bd9Sstevel@tonic-gate err = errno; 12687c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 12697c478bd9Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 12707c478bd9Sstevel@tonic-gate strerror(err)); 12717c478bd9Sstevel@tonic-gate cryptodebug("failed to rename %s to %s: %s", tmpfile_name, 12727c478bd9Sstevel@tonic-gate _PATH_PKCS11_CONF, strerror(err)); 12737c478bd9Sstevel@tonic-gate rc = FAILURE; 12747c478bd9Sstevel@tonic-gate } else if (chmod(_PATH_PKCS11_CONF, 12757c478bd9Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 12767c478bd9Sstevel@tonic-gate err = errno; 12777c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, 12787c478bd9Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 12797c478bd9Sstevel@tonic-gate strerror(err)); 12807c478bd9Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF, 12817c478bd9Sstevel@tonic-gate strerror(err)); 12827c478bd9Sstevel@tonic-gate rc = FAILURE; 12837c478bd9Sstevel@tonic-gate } else { 12847c478bd9Sstevel@tonic-gate rc = SUCCESS; 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 12887c478bd9Sstevel@tonic-gate err = errno; 12897c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 12907c478bd9Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 12917c478bd9Sstevel@tonic-gate tmpfile_name, strerror(err)); 12927c478bd9Sstevel@tonic-gate } 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate return (rc); 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate /* 12997c478bd9Sstevel@tonic-gate * Convert an uentry to a character string 13007c478bd9Sstevel@tonic-gate */ 13017c478bd9Sstevel@tonic-gate static char * 13027c478bd9Sstevel@tonic-gate uent2str(uentry_t *puent) 13037c478bd9Sstevel@tonic-gate { 13047c478bd9Sstevel@tonic-gate umechlist_t *phead; 13057c478bd9Sstevel@tonic-gate boolean_t tok1_present = B_FALSE; 13067c478bd9Sstevel@tonic-gate char *buf; 13077c478bd9Sstevel@tonic-gate char blank_buf[128]; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate if (puent == NULL) { 13107c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 13117c478bd9Sstevel@tonic-gate return (NULL); 13127c478bd9Sstevel@tonic-gate } 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate buf = malloc(BUFSIZ); 13157c478bd9Sstevel@tonic-gate if (buf == NULL) { 13167c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("out of memory.")); 13177c478bd9Sstevel@tonic-gate return (NULL); 13187c478bd9Sstevel@tonic-gate } 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate /* convert the library name */ 13217c478bd9Sstevel@tonic-gate if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) { 13227c478bd9Sstevel@tonic-gate free(buf); 13237c478bd9Sstevel@tonic-gate return (NULL); 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate /* convert the enabledlist or the disabledlist */ 13287c478bd9Sstevel@tonic-gate if (puent->flag_enabledlist == B_TRUE) { 13297c478bd9Sstevel@tonic-gate if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) { 13307c478bd9Sstevel@tonic-gate free(buf); 13317c478bd9Sstevel@tonic-gate return (NULL); 13327c478bd9Sstevel@tonic-gate } 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) { 13357c478bd9Sstevel@tonic-gate free(buf); 13367c478bd9Sstevel@tonic-gate return (NULL); 13377c478bd9Sstevel@tonic-gate } 13387c478bd9Sstevel@tonic-gate 13397c478bd9Sstevel@tonic-gate phead = puent->policylist; 13407c478bd9Sstevel@tonic-gate while (phead != NULL) { 13417c478bd9Sstevel@tonic-gate if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) { 13427c478bd9Sstevel@tonic-gate free(buf); 13437c478bd9Sstevel@tonic-gate return (NULL); 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate phead = phead->next; 13477c478bd9Sstevel@tonic-gate if (phead != NULL) { 13487c478bd9Sstevel@tonic-gate if (strlcat(buf, SEP_COMMA, BUFSIZ) 13497c478bd9Sstevel@tonic-gate >= BUFSIZ) { 13507c478bd9Sstevel@tonic-gate free(buf); 13517c478bd9Sstevel@tonic-gate return (NULL); 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate } 13547c478bd9Sstevel@tonic-gate } 13557c478bd9Sstevel@tonic-gate tok1_present = B_TRUE; 13567c478bd9Sstevel@tonic-gate } else if (puent->policylist != NULL) { 13577c478bd9Sstevel@tonic-gate if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) { 13587c478bd9Sstevel@tonic-gate free(buf); 13597c478bd9Sstevel@tonic-gate return (NULL); 13607c478bd9Sstevel@tonic-gate } 13617c478bd9Sstevel@tonic-gate 13627c478bd9Sstevel@tonic-gate if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) { 13637c478bd9Sstevel@tonic-gate free(buf); 13647c478bd9Sstevel@tonic-gate return (NULL); 13657c478bd9Sstevel@tonic-gate } 13667c478bd9Sstevel@tonic-gate phead = puent->policylist; 13677c478bd9Sstevel@tonic-gate while (phead != NULL) { 13687c478bd9Sstevel@tonic-gate if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) { 13697c478bd9Sstevel@tonic-gate free(buf); 13707c478bd9Sstevel@tonic-gate return (NULL); 13717c478bd9Sstevel@tonic-gate } 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate phead = phead->next; 13747c478bd9Sstevel@tonic-gate if (phead != NULL) { 13757c478bd9Sstevel@tonic-gate if (strlcat(buf, SEP_COMMA, BUFSIZ) 13767c478bd9Sstevel@tonic-gate >= BUFSIZ) { 13777c478bd9Sstevel@tonic-gate free(buf); 13787c478bd9Sstevel@tonic-gate return (NULL); 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate } 13817c478bd9Sstevel@tonic-gate } 13827c478bd9Sstevel@tonic-gate tok1_present = B_TRUE; 13837c478bd9Sstevel@tonic-gate } 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate if (puent->flag_norandom == B_TRUE) { 13867c478bd9Sstevel@tonic-gate if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON), 13877c478bd9Sstevel@tonic-gate BUFSIZ) >= BUFSIZ) { 13887c478bd9Sstevel@tonic-gate free(buf); 13897c478bd9Sstevel@tonic-gate return (NULL); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) { 13937c478bd9Sstevel@tonic-gate free(buf); 13947c478bd9Sstevel@tonic-gate return (NULL); 13957c478bd9Sstevel@tonic-gate } 13967c478bd9Sstevel@tonic-gate } 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate if (strcmp(puent->name, METASLOT_KEYWORD) == 0) { 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate /* write the metaslot_status= value */ 14017c478bd9Sstevel@tonic-gate if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON), 14027c478bd9Sstevel@tonic-gate BUFSIZ) >= BUFSIZ) { 14037c478bd9Sstevel@tonic-gate free(buf); 14047c478bd9Sstevel@tonic-gate return (NULL); 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) { 14087c478bd9Sstevel@tonic-gate free(buf); 14097c478bd9Sstevel@tonic-gate return (NULL); 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate if (puent->flag_metaslot_enabled) { 1413b5a2d845SHai-May Chao if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) { 14147c478bd9Sstevel@tonic-gate free(buf); 14157c478bd9Sstevel@tonic-gate return (NULL); 14167c478bd9Sstevel@tonic-gate } 14177c478bd9Sstevel@tonic-gate } else { 1418b5a2d845SHai-May Chao if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ) 14197c478bd9Sstevel@tonic-gate >= BUFSIZ) { 14207c478bd9Sstevel@tonic-gate free(buf); 14217c478bd9Sstevel@tonic-gate return (NULL); 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate if (!tok1_present) { 14267c478bd9Sstevel@tonic-gate tok1_present = B_TRUE; 14277c478bd9Sstevel@tonic-gate } 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) { 14307c478bd9Sstevel@tonic-gate free(buf); 14317c478bd9Sstevel@tonic-gate return (NULL); 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) { 14357c478bd9Sstevel@tonic-gate free(buf); 14367c478bd9Sstevel@tonic-gate return (NULL); 14377c478bd9Sstevel@tonic-gate } 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate if (puent->flag_metaslot_auto_key_migrate) { 1440b5a2d845SHai-May Chao if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) { 14417c478bd9Sstevel@tonic-gate free(buf); 14427c478bd9Sstevel@tonic-gate return (NULL); 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate } else { 1445b5a2d845SHai-May Chao if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ) >= BUFSIZ) { 14467c478bd9Sstevel@tonic-gate free(buf); 14477c478bd9Sstevel@tonic-gate return (NULL); 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate 14517c478bd9Sstevel@tonic-gate bzero(blank_buf, sizeof (blank_buf)); 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* write metaslot_token= if specified */ 14547c478bd9Sstevel@tonic-gate if (memcmp(puent->metaslot_ks_token, blank_buf, 14557c478bd9Sstevel@tonic-gate TOKEN_LABEL_SIZE) != 0) { 14567c478bd9Sstevel@tonic-gate /* write the metaslot_status= value */ 14577c478bd9Sstevel@tonic-gate if (strlcat(buf, (tok1_present ? 14587c478bd9Sstevel@tonic-gate SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) { 14597c478bd9Sstevel@tonic-gate free(buf); 14607c478bd9Sstevel@tonic-gate return (NULL); 14617c478bd9Sstevel@tonic-gate } 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) { 14647c478bd9Sstevel@tonic-gate free(buf); 14657c478bd9Sstevel@tonic-gate return (NULL); 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate if (strlcat(buf, 14697c478bd9Sstevel@tonic-gate (const char *)puent->metaslot_ks_token, BUFSIZ) 14707c478bd9Sstevel@tonic-gate >= BUFSIZ) { 14717c478bd9Sstevel@tonic-gate free(buf); 14727c478bd9Sstevel@tonic-gate return (NULL); 14737c478bd9Sstevel@tonic-gate } 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate /* write metaslot_slot= if specified */ 14777c478bd9Sstevel@tonic-gate if (memcmp(puent->metaslot_ks_slot, blank_buf, 14787c478bd9Sstevel@tonic-gate SLOT_DESCRIPTION_SIZE) != 0) { 14797c478bd9Sstevel@tonic-gate /* write the metaslot_status= value */ 14807c478bd9Sstevel@tonic-gate if (strlcat(buf, (tok1_present ? 14817c478bd9Sstevel@tonic-gate SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) { 14827c478bd9Sstevel@tonic-gate free(buf); 14837c478bd9Sstevel@tonic-gate return (NULL); 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) { 14877c478bd9Sstevel@tonic-gate free(buf); 14887c478bd9Sstevel@tonic-gate return (NULL); 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate if (strlcat(buf, 14927c478bd9Sstevel@tonic-gate (const char *)puent->metaslot_ks_slot, BUFSIZ) 14937c478bd9Sstevel@tonic-gate >= BUFSIZ) { 14947c478bd9Sstevel@tonic-gate free(buf); 14957c478bd9Sstevel@tonic-gate return (NULL); 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) { 15017c478bd9Sstevel@tonic-gate free(buf); 15027c478bd9Sstevel@tonic-gate return (NULL); 15037c478bd9Sstevel@tonic-gate } 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate return (buf); 15067c478bd9Sstevel@tonic-gate } 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate /* 15107c478bd9Sstevel@tonic-gate * This function updates the default policy mode and the policy exception list 15117c478bd9Sstevel@tonic-gate * for a user-level provider based on the mechanism specified in the disable 15127c478bd9Sstevel@tonic-gate * or enable subcommand and the update mode. This function is called by the 15137c478bd9Sstevel@tonic-gate * enable_uef_lib() or disable_uef_lib(). 15147c478bd9Sstevel@tonic-gate */ 15157c478bd9Sstevel@tonic-gate int 15167c478bd9Sstevel@tonic-gate update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode) 15177c478bd9Sstevel@tonic-gate { 15187c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mech_type; 15197c478bd9Sstevel@tonic-gate midstr_t midname; 15207c478bd9Sstevel@tonic-gate umechlist_t *phead; 15217c478bd9Sstevel@tonic-gate umechlist_t *pcur; 15227c478bd9Sstevel@tonic-gate umechlist_t *pumech; 15237c478bd9Sstevel@tonic-gate boolean_t found; 15247c478bd9Sstevel@tonic-gate int rc = SUCCESS; 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate if ((puent == NULL) || (marglist == NULL)) { 15277c478bd9Sstevel@tonic-gate /* should not happen */ 15287c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 15297c478bd9Sstevel@tonic-gate cryptodebug("update_policylist()- puent or marglist is NULL."); 15307c478bd9Sstevel@tonic-gate return (FAILURE); 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) { 15347c478bd9Sstevel@tonic-gate /* should not happen */ 15357c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 15367c478bd9Sstevel@tonic-gate cryptodebug("update_policylist() - update_mode is incorrect."); 15377c478bd9Sstevel@tonic-gate return (FAILURE); 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate /* 15417c478bd9Sstevel@tonic-gate * For each mechanism operand, get its mechanism type first. 15427c478bd9Sstevel@tonic-gate * If fails to get the mechanism type, the mechanism operand must be 15437c478bd9Sstevel@tonic-gate * invalid, gives an warning and ignore it. Otherwise, 15447c478bd9Sstevel@tonic-gate * - convert the mechanism type to the internal representation (hex) 15457c478bd9Sstevel@tonic-gate * in the pkcs11.conf file 15467c478bd9Sstevel@tonic-gate * - If update_mode == DELETE_MODE, 15477c478bd9Sstevel@tonic-gate * If the mechanism is in the policy list, delete it. 15487c478bd9Sstevel@tonic-gate * If the mechanism is not in the policy list, do nothing. 15497c478bd9Sstevel@tonic-gate * - If update_mode == ADD_MODE, 15507c478bd9Sstevel@tonic-gate * If the mechanism is not in the policy list, add it. 15517c478bd9Sstevel@tonic-gate * If the mechanism is in the policy list already, do nothing. 15527c478bd9Sstevel@tonic-gate */ 15537c478bd9Sstevel@tonic-gate while (marglist) { 15547c478bd9Sstevel@tonic-gate if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) { 15557c478bd9Sstevel@tonic-gate /* 15567c478bd9Sstevel@tonic-gate * This mechanism is not a valid PKCS11 mechanism, 15577c478bd9Sstevel@tonic-gate * give warning and ignore it. 15587c478bd9Sstevel@tonic-gate */ 15597c478bd9Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 15607c478bd9Sstevel@tonic-gate "(Warning) %s is not a valid PKCS#11 mechanism."), 15617c478bd9Sstevel@tonic-gate marglist->name); 15627c478bd9Sstevel@tonic-gate rc = FAILURE; 15637c478bd9Sstevel@tonic-gate } else { 15647c478bd9Sstevel@tonic-gate (void) snprintf(midname, sizeof (midname), "%#010x", 15657c478bd9Sstevel@tonic-gate (int)mech_type); 15667c478bd9Sstevel@tonic-gate if (update_mode == DELETE_MODE) { 15677c478bd9Sstevel@tonic-gate found = B_FALSE; 15687c478bd9Sstevel@tonic-gate phead = pcur = puent->policylist; 15697c478bd9Sstevel@tonic-gate while (!found && pcur) { 15707c478bd9Sstevel@tonic-gate if (strcmp(pcur->name, midname) == 0) { 15717c478bd9Sstevel@tonic-gate found = B_TRUE; 15727c478bd9Sstevel@tonic-gate } else { 15737c478bd9Sstevel@tonic-gate phead = pcur; 15747c478bd9Sstevel@tonic-gate pcur = pcur->next; 15757c478bd9Sstevel@tonic-gate } 15767c478bd9Sstevel@tonic-gate } 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate if (found) { 15797c478bd9Sstevel@tonic-gate if (phead == pcur) { 15807c478bd9Sstevel@tonic-gate puent->policylist = 15817c478bd9Sstevel@tonic-gate puent->policylist->next; 15827c478bd9Sstevel@tonic-gate free(pcur); 15837c478bd9Sstevel@tonic-gate } else { 15847c478bd9Sstevel@tonic-gate phead->next = pcur->next; 15857c478bd9Sstevel@tonic-gate free(pcur); 15867c478bd9Sstevel@tonic-gate } 15877c478bd9Sstevel@tonic-gate puent->count--; 15887c478bd9Sstevel@tonic-gate if (puent->count == 0) { 15897c478bd9Sstevel@tonic-gate puent->policylist = NULL; 15907c478bd9Sstevel@tonic-gate } 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate } else if (update_mode == ADD_MODE) { 15937c478bd9Sstevel@tonic-gate if (!is_in_policylist(midname, 15947c478bd9Sstevel@tonic-gate puent->policylist)) { 15957c478bd9Sstevel@tonic-gate pumech = create_umech(midname); 15967c478bd9Sstevel@tonic-gate if (pumech == NULL) { 15977c478bd9Sstevel@tonic-gate rc = FAILURE; 15987c478bd9Sstevel@tonic-gate break; 15997c478bd9Sstevel@tonic-gate } 16007c478bd9Sstevel@tonic-gate phead = puent->policylist; 16017c478bd9Sstevel@tonic-gate puent->policylist = pumech; 16027c478bd9Sstevel@tonic-gate pumech->next = phead; 16037c478bd9Sstevel@tonic-gate puent->count++; 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate } 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate marglist = marglist->next; 16087c478bd9Sstevel@tonic-gate } 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate return (rc); 16117c478bd9Sstevel@tonic-gate } 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate /* 16147c478bd9Sstevel@tonic-gate * Open a session to the given slot and check if we can do 16157c478bd9Sstevel@tonic-gate * random numbers by asking for one byte. 16167c478bd9Sstevel@tonic-gate */ 16177c478bd9Sstevel@tonic-gate static boolean_t 16187c478bd9Sstevel@tonic-gate check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs) 16197c478bd9Sstevel@tonic-gate { 16207c478bd9Sstevel@tonic-gate CK_RV rv; 16217c478bd9Sstevel@tonic-gate CK_SESSION_HANDLE hSession; 16227c478bd9Sstevel@tonic-gate CK_BYTE test_byte; 16237c478bd9Sstevel@tonic-gate CK_BYTE_PTR test_byte_ptr = &test_byte; 16247c478bd9Sstevel@tonic-gate 16257c478bd9Sstevel@tonic-gate rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION, 16267c478bd9Sstevel@tonic-gate NULL_PTR, NULL, &hSession); 16277c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 16287c478bd9Sstevel@tonic-gate return (B_FALSE); 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate /* We care only about the return value */ 16317c478bd9Sstevel@tonic-gate rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr, 16327c478bd9Sstevel@tonic-gate sizeof (test_byte)); 16337c478bd9Sstevel@tonic-gate (void) prov_funcs->C_CloseSession(hSession); 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate /* 16367c478bd9Sstevel@tonic-gate * These checks are purely to determine whether the slot can do 16377c478bd9Sstevel@tonic-gate * random numbers. So, we don't check whether the routine 16387c478bd9Sstevel@tonic-gate * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that 16397c478bd9Sstevel@tonic-gate * this error effectively means CKR_FUNCTION_NOT_SUPPORTED. 16407c478bd9Sstevel@tonic-gate */ 16417c478bd9Sstevel@tonic-gate if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG) 16427c478bd9Sstevel@tonic-gate return (B_TRUE); 16437c478bd9Sstevel@tonic-gate else 16447c478bd9Sstevel@tonic-gate return (B_FALSE); 16457c478bd9Sstevel@tonic-gate } 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate void 16487c478bd9Sstevel@tonic-gate display_verbose_mech_header() 16497c478bd9Sstevel@tonic-gate { 16507c478bd9Sstevel@tonic-gate (void) printf("%28s %s", " ", HDR1); 16517c478bd9Sstevel@tonic-gate (void) printf("%28s %s", " ", HDR2); 16527c478bd9Sstevel@tonic-gate (void) printf("%28s %s", " ", HDR3); 16537c478bd9Sstevel@tonic-gate (void) printf("%28s %s", " ", HDR4); 16547c478bd9Sstevel@tonic-gate (void) printf("%28s %s", " ", HDR5); 16557c478bd9Sstevel@tonic-gate (void) printf("%28s %s", " ", HDR6); 16567c478bd9Sstevel@tonic-gate (void) printf("%-28.28s %s", gettext("mechanism name"), HDR7); 16577c478bd9Sstevel@tonic-gate /* 16580a85b835SDaniel Anderson * TRANSLATION_NOTE 16597c478bd9Sstevel@tonic-gate * Strictly for appearance's sake, the first header line should be 16607c478bd9Sstevel@tonic-gate * as long as the length of the translated text above. The format 16617c478bd9Sstevel@tonic-gate * lengths should all match too. 16627c478bd9Sstevel@tonic-gate */ 16637c478bd9Sstevel@tonic-gate (void) printf("%28s ---- ---- " 16647c478bd9Sstevel@tonic-gate "- - - - - - - - - - - - - -\n", 16657c478bd9Sstevel@tonic-gate gettext("----------------------------")); 16667c478bd9Sstevel@tonic-gate } 1667