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