10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53089Swyllys  * Common Development and Distribution License (the "License").
63089Swyllys  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*10500SHai-May.Chao@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <cryptoutil.h>
270Sstevel@tonic-gate #include <fcntl.h>
280Sstevel@tonic-gate #include <libintl.h>
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <strings.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <errno.h>
340Sstevel@tonic-gate #include <dlfcn.h>
350Sstevel@tonic-gate #include <link.h>
360Sstevel@tonic-gate #include <sys/types.h>
370Sstevel@tonic-gate #include <sys/stat.h>
380Sstevel@tonic-gate #include <security/cryptoki.h>
390Sstevel@tonic-gate #include "cryptoadm.h"
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #define	HDR1 "                                     P\n"
420Sstevel@tonic-gate #define	HDR2 "                         S     V  K  a     U  D\n"
430Sstevel@tonic-gate #define	HDR3 "                         i     e  e  i     n  e\n"
440Sstevel@tonic-gate #define	HDR4 "                      S  g  V  r  y  r  W  w  r\n"
450Sstevel@tonic-gate #define	HDR5 "             E  D  D  i  n  e  i  G  G  r  r  i\n"
460Sstevel@tonic-gate #define	HDR6 "          H  n  e  i  g  +  r  +  e  e  a  a  v  E\n"
470Sstevel@tonic-gate #define	HDR7 "min  max  W  c  c  g  n  R  i  R  n  n  p  p  e  C\n"
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 
500Sstevel@tonic-gate static int err; /* To store errno which may be overwritten by gettext() */
510Sstevel@tonic-gate static boolean_t is_in_policylist(midstr_t, umechlist_t *);
520Sstevel@tonic-gate static char *uent2str(uentry_t *);
530Sstevel@tonic-gate static boolean_t check_random(CK_SLOT_ID, CK_FUNCTION_LIST_PTR);
540Sstevel@tonic-gate 
550Sstevel@tonic-gate static void display_slot_flags(CK_FLAGS flags)
560Sstevel@tonic-gate {
570Sstevel@tonic-gate 	(void) printf(gettext("Slot Flags: "));
580Sstevel@tonic-gate 	if (flags & CKF_TOKEN_PRESENT)
590Sstevel@tonic-gate 		(void) printf("CKF_TOKEN_PRESENT ");
600Sstevel@tonic-gate 	if (flags & CKF_REMOVABLE_DEVICE)
610Sstevel@tonic-gate 		(void) printf("CKF_REMOVABLE_DEVICE ");
620Sstevel@tonic-gate 	if (flags & CKF_HW_SLOT)
630Sstevel@tonic-gate 		(void) printf("CKF_HW_SLOT ");
640Sstevel@tonic-gate 	(void) printf("\n");
650Sstevel@tonic-gate }
660Sstevel@tonic-gate 
670Sstevel@tonic-gate void
680Sstevel@tonic-gate display_token_flags(CK_FLAGS flags)
690Sstevel@tonic-gate {
700Sstevel@tonic-gate 	(void) printf(gettext("Flags: "));
710Sstevel@tonic-gate 	if (flags & CKF_RNG)
720Sstevel@tonic-gate 		(void) printf("CKF_RNG ");
730Sstevel@tonic-gate 	if (flags & CKF_WRITE_PROTECTED)
740Sstevel@tonic-gate 		(void) printf("CKF_WRITE_PROTECTED ");
750Sstevel@tonic-gate 	if (flags & CKF_LOGIN_REQUIRED)
760Sstevel@tonic-gate 		(void) printf("CKF_LOGIN_REQUIRED ");
770Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_INITIALIZED)
780Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_INITIALIZED ");
790Sstevel@tonic-gate 	if (flags & CKF_RESTORE_KEY_NOT_NEEDED)
800Sstevel@tonic-gate 		(void) printf("CKF_RESTORE_KEY_NOT_NEEDED ");
810Sstevel@tonic-gate 	if (flags & CKF_CLOCK_ON_TOKEN)
820Sstevel@tonic-gate 		(void) printf("CKF_CLOCK_ON_TOKEN ");
830Sstevel@tonic-gate 	if (flags & CKF_PROTECTED_AUTHENTICATION_PATH)
840Sstevel@tonic-gate 		(void) printf("CKF_PROTECTED_AUTHENTICATION_PATH ");
850Sstevel@tonic-gate 	if (flags & CKF_DUAL_CRYPTO_OPERATIONS)
860Sstevel@tonic-gate 		(void) printf("CKF_DUAL_CRYPTO_OPERATIONS ");
870Sstevel@tonic-gate 	if (flags & CKF_TOKEN_INITIALIZED)
880Sstevel@tonic-gate 		(void) printf("CKF_TOKEN_INITIALIZED ");
890Sstevel@tonic-gate 	if (flags & CKF_SECONDARY_AUTHENTICATION)
900Sstevel@tonic-gate 		(void) printf("CKF_SECONDARY_AUTHENTICATION ");
910Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_COUNT_LOW)
920Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_COUNT_LOW ");
930Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_FINAL_TRY)
940Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_FINAL_TRY ");
950Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_LOCKED)
960Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_LOCKED ");
970Sstevel@tonic-gate 	if (flags & CKF_USER_PIN_TO_BE_CHANGED)
980Sstevel@tonic-gate 		(void) printf("CKF_USER_PIN_TO_BE_CHANGED ");
990Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_COUNT_LOW)
1000Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_COUNT_LOW ");
1010Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_FINAL_TRY)
1020Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_FINAL_TRY ");
1030Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_LOCKED)
1040Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_LOCKED ");
1050Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_TO_BE_CHANGED)
1060Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
1070Sstevel@tonic-gate 	if (flags & CKF_SO_PIN_TO_BE_CHANGED)
1080Sstevel@tonic-gate 		(void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
1090Sstevel@tonic-gate 	(void) printf("\n");
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate void
1130Sstevel@tonic-gate display_mech_info(CK_MECHANISM_INFO *mechInfo)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate 	CK_FLAGS ec_flags = CKF_EC_F_P | CKF_EC_F_2M | CKF_EC_ECPARAMETERS |
1167011Sda73024 	    CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS | CKF_EC_COMPRESS;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	(void) printf("%-4ld %-4ld ", mechInfo->ulMinKeySize,
1197011Sda73024 	    mechInfo->ulMaxKeySize);
1200Sstevel@tonic-gate 	(void) printf("%s  %s  %s  %s  %s  %s  %s  %s  %s  %s  %s  %s  "
1217011Sda73024 	    "%s  %s",
1227011Sda73024 	    (mechInfo->flags & CKF_HW) ? "X" : ".",
1237011Sda73024 	    (mechInfo->flags & CKF_ENCRYPT) ? "X" : ".",
1247011Sda73024 	    (mechInfo->flags & CKF_DECRYPT) ? "X" : ".",
1257011Sda73024 	    (mechInfo->flags & CKF_DIGEST) ? "X" : ".",
1267011Sda73024 	    (mechInfo->flags & CKF_SIGN) ? "X" : ".",
1277011Sda73024 	    (mechInfo->flags & CKF_SIGN_RECOVER) ? "X" : ".",
1287011Sda73024 	    (mechInfo->flags & CKF_VERIFY) ? "X" : ".",
1297011Sda73024 	    (mechInfo->flags & CKF_VERIFY_RECOVER) ? "X" : ".",
1307011Sda73024 	    (mechInfo->flags & CKF_GENERATE) ? "X" : ".",
1317011Sda73024 	    (mechInfo->flags & CKF_GENERATE_KEY_PAIR) ? "X" : ".",
1327011Sda73024 	    (mechInfo->flags & CKF_WRAP) ? "X" : ".",
1337011Sda73024 	    (mechInfo->flags & CKF_UNWRAP) ? "X" : ".",
1347011Sda73024 	    (mechInfo->flags & CKF_DERIVE) ? "X" : ".",
1357011Sda73024 	    (mechInfo->flags & ec_flags) ? "X" : ".");
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate /*
1390Sstevel@tonic-gate  * Converts the provided list of mechanism names in their string format to
1407011Sda73024  * their corresponding PKCS#11 mechanism IDs.
1410Sstevel@tonic-gate  *
1420Sstevel@tonic-gate  * The list of mechanism names to be converted is provided in the
1430Sstevel@tonic-gate  * "mlist" argument.  The list of converted mechanism IDs is returned
1440Sstevel@tonic-gate  * in the "pmech_list" argument.
1450Sstevel@tonic-gate  *
1460Sstevel@tonic-gate  * This function is called by list_metaslot_info() and
1470Sstevel@tonic-gate  * list_mechlist_for_lib() functions.
1480Sstevel@tonic-gate  */
1490Sstevel@tonic-gate int
1500Sstevel@tonic-gate convert_mechlist(CK_MECHANISM_TYPE **pmech_list, CK_ULONG *mech_count,
1510Sstevel@tonic-gate     mechlist_t *mlist)
1520Sstevel@tonic-gate {
1530Sstevel@tonic-gate 	int i, n = 0;
1540Sstevel@tonic-gate 	mechlist_t *p = mlist;
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	while (p != NULL) {
1570Sstevel@tonic-gate 		p = p->next;
1580Sstevel@tonic-gate 		n++;
1590Sstevel@tonic-gate 	}
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	*pmech_list = malloc(n * sizeof (CK_MECHANISM_TYPE));
1620Sstevel@tonic-gate 	if (pmech_list == NULL) {
1630Sstevel@tonic-gate 		cryptodebug("out of memory");
1640Sstevel@tonic-gate 		return (FAILURE);
1650Sstevel@tonic-gate 	}
1660Sstevel@tonic-gate 	p = mlist;
1670Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
1680Sstevel@tonic-gate 		if (pkcs11_str2mech(p->name, &(*pmech_list[i])) != CKR_OK) {
1690Sstevel@tonic-gate 			free(*pmech_list);
1700Sstevel@tonic-gate 			return (FAILURE);
1710Sstevel@tonic-gate 		}
1720Sstevel@tonic-gate 		p = p->next;
1730Sstevel@tonic-gate 	}
1740Sstevel@tonic-gate 	*mech_count = n;
1750Sstevel@tonic-gate 	return (SUCCESS);
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate /*
1790Sstevel@tonic-gate  * Display the mechanism list for a user-level library
1800Sstevel@tonic-gate  */
1810Sstevel@tonic-gate int
1820Sstevel@tonic-gate list_mechlist_for_lib(char *libname, mechlist_t *mlist,
1830Sstevel@tonic-gate 		flag_val_t *rng_flag, boolean_t no_warn,
1840Sstevel@tonic-gate 		boolean_t verbose, boolean_t show_mechs)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate 	CK_RV	rv = CKR_OK;
1870Sstevel@tonic-gate 	CK_RV	(*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR);
1880Sstevel@tonic-gate 	CK_FUNCTION_LIST_PTR	prov_funcs; /* Provider's function list */
1890Sstevel@tonic-gate 	CK_SLOT_ID_PTR		prov_slots = NULL; /* Provider's slot list */
1900Sstevel@tonic-gate 	CK_MECHANISM_TYPE_PTR	pmech_list; /* mechanism list for a slot */
1910Sstevel@tonic-gate 	CK_SLOT_INFO	slotinfo;
1920Sstevel@tonic-gate 	CK_ULONG	slot_count;
1930Sstevel@tonic-gate 	CK_ULONG	mech_count;
1940Sstevel@tonic-gate 	uentry_t	*puent = NULL;
1957011Sda73024 	boolean_t	lib_initialized = B_FALSE;
1967011Sda73024 	void		*dldesc = NULL;
1977011Sda73024 	char		*dl_error;
1987011Sda73024 	const char 	*mech_name;
1997011Sda73024 	char		*isa;
2007011Sda73024 	char		libpath[MAXPATHLEN];
2017011Sda73024 	char		buf[MAXPATHLEN];
2027011Sda73024 	int		i, j;
2037011Sda73024 	int		rc = SUCCESS;
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if (libname == NULL) {
2060Sstevel@tonic-gate 		/* should not happen */
2070Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
2080Sstevel@tonic-gate 		cryptodebug("list_mechlist_for_lib() - libname is NULL.");
2090Sstevel@tonic-gate 		return (FAILURE);
2100Sstevel@tonic-gate 	}
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	/* Check if the library is in the pkcs11.conf file */
2130Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
2140Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
2150Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
2160Sstevel@tonic-gate 		return (FAILURE);
2170Sstevel@tonic-gate 	}
2180Sstevel@tonic-gate 	free_uentry(puent);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	/* Remove $ISA from the library name */
2210Sstevel@tonic-gate 	if (strlcpy(buf, libname, sizeof (buf)) >= sizeof (buf)) {
2220Sstevel@tonic-gate 		(void) printf(gettext("%s: the provider name is too long."),
2230Sstevel@tonic-gate 		    libname);
2240Sstevel@tonic-gate 		return (FAILURE);
2250Sstevel@tonic-gate 	}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
2280Sstevel@tonic-gate 		*isa = '\000';
2290Sstevel@tonic-gate 		isa += strlen(PKCS11_ISA);
2300Sstevel@tonic-gate 		(void) snprintf(libpath, MAXPATHLEN, "%s%s%s", buf, "/", isa);
2310Sstevel@tonic-gate 	} else {
2320Sstevel@tonic-gate 		(void) strlcpy(libpath, libname, sizeof (libpath));
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	/* Open the provider */
2360Sstevel@tonic-gate 	dldesc = dlopen(libpath, RTLD_NOW);
2370Sstevel@tonic-gate 	if (dldesc == NULL) {
2380Sstevel@tonic-gate 		dl_error = dlerror();
2390Sstevel@tonic-gate 		cryptodebug("Cannot load PKCS#11 library %s.  dlerror: %s",
2400Sstevel@tonic-gate 		    libname, dl_error != NULL ? dl_error : "Unknown");
2410Sstevel@tonic-gate 		rc = FAILURE;
2420Sstevel@tonic-gate 		goto clean_exit;
2430Sstevel@tonic-gate 	}
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	/* Get the pointer to provider's C_GetFunctionList() */
2460Sstevel@tonic-gate 	Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");
2470Sstevel@tonic-gate 	if (Tmp_C_GetFunctionList == NULL) {
2480Sstevel@tonic-gate 		cryptodebug("Cannot get the address of the C_GetFunctionList "
2490Sstevel@tonic-gate 		    "from %s", libname);
2500Sstevel@tonic-gate 		rc = FAILURE;
2510Sstevel@tonic-gate 		goto clean_exit;
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	/* Get the provider's function list */
2550Sstevel@tonic-gate 	rv = Tmp_C_GetFunctionList(&prov_funcs);
2560Sstevel@tonic-gate 	if (rv != CKR_OK) {
2570Sstevel@tonic-gate 		cryptodebug("failed to call C_GetFunctionList from %s",
2580Sstevel@tonic-gate 		    libname);
2590Sstevel@tonic-gate 		rc = FAILURE;
2600Sstevel@tonic-gate 		goto clean_exit;
2610Sstevel@tonic-gate 	}
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	/* Initialize this provider */
2640Sstevel@tonic-gate 	rv = prov_funcs->C_Initialize(NULL_PTR);
2650Sstevel@tonic-gate 	if (rv != CKR_OK) {
2660Sstevel@tonic-gate 		cryptodebug("failed to call C_Initialize from %s, "
2670Sstevel@tonic-gate 		    "return code = %d", libname, rv);
2680Sstevel@tonic-gate 		rc = FAILURE;
2690Sstevel@tonic-gate 		goto clean_exit;
2700Sstevel@tonic-gate 	} else {
2710Sstevel@tonic-gate 		lib_initialized = B_TRUE;
2720Sstevel@tonic-gate 	}
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	/*
2750Sstevel@tonic-gate 	 * Find out how many slots this provider has, call with tokenPresent
2760Sstevel@tonic-gate 	 * set to FALSE so all potential slots are returned.
2770Sstevel@tonic-gate 	 */
2780Sstevel@tonic-gate 	rv = prov_funcs->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
2790Sstevel@tonic-gate 	if (rv != CKR_OK) {
2800Sstevel@tonic-gate 		cryptodebug("failed to get the slotlist from %s.", libname);
2810Sstevel@tonic-gate 		rc = FAILURE;
2820Sstevel@tonic-gate 		goto clean_exit;
2830Sstevel@tonic-gate 	} else if (slot_count == 0) {
2840Sstevel@tonic-gate 		if (!no_warn)
2850Sstevel@tonic-gate 			(void) printf(gettext("%s: no slots presented.\n"),
2867011Sda73024 			    libname);
2870Sstevel@tonic-gate 		rc = SUCCESS;
2880Sstevel@tonic-gate 		goto clean_exit;
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	/* Allocate memory for the slot list */
2920Sstevel@tonic-gate 	prov_slots = malloc(slot_count * sizeof (CK_SLOT_ID));
2930Sstevel@tonic-gate 	if (prov_slots == NULL) {
2940Sstevel@tonic-gate 		cryptodebug("out of memory.");
2950Sstevel@tonic-gate 		rc = FAILURE;
2960Sstevel@tonic-gate 		goto clean_exit;
2970Sstevel@tonic-gate 	}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	/* Get the slot list from provider */
3000Sstevel@tonic-gate 	rv = prov_funcs->C_GetSlotList(FALSE, prov_slots, &slot_count);
3010Sstevel@tonic-gate 	if (rv != CKR_OK) {
3020Sstevel@tonic-gate 		cryptodebug("failed to call C_GetSlotList() from %s.",
3030Sstevel@tonic-gate 		    libname);
3040Sstevel@tonic-gate 		rc = FAILURE;
3050Sstevel@tonic-gate 		goto clean_exit;
3060Sstevel@tonic-gate 	}
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	if (verbose) {
3090Sstevel@tonic-gate 		(void) printf(gettext("Number of slots: %d\n"), slot_count);
3100Sstevel@tonic-gate 	}
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	/* Get the mechanism list for each slot */
3130Sstevel@tonic-gate 	for (i = 0; i < slot_count; i++) {
3140Sstevel@tonic-gate 		if (verbose)
3150Sstevel@tonic-gate 			/*
3167334SDaniel.Anderson@Sun.COM 			 * TRANSLATION_NOTE
3170Sstevel@tonic-gate 			 * In some languages, the # symbol should be
3180Sstevel@tonic-gate 			 * converted to "no", an "n" followed by a
3190Sstevel@tonic-gate 			 * superscript "o"..
3200Sstevel@tonic-gate 			 */
3210Sstevel@tonic-gate 			(void) printf(gettext("\nSlot #%d\n"), i+1);
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 		if ((rng_flag != NULL) && (*rng_flag == NO_RNG)) {
3240Sstevel@tonic-gate 			if (check_random(prov_slots[i], prov_funcs)) {
3250Sstevel@tonic-gate 				*rng_flag = HAS_RNG;
3260Sstevel@tonic-gate 				rc = SUCCESS;
3270Sstevel@tonic-gate 				goto clean_exit;
3280Sstevel@tonic-gate 			} else
3290Sstevel@tonic-gate 				continue;
3300Sstevel@tonic-gate 		}
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 		rv = prov_funcs->C_GetSlotInfo(prov_slots[i], &slotinfo);
3330Sstevel@tonic-gate 		if (rv != CKR_OK) {
3340Sstevel@tonic-gate 			cryptodebug("failed to get slotinfo from %s", libname);
3350Sstevel@tonic-gate 			rc = FAILURE;
3360Sstevel@tonic-gate 			break;
3370Sstevel@tonic-gate 		}
3380Sstevel@tonic-gate 		if (verbose) {
3390Sstevel@tonic-gate 			CK_TOKEN_INFO tokeninfo;
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 			(void) printf(gettext("Description: %.64s\n"
3427011Sda73024 			    "Manufacturer: %.32s\n"
3437011Sda73024 			    "PKCS#11 Version: %d.%d\n"),
3447011Sda73024 			    slotinfo.slotDescription,
3457011Sda73024 			    slotinfo.manufacturerID,
3467011Sda73024 			    prov_funcs->version.major,
3477011Sda73024 			    prov_funcs->version.minor);
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 			(void) printf(gettext("Hardware Version: %d.%d\n"
3507011Sda73024 			    "Firmware Version: %d.%d\n"),
3517011Sda73024 			    slotinfo.hardwareVersion.major,
3527011Sda73024 			    slotinfo.hardwareVersion.minor,
3537011Sda73024 			    slotinfo.firmwareVersion.major,
3547011Sda73024 			    slotinfo.firmwareVersion.minor);
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 			(void) printf(gettext("Token Present: %s\n"),
3577011Sda73024 			    (slotinfo.flags & CKF_TOKEN_PRESENT ?
3587011Sda73024 			    gettext("True") : gettext("False")));
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 			display_slot_flags(slotinfo.flags);
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 			rv = prov_funcs->C_GetTokenInfo(prov_slots[i],
3637011Sda73024 			    &tokeninfo);
3640Sstevel@tonic-gate 			if (rv != CKR_OK) {
3650Sstevel@tonic-gate 				cryptodebug("Failed to get "
3667011Sda73024 				    "token info from %s", libname);
3670Sstevel@tonic-gate 				rc = FAILURE;
3680Sstevel@tonic-gate 				break;
3690Sstevel@tonic-gate 			}
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 			(void) printf(gettext("Token Label: %.32s\n"
3727011Sda73024 			    "Manufacturer ID: %.32s\n"
3737011Sda73024 			    "Model: %.16s\n"
3747011Sda73024 			    "Serial Number: %.16s\n"
3757011Sda73024 			    "Hardware Version: %d.%d\n"
3767011Sda73024 			    "Firmware Version: %d.%d\n"
3777011Sda73024 			    "UTC Time: %.16s\n"
3787304SDarren.Moffat@Sun.COM 			    "PIN Min Length: %d\n"
3797304SDarren.Moffat@Sun.COM 			    "PIN Max Length: %d\n"),
3807011Sda73024 			    tokeninfo.label,
3817011Sda73024 			    tokeninfo.manufacturerID,
3827011Sda73024 			    tokeninfo.model,
3837011Sda73024 			    tokeninfo.serialNumber,
3847011Sda73024 			    tokeninfo.hardwareVersion.major,
3857011Sda73024 			    tokeninfo.hardwareVersion.minor,
3867011Sda73024 			    tokeninfo.firmwareVersion.major,
3877011Sda73024 			    tokeninfo.firmwareVersion.minor,
3887011Sda73024 			    tokeninfo.utcTime,
3897011Sda73024 			    tokeninfo.ulMinPinLen,
3907011Sda73024 			    tokeninfo.ulMaxPinLen);
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 			display_token_flags(tokeninfo.flags);
3930Sstevel@tonic-gate 		}
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 		if (mlist == NULL) {
3960Sstevel@tonic-gate 			rv = prov_funcs->C_GetMechanismList(prov_slots[i],
3977011Sda73024 			    NULL_PTR, &mech_count);
3980Sstevel@tonic-gate 			if (rv != CKR_OK) {
3990Sstevel@tonic-gate 				cryptodebug(
4007011Sda73024 				    "failed to call C_GetMechanismList() "
4017011Sda73024 				    "from %s.", libname);
4020Sstevel@tonic-gate 				rc = FAILURE;
4030Sstevel@tonic-gate 				break;
4040Sstevel@tonic-gate 			}
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 			if (mech_count == 0) {
4070Sstevel@tonic-gate 				/* no mechanisms in this slot */
4080Sstevel@tonic-gate 				continue;
4090Sstevel@tonic-gate 			}
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 			pmech_list = malloc(mech_count *
4127011Sda73024 			    sizeof (CK_MECHANISM_TYPE));
4130Sstevel@tonic-gate 			if (pmech_list == NULL) {
4140Sstevel@tonic-gate 				cryptodebug("out of memory");
4150Sstevel@tonic-gate 				rc = FAILURE;
4160Sstevel@tonic-gate 				break;
4170Sstevel@tonic-gate 			}
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 			/* Get the actual mechanism list */
4200Sstevel@tonic-gate 			rv = prov_funcs->C_GetMechanismList(prov_slots[i],
4217011Sda73024 			    pmech_list, &mech_count);
4220Sstevel@tonic-gate 			if (rv != CKR_OK) {
4230Sstevel@tonic-gate 				cryptodebug(
4247011Sda73024 				    "failed to call C_GetMechanismList() "
4257011Sda73024 				    "from %s.", libname);
4260Sstevel@tonic-gate 				(void) free(pmech_list);
4270Sstevel@tonic-gate 				rc = FAILURE;
4280Sstevel@tonic-gate 				break;
4290Sstevel@tonic-gate 			}
4300Sstevel@tonic-gate 		} else  {
4310Sstevel@tonic-gate 			/* use the mechanism list passed in */
4320Sstevel@tonic-gate 			rc = convert_mechlist(&pmech_list, &mech_count, mlist);
4330Sstevel@tonic-gate 			if (rc != SUCCESS) {
4340Sstevel@tonic-gate 				goto clean_exit;
4350Sstevel@tonic-gate 			}
4360Sstevel@tonic-gate 		}
4370Sstevel@tonic-gate 		if (show_mechs)
4380Sstevel@tonic-gate 			(void) printf(gettext("Mechanisms:\n"));
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 		if (verbose && show_mechs) {
4410Sstevel@tonic-gate 			display_verbose_mech_header();
4420Sstevel@tonic-gate 		}
4430Sstevel@tonic-gate 		/*
4440Sstevel@tonic-gate 		 * Merge the current mechanism list into the returning
4450Sstevel@tonic-gate 		 * mechanism list.
4460Sstevel@tonic-gate 		 */
4470Sstevel@tonic-gate 		for (j = 0; show_mechs && j < mech_count; j++) {
4487011Sda73024 			CK_MECHANISM_TYPE	mech = pmech_list[j];
4497011Sda73024 
4507106Sda73024 			if (mech >= CKM_VENDOR_DEFINED) {
4517011Sda73024 				(void) printf("%#lx", mech);
4527011Sda73024 			} else {
4537011Sda73024 				mech_name = pkcs11_mech2str(mech);
4547011Sda73024 				(void) printf("%-29s", mech_name);
4557011Sda73024 			}
4567011Sda73024 
4570Sstevel@tonic-gate 			if (verbose) {
4580Sstevel@tonic-gate 				CK_MECHANISM_INFO mech_info;
4590Sstevel@tonic-gate 				rv = prov_funcs->C_GetMechanismInfo(
4607011Sda73024 				    prov_slots[i], mech, &mech_info);
4610Sstevel@tonic-gate 				if (rv != CKR_OK) {
4620Sstevel@tonic-gate 					cryptodebug(
4630Sstevel@tonic-gate 					    "failed to call "
4640Sstevel@tonic-gate 					    "C_GetMechanismInfo() from %s.",
4650Sstevel@tonic-gate 					    libname);
4660Sstevel@tonic-gate 					(void) free(pmech_list);
4670Sstevel@tonic-gate 					rc = FAILURE;
4680Sstevel@tonic-gate 					break;
4690Sstevel@tonic-gate 				}
4700Sstevel@tonic-gate 				display_mech_info(&mech_info);
4710Sstevel@tonic-gate 			}
4720Sstevel@tonic-gate 			(void) printf("\n");
4730Sstevel@tonic-gate 		}
4740Sstevel@tonic-gate 		(void) free(pmech_list);
4750Sstevel@tonic-gate 		if (rc == FAILURE) {
4760Sstevel@tonic-gate 			break;
4770Sstevel@tonic-gate 		}
4780Sstevel@tonic-gate 	}
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	if (rng_flag != NULL || rc == FAILURE) {
4810Sstevel@tonic-gate 		goto clean_exit;
4820Sstevel@tonic-gate 	}
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate clean_exit:
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 	if (rc == FAILURE) {
4870Sstevel@tonic-gate 		(void) printf(gettext(
4880Sstevel@tonic-gate 		    "%s: failed to retrieve the mechanism list.\n"), libname);
4890Sstevel@tonic-gate 	}
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	if (lib_initialized) {
4920Sstevel@tonic-gate 		(void) prov_funcs->C_Finalize(NULL_PTR);
4930Sstevel@tonic-gate 	}
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	if (dldesc != NULL) {
4960Sstevel@tonic-gate 		(void) dlclose(dldesc);
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	if (prov_slots != NULL) {
5000Sstevel@tonic-gate 		(void) free(prov_slots);
5010Sstevel@tonic-gate 	}
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	return (rc);
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate /*
5080Sstevel@tonic-gate  * Display the mechanism policy for a user-level library
5090Sstevel@tonic-gate  */
5100Sstevel@tonic-gate int
5110Sstevel@tonic-gate list_policy_for_lib(char *libname)
5120Sstevel@tonic-gate {
5130Sstevel@tonic-gate 	uentry_t *puent = NULL;
5140Sstevel@tonic-gate 	int rc;
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 	if (libname == NULL) {
5170Sstevel@tonic-gate 		/* should not happen */
5180Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
5190Sstevel@tonic-gate 		cryptodebug("list_policy_for_lib() - libname is NULL.");
5200Sstevel@tonic-gate 		return (FAILURE);
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	/* Get the library entry from the pkcs11.conf file */
5240Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
5250Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
5260Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
5270Sstevel@tonic-gate 		return (FAILURE);
5280Sstevel@tonic-gate 	}
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	/* Print the policy for this library */
5310Sstevel@tonic-gate 	rc = print_uef_policy(puent);
5320Sstevel@tonic-gate 	free_uentry(puent);
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	return (rc);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate /*
5390Sstevel@tonic-gate  * Disable mechanisms for a user-level library
5400Sstevel@tonic-gate  */
5410Sstevel@tonic-gate int
5420Sstevel@tonic-gate disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
5430Sstevel@tonic-gate     mechlist_t *marglist)
5440Sstevel@tonic-gate {
5450Sstevel@tonic-gate 	uentry_t	*puent;
5460Sstevel@tonic-gate 	int	rc;
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	if (libname == NULL) {
5490Sstevel@tonic-gate 		/* should not happen */
5500Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
5510Sstevel@tonic-gate 		cryptodebug("disable_uef_lib() - libname is NULL.");
5520Sstevel@tonic-gate 		return (FAILURE);
5530Sstevel@tonic-gate 	}
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	/* Get the provider entry from the pkcs11.conf file */
5560Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
5570Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
5580Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
5590Sstevel@tonic-gate 		return (FAILURE);
5600Sstevel@tonic-gate 	}
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	/*
5630Sstevel@tonic-gate 	 * Update the mechanism policy of this library entry, based on
5640Sstevel@tonic-gate 	 * the current policy mode of the library and the mechanisms specified
5650Sstevel@tonic-gate 	 * in CLI.
5660Sstevel@tonic-gate 	 */
5670Sstevel@tonic-gate 	if (allflag) {
5680Sstevel@tonic-gate 		/*
5690Sstevel@tonic-gate 		 * If disabling all, just need to clean up the policylist and
5700Sstevel@tonic-gate 		 * set the flag_enabledlist flag to be B_TRUE.
5710Sstevel@tonic-gate 		 */
5720Sstevel@tonic-gate 		free_umechlist(puent->policylist);
5730Sstevel@tonic-gate 		puent->policylist = NULL;
5740Sstevel@tonic-gate 		puent->count = 0;
5750Sstevel@tonic-gate 		puent->flag_enabledlist = B_TRUE;
5760Sstevel@tonic-gate 		rc = SUCCESS;
5770Sstevel@tonic-gate 	} else if (marglist != NULL) {
5780Sstevel@tonic-gate 		if (puent->flag_enabledlist == B_TRUE) {
5790Sstevel@tonic-gate 			/*
5800Sstevel@tonic-gate 			 * The current default policy mode of this library
5810Sstevel@tonic-gate 			 * is "all are disabled, except ...", so if a
5820Sstevel@tonic-gate 			 * specified mechanism is in the exception list
5830Sstevel@tonic-gate 			 * (the policylist), delete it from the policylist.
5840Sstevel@tonic-gate 			 */
5850Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, DELETE_MODE);
5860Sstevel@tonic-gate 		} else {
5870Sstevel@tonic-gate 			/*
5880Sstevel@tonic-gate 			 * The current default policy mode of this library
5890Sstevel@tonic-gate 			 * is "all are enabled", so if a specified mechanism
5900Sstevel@tonic-gate 			 * is not in the exception list (policylist), add
5910Sstevel@tonic-gate 			 * it into the policylist.
5920Sstevel@tonic-gate 			 */
5930Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, ADD_MODE);
5940Sstevel@tonic-gate 		}
5950Sstevel@tonic-gate 	} else if (!rndflag) {
5960Sstevel@tonic-gate 		/* should not happen */
5970Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
5980Sstevel@tonic-gate 		cryptodebug("disable_uef_lib() - wrong arguments.");
5990Sstevel@tonic-gate 		return (FAILURE);
6000Sstevel@tonic-gate 	}
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	if (rndflag)
6030Sstevel@tonic-gate 		puent->flag_norandom = B_TRUE;
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 	if (rc == FAILURE) {
6060Sstevel@tonic-gate 		free_uentry(puent);
6070Sstevel@tonic-gate 		return (FAILURE);
6080Sstevel@tonic-gate 	}
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	/* Update the pkcs11.conf file with the updated entry */
6110Sstevel@tonic-gate 	rc = update_pkcs11conf(puent);
6120Sstevel@tonic-gate 	free_uentry(puent);
6130Sstevel@tonic-gate 	return (rc);
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate /*
6180Sstevel@tonic-gate  * Enable disabled mechanisms for a user-level library.
6190Sstevel@tonic-gate  */
6200Sstevel@tonic-gate int
6210Sstevel@tonic-gate enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
6220Sstevel@tonic-gate     mechlist_t *marglist)
6230Sstevel@tonic-gate {
6240Sstevel@tonic-gate 	uentry_t	*puent;
6250Sstevel@tonic-gate 	int	rc = SUCCESS;
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	if (libname == NULL) {
6280Sstevel@tonic-gate 		/* should not happen */
6290Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
6300Sstevel@tonic-gate 		cryptodebug("enable_uef_lib() - libname is NULL.");
6310Sstevel@tonic-gate 		return (FAILURE);
6320Sstevel@tonic-gate 	}
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	/* Get the provider entry from the pkcs11.conf file */
6350Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
6360Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
6370Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
6380Sstevel@tonic-gate 		return (FAILURE);
6390Sstevel@tonic-gate 	}
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	/*
6420Sstevel@tonic-gate 	 * Update the mechanism policy of this library entry, based on
6430Sstevel@tonic-gate 	 * the current policy mode of the library and the mechanisms
6440Sstevel@tonic-gate 	 * specified in CLI.
6450Sstevel@tonic-gate 	 */
6460Sstevel@tonic-gate 	if (allflag) {
6470Sstevel@tonic-gate 		/*
6480Sstevel@tonic-gate 		 * If enabling all, what needs to be done are cleaning up the
6490Sstevel@tonic-gate 		 * policylist and setting the "flag_enabledlist" flag to
6500Sstevel@tonic-gate 		 * B_FALSE.
6510Sstevel@tonic-gate 		 */
6520Sstevel@tonic-gate 		free_umechlist(puent->policylist);
6530Sstevel@tonic-gate 		puent->policylist = NULL;
6540Sstevel@tonic-gate 		puent->count = 0;
6550Sstevel@tonic-gate 		puent->flag_enabledlist = B_FALSE;
6560Sstevel@tonic-gate 		rc = SUCCESS;
6570Sstevel@tonic-gate 	} else if (marglist != NULL) {
6580Sstevel@tonic-gate 		if (puent->flag_enabledlist == B_TRUE) {
6590Sstevel@tonic-gate 			/*
6600Sstevel@tonic-gate 			 * The current default policy mode of this library
6610Sstevel@tonic-gate 			 * is "all are disabled, except ...", so if a
6620Sstevel@tonic-gate 			 * specified mechanism is not in the exception list
6630Sstevel@tonic-gate 			 * (policylist), add it.
6640Sstevel@tonic-gate 			 */
6650Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, ADD_MODE);
6660Sstevel@tonic-gate 		} else {
6670Sstevel@tonic-gate 			/*
6680Sstevel@tonic-gate 			 * The current default policy mode of this library
6690Sstevel@tonic-gate 			 * is "all are enabled, except", so if a specified
6700Sstevel@tonic-gate 			 * mechanism is in the exception list (policylist),
6710Sstevel@tonic-gate 			 * delete it.
6720Sstevel@tonic-gate 			 */
6730Sstevel@tonic-gate 			rc = update_policylist(puent, marglist, DELETE_MODE);
6740Sstevel@tonic-gate 		}
6750Sstevel@tonic-gate 	} else if (!rndflag) {
6760Sstevel@tonic-gate 		/* should not come here */
6770Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
6780Sstevel@tonic-gate 		cryptodebug("enable_uef_lib() - wrong arguments.");
6790Sstevel@tonic-gate 		return (FAILURE);
6800Sstevel@tonic-gate 	}
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	if (rndflag)
6830Sstevel@tonic-gate 		puent->flag_norandom = B_FALSE;
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 	if (rc == FAILURE) {
6860Sstevel@tonic-gate 		free_uentry(puent);
6870Sstevel@tonic-gate 		return (FAILURE);
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	/* Update the pkcs11.conf file with the updated entry */
6910Sstevel@tonic-gate 	rc = update_pkcs11conf(puent);
6920Sstevel@tonic-gate 	free_uentry(puent);
6930Sstevel@tonic-gate 	return (rc);
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate /*
6980Sstevel@tonic-gate  * Install a user-level library.
6990Sstevel@tonic-gate  */
7000Sstevel@tonic-gate int
7010Sstevel@tonic-gate install_uef_lib(char *libname)
7020Sstevel@tonic-gate {
7030Sstevel@tonic-gate 	uentry_t	*puent;
7040Sstevel@tonic-gate 	struct stat 	statbuf;
7050Sstevel@tonic-gate 	char	libpath[MAXPATHLEN];
7060Sstevel@tonic-gate 	char	libbuf[MAXPATHLEN];
7070Sstevel@tonic-gate 	char	*isa;
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate 	if (libname == NULL) {
7100Sstevel@tonic-gate 		/* should not happen */
7110Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
7120Sstevel@tonic-gate 		cryptodebug("install_uef_lib() - libname is NULL.");
7130Sstevel@tonic-gate 		return (FAILURE);
7140Sstevel@tonic-gate 	}
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 	/* Check if the provider already exists in the framework */
7170Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) != NULL) {
7180Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s exists already."),
7190Sstevel@tonic-gate 		    libname);
7200Sstevel@tonic-gate 		free_uentry(puent);
7210Sstevel@tonic-gate 		return (FAILURE);
7220Sstevel@tonic-gate 	}
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 	/*
7250Sstevel@tonic-gate 	 * Check if the library exists in the system. if $ISA is in the
7260Sstevel@tonic-gate 	 * path, only check the 32bit version.
7270Sstevel@tonic-gate 	 */
7280Sstevel@tonic-gate 	if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) {
7290Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7300Sstevel@tonic-gate 		    gettext("the provider name is too long - %s"), libname);
7310Sstevel@tonic-gate 		return (FAILURE);
7320Sstevel@tonic-gate 	}
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) {
7350Sstevel@tonic-gate 		*isa = '\000';
7360Sstevel@tonic-gate 		isa += strlen(PKCS11_ISA);
7370Sstevel@tonic-gate 		(void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf,
7380Sstevel@tonic-gate 		    "/", isa);
7390Sstevel@tonic-gate 	} else {
7400Sstevel@tonic-gate 		(void) strlcpy(libpath, libname, sizeof (libpath));
7410Sstevel@tonic-gate 	}
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	/* Check if it is same as the framework library */
7440Sstevel@tonic-gate 	if (strcmp(libpath, UEF_FRAME_LIB) == 0) {
7450Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
7460Sstevel@tonic-gate 		    "The framework library %s can not be installed."),
7470Sstevel@tonic-gate 		    libname);
7480Sstevel@tonic-gate 		return (FAILURE);
7490Sstevel@tonic-gate 	}
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	if (stat(libpath, &statbuf) != 0) {
7520Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("%s not found"), libname);
7530Sstevel@tonic-gate 		return (FAILURE);
7540Sstevel@tonic-gate 	}
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 	/* Need to add "\n" to libname for adding into the config file */
7570Sstevel@tonic-gate 	if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) {
7580Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
7590Sstevel@tonic-gate 		    "can not install %s; the name is too long."), libname);
7600Sstevel@tonic-gate 		return (FAILURE);
7610Sstevel@tonic-gate 	}
7620Sstevel@tonic-gate 
763*10500SHai-May.Chao@Sun.COM 	return (update_conf(_PATH_PKCS11_CONF, libname));
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate }
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate /*
7690Sstevel@tonic-gate  * Uninstall a user-level library.
7700Sstevel@tonic-gate  */
7710Sstevel@tonic-gate int
7720Sstevel@tonic-gate uninstall_uef_lib(char *libname)
7730Sstevel@tonic-gate {
7740Sstevel@tonic-gate 	uentry_t	*puent;
7750Sstevel@tonic-gate 	FILE	*pfile;
7760Sstevel@tonic-gate 	FILE	*pfile_tmp;
7770Sstevel@tonic-gate 	char 	buffer[BUFSIZ];
7780Sstevel@tonic-gate 	char 	buffer2[BUFSIZ];
7790Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
7800Sstevel@tonic-gate 	char 	*name;
7810Sstevel@tonic-gate 	boolean_t	found;
7820Sstevel@tonic-gate 	boolean_t	in_package;
7830Sstevel@tonic-gate 	int	len;
7840Sstevel@tonic-gate 	int	rc = SUCCESS;
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate 	if (libname == NULL) {
7870Sstevel@tonic-gate 		/* should not happen */
7880Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
7890Sstevel@tonic-gate 		cryptodebug("uninstall_uef_lib() - libname is NULL.");
7900Sstevel@tonic-gate 		return (FAILURE);
7910Sstevel@tonic-gate 	}
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	/* Check if the provider exists */
7940Sstevel@tonic-gate 	if ((puent = getent_uef(libname)) == NULL) {
7950Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
7960Sstevel@tonic-gate 		    gettext("%s does not exist."), libname);
7970Sstevel@tonic-gate 		return (FAILURE);
7980Sstevel@tonic-gate 	}
7990Sstevel@tonic-gate 	free_uentry(puent);
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate 	/*  Open the pkcs11.conf file and lock it */
8020Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
8030Sstevel@tonic-gate 		err = errno;
8040Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8050Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
8060Sstevel@tonic-gate 		    strerror(err));
8070Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
8080Sstevel@tonic-gate 		return (FAILURE);
8090Sstevel@tonic-gate 	}
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
8120Sstevel@tonic-gate 		err = errno;
8130Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8140Sstevel@tonic-gate 		    gettext("failed to lock the configuration - %s"),
8150Sstevel@tonic-gate 		    strerror(err));
8160Sstevel@tonic-gate 		(void) fclose(pfile);
8170Sstevel@tonic-gate 		return (FAILURE);
8180Sstevel@tonic-gate 	}
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 	/*
8210Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
8220Sstevel@tonic-gate 	 * the new configuration file first.
8230Sstevel@tonic-gate 	 */
8240Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
8250Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
8260Sstevel@tonic-gate 		err = errno;
8270Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8280Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
8290Sstevel@tonic-gate 		    strerror(err));
8300Sstevel@tonic-gate 		(void) fclose(pfile);
8310Sstevel@tonic-gate 		return (FAILURE);
8320Sstevel@tonic-gate 	}
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
8350Sstevel@tonic-gate 		err = errno;
8360Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
8370Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
8380Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
8390Sstevel@tonic-gate 			err = errno;
8400Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
8410Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
8420Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
8430Sstevel@tonic-gate 		}
8440Sstevel@tonic-gate 		(void) fclose(pfile);
8450Sstevel@tonic-gate 		return (FAILURE);
8460Sstevel@tonic-gate 	}
8470Sstevel@tonic-gate 
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 	/*
8500Sstevel@tonic-gate 	 * Loop thru the config file.  If the library to be uninstalled
8510Sstevel@tonic-gate 	 * is in a package, just comment it off.
8520Sstevel@tonic-gate 	 */
8530Sstevel@tonic-gate 	in_package = B_FALSE;
8540Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
8550Sstevel@tonic-gate 		found = B_FALSE;
8560Sstevel@tonic-gate 		if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
8570Sstevel@tonic-gate 		    buffer[0] == '\t')) {
8580Sstevel@tonic-gate 			if (strstr(buffer, " Start ") != NULL) {
8590Sstevel@tonic-gate 				in_package = B_TRUE;
8600Sstevel@tonic-gate 			} else if (strstr(buffer, " End ") != NULL) {
8610Sstevel@tonic-gate 				in_package = B_FALSE;
8620Sstevel@tonic-gate 			} else if (buffer[0] != '#') {
8630Sstevel@tonic-gate 				(void) strlcpy(buffer2, buffer, BUFSIZ);
8640Sstevel@tonic-gate 
8650Sstevel@tonic-gate 				/* get rid of trailing '\n' */
8660Sstevel@tonic-gate 				len = strlen(buffer2);
8670Sstevel@tonic-gate 				if (buffer2[len-1] == '\n') {
8680Sstevel@tonic-gate 					len--;
8690Sstevel@tonic-gate 				}
8700Sstevel@tonic-gate 				buffer2[len] = '\0';
8710Sstevel@tonic-gate 
8720Sstevel@tonic-gate 				if ((name = strtok(buffer2, SEP_COLON))
8730Sstevel@tonic-gate 				    == NULL) {
8740Sstevel@tonic-gate 					rc = FAILURE;
8750Sstevel@tonic-gate 					break;
8760Sstevel@tonic-gate 				} else if (strcmp(libname, name) == 0) {
8770Sstevel@tonic-gate 					found = B_TRUE;
8780Sstevel@tonic-gate 				}
8790Sstevel@tonic-gate 			}
8800Sstevel@tonic-gate 		}
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 		if (found) {
8830Sstevel@tonic-gate 			if (in_package) {
8840Sstevel@tonic-gate 				(void) snprintf(buffer2, sizeof (buffer2),
8850Sstevel@tonic-gate 				    "%s%s%s", "#", libname, "\n");
8860Sstevel@tonic-gate 				if (fputs(buffer2, pfile_tmp) == EOF) {
8870Sstevel@tonic-gate 					rc = FAILURE;
8880Sstevel@tonic-gate 				}
8890Sstevel@tonic-gate 			}
8900Sstevel@tonic-gate 		} else {
8910Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
8920Sstevel@tonic-gate 				rc = FAILURE;
8930Sstevel@tonic-gate 			}
8940Sstevel@tonic-gate 		}
8950Sstevel@tonic-gate 
8960Sstevel@tonic-gate 		if (rc == FAILURE) {
8970Sstevel@tonic-gate 			break;
8980Sstevel@tonic-gate 		}
8990Sstevel@tonic-gate 	}
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 	if (rc == FAILURE) {
9020Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("write error."));
9030Sstevel@tonic-gate 		(void) fclose(pfile);
9040Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
9050Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
9060Sstevel@tonic-gate 			err = errno;
9070Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
9080Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
9090Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
9100Sstevel@tonic-gate 		}
9110Sstevel@tonic-gate 		return (FAILURE);
9120Sstevel@tonic-gate 	}
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate 	(void) fclose(pfile);
9150Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
9160Sstevel@tonic-gate 		err = errno;
9170Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9180Sstevel@tonic-gate 		    gettext("failed to close a temporary file - %s"),
9190Sstevel@tonic-gate 		    strerror(err));
9200Sstevel@tonic-gate 		return (FAILURE);
9210Sstevel@tonic-gate 	}
9220Sstevel@tonic-gate 
9230Sstevel@tonic-gate 	/* Now update the real config file */
9240Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
9250Sstevel@tonic-gate 		err = errno;
9260Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9270Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
9280Sstevel@tonic-gate 		    strerror(err));
9290Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile,
9300Sstevel@tonic-gate 		    _PATH_PKCS11_CONF, strerror(err));
9310Sstevel@tonic-gate 		rc = FAILURE;
9320Sstevel@tonic-gate 	} else if (chmod(_PATH_PKCS11_CONF,
9330Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
9340Sstevel@tonic-gate 		err = errno;
9350Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9360Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
9370Sstevel@tonic-gate 		    strerror(err));
9380Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
9390Sstevel@tonic-gate 		    strerror(err));
9400Sstevel@tonic-gate 		rc = FAILURE;
9410Sstevel@tonic-gate 	} else {
9420Sstevel@tonic-gate 		rc = SUCCESS;
9430Sstevel@tonic-gate 	}
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
9460Sstevel@tonic-gate 		err = errno;
9470Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
9480Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"),
9490Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
9500Sstevel@tonic-gate 	}
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 	return (rc);
9530Sstevel@tonic-gate }
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate int
9570Sstevel@tonic-gate display_policy(uentry_t *puent)
9580Sstevel@tonic-gate {
9597011Sda73024 	CK_MECHANISM_TYPE	mech_id;
9607011Sda73024 	const char		*mech_name;
9617011Sda73024 	umechlist_t		*ptr;
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 	if (puent == NULL) {
9640Sstevel@tonic-gate 		return (SUCCESS);
9650Sstevel@tonic-gate 	}
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 	if (puent->flag_enabledlist == B_FALSE) {
9680Sstevel@tonic-gate 		(void) printf(gettext("%s: all mechanisms are enabled"),
9690Sstevel@tonic-gate 		    puent->name);
9700Sstevel@tonic-gate 		ptr = puent->policylist;
9710Sstevel@tonic-gate 		if (ptr == NULL) {
9720Sstevel@tonic-gate 			(void) printf(".");
9730Sstevel@tonic-gate 		} else {
9740Sstevel@tonic-gate 			(void) printf(gettext(", except "));
9750Sstevel@tonic-gate 			while (ptr != NULL) {
9760Sstevel@tonic-gate 				mech_id = strtoul(ptr->name, NULL, 0);
9770Sstevel@tonic-gate 				if (mech_id & CKO_VENDOR_DEFINED) {
9780Sstevel@tonic-gate 					/* vendor defined mechanism */
9790Sstevel@tonic-gate 					(void) printf("%s", ptr->name);
9800Sstevel@tonic-gate 				} else {
9817106Sda73024 					if (mech_id >= CKM_VENDOR_DEFINED) {
9827011Sda73024 						(void) printf("%#lx", mech_id);
9837011Sda73024 					} else {
9847011Sda73024 						mech_name = pkcs11_mech2str(
9857011Sda73024 						    mech_id);
9867011Sda73024 						if (mech_name == NULL) {
9877011Sda73024 							return (FAILURE);
9887011Sda73024 						}
9897011Sda73024 						(void) printf("%s", mech_name);
9900Sstevel@tonic-gate 					}
9910Sstevel@tonic-gate 				}
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 				ptr = ptr->next;
9940Sstevel@tonic-gate 				if (ptr == NULL) {
9950Sstevel@tonic-gate 					(void) printf(".");
9960Sstevel@tonic-gate 				} else {
9970Sstevel@tonic-gate 					(void) printf(",");
9980Sstevel@tonic-gate 				}
9990Sstevel@tonic-gate 			}
10000Sstevel@tonic-gate 		}
10010Sstevel@tonic-gate 	} else { /* puent->flag_enabledlist == B_TRUE */
10020Sstevel@tonic-gate 		(void) printf(gettext("%s: all mechanisms are disabled"),
10030Sstevel@tonic-gate 		    puent->name);
10040Sstevel@tonic-gate 		ptr = puent->policylist;
10050Sstevel@tonic-gate 		if (ptr == NULL) {
10060Sstevel@tonic-gate 			(void) printf(".");
10070Sstevel@tonic-gate 		} else {
10080Sstevel@tonic-gate 			(void) printf(gettext(", except "));
10090Sstevel@tonic-gate 			while (ptr != NULL) {
10100Sstevel@tonic-gate 				mech_id = strtoul(ptr->name, NULL, 0);
10110Sstevel@tonic-gate 				if (mech_id & CKO_VENDOR_DEFINED) {
10120Sstevel@tonic-gate 					/* vendor defined mechanism */
10130Sstevel@tonic-gate 					(void) printf("%s", ptr->name);
10140Sstevel@tonic-gate 				} else {
10150Sstevel@tonic-gate 					mech_name = pkcs11_mech2str(mech_id);
10160Sstevel@tonic-gate 					if (mech_name == NULL) {
10170Sstevel@tonic-gate 						return (FAILURE);
10180Sstevel@tonic-gate 					}
10190Sstevel@tonic-gate 					(void) printf("%s", mech_name);
10200Sstevel@tonic-gate 				}
10210Sstevel@tonic-gate 				ptr = ptr->next;
10220Sstevel@tonic-gate 				if (ptr == NULL) {
10230Sstevel@tonic-gate 					(void) printf(".");
10240Sstevel@tonic-gate 				} else {
10250Sstevel@tonic-gate 					(void) printf(",");
10260Sstevel@tonic-gate 				}
10270Sstevel@tonic-gate 			}
10280Sstevel@tonic-gate 		}
10290Sstevel@tonic-gate 	}
10300Sstevel@tonic-gate 	return (SUCCESS);
10310Sstevel@tonic-gate }
10320Sstevel@tonic-gate 
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 
10350Sstevel@tonic-gate /*
10360Sstevel@tonic-gate  * Print out the mechanism policy for a user-level provider pointed by puent.
10370Sstevel@tonic-gate  */
10380Sstevel@tonic-gate int
10390Sstevel@tonic-gate print_uef_policy(uentry_t *puent)
10400Sstevel@tonic-gate {
10410Sstevel@tonic-gate 	flag_val_t rng_flag;
10420Sstevel@tonic-gate 
10430Sstevel@tonic-gate 	if (puent == NULL) {
10440Sstevel@tonic-gate 		return (FAILURE);
10450Sstevel@tonic-gate 	}
10460Sstevel@tonic-gate 
10470Sstevel@tonic-gate 	rng_flag = NO_RNG;
10480Sstevel@tonic-gate 	if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE,
10497011Sda73024 	    B_FALSE, B_FALSE) != SUCCESS) {
10500Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10510Sstevel@tonic-gate 		    gettext("%s internal error."), puent->name);
10520Sstevel@tonic-gate 		return (FAILURE);
10530Sstevel@tonic-gate 	}
10540Sstevel@tonic-gate 
10550Sstevel@tonic-gate 	if (display_policy(puent) != SUCCESS) {
10560Sstevel@tonic-gate 		goto failed_exit;
10570Sstevel@tonic-gate 	}
10580Sstevel@tonic-gate 
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 	if (puent->flag_norandom == B_TRUE)
10610Sstevel@tonic-gate 		/*
10627334SDaniel.Anderson@Sun.COM 		 * TRANSLATION_NOTE
10630Sstevel@tonic-gate 		 * "random" is a keyword and not to be translated.
10640Sstevel@tonic-gate 		 */
10650Sstevel@tonic-gate 		(void) printf(gettext(" %s is disabled."), "random");
10660Sstevel@tonic-gate 	else {
10670Sstevel@tonic-gate 		if (rng_flag == HAS_RNG)
10680Sstevel@tonic-gate 			/*
10697334SDaniel.Anderson@Sun.COM 			 * TRANSLATION_NOTE
10700Sstevel@tonic-gate 			 * "random" is a keyword and not to be translated.
10710Sstevel@tonic-gate 			 */
10720Sstevel@tonic-gate 			(void) printf(gettext(" %s is enabled."), "random");
10730Sstevel@tonic-gate 	}
10740Sstevel@tonic-gate 	(void) printf("\n");
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate 	return (SUCCESS);
10770Sstevel@tonic-gate 
10780Sstevel@tonic-gate failed_exit:
10790Sstevel@tonic-gate 
10800Sstevel@tonic-gate 	(void) printf(gettext("\nout of memory.\n"));
10810Sstevel@tonic-gate 	return (FAILURE);
10820Sstevel@tonic-gate }
10830Sstevel@tonic-gate 
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate /*
10860Sstevel@tonic-gate  * Check if the mechanism is in the mechanism list.
10870Sstevel@tonic-gate  */
10880Sstevel@tonic-gate static boolean_t
10890Sstevel@tonic-gate is_in_policylist(midstr_t mechname, umechlist_t *plist)
10900Sstevel@tonic-gate {
10910Sstevel@tonic-gate 	boolean_t found = B_FALSE;
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 	if (mechname == NULL) {
10940Sstevel@tonic-gate 		return (B_FALSE);
10950Sstevel@tonic-gate 	}
10960Sstevel@tonic-gate 
10970Sstevel@tonic-gate 	while (plist != NULL) {
10980Sstevel@tonic-gate 		if (strcmp(plist->name, mechname) == 0) {
10990Sstevel@tonic-gate 			found = B_TRUE;
11000Sstevel@tonic-gate 			break;
11010Sstevel@tonic-gate 		}
11020Sstevel@tonic-gate 		plist = plist->next;
11030Sstevel@tonic-gate 	}
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate 	return (found);
11060Sstevel@tonic-gate }
11070Sstevel@tonic-gate 
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate /*
11100Sstevel@tonic-gate  * Update the pkcs11.conf file with the updated entry.
11110Sstevel@tonic-gate  */
11120Sstevel@tonic-gate int
11130Sstevel@tonic-gate update_pkcs11conf(uentry_t *puent)
11140Sstevel@tonic-gate {
11150Sstevel@tonic-gate 	FILE	*pfile;
11160Sstevel@tonic-gate 	FILE	*pfile_tmp;
11170Sstevel@tonic-gate 	char buffer[BUFSIZ];
11180Sstevel@tonic-gate 	char buffer2[BUFSIZ];
11190Sstevel@tonic-gate 	char tmpfile_name[MAXPATHLEN];
11200Sstevel@tonic-gate 	char *name;
11210Sstevel@tonic-gate 	char *str;
11220Sstevel@tonic-gate 	int len;
11230Sstevel@tonic-gate 	int rc = SUCCESS;
11240Sstevel@tonic-gate 	boolean_t found;
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 	if (puent == NULL) {
11270Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
11280Sstevel@tonic-gate 		return (FAILURE);
11290Sstevel@tonic-gate 	}
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate 	/* Open the pkcs11.conf file */
11320Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
11330Sstevel@tonic-gate 		err = errno;
11340Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11350Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
11360Sstevel@tonic-gate 		    strerror(err));
11370Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
11380Sstevel@tonic-gate 		return (FAILURE);
11390Sstevel@tonic-gate 	}
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	/* Lock the pkcs11.conf file */
11420Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
11430Sstevel@tonic-gate 		err = errno;
11440Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11450Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
11467011Sda73024 		    strerror(err));
11470Sstevel@tonic-gate 		(void) fclose(pfile);
11480Sstevel@tonic-gate 		return (FAILURE);
11490Sstevel@tonic-gate 	}
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 	/*
11520Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
11530Sstevel@tonic-gate 	 * updated configuration file first.
11540Sstevel@tonic-gate 	 */
11550Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
11560Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
11570Sstevel@tonic-gate 		err = errno;
11580Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11590Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
11600Sstevel@tonic-gate 		    strerror(err));
11610Sstevel@tonic-gate 		(void) fclose(pfile);
11620Sstevel@tonic-gate 		return (FAILURE);
11630Sstevel@tonic-gate 	}
11640Sstevel@tonic-gate 
11650Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
11660Sstevel@tonic-gate 		err = errno;
11670Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
11680Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
11690Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
11700Sstevel@tonic-gate 			err = errno;
11710Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
11720Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
11730Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
11740Sstevel@tonic-gate 		}
11750Sstevel@tonic-gate 		(void) fclose(pfile);
11760Sstevel@tonic-gate 		return (FAILURE);
11770Sstevel@tonic-gate 	}
11780Sstevel@tonic-gate 
11790Sstevel@tonic-gate 
11800Sstevel@tonic-gate 	/*
11810Sstevel@tonic-gate 	 * Loop thru entire pkcs11.conf file, update the entry to be
11820Sstevel@tonic-gate 	 * updated and save the updated file to the temporary file first.
11830Sstevel@tonic-gate 	 */
11840Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
11850Sstevel@tonic-gate 		found = B_FALSE;
11860Sstevel@tonic-gate 		if (!(buffer[0] == '#' || buffer[0] == ' ' ||
11870Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t')) {
11880Sstevel@tonic-gate 			/*
11890Sstevel@tonic-gate 			 * Get the provider name from this line and check if
11900Sstevel@tonic-gate 			 * this is the entry to be updated. Note: can not use
11910Sstevel@tonic-gate 			 * "buffer" directly because strtok will change its
11920Sstevel@tonic-gate 			 * value.
11930Sstevel@tonic-gate 			 */
11940Sstevel@tonic-gate 			(void) strlcpy(buffer2, buffer, BUFSIZ);
11950Sstevel@tonic-gate 
11960Sstevel@tonic-gate 			/* get rid of trailing '\n' */
11970Sstevel@tonic-gate 			len = strlen(buffer2);
11980Sstevel@tonic-gate 			if (buffer2[len-1] == '\n') {
11990Sstevel@tonic-gate 				len--;
12000Sstevel@tonic-gate 			}
12010Sstevel@tonic-gate 			buffer2[len] = '\0';
12020Sstevel@tonic-gate 
12030Sstevel@tonic-gate 			if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
12040Sstevel@tonic-gate 				rc = FAILURE;
12050Sstevel@tonic-gate 				break;
12060Sstevel@tonic-gate 			} else if (strcmp(puent->name, name) == 0) {
12070Sstevel@tonic-gate 				found = B_TRUE;
12080Sstevel@tonic-gate 			}
12090Sstevel@tonic-gate 		}
12100Sstevel@tonic-gate 
12110Sstevel@tonic-gate 		if (found) {
12120Sstevel@tonic-gate 			/*
12130Sstevel@tonic-gate 			 * This is the entry to be modified, get the updated
12140Sstevel@tonic-gate 			 * string.
12150Sstevel@tonic-gate 			 */
12160Sstevel@tonic-gate 			if ((str = uent2str(puent)) == NULL) {
12170Sstevel@tonic-gate 				rc = FAILURE;
12180Sstevel@tonic-gate 				break;
12190Sstevel@tonic-gate 			} else {
12200Sstevel@tonic-gate 				(void) strlcpy(buffer, str, BUFSIZ);
12210Sstevel@tonic-gate 				free(str);
12220Sstevel@tonic-gate 			}
12230Sstevel@tonic-gate 		}
12240Sstevel@tonic-gate 
12250Sstevel@tonic-gate 		if (fputs(buffer, pfile_tmp) == EOF) {
12260Sstevel@tonic-gate 			err = errno;
12270Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
12280Sstevel@tonic-gate 			    "failed to write to a temp file: %s."),
12290Sstevel@tonic-gate 			    strerror(err));
12300Sstevel@tonic-gate 			rc = FAILURE;
12310Sstevel@tonic-gate 			break;
12320Sstevel@tonic-gate 		}
12330Sstevel@tonic-gate 	}
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 	if (rc == FAILURE) {
12360Sstevel@tonic-gate 		(void) fclose(pfile);
12370Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
12380Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
12390Sstevel@tonic-gate 			err = errno;
12400Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
12410Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
12420Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
12430Sstevel@tonic-gate 		}
12440Sstevel@tonic-gate 		return (FAILURE);
12450Sstevel@tonic-gate 	}
12460Sstevel@tonic-gate 
12470Sstevel@tonic-gate 	(void) fclose(pfile);
12480Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
12490Sstevel@tonic-gate 		err = errno;
12500Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
12510Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
12520Sstevel@tonic-gate 		    strerror(err));
12530Sstevel@tonic-gate 		return (FAILURE);
12540Sstevel@tonic-gate 	}
12550Sstevel@tonic-gate 
12560Sstevel@tonic-gate 	/* Copy the temporary file to the pkcs11.conf file */
12570Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
12580Sstevel@tonic-gate 		err = errno;
12590Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
12600Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
12610Sstevel@tonic-gate 		    strerror(err));
12620Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
12630Sstevel@tonic-gate 		    _PATH_PKCS11_CONF, strerror(err));
12640Sstevel@tonic-gate 		rc = FAILURE;
12650Sstevel@tonic-gate 	} else if (chmod(_PATH_PKCS11_CONF,
12660Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
12670Sstevel@tonic-gate 		err = errno;
12680Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
12690Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
12700Sstevel@tonic-gate 		    strerror(err));
12710Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
12720Sstevel@tonic-gate 		    strerror(err));
12730Sstevel@tonic-gate 		rc = FAILURE;
12740Sstevel@tonic-gate 	} else {
12750Sstevel@tonic-gate 		rc = SUCCESS;
12760Sstevel@tonic-gate 	}
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
12790Sstevel@tonic-gate 		err = errno;
12800Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
12810Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"),
12820Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
12830Sstevel@tonic-gate 	}
12840Sstevel@tonic-gate 
12850Sstevel@tonic-gate 	return (rc);
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate /*
12900Sstevel@tonic-gate  * Convert an uentry to a character string
12910Sstevel@tonic-gate  */
12920Sstevel@tonic-gate static char *
12930Sstevel@tonic-gate uent2str(uentry_t *puent)
12940Sstevel@tonic-gate {
12950Sstevel@tonic-gate 	umechlist_t	*phead;
12960Sstevel@tonic-gate 	boolean_t tok1_present = B_FALSE;
12970Sstevel@tonic-gate 	char *buf;
12980Sstevel@tonic-gate 	char blank_buf[128];
12990Sstevel@tonic-gate 
13000Sstevel@tonic-gate 	if (puent == NULL) {
13010Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
13020Sstevel@tonic-gate 		return (NULL);
13030Sstevel@tonic-gate 	}
13040Sstevel@tonic-gate 
13050Sstevel@tonic-gate 	buf = malloc(BUFSIZ);
13060Sstevel@tonic-gate 	if (buf == NULL) {
13070Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("out of memory."));
13080Sstevel@tonic-gate 		return (NULL);
13090Sstevel@tonic-gate 	}
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 	/* convert the library name */
13120Sstevel@tonic-gate 	if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) {
13130Sstevel@tonic-gate 		free(buf);
13140Sstevel@tonic-gate 		return (NULL);
13150Sstevel@tonic-gate 	}
13160Sstevel@tonic-gate 
13170Sstevel@tonic-gate 
13180Sstevel@tonic-gate 	/* convert the enabledlist or the disabledlist */
13190Sstevel@tonic-gate 	if (puent->flag_enabledlist == B_TRUE) {
13200Sstevel@tonic-gate 		if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
13210Sstevel@tonic-gate 			free(buf);
13220Sstevel@tonic-gate 			return (NULL);
13230Sstevel@tonic-gate 		}
13240Sstevel@tonic-gate 
13250Sstevel@tonic-gate 		if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) {
13260Sstevel@tonic-gate 			free(buf);
13270Sstevel@tonic-gate 			return (NULL);
13280Sstevel@tonic-gate 		}
13290Sstevel@tonic-gate 
13300Sstevel@tonic-gate 		phead = puent->policylist;
13310Sstevel@tonic-gate 		while (phead != NULL) {
13320Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
13330Sstevel@tonic-gate 				free(buf);
13340Sstevel@tonic-gate 				return (NULL);
13350Sstevel@tonic-gate 			}
13360Sstevel@tonic-gate 
13370Sstevel@tonic-gate 			phead = phead->next;
13380Sstevel@tonic-gate 			if (phead != NULL) {
13390Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
13400Sstevel@tonic-gate 				    >= BUFSIZ) {
13410Sstevel@tonic-gate 					free(buf);
13420Sstevel@tonic-gate 					return (NULL);
13430Sstevel@tonic-gate 				}
13440Sstevel@tonic-gate 			}
13450Sstevel@tonic-gate 		}
13460Sstevel@tonic-gate 		tok1_present = B_TRUE;
13470Sstevel@tonic-gate 	} else if (puent->policylist != NULL) {
13480Sstevel@tonic-gate 		if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
13490Sstevel@tonic-gate 			free(buf);
13500Sstevel@tonic-gate 			return (NULL);
13510Sstevel@tonic-gate 		}
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 		if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) {
13540Sstevel@tonic-gate 			free(buf);
13550Sstevel@tonic-gate 			return (NULL);
13560Sstevel@tonic-gate 		}
13570Sstevel@tonic-gate 		phead = puent->policylist;
13580Sstevel@tonic-gate 		while (phead != NULL) {
13590Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
13600Sstevel@tonic-gate 				free(buf);
13610Sstevel@tonic-gate 				return (NULL);
13620Sstevel@tonic-gate 			}
13630Sstevel@tonic-gate 
13640Sstevel@tonic-gate 			phead = phead->next;
13650Sstevel@tonic-gate 			if (phead != NULL) {
13660Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
13670Sstevel@tonic-gate 				    >= BUFSIZ) {
13680Sstevel@tonic-gate 					free(buf);
13690Sstevel@tonic-gate 					return (NULL);
13700Sstevel@tonic-gate 				}
13710Sstevel@tonic-gate 			}
13720Sstevel@tonic-gate 		}
13730Sstevel@tonic-gate 		tok1_present = B_TRUE;
13740Sstevel@tonic-gate 	}
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate 	if (puent->flag_norandom == B_TRUE) {
13770Sstevel@tonic-gate 		if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
13780Sstevel@tonic-gate 		    BUFSIZ) >= BUFSIZ) {
13790Sstevel@tonic-gate 			free(buf);
13800Sstevel@tonic-gate 			return (NULL);
13810Sstevel@tonic-gate 		}
13820Sstevel@tonic-gate 
13830Sstevel@tonic-gate 		if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) {
13840Sstevel@tonic-gate 			free(buf);
13850Sstevel@tonic-gate 			return (NULL);
13860Sstevel@tonic-gate 		}
13870Sstevel@tonic-gate 	}
13880Sstevel@tonic-gate 
13890Sstevel@tonic-gate 	if (strcmp(puent->name, METASLOT_KEYWORD) == 0) {
13900Sstevel@tonic-gate 
13910Sstevel@tonic-gate 		/* write the metaslot_status= value */
13920Sstevel@tonic-gate 		if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
13930Sstevel@tonic-gate 		    BUFSIZ) >= BUFSIZ) {
13940Sstevel@tonic-gate 			free(buf);
13950Sstevel@tonic-gate 			return (NULL);
13960Sstevel@tonic-gate 		}
13970Sstevel@tonic-gate 
13980Sstevel@tonic-gate 		if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) {
13990Sstevel@tonic-gate 			free(buf);
14000Sstevel@tonic-gate 			return (NULL);
14010Sstevel@tonic-gate 		}
14020Sstevel@tonic-gate 
14030Sstevel@tonic-gate 		if (puent->flag_metaslot_enabled) {
1404*10500SHai-May.Chao@Sun.COM 			if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
14050Sstevel@tonic-gate 				free(buf);
14060Sstevel@tonic-gate 				return (NULL);
14070Sstevel@tonic-gate 			}
14080Sstevel@tonic-gate 		} else {
1409*10500SHai-May.Chao@Sun.COM 			if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ)
14100Sstevel@tonic-gate 			    >= BUFSIZ) {
14110Sstevel@tonic-gate 				free(buf);
14120Sstevel@tonic-gate 				return (NULL);
14130Sstevel@tonic-gate 			}
14140Sstevel@tonic-gate 		}
14150Sstevel@tonic-gate 
14160Sstevel@tonic-gate 		if (!tok1_present) {
14170Sstevel@tonic-gate 			tok1_present = B_TRUE;
14180Sstevel@tonic-gate 		}
14190Sstevel@tonic-gate 
14200Sstevel@tonic-gate 		if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) {
14210Sstevel@tonic-gate 			free(buf);
14220Sstevel@tonic-gate 			return (NULL);
14230Sstevel@tonic-gate 		}
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate 		if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) {
14260Sstevel@tonic-gate 			free(buf);
14270Sstevel@tonic-gate 			return (NULL);
14280Sstevel@tonic-gate 		}
14290Sstevel@tonic-gate 
14300Sstevel@tonic-gate 		if (puent->flag_metaslot_auto_key_migrate) {
1431*10500SHai-May.Chao@Sun.COM 			if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
14320Sstevel@tonic-gate 				free(buf);
14330Sstevel@tonic-gate 				return (NULL);
14340Sstevel@tonic-gate 			}
14350Sstevel@tonic-gate 		} else {
1436*10500SHai-May.Chao@Sun.COM 			if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
14370Sstevel@tonic-gate 				free(buf);
14380Sstevel@tonic-gate 				return (NULL);
14390Sstevel@tonic-gate 			}
14400Sstevel@tonic-gate 		}
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 		bzero(blank_buf, sizeof (blank_buf));
14430Sstevel@tonic-gate 
14440Sstevel@tonic-gate 		/* write metaslot_token= if specified */
14450Sstevel@tonic-gate 		if (memcmp(puent->metaslot_ks_token, blank_buf,
14460Sstevel@tonic-gate 		    TOKEN_LABEL_SIZE) != 0) {
14470Sstevel@tonic-gate 			/* write the metaslot_status= value */
14480Sstevel@tonic-gate 			if (strlcat(buf, (tok1_present ?
14490Sstevel@tonic-gate 			    SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
14500Sstevel@tonic-gate 				free(buf);
14510Sstevel@tonic-gate 				return (NULL);
14520Sstevel@tonic-gate 			}
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) {
14550Sstevel@tonic-gate 				free(buf);
14560Sstevel@tonic-gate 				return (NULL);
14570Sstevel@tonic-gate 			}
14580Sstevel@tonic-gate 
14590Sstevel@tonic-gate 			if (strlcat(buf,
14600Sstevel@tonic-gate 			    (const char *)puent->metaslot_ks_token, BUFSIZ)
14610Sstevel@tonic-gate 			    >= BUFSIZ) {
14620Sstevel@tonic-gate 				free(buf);
14630Sstevel@tonic-gate 				return (NULL);
14640Sstevel@tonic-gate 			}
14650Sstevel@tonic-gate 		}
14660Sstevel@tonic-gate 
14670Sstevel@tonic-gate 		/* write metaslot_slot= if specified */
14680Sstevel@tonic-gate 		if (memcmp(puent->metaslot_ks_slot, blank_buf,
14690Sstevel@tonic-gate 		    SLOT_DESCRIPTION_SIZE) != 0) {
14700Sstevel@tonic-gate 			/* write the metaslot_status= value */
14710Sstevel@tonic-gate 			if (strlcat(buf, (tok1_present ?
14720Sstevel@tonic-gate 			    SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
14730Sstevel@tonic-gate 				free(buf);
14740Sstevel@tonic-gate 				return (NULL);
14750Sstevel@tonic-gate 			}
14760Sstevel@tonic-gate 
14770Sstevel@tonic-gate 			if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) {
14780Sstevel@tonic-gate 				free(buf);
14790Sstevel@tonic-gate 				return (NULL);
14800Sstevel@tonic-gate 			}
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate 			if (strlcat(buf,
14830Sstevel@tonic-gate 			    (const char *)puent->metaslot_ks_slot, BUFSIZ)
14840Sstevel@tonic-gate 			    >= BUFSIZ) {
14850Sstevel@tonic-gate 				free(buf);
14860Sstevel@tonic-gate 				return (NULL);
14870Sstevel@tonic-gate 			}
14880Sstevel@tonic-gate 		}
14890Sstevel@tonic-gate 	}
14900Sstevel@tonic-gate 
14910Sstevel@tonic-gate 	if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
14920Sstevel@tonic-gate 		free(buf);
14930Sstevel@tonic-gate 		return (NULL);
14940Sstevel@tonic-gate 	}
14950Sstevel@tonic-gate 
14960Sstevel@tonic-gate 	return (buf);
14970Sstevel@tonic-gate }
14980Sstevel@tonic-gate 
14990Sstevel@tonic-gate 
15000Sstevel@tonic-gate /*
15010Sstevel@tonic-gate  * This function updates the default policy mode and the policy exception list
15020Sstevel@tonic-gate  * for a user-level provider based on the mechanism specified in the disable
15030Sstevel@tonic-gate  * or enable subcommand and the update mode.   This function is called by the
15040Sstevel@tonic-gate  * enable_uef_lib() or disable_uef_lib().
15050Sstevel@tonic-gate  */
15060Sstevel@tonic-gate int
15070Sstevel@tonic-gate update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode)
15080Sstevel@tonic-gate {
15090Sstevel@tonic-gate 	CK_MECHANISM_TYPE mech_type;
15100Sstevel@tonic-gate 	midstr_t	midname;
15110Sstevel@tonic-gate 	umechlist_t	*phead;
15120Sstevel@tonic-gate 	umechlist_t	*pcur;
15130Sstevel@tonic-gate 	umechlist_t	*pumech;
15140Sstevel@tonic-gate 	boolean_t	found;
15150Sstevel@tonic-gate 	int	rc = SUCCESS;
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 	if ((puent == NULL) || (marglist == NULL)) {
15180Sstevel@tonic-gate 		/* should not happen */
15190Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
15200Sstevel@tonic-gate 		cryptodebug("update_policylist()- puent or marglist is NULL.");
15210Sstevel@tonic-gate 		return (FAILURE);
15220Sstevel@tonic-gate 	}
15230Sstevel@tonic-gate 
15240Sstevel@tonic-gate 	if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) {
15250Sstevel@tonic-gate 		/* should not happen */
15260Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
15270Sstevel@tonic-gate 		cryptodebug("update_policylist() - update_mode is incorrect.");
15280Sstevel@tonic-gate 		return (FAILURE);
15290Sstevel@tonic-gate 	}
15300Sstevel@tonic-gate 
15310Sstevel@tonic-gate 	/*
15320Sstevel@tonic-gate 	 * For each mechanism operand, get its mechanism type first.
15330Sstevel@tonic-gate 	 * If fails to get the mechanism type, the mechanism operand must be
15340Sstevel@tonic-gate 	 * invalid, gives an warning and ignore it. Otherwise,
15350Sstevel@tonic-gate 	 * - convert the mechanism type to the internal representation (hex)
15360Sstevel@tonic-gate 	 *   in the pkcs11.conf file
15370Sstevel@tonic-gate 	 * - If update_mode == DELETE_MODE,
15380Sstevel@tonic-gate 	 *	If the mechanism is in the policy list, delete it.
15390Sstevel@tonic-gate 	 *	If the mechanism is not in the policy list, do nothing.
15400Sstevel@tonic-gate 	 * - If update_mode == ADD_MODE,
15410Sstevel@tonic-gate 	 *	If the mechanism is not in the policy list, add it.
15420Sstevel@tonic-gate 	 *	If the mechanism is in the policy list already, do nothing.
15430Sstevel@tonic-gate 	 */
15440Sstevel@tonic-gate 	while (marglist) {
15450Sstevel@tonic-gate 		if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) {
15460Sstevel@tonic-gate 			/*
15470Sstevel@tonic-gate 			 * This mechanism is not a valid PKCS11 mechanism,
15480Sstevel@tonic-gate 			 * give warning and ignore it.
15490Sstevel@tonic-gate 			 */
15500Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
15510Sstevel@tonic-gate 			    "(Warning) %s is not a valid PKCS#11 mechanism."),
15520Sstevel@tonic-gate 			    marglist->name);
15530Sstevel@tonic-gate 			rc = FAILURE;
15540Sstevel@tonic-gate 		} else {
15550Sstevel@tonic-gate 			(void) snprintf(midname, sizeof (midname), "%#010x",
15560Sstevel@tonic-gate 			    (int)mech_type);
15570Sstevel@tonic-gate 			if (update_mode == DELETE_MODE) {
15580Sstevel@tonic-gate 				found = B_FALSE;
15590Sstevel@tonic-gate 				phead = pcur = puent->policylist;
15600Sstevel@tonic-gate 				while (!found && pcur) {
15610Sstevel@tonic-gate 					if (strcmp(pcur->name, midname) == 0) {
15620Sstevel@tonic-gate 						found = B_TRUE;
15630Sstevel@tonic-gate 					} else {
15640Sstevel@tonic-gate 						phead = pcur;
15650Sstevel@tonic-gate 						pcur = pcur->next;
15660Sstevel@tonic-gate 					}
15670Sstevel@tonic-gate 				}
15680Sstevel@tonic-gate 
15690Sstevel@tonic-gate 				if (found) {
15700Sstevel@tonic-gate 					if (phead == pcur) {
15710Sstevel@tonic-gate 						puent->policylist =
15720Sstevel@tonic-gate 						    puent->policylist->next;
15730Sstevel@tonic-gate 						free(pcur);
15740Sstevel@tonic-gate 					} else {
15750Sstevel@tonic-gate 						phead->next = pcur->next;
15760Sstevel@tonic-gate 						free(pcur);
15770Sstevel@tonic-gate 					}
15780Sstevel@tonic-gate 					puent->count--;
15790Sstevel@tonic-gate 					if (puent->count == 0) {
15800Sstevel@tonic-gate 						puent->policylist = NULL;
15810Sstevel@tonic-gate 					}
15820Sstevel@tonic-gate 				}
15830Sstevel@tonic-gate 			} else if (update_mode == ADD_MODE) {
15840Sstevel@tonic-gate 				if (!is_in_policylist(midname,
15850Sstevel@tonic-gate 				    puent->policylist)) {
15860Sstevel@tonic-gate 					pumech = create_umech(midname);
15870Sstevel@tonic-gate 					if (pumech == NULL) {
15880Sstevel@tonic-gate 						rc = FAILURE;
15890Sstevel@tonic-gate 						break;
15900Sstevel@tonic-gate 					}
15910Sstevel@tonic-gate 					phead = puent->policylist;
15920Sstevel@tonic-gate 					puent->policylist = pumech;
15930Sstevel@tonic-gate 					pumech->next = phead;
15940Sstevel@tonic-gate 					puent->count++;
15950Sstevel@tonic-gate 				}
15960Sstevel@tonic-gate 			}
15970Sstevel@tonic-gate 		}
15980Sstevel@tonic-gate 		marglist = marglist->next;
15990Sstevel@tonic-gate 	}
16000Sstevel@tonic-gate 
16010Sstevel@tonic-gate 	return (rc);
16020Sstevel@tonic-gate }
16030Sstevel@tonic-gate 
16040Sstevel@tonic-gate /*
16050Sstevel@tonic-gate  * Open a session to the given slot and check if we can do
16060Sstevel@tonic-gate  * random numbers by asking for one byte.
16070Sstevel@tonic-gate  */
16080Sstevel@tonic-gate static boolean_t
16090Sstevel@tonic-gate check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs)
16100Sstevel@tonic-gate {
16110Sstevel@tonic-gate 	CK_RV rv;
16120Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession;
16130Sstevel@tonic-gate 	CK_BYTE test_byte;
16140Sstevel@tonic-gate 	CK_BYTE_PTR test_byte_ptr = &test_byte;
16150Sstevel@tonic-gate 
16160Sstevel@tonic-gate 	rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION,
16170Sstevel@tonic-gate 	    NULL_PTR, NULL, &hSession);
16180Sstevel@tonic-gate 	if (rv != CKR_OK)
16190Sstevel@tonic-gate 		return (B_FALSE);
16200Sstevel@tonic-gate 
16210Sstevel@tonic-gate 	/* We care only about the return value */
16220Sstevel@tonic-gate 	rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr,
16230Sstevel@tonic-gate 	    sizeof (test_byte));
16240Sstevel@tonic-gate 	(void) prov_funcs->C_CloseSession(hSession);
16250Sstevel@tonic-gate 
16260Sstevel@tonic-gate 	/*
16270Sstevel@tonic-gate 	 * These checks are purely to determine whether the slot can do
16280Sstevel@tonic-gate 	 * random numbers. So, we don't check whether the routine
16290Sstevel@tonic-gate 	 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that
16300Sstevel@tonic-gate 	 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED.
16310Sstevel@tonic-gate 	 */
16320Sstevel@tonic-gate 	if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG)
16330Sstevel@tonic-gate 		return (B_TRUE);
16340Sstevel@tonic-gate 	else
16350Sstevel@tonic-gate 		return (B_FALSE);
16360Sstevel@tonic-gate }
16370Sstevel@tonic-gate 
16380Sstevel@tonic-gate void
16390Sstevel@tonic-gate display_verbose_mech_header()
16400Sstevel@tonic-gate {
16410Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR1);
16420Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR2);
16430Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR3);
16440Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR4);
16450Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR5);
16460Sstevel@tonic-gate 	(void) printf("%28s %s", " ", HDR6);
16470Sstevel@tonic-gate 	(void) printf("%-28.28s %s", gettext("mechanism name"), HDR7);
16480Sstevel@tonic-gate 	/*
16497334SDaniel.Anderson@Sun.COM 	 * TRANSLATION_NOTE
16500Sstevel@tonic-gate 	 * Strictly for appearance's sake, the first header line should be
16510Sstevel@tonic-gate 	 * as long as the length of the translated text above.  The format
16520Sstevel@tonic-gate 	 * lengths should all match too.
16530Sstevel@tonic-gate 	 */
16540Sstevel@tonic-gate 	(void) printf("%28s ---- ---- "
16550Sstevel@tonic-gate 	    "-  -  -  -  -  -  -  -  -  -  -  -  -  -\n",
16560Sstevel@tonic-gate 	    gettext("----------------------------"));
16570Sstevel@tonic-gate }
1658