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 <errno.h>
30*0Sstevel@tonic-gate #include <fcntl.h>
31*0Sstevel@tonic-gate #include <stdio.h>
32*0Sstevel@tonic-gate #include <stdlib.h>
33*0Sstevel@tonic-gate #include <strings.h>
34*0Sstevel@tonic-gate #include <time.h>
35*0Sstevel@tonic-gate #include <unistd.h>
36*0Sstevel@tonic-gate #include <locale.h>
37*0Sstevel@tonic-gate #include <sys/types.h>
38*0Sstevel@tonic-gate #include <sys/stat.h>
39*0Sstevel@tonic-gate #include "cryptoadm.h"
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate static int err; /* To store errno which may be overwritten by gettext() */
42*0Sstevel@tonic-gate static int build_entrylist(entry_t *, entrylist_t **);
43*0Sstevel@tonic-gate static entry_t *dup_entry(entry_t *);
44*0Sstevel@tonic-gate static mechlist_t *dup_mechlist(mechlist_t *);
45*0Sstevel@tonic-gate static entry_t *getent(char *, entrylist_t *);
46*0Sstevel@tonic-gate static int interpret(char *, entry_t **);
47*0Sstevel@tonic-gate static int parse_dislist(char *, entry_t *);
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate /*
51*0Sstevel@tonic-gate  * Duplicate the mechanism list.  A null pointer is returned if the storage
52*0Sstevel@tonic-gate  * space available is insufficient or the input argument is NULL.
53*0Sstevel@tonic-gate  */
54*0Sstevel@tonic-gate static mechlist_t *
55*0Sstevel@tonic-gate dup_mechlist(mechlist_t *plist)
56*0Sstevel@tonic-gate {
57*0Sstevel@tonic-gate 	mechlist_t *pres = NULL;
58*0Sstevel@tonic-gate 	mechlist_t *pcur;
59*0Sstevel@tonic-gate 	mechlist_t *ptmp;
60*0Sstevel@tonic-gate 	int rc = SUCCESS;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	while (plist != NULL) {
63*0Sstevel@tonic-gate 		if (!(ptmp = create_mech(plist->name))) {
64*0Sstevel@tonic-gate 			rc = FAILURE;
65*0Sstevel@tonic-gate 			break;
66*0Sstevel@tonic-gate 		}
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate 		if (pres == NULL) {
69*0Sstevel@tonic-gate 			pres = pcur = ptmp;
70*0Sstevel@tonic-gate 		} else {
71*0Sstevel@tonic-gate 			pcur->next = ptmp;
72*0Sstevel@tonic-gate 			pcur = pcur->next;
73*0Sstevel@tonic-gate 		}
74*0Sstevel@tonic-gate 		plist = plist->next;
75*0Sstevel@tonic-gate 	}
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate 	if (rc != SUCCESS) {
78*0Sstevel@tonic-gate 		free_mechlist(pres);
79*0Sstevel@tonic-gate 		return (NULL);
80*0Sstevel@tonic-gate 	}
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	return (pres);
83*0Sstevel@tonic-gate }
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate /*
87*0Sstevel@tonic-gate  * Get the number of mechanisms in the mechanism list.
88*0Sstevel@tonic-gate  */
89*0Sstevel@tonic-gate int
90*0Sstevel@tonic-gate get_mech_count(mechlist_t *plist)
91*0Sstevel@tonic-gate {
92*0Sstevel@tonic-gate 	int count = 0;
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	while (plist != NULL) {
95*0Sstevel@tonic-gate 		count++;
96*0Sstevel@tonic-gate 		plist = plist->next;
97*0Sstevel@tonic-gate 	}
98*0Sstevel@tonic-gate 	return (count);
99*0Sstevel@tonic-gate }
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate /*
103*0Sstevel@tonic-gate  * Duplicate an entry.  A null pointer is returned if the storage space
104*0Sstevel@tonic-gate  * available is insufficient or the input argument is NULL.
105*0Sstevel@tonic-gate  */
106*0Sstevel@tonic-gate static entry_t *
107*0Sstevel@tonic-gate dup_entry(entry_t *pent1)
108*0Sstevel@tonic-gate {
109*0Sstevel@tonic-gate 	entry_t	*pent2 = NULL;
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 	if (pent1 == NULL) {
112*0Sstevel@tonic-gate 		return (NULL);
113*0Sstevel@tonic-gate 	}
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 	if ((pent2 = malloc(sizeof (entry_t))) == NULL) {
116*0Sstevel@tonic-gate 		cryptodebug("out of memory.");
117*0Sstevel@tonic-gate 		return (NULL);
118*0Sstevel@tonic-gate 	}
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 	(void) strlcpy(pent2->name, pent1->name, sizeof (pent2->name));
121*0Sstevel@tonic-gate 	pent2->sup_count = pent1->sup_count;
122*0Sstevel@tonic-gate 	pent2->dis_count = pent1->dis_count;
123*0Sstevel@tonic-gate 	pent2->suplist = NULL;
124*0Sstevel@tonic-gate 	pent2->dislist = NULL;
125*0Sstevel@tonic-gate 	if (pent1->suplist != NULL) {
126*0Sstevel@tonic-gate 		pent2->suplist = dup_mechlist(pent1->suplist);
127*0Sstevel@tonic-gate 		if (pent2->suplist == NULL) {
128*0Sstevel@tonic-gate 			free_entry(pent2);
129*0Sstevel@tonic-gate 			return (NULL);
130*0Sstevel@tonic-gate 		}
131*0Sstevel@tonic-gate 	}
132*0Sstevel@tonic-gate 	if (pent1->dislist != NULL) {
133*0Sstevel@tonic-gate 		pent2->dislist = dup_mechlist(pent1->dislist);
134*0Sstevel@tonic-gate 		if (pent2->dislist == NULL) {
135*0Sstevel@tonic-gate 			free_entry(pent2);
136*0Sstevel@tonic-gate 			return (NULL);
137*0Sstevel@tonic-gate 		}
138*0Sstevel@tonic-gate 	}
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	return (pent2);
141*0Sstevel@tonic-gate }
142*0Sstevel@tonic-gate 
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate /*
145*0Sstevel@tonic-gate  * This routine parses the disabledlist or the supportedlist of an entry
146*0Sstevel@tonic-gate  * in the kcf.conf configuration file.
147*0Sstevel@tonic-gate  *
148*0Sstevel@tonic-gate  * Arguments:
149*0Sstevel@tonic-gate  * 	buf: an input argument which is a char string with the format of
150*0Sstevel@tonic-gate  *	     "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
151*0Sstevel@tonic-gate  *	pent: the entry for the disabledlist.  This is an IN/OUT argument.
152*0Sstevel@tonic-gate  *
153*0Sstevel@tonic-gate  * Return value: SUCCESS or FAILURE.
154*0Sstevel@tonic-gate  */
155*0Sstevel@tonic-gate static int
156*0Sstevel@tonic-gate parse_dislist(char *buf, entry_t *pent)
157*0Sstevel@tonic-gate {
158*0Sstevel@tonic-gate 	mechlist_t *pmech;
159*0Sstevel@tonic-gate 	mechlist_t *phead;
160*0Sstevel@tonic-gate 	char *next_token;
161*0Sstevel@tonic-gate 	char *value;
162*0Sstevel@tonic-gate 	int count;
163*0Sstevel@tonic-gate 	int supflag = B_FALSE;
164*0Sstevel@tonic-gate 	int disflag = B_FALSE;
165*0Sstevel@tonic-gate 	int rc = SUCCESS;
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 	if (strncmp(buf, EF_SUPPORTED, strlen(EF_SUPPORTED)) == 0) {
168*0Sstevel@tonic-gate 		supflag = B_TRUE;
169*0Sstevel@tonic-gate 	} else if (strncmp(buf, EF_DISABLED, strlen(EF_DISABLED)) == 0) {
170*0Sstevel@tonic-gate 		disflag = B_TRUE;
171*0Sstevel@tonic-gate 	} else {
172*0Sstevel@tonic-gate 		/* should not come here */
173*0Sstevel@tonic-gate 		return (FAILURE);
174*0Sstevel@tonic-gate 	}
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	if (value = strpbrk(buf, SEP_EQUAL)) {
177*0Sstevel@tonic-gate 		value++; /* get rid of = */
178*0Sstevel@tonic-gate 	} else {
179*0Sstevel@tonic-gate 		cryptodebug("failed to parse the kcf.conf file.");
180*0Sstevel@tonic-gate 		return (FAILURE);
181*0Sstevel@tonic-gate 	}
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	if ((next_token = strtok(value, SEP_COMMA)) == NULL) {
184*0Sstevel@tonic-gate 		cryptodebug("failed to parse the kcf.conf file.");
185*0Sstevel@tonic-gate 		return (FAILURE);
186*0Sstevel@tonic-gate 	}
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	if ((pmech = create_mech(next_token)) == NULL) {
189*0Sstevel@tonic-gate 		return (FAILURE);
190*0Sstevel@tonic-gate 	}
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 	if (supflag) {
193*0Sstevel@tonic-gate 		pent->suplist = phead = pmech;
194*0Sstevel@tonic-gate 	} else if (disflag) {
195*0Sstevel@tonic-gate 		pent->dislist = phead = pmech;
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 	count = 1;
199*0Sstevel@tonic-gate 	while (next_token) {
200*0Sstevel@tonic-gate 		if (next_token = strtok(NULL, SEP_COMMA)) {
201*0Sstevel@tonic-gate 			if ((pmech = create_mech(next_token)) == NULL) {
202*0Sstevel@tonic-gate 				rc = FAILURE;
203*0Sstevel@tonic-gate 				break;
204*0Sstevel@tonic-gate 			}
205*0Sstevel@tonic-gate 			count++;
206*0Sstevel@tonic-gate 			phead->next = pmech;
207*0Sstevel@tonic-gate 			phead = phead->next;
208*0Sstevel@tonic-gate 		}
209*0Sstevel@tonic-gate 	}
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	if (rc == SUCCESS) {
212*0Sstevel@tonic-gate 		if (supflag) {
213*0Sstevel@tonic-gate 			pent->sup_count = count;
214*0Sstevel@tonic-gate 		} else if (disflag) {
215*0Sstevel@tonic-gate 			pent->dis_count = count;
216*0Sstevel@tonic-gate 		}
217*0Sstevel@tonic-gate 	} else {
218*0Sstevel@tonic-gate 		free_mechlist(phead);
219*0Sstevel@tonic-gate 	}
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 	return (rc);
222*0Sstevel@tonic-gate }
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate /*
227*0Sstevel@tonic-gate  * This routine converts a char string into an entry_t structure
228*0Sstevel@tonic-gate  */
229*0Sstevel@tonic-gate static int
230*0Sstevel@tonic-gate interpret(char *buf, entry_t **ppent)
231*0Sstevel@tonic-gate {
232*0Sstevel@tonic-gate 	entry_t *pent;
233*0Sstevel@tonic-gate 	char *token1;
234*0Sstevel@tonic-gate 	char *token2;
235*0Sstevel@tonic-gate 	char *token3;
236*0Sstevel@tonic-gate 	int rc;
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 	if ((token1 = strtok(buf, SEP_COLON)) == NULL) { /* buf is NULL */
239*0Sstevel@tonic-gate 		return (FAILURE);
240*0Sstevel@tonic-gate 	};
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	pent = malloc(sizeof (entry_t));
243*0Sstevel@tonic-gate 	if (pent == NULL) {
244*0Sstevel@tonic-gate 		cryptodebug("out of memory.");
245*0Sstevel@tonic-gate 		return (FAILURE);
246*0Sstevel@tonic-gate 	}
247*0Sstevel@tonic-gate 	(void) strlcpy(pent->name, token1, sizeof (pent->name));
248*0Sstevel@tonic-gate 	pent->suplist = NULL;
249*0Sstevel@tonic-gate 	pent->dislist = NULL;
250*0Sstevel@tonic-gate 	pent->sup_count = 0;
251*0Sstevel@tonic-gate 	pent->dis_count = 0;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
254*0Sstevel@tonic-gate 		/* The entry contains a provider name only */
255*0Sstevel@tonic-gate 		free_entry(pent);
256*0Sstevel@tonic-gate 		return (FAILURE);
257*0Sstevel@tonic-gate 	}
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 	/* need to get token3 first to satisfy nested strtok invocations */
260*0Sstevel@tonic-gate 	token3 = strtok(NULL, SEP_SEMICOLON);
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate 	if (token2 && ((rc = parse_dislist(token2, pent)) != SUCCESS)) {
263*0Sstevel@tonic-gate 		free_entry(pent);
264*0Sstevel@tonic-gate 		return (rc);
265*0Sstevel@tonic-gate 	}
266*0Sstevel@tonic-gate 
267*0Sstevel@tonic-gate 	if (token3 && ((rc = parse_dislist(token3, pent)) != SUCCESS)) {
268*0Sstevel@tonic-gate 		free_entry(pent);
269*0Sstevel@tonic-gate 		return (rc);
270*0Sstevel@tonic-gate 	}
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	*ppent = pent;
273*0Sstevel@tonic-gate 	return (SUCCESS);
274*0Sstevel@tonic-gate }
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate /*
278*0Sstevel@tonic-gate  * Add an entry to the end of an entry list. If the entry list is NULL, will
279*0Sstevel@tonic-gate  * create an entry list with the pent.
280*0Sstevel@tonic-gate  */
281*0Sstevel@tonic-gate static int
282*0Sstevel@tonic-gate build_entrylist(entry_t *pent, entrylist_t **pplist)
283*0Sstevel@tonic-gate {
284*0Sstevel@tonic-gate 	entrylist_t *pentlist;
285*0Sstevel@tonic-gate 	entrylist_t *pcur;
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 	pentlist = malloc(sizeof (entrylist_t));
288*0Sstevel@tonic-gate 	if (pentlist == NULL) {
289*0Sstevel@tonic-gate 		cryptodebug("out of memory.");
290*0Sstevel@tonic-gate 		return (FAILURE);
291*0Sstevel@tonic-gate 	}
292*0Sstevel@tonic-gate 	pentlist->pent = pent;
293*0Sstevel@tonic-gate 	pentlist->next = NULL;
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 	if (*pplist) {
296*0Sstevel@tonic-gate 		pcur = *pplist;
297*0Sstevel@tonic-gate 		while (pcur->next != NULL)
298*0Sstevel@tonic-gate 			pcur = pcur->next;
299*0Sstevel@tonic-gate 		pcur->next = pentlist;
300*0Sstevel@tonic-gate 	} else { /* empty list */
301*0Sstevel@tonic-gate 		*pplist = pentlist;
302*0Sstevel@tonic-gate 	}
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 	return (SUCCESS);
305*0Sstevel@tonic-gate }
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate /*
310*0Sstevel@tonic-gate  * Find the entry with the "provname" name from the entry list and duplicate
311*0Sstevel@tonic-gate  * it.
312*0Sstevel@tonic-gate  */
313*0Sstevel@tonic-gate static entry_t *
314*0Sstevel@tonic-gate getent(char *provname, entrylist_t *entrylist)
315*0Sstevel@tonic-gate {
316*0Sstevel@tonic-gate 	boolean_t	found = B_FALSE;
317*0Sstevel@tonic-gate 	entry_t		*pent1 = NULL;
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	if ((provname == NULL) || (entrylist == NULL)) {
320*0Sstevel@tonic-gate 		return (NULL);
321*0Sstevel@tonic-gate 	}
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 	while (!found && entrylist) {
324*0Sstevel@tonic-gate 		if (strcmp(entrylist->pent->name, provname) == 0) {
325*0Sstevel@tonic-gate 			found = B_TRUE;
326*0Sstevel@tonic-gate 			pent1 = entrylist->pent;
327*0Sstevel@tonic-gate 		} else {
328*0Sstevel@tonic-gate 			entrylist = entrylist->next;
329*0Sstevel@tonic-gate 		}
330*0Sstevel@tonic-gate 	}
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate 	if (!found) {
333*0Sstevel@tonic-gate 		return (NULL);
334*0Sstevel@tonic-gate 	}
335*0Sstevel@tonic-gate 
336*0Sstevel@tonic-gate 	/* duplicate the entry to be returned */
337*0Sstevel@tonic-gate 	return (dup_entry(pent1));
338*0Sstevel@tonic-gate }
339*0Sstevel@tonic-gate 
340*0Sstevel@tonic-gate 
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate void
343*0Sstevel@tonic-gate free_entry(entry_t  *pent)
344*0Sstevel@tonic-gate {
345*0Sstevel@tonic-gate 	if (pent == NULL) {
346*0Sstevel@tonic-gate 		return;
347*0Sstevel@tonic-gate 	} else {
348*0Sstevel@tonic-gate 		free_mechlist(pent->suplist);
349*0Sstevel@tonic-gate 		free_mechlist(pent->dislist);
350*0Sstevel@tonic-gate 		free(pent);
351*0Sstevel@tonic-gate 	}
352*0Sstevel@tonic-gate }
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate void
356*0Sstevel@tonic-gate free_entrylist(entrylist_t *entrylist)
357*0Sstevel@tonic-gate {
358*0Sstevel@tonic-gate 	entrylist_t *pnext;
359*0Sstevel@tonic-gate 
360*0Sstevel@tonic-gate 	while (entrylist != NULL) {
361*0Sstevel@tonic-gate 		pnext = entrylist->next;
362*0Sstevel@tonic-gate 		free_entry(entrylist->pent);
363*0Sstevel@tonic-gate 		entrylist = pnext;
364*0Sstevel@tonic-gate 	}
365*0Sstevel@tonic-gate }
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate /*
369*0Sstevel@tonic-gate  * Convert an entry to a string.  This routine builds a string for the entry
370*0Sstevel@tonic-gate  * to be inserted in the config file.  Based on the content of each entry,
371*0Sstevel@tonic-gate  * the result string can be one of the 4 forms:
372*0Sstevel@tonic-gate  *  - name
373*0Sstevel@tonic-gate  *  - name:supportedlist=m1,m2,...,mj
374*0Sstevel@tonic-gate  *  - name:disabledlist=m1,m2,...,mj
375*0Sstevel@tonic-gate  *  - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
376*0Sstevel@tonic-gate  *
377*0Sstevel@tonic-gate  * Note that the caller is responsible for freeing the returned string.
378*0Sstevel@tonic-gate  */
379*0Sstevel@tonic-gate char *
380*0Sstevel@tonic-gate ent2str(entry_t *pent)
381*0Sstevel@tonic-gate {
382*0Sstevel@tonic-gate 	char	*buf;
383*0Sstevel@tonic-gate 	mechlist_t  *phead;
384*0Sstevel@tonic-gate 	boolean_t supflag = B_FALSE;
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate 	if (pent == NULL) {
388*0Sstevel@tonic-gate 		return (NULL);
389*0Sstevel@tonic-gate 	}
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 	if ((buf = malloc(BUFSIZ)) == NULL) {
392*0Sstevel@tonic-gate 		return (NULL);
393*0Sstevel@tonic-gate 	}
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate 	/* convert the provider name */
396*0Sstevel@tonic-gate 	if (strlcpy(buf, pent->name, BUFSIZ) >= BUFSIZ) {
397*0Sstevel@tonic-gate 		free(buf);
398*0Sstevel@tonic-gate 		return (NULL);
399*0Sstevel@tonic-gate 	}
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate 	/* convert the supported list if any */
402*0Sstevel@tonic-gate 	phead = pent->suplist;
403*0Sstevel@tonic-gate 	if (phead != NULL) {
404*0Sstevel@tonic-gate 		supflag = B_TRUE;
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 		if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
407*0Sstevel@tonic-gate 			free(buf);
408*0Sstevel@tonic-gate 			return (NULL);
409*0Sstevel@tonic-gate 		}
410*0Sstevel@tonic-gate 
411*0Sstevel@tonic-gate 		if (strlcat(buf, EF_SUPPORTED, BUFSIZ) >= BUFSIZ) {
412*0Sstevel@tonic-gate 			free(buf);
413*0Sstevel@tonic-gate 			return (NULL);
414*0Sstevel@tonic-gate 		}
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 		while (phead != NULL) {
417*0Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
418*0Sstevel@tonic-gate 				free(buf);
419*0Sstevel@tonic-gate 				return (NULL);
420*0Sstevel@tonic-gate 			}
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate 			phead = phead->next;
423*0Sstevel@tonic-gate 			if (phead != NULL) {
424*0Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
425*0Sstevel@tonic-gate 				    >= BUFSIZ) {
426*0Sstevel@tonic-gate 					free(buf);
427*0Sstevel@tonic-gate 					return (NULL);
428*0Sstevel@tonic-gate 				}
429*0Sstevel@tonic-gate 			}
430*0Sstevel@tonic-gate 		}
431*0Sstevel@tonic-gate 	}
432*0Sstevel@tonic-gate 
433*0Sstevel@tonic-gate 	/* convert the disabled list if any */
434*0Sstevel@tonic-gate 	phead = pent->dislist;
435*0Sstevel@tonic-gate 	if (phead != NULL) {
436*0Sstevel@tonic-gate 		if (supflag) {
437*0Sstevel@tonic-gate 			if (strlcat(buf, ";disabledlist=", BUFSIZ) >= BUFSIZ) {
438*0Sstevel@tonic-gate 				free(buf);
439*0Sstevel@tonic-gate 				return (NULL);
440*0Sstevel@tonic-gate 			}
441*0Sstevel@tonic-gate 		} else {
442*0Sstevel@tonic-gate 			if (strlcat(buf, ":disabledlist=", BUFSIZ) >= BUFSIZ) {
443*0Sstevel@tonic-gate 				free(buf);
444*0Sstevel@tonic-gate 				return (NULL);
445*0Sstevel@tonic-gate 			}
446*0Sstevel@tonic-gate 		}
447*0Sstevel@tonic-gate 
448*0Sstevel@tonic-gate 		while (phead != NULL) {
449*0Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
450*0Sstevel@tonic-gate 				free(buf);
451*0Sstevel@tonic-gate 				return (NULL);
452*0Sstevel@tonic-gate 			}
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate 			phead = phead->next;
455*0Sstevel@tonic-gate 			if (phead != NULL) {
456*0Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
457*0Sstevel@tonic-gate 				    >= BUFSIZ) {
458*0Sstevel@tonic-gate 					free(buf);
459*0Sstevel@tonic-gate 					return (NULL);
460*0Sstevel@tonic-gate 				}
461*0Sstevel@tonic-gate 			}
462*0Sstevel@tonic-gate 		}
463*0Sstevel@tonic-gate 	}
464*0Sstevel@tonic-gate 
465*0Sstevel@tonic-gate 	if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
466*0Sstevel@tonic-gate 		free(buf);
467*0Sstevel@tonic-gate 		return (NULL);
468*0Sstevel@tonic-gate 	}
469*0Sstevel@tonic-gate 
470*0Sstevel@tonic-gate 	return (buf);
471*0Sstevel@tonic-gate }
472*0Sstevel@tonic-gate 
473*0Sstevel@tonic-gate 
474*0Sstevel@tonic-gate /*
475*0Sstevel@tonic-gate  * Enable the mechanisms for the provider pointed by *ppent.  If allflag is
476*0Sstevel@tonic-gate  * TRUE, enable all.  Otherwise, enable the mechanisms specified in the 3rd
477*0Sstevel@tonic-gate  * argument "mlist".  The result will be stored in ppent also.
478*0Sstevel@tonic-gate  */
479*0Sstevel@tonic-gate int
480*0Sstevel@tonic-gate enable_mechs(entry_t **ppent, boolean_t allflag, mechlist_t *mlist)
481*0Sstevel@tonic-gate {
482*0Sstevel@tonic-gate 	entry_t *pent;
483*0Sstevel@tonic-gate 	mechlist_t *phead; /* the current and resulting disabled list */
484*0Sstevel@tonic-gate 	mechlist_t *ptr;
485*0Sstevel@tonic-gate 	mechlist_t *pcur;
486*0Sstevel@tonic-gate 	boolean_t found;
487*0Sstevel@tonic-gate 
488*0Sstevel@tonic-gate 	pent = *ppent;
489*0Sstevel@tonic-gate 	if (pent == NULL) {
490*0Sstevel@tonic-gate 		return (FAILURE);
491*0Sstevel@tonic-gate 	}
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 	if (allflag) {
494*0Sstevel@tonic-gate 		free_mechlist(pent->dislist);
495*0Sstevel@tonic-gate 		pent->dis_count = 0;
496*0Sstevel@tonic-gate 		pent->dislist = NULL;
497*0Sstevel@tonic-gate 		return (SUCCESS);
498*0Sstevel@tonic-gate 	}
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate 	/*
501*0Sstevel@tonic-gate 	 * for each mechanism in the to-be-enabled mechanism list,
502*0Sstevel@tonic-gate 	 * -	check if it is in the current disabled list
503*0Sstevel@tonic-gate 	 * -	if found, delete it from the disabled list
504*0Sstevel@tonic-gate 	 * 	otherwise, give a warning.
505*0Sstevel@tonic-gate 	 */
506*0Sstevel@tonic-gate 	ptr = mlist;
507*0Sstevel@tonic-gate 	while (ptr != NULL) {
508*0Sstevel@tonic-gate 		found = B_FALSE;
509*0Sstevel@tonic-gate 		phead = pcur =  pent->dislist;
510*0Sstevel@tonic-gate 		while (!found && pcur) {
511*0Sstevel@tonic-gate 			if (strcmp(pcur->name, ptr->name) == 0) {
512*0Sstevel@tonic-gate 				found = B_TRUE;
513*0Sstevel@tonic-gate 			} else {
514*0Sstevel@tonic-gate 				phead = pcur;
515*0Sstevel@tonic-gate 				pcur = pcur->next;
516*0Sstevel@tonic-gate 			}
517*0Sstevel@tonic-gate 		}
518*0Sstevel@tonic-gate 
519*0Sstevel@tonic-gate 		if (found) {
520*0Sstevel@tonic-gate 			if (phead == pcur) {
521*0Sstevel@tonic-gate 				pent->dislist = pent->dislist->next;
522*0Sstevel@tonic-gate 				free(pcur);
523*0Sstevel@tonic-gate 			} else {
524*0Sstevel@tonic-gate 				phead->next = pcur->next;
525*0Sstevel@tonic-gate 				free(pcur);
526*0Sstevel@tonic-gate 			}
527*0Sstevel@tonic-gate 			pent->dis_count--;
528*0Sstevel@tonic-gate 		} else {
529*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
530*0Sstevel@tonic-gate 			    "(Warning) %1$s is either enabled already or not "
531*0Sstevel@tonic-gate 			    "a valid mechanism for %2$s"), ptr->name,
532*0Sstevel@tonic-gate 			    pent->name);
533*0Sstevel@tonic-gate 		}
534*0Sstevel@tonic-gate 		ptr = ptr->next;
535*0Sstevel@tonic-gate 	}
536*0Sstevel@tonic-gate 
537*0Sstevel@tonic-gate 	if (pent->dis_count == 0) {
538*0Sstevel@tonic-gate 		pent->dislist = NULL;
539*0Sstevel@tonic-gate 	}
540*0Sstevel@tonic-gate 
541*0Sstevel@tonic-gate 	return (SUCCESS);
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate }
544*0Sstevel@tonic-gate 
545*0Sstevel@tonic-gate 
546*0Sstevel@tonic-gate boolean_t
547*0Sstevel@tonic-gate is_device(char *path)
548*0Sstevel@tonic-gate {
549*0Sstevel@tonic-gate 	if (strchr(path, SEP_SLASH) != NULL) {
550*0Sstevel@tonic-gate 		return (B_TRUE);
551*0Sstevel@tonic-gate 	} else {
552*0Sstevel@tonic-gate 		return (B_FALSE);
553*0Sstevel@tonic-gate 	}
554*0Sstevel@tonic-gate }
555*0Sstevel@tonic-gate 
556*0Sstevel@tonic-gate /*
557*0Sstevel@tonic-gate  * Split a hardware provider name with the "name/inst_num" format into
558*0Sstevel@tonic-gate  * a name and a number.
559*0Sstevel@tonic-gate  */
560*0Sstevel@tonic-gate int
561*0Sstevel@tonic-gate split_hw_provname(char *provname, char *pname, int *inst_num)
562*0Sstevel@tonic-gate {
563*0Sstevel@tonic-gate 	char	name[MAXNAMELEN];
564*0Sstevel@tonic-gate 	char	*inst_str;
565*0Sstevel@tonic-gate 
566*0Sstevel@tonic-gate 	if (provname == NULL) {
567*0Sstevel@tonic-gate 		return (FAILURE);
568*0Sstevel@tonic-gate 	}
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 	(void) strlcpy(name, provname, MAXNAMELEN);
571*0Sstevel@tonic-gate 	if (strtok(name, "/") == NULL) {
572*0Sstevel@tonic-gate 		return (FAILURE);
573*0Sstevel@tonic-gate 	}
574*0Sstevel@tonic-gate 
575*0Sstevel@tonic-gate 	if ((inst_str = strtok(NULL, "/")) == NULL) {
576*0Sstevel@tonic-gate 		return (FAILURE);
577*0Sstevel@tonic-gate 	}
578*0Sstevel@tonic-gate 
579*0Sstevel@tonic-gate 	(void) strlcpy(pname, name, MAXNAMELEN);
580*0Sstevel@tonic-gate 	*inst_num = atoi(inst_str);
581*0Sstevel@tonic-gate 
582*0Sstevel@tonic-gate 	return (SUCCESS);
583*0Sstevel@tonic-gate }
584*0Sstevel@tonic-gate 
585*0Sstevel@tonic-gate 
586*0Sstevel@tonic-gate /*
587*0Sstevel@tonic-gate  * Retrieve information from kcf.conf and build a device entry list and
588*0Sstevel@tonic-gate  * a software entry list
589*0Sstevel@tonic-gate  */
590*0Sstevel@tonic-gate int
591*0Sstevel@tonic-gate get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
592*0Sstevel@tonic-gate {
593*0Sstevel@tonic-gate 	FILE *pfile;
594*0Sstevel@tonic-gate 	char buffer[BUFSIZ];
595*0Sstevel@tonic-gate 	int len;
596*0Sstevel@tonic-gate 	entry_t *pent = NULL;
597*0Sstevel@tonic-gate 	int rc = SUCCESS;
598*0Sstevel@tonic-gate 
599*0Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) {
600*0Sstevel@tonic-gate 		cryptodebug("failed to open the kcf.conf file for read only");
601*0Sstevel@tonic-gate 		return (FAILURE);
602*0Sstevel@tonic-gate 	}
603*0Sstevel@tonic-gate 
604*0Sstevel@tonic-gate 	*ppdevlist = NULL;
605*0Sstevel@tonic-gate 	*ppsoftlist = NULL;
606*0Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
607*0Sstevel@tonic-gate 		if (buffer[0] == '#' || buffer[0] == ' ' ||
608*0Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t') {
609*0Sstevel@tonic-gate 			continue;   /* ignore comment lines */
610*0Sstevel@tonic-gate 		}
611*0Sstevel@tonic-gate 
612*0Sstevel@tonic-gate 		len = strlen(buffer);
613*0Sstevel@tonic-gate 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
614*0Sstevel@tonic-gate 			len--;
615*0Sstevel@tonic-gate 		}
616*0Sstevel@tonic-gate 		buffer[len] = '\0';
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate 		if ((rc = interpret(buffer,  &pent)) == SUCCESS) {
619*0Sstevel@tonic-gate 			if (is_device(pent->name)) {
620*0Sstevel@tonic-gate 				rc = build_entrylist(pent, ppdevlist);
621*0Sstevel@tonic-gate 			} else {
622*0Sstevel@tonic-gate 				rc = build_entrylist(pent, ppsoftlist);
623*0Sstevel@tonic-gate 			}
624*0Sstevel@tonic-gate 		} else {
625*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
626*0Sstevel@tonic-gate 			    "failed to parse configuration."));
627*0Sstevel@tonic-gate 		}
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate 		if (rc != SUCCESS) {
630*0Sstevel@tonic-gate 			free_entrylist(*ppdevlist);
631*0Sstevel@tonic-gate 			free_entrylist(*ppsoftlist);
632*0Sstevel@tonic-gate 			free_entry(pent);
633*0Sstevel@tonic-gate 			break;
634*0Sstevel@tonic-gate 		}
635*0Sstevel@tonic-gate 	}
636*0Sstevel@tonic-gate 
637*0Sstevel@tonic-gate 	(void) fclose(pfile);
638*0Sstevel@tonic-gate 	return (rc);
639*0Sstevel@tonic-gate }
640*0Sstevel@tonic-gate 
641*0Sstevel@tonic-gate /*
642*0Sstevel@tonic-gate  * Retrieve information from admin device and build a device entry list and
643*0Sstevel@tonic-gate  * a software entry list.  This is used where there is no kcf.conf, e.g.
644*0Sstevel@tonic-gate  * non-global zone.
645*0Sstevel@tonic-gate  */
646*0Sstevel@tonic-gate int
647*0Sstevel@tonic-gate get_admindev_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
648*0Sstevel@tonic-gate {
649*0Sstevel@tonic-gate 	crypto_get_dev_list_t *pdevlist_kernel = NULL;
650*0Sstevel@tonic-gate 	crypto_get_soft_list_t *psoftlist_kernel = NULL;
651*0Sstevel@tonic-gate 	char *devname;
652*0Sstevel@tonic-gate 	int inst_num;
653*0Sstevel@tonic-gate 	int mcount;
654*0Sstevel@tonic-gate 	mechlist_t *pmech;
655*0Sstevel@tonic-gate 	entry_t *pent = NULL;
656*0Sstevel@tonic-gate 	int i;
657*0Sstevel@tonic-gate 	char *psoftname;
658*0Sstevel@tonic-gate 	entrylist_t *tmp_pdev = NULL;
659*0Sstevel@tonic-gate 	entrylist_t *tmp_psoft = NULL;
660*0Sstevel@tonic-gate 
661*0Sstevel@tonic-gate 	if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
662*0Sstevel@tonic-gate 		cryptodebug("failed to get hardware provider list from kernel");
663*0Sstevel@tonic-gate 		return (FAILURE);
664*0Sstevel@tonic-gate 	}
665*0Sstevel@tonic-gate 
666*0Sstevel@tonic-gate 	for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
667*0Sstevel@tonic-gate 		devname = pdevlist_kernel->dl_devs[i].le_dev_name;
668*0Sstevel@tonic-gate 		inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance;
669*0Sstevel@tonic-gate 		mcount = pdevlist_kernel->dl_devs[i].le_mechanism_count;
670*0Sstevel@tonic-gate 
671*0Sstevel@tonic-gate 		pmech = NULL;
672*0Sstevel@tonic-gate 		if (get_dev_info(devname, inst_num, mcount, &pmech) !=
673*0Sstevel@tonic-gate 		    SUCCESS) {
674*0Sstevel@tonic-gate 			cryptodebug(
675*0Sstevel@tonic-gate 			    "failed to retrieve the mechanism list for %s/%d.",
676*0Sstevel@tonic-gate 			    devname, inst_num);
677*0Sstevel@tonic-gate 			goto fail_out;
678*0Sstevel@tonic-gate 		}
679*0Sstevel@tonic-gate 
680*0Sstevel@tonic-gate 		if ((pent = malloc(sizeof (entry_t))) == NULL) {
681*0Sstevel@tonic-gate 			cryptodebug("out of memory.");
682*0Sstevel@tonic-gate 			free_mechlist(pmech);
683*0Sstevel@tonic-gate 			goto fail_out;
684*0Sstevel@tonic-gate 		}
685*0Sstevel@tonic-gate 
686*0Sstevel@tonic-gate 		(void) strlcpy(pent->name, devname, MAXNAMELEN);
687*0Sstevel@tonic-gate 		pent->suplist = pmech;
688*0Sstevel@tonic-gate 		pent->sup_count = mcount;
689*0Sstevel@tonic-gate 		pent->dislist = NULL;
690*0Sstevel@tonic-gate 		pent->dis_count = 0;
691*0Sstevel@tonic-gate 
692*0Sstevel@tonic-gate 		if (build_entrylist(pent, &tmp_pdev) != SUCCESS) {
693*0Sstevel@tonic-gate 			goto fail_out;
694*0Sstevel@tonic-gate 		}
695*0Sstevel@tonic-gate 
696*0Sstevel@tonic-gate 		/* because incorporated in tmp_pdev */
697*0Sstevel@tonic-gate 		pent = NULL;
698*0Sstevel@tonic-gate 	}
699*0Sstevel@tonic-gate 
700*0Sstevel@tonic-gate 	free(pdevlist_kernel);
701*0Sstevel@tonic-gate 	pdevlist_kernel = NULL;
702*0Sstevel@tonic-gate 
703*0Sstevel@tonic-gate 	if (get_soft_list(&psoftlist_kernel) != SUCCESS) {
704*0Sstevel@tonic-gate 		cryptodebug("failed to get software provider list from kernel");
705*0Sstevel@tonic-gate 		goto fail_out;
706*0Sstevel@tonic-gate 	}
707*0Sstevel@tonic-gate 
708*0Sstevel@tonic-gate 	for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
709*0Sstevel@tonic-gate 	    i < psoftlist_kernel->sl_soft_count;
710*0Sstevel@tonic-gate 	    i++, psoftname = psoftname + strlen(psoftname) + 1) {
711*0Sstevel@tonic-gate 		pmech = NULL;
712*0Sstevel@tonic-gate 		if (get_soft_info(psoftname, &pmech) != SUCCESS) {
713*0Sstevel@tonic-gate 			cryptodebug(
714*0Sstevel@tonic-gate 			    "failed to retrieve the mechanism list for %s.",
715*0Sstevel@tonic-gate 			    psoftname);
716*0Sstevel@tonic-gate 			goto fail_out;
717*0Sstevel@tonic-gate 		}
718*0Sstevel@tonic-gate 
719*0Sstevel@tonic-gate 		if ((pent = malloc(sizeof (entry_t))) == NULL) {
720*0Sstevel@tonic-gate 			cryptodebug("out of memory.");
721*0Sstevel@tonic-gate 			free_mechlist(pmech);
722*0Sstevel@tonic-gate 			goto fail_out;
723*0Sstevel@tonic-gate 		}
724*0Sstevel@tonic-gate 
725*0Sstevel@tonic-gate 		(void) strlcpy(pent->name, psoftname, MAXNAMELEN);
726*0Sstevel@tonic-gate 		pent->suplist = pmech;
727*0Sstevel@tonic-gate 		pent->sup_count = get_mech_count(pmech);
728*0Sstevel@tonic-gate 		pent->dislist = NULL;
729*0Sstevel@tonic-gate 		pent->dis_count = 0;
730*0Sstevel@tonic-gate 
731*0Sstevel@tonic-gate 		if (build_entrylist(pent, &tmp_psoft) != SUCCESS) {
732*0Sstevel@tonic-gate 			goto fail_out;
733*0Sstevel@tonic-gate 		}
734*0Sstevel@tonic-gate 	}
735*0Sstevel@tonic-gate 
736*0Sstevel@tonic-gate 	free(psoftlist_kernel);
737*0Sstevel@tonic-gate 	psoftlist_kernel = NULL;
738*0Sstevel@tonic-gate 
739*0Sstevel@tonic-gate 	*ppdevlist = tmp_pdev;
740*0Sstevel@tonic-gate 	*ppsoftlist = tmp_psoft;
741*0Sstevel@tonic-gate 
742*0Sstevel@tonic-gate 	return (SUCCESS);
743*0Sstevel@tonic-gate 
744*0Sstevel@tonic-gate fail_out:
745*0Sstevel@tonic-gate 	if (pent != NULL)
746*0Sstevel@tonic-gate 		free_entry(pent);
747*0Sstevel@tonic-gate 
748*0Sstevel@tonic-gate 	free_entrylist(tmp_pdev);
749*0Sstevel@tonic-gate 	free_entrylist(tmp_psoft);
750*0Sstevel@tonic-gate 
751*0Sstevel@tonic-gate 	if (pdevlist_kernel != NULL)
752*0Sstevel@tonic-gate 		free(pdevlist_kernel);
753*0Sstevel@tonic-gate 	if (psoftlist_kernel != NULL)
754*0Sstevel@tonic-gate 		free(psoftlist_kernel);
755*0Sstevel@tonic-gate 
756*0Sstevel@tonic-gate 	return (FAILURE);
757*0Sstevel@tonic-gate }
758*0Sstevel@tonic-gate 
759*0Sstevel@tonic-gate /*
760*0Sstevel@tonic-gate  * Find the entry in the "kcf.conf" file with "provname" as the provider name.
761*0Sstevel@tonic-gate  * Return the entry if found, otherwise return NULL.
762*0Sstevel@tonic-gate  */
763*0Sstevel@tonic-gate entry_t *
764*0Sstevel@tonic-gate getent_kef(char *provname)
765*0Sstevel@tonic-gate {
766*0Sstevel@tonic-gate 	entrylist_t *pdevlist = NULL;
767*0Sstevel@tonic-gate 	entrylist_t *psoftlist = NULL;
768*0Sstevel@tonic-gate 	entry_t *pent = NULL;
769*0Sstevel@tonic-gate 
770*0Sstevel@tonic-gate 	if (get_kcfconf_info(&pdevlist, &psoftlist) != SUCCESS) {
771*0Sstevel@tonic-gate 		return (NULL);
772*0Sstevel@tonic-gate 	}
773*0Sstevel@tonic-gate 
774*0Sstevel@tonic-gate 	if (is_device(provname)) {
775*0Sstevel@tonic-gate 		pent = getent(provname, pdevlist);
776*0Sstevel@tonic-gate 	} else {
777*0Sstevel@tonic-gate 		pent = getent(provname, psoftlist);
778*0Sstevel@tonic-gate 	}
779*0Sstevel@tonic-gate 
780*0Sstevel@tonic-gate 	free_entrylist(pdevlist);
781*0Sstevel@tonic-gate 	free_entrylist(psoftlist);
782*0Sstevel@tonic-gate 
783*0Sstevel@tonic-gate 	return (pent);
784*0Sstevel@tonic-gate }
785*0Sstevel@tonic-gate 
786*0Sstevel@tonic-gate /*
787*0Sstevel@tonic-gate  * Print out the provider name and the mechanism list.
788*0Sstevel@tonic-gate  */
789*0Sstevel@tonic-gate void
790*0Sstevel@tonic-gate print_mechlist(char *provname, mechlist_t *pmechlist)
791*0Sstevel@tonic-gate {
792*0Sstevel@tonic-gate 	mechlist_t *ptr;
793*0Sstevel@tonic-gate 
794*0Sstevel@tonic-gate 	if (provname == NULL) {
795*0Sstevel@tonic-gate 		return;
796*0Sstevel@tonic-gate 	}
797*0Sstevel@tonic-gate 
798*0Sstevel@tonic-gate 	(void) printf("%s: ", provname);
799*0Sstevel@tonic-gate 	if (pmechlist == NULL) {
800*0Sstevel@tonic-gate 		(void) printf(gettext("No mechanisms presented.\n"));
801*0Sstevel@tonic-gate 		return;
802*0Sstevel@tonic-gate 	}
803*0Sstevel@tonic-gate 
804*0Sstevel@tonic-gate 	ptr = pmechlist;
805*0Sstevel@tonic-gate 	while (ptr != NULL) {
806*0Sstevel@tonic-gate 		(void) printf("%s", ptr->name);
807*0Sstevel@tonic-gate 		ptr = ptr->next;
808*0Sstevel@tonic-gate 		if (ptr == NULL) {
809*0Sstevel@tonic-gate 			(void) printf("\n");
810*0Sstevel@tonic-gate 		} else {
811*0Sstevel@tonic-gate 			(void) printf(",");
812*0Sstevel@tonic-gate 		}
813*0Sstevel@tonic-gate 	}
814*0Sstevel@tonic-gate }
815*0Sstevel@tonic-gate 
816*0Sstevel@tonic-gate 
817*0Sstevel@tonic-gate /*
818*0Sstevel@tonic-gate  * Update the kcf.conf file based on the specified entry and the update mode.
819*0Sstevel@tonic-gate  * - If update_mode is MODIFY_MODE or DELETE_MODE, the entry with the same
820*0Sstevel@tonic-gate  *   provider name will be modified or deleted.
821*0Sstevel@tonic-gate  * - If update_mode is ADD_MODE, this must be a hardware provider without
822*0Sstevel@tonic-gate  *   an entry in the kcf.conf file yet.  Need to locate its driver package
823*0Sstevel@tonic-gate  *   bracket and insert an entry into the bracket.
824*0Sstevel@tonic-gate  */
825*0Sstevel@tonic-gate int
826*0Sstevel@tonic-gate update_kcfconf(entry_t *pent, int update_mode)
827*0Sstevel@tonic-gate {
828*0Sstevel@tonic-gate 	boolean_t	add_it = B_FALSE;
829*0Sstevel@tonic-gate 	boolean_t	delete_it = B_FALSE;
830*0Sstevel@tonic-gate 	boolean_t	found_package = B_FALSE;
831*0Sstevel@tonic-gate 	boolean_t	found_entry = B_FALSE;
832*0Sstevel@tonic-gate 	FILE	*pfile;
833*0Sstevel@tonic-gate 	FILE	*pfile_tmp;
834*0Sstevel@tonic-gate 	char	buffer[BUFSIZ];
835*0Sstevel@tonic-gate 	char	buffer2[BUFSIZ];
836*0Sstevel@tonic-gate 	char	devname[MAXNAMELEN];
837*0Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
838*0Sstevel@tonic-gate 	char	*name;
839*0Sstevel@tonic-gate 	char	*str;
840*0Sstevel@tonic-gate 	char	*new_str = NULL;
841*0Sstevel@tonic-gate 	int	inst_num;
842*0Sstevel@tonic-gate 	int rc = SUCCESS;
843*0Sstevel@tonic-gate 
844*0Sstevel@tonic-gate 
845*0Sstevel@tonic-gate 	if (pent == NULL) {
846*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
847*0Sstevel@tonic-gate 		return (FAILURE);
848*0Sstevel@tonic-gate 	}
849*0Sstevel@tonic-gate 
850*0Sstevel@tonic-gate 	/* Check the update_mode */
851*0Sstevel@tonic-gate 	if (update_mode == ADD_MODE) {
852*0Sstevel@tonic-gate 		add_it = B_TRUE;
853*0Sstevel@tonic-gate 		/* Get the hardware provider name first */
854*0Sstevel@tonic-gate 		if (split_hw_provname(pent->name, devname, &inst_num) ==
855*0Sstevel@tonic-gate 		    FAILURE) {
856*0Sstevel@tonic-gate 			return (FAILURE);
857*0Sstevel@tonic-gate 		}
858*0Sstevel@tonic-gate 
859*0Sstevel@tonic-gate 		/* Convert the entry to be a string  */
860*0Sstevel@tonic-gate 		if ((new_str = ent2str(pent)) == NULL) {
861*0Sstevel@tonic-gate 			return (FAILURE);
862*0Sstevel@tonic-gate 		}
863*0Sstevel@tonic-gate 	} else if (update_mode == DELETE_MODE) {
864*0Sstevel@tonic-gate 		delete_it = B_TRUE;
865*0Sstevel@tonic-gate 	} else if (update_mode != MODIFY_MODE) {
866*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
867*0Sstevel@tonic-gate 		return (FAILURE);
868*0Sstevel@tonic-gate 	}
869*0Sstevel@tonic-gate 
870*0Sstevel@tonic-gate 
871*0Sstevel@tonic-gate 	/* Open the kcf.conf file */
872*0Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
873*0Sstevel@tonic-gate 		err = errno;
874*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
875*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
876*0Sstevel@tonic-gate 		    strerror(err));
877*0Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
878*0Sstevel@tonic-gate 		return (FAILURE);
879*0Sstevel@tonic-gate 	}
880*0Sstevel@tonic-gate 
881*0Sstevel@tonic-gate 	/* Lock the kcf.conf file */
882*0Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
883*0Sstevel@tonic-gate 		err = errno;
884*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
885*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
886*0Sstevel@tonic-gate 			strerror(err));
887*0Sstevel@tonic-gate 		(void) fclose(pfile);
888*0Sstevel@tonic-gate 		return (FAILURE);
889*0Sstevel@tonic-gate 	}
890*0Sstevel@tonic-gate 
891*0Sstevel@tonic-gate 	/*
892*0Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
893*0Sstevel@tonic-gate 	 * updated configuration file first.
894*0Sstevel@tonic-gate 	 */
895*0Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
896*0Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
897*0Sstevel@tonic-gate 		err = errno;
898*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
899*0Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
900*0Sstevel@tonic-gate 		    strerror(err));
901*0Sstevel@tonic-gate 		(void) fclose(pfile);
902*0Sstevel@tonic-gate 		return (FAILURE);
903*0Sstevel@tonic-gate 	}
904*0Sstevel@tonic-gate 
905*0Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
906*0Sstevel@tonic-gate 		err = errno;
907*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
908*0Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
909*0Sstevel@tonic-gate 		(void) fclose(pfile);
910*0Sstevel@tonic-gate 		return (FAILURE);
911*0Sstevel@tonic-gate 	}
912*0Sstevel@tonic-gate 
913*0Sstevel@tonic-gate 	/*
914*0Sstevel@tonic-gate 	 * Loop thru the entire kcf.conf file, insert, modify or delete
915*0Sstevel@tonic-gate 	 * an entry.
916*0Sstevel@tonic-gate 	 */
917*0Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
918*0Sstevel@tonic-gate 		if (add_it) {
919*0Sstevel@tonic-gate 			/* always keep the current line */
920*0Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
921*0Sstevel@tonic-gate 				err = errno;
922*0Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
923*0Sstevel@tonic-gate 				    "failed to write to a temp file: %s."),
924*0Sstevel@tonic-gate 				    strerror(err));
925*0Sstevel@tonic-gate 				rc = FAILURE;
926*0Sstevel@tonic-gate 				break;
927*0Sstevel@tonic-gate 			}
928*0Sstevel@tonic-gate 
929*0Sstevel@tonic-gate 			/*
930*0Sstevel@tonic-gate 			 * If the current position is the beginning of a driver
931*0Sstevel@tonic-gate 			 * package and if the driver name matches the hardware
932*0Sstevel@tonic-gate 			 * provider name, then we want to insert the entry
933*0Sstevel@tonic-gate 			 * here.
934*0Sstevel@tonic-gate 			 */
935*0Sstevel@tonic-gate 			if ((strstr(buffer, HW_DRIVER_STRING) != NULL) &&
936*0Sstevel@tonic-gate 			    (strstr(buffer, devname) != NULL)) {
937*0Sstevel@tonic-gate 				found_package = B_TRUE;
938*0Sstevel@tonic-gate 				if (fputs(new_str, pfile_tmp) == EOF) {
939*0Sstevel@tonic-gate 					err = errno;
940*0Sstevel@tonic-gate 					cryptoerror(LOG_STDERR, gettext(
941*0Sstevel@tonic-gate 					    "failed to write to a temp file: "
942*0Sstevel@tonic-gate 					    "%s."), strerror(err));
943*0Sstevel@tonic-gate 					rc = FAILURE;
944*0Sstevel@tonic-gate 					break;
945*0Sstevel@tonic-gate 				}
946*0Sstevel@tonic-gate 			}
947*0Sstevel@tonic-gate 		} else { /* modify or delete */
948*0Sstevel@tonic-gate 			found_entry = B_FALSE;
949*0Sstevel@tonic-gate 			if (!(buffer[0] == '#' || buffer[0] == ' ' ||
950*0Sstevel@tonic-gate 			    buffer[0] == '\n'|| buffer[0] == '\t')) {
951*0Sstevel@tonic-gate 				/*
952*0Sstevel@tonic-gate 				 * Get the provider name from this line and
953*0Sstevel@tonic-gate 				 * check if this is the entry to be updated
954*0Sstevel@tonic-gate 				 * or deleted. Note: can not use "buffer"
955*0Sstevel@tonic-gate 				 * directly because strtok will change its
956*0Sstevel@tonic-gate 				 * value.
957*0Sstevel@tonic-gate 				 */
958*0Sstevel@tonic-gate 				(void) strlcpy(buffer2, buffer, BUFSIZ);
959*0Sstevel@tonic-gate 				if ((name = strtok(buffer2, SEP_COLON)) ==
960*0Sstevel@tonic-gate 				    NULL) {
961*0Sstevel@tonic-gate 					rc = FAILURE;
962*0Sstevel@tonic-gate 					break;
963*0Sstevel@tonic-gate 				}
964*0Sstevel@tonic-gate 
965*0Sstevel@tonic-gate 				if (strcmp(pent->name, name) == 0) {
966*0Sstevel@tonic-gate 					found_entry = B_TRUE;
967*0Sstevel@tonic-gate 				}
968*0Sstevel@tonic-gate 			}
969*0Sstevel@tonic-gate 
970*0Sstevel@tonic-gate 			if (found_entry && !delete_it) {
971*0Sstevel@tonic-gate 				/*
972*0Sstevel@tonic-gate 				 * This is the entry to be updated; get the
973*0Sstevel@tonic-gate 				 * updated string and place into buffer.
974*0Sstevel@tonic-gate 				 */
975*0Sstevel@tonic-gate 				if ((str = ent2str(pent)) == NULL) {
976*0Sstevel@tonic-gate 					rc = FAILURE;
977*0Sstevel@tonic-gate 					break;
978*0Sstevel@tonic-gate 				} else {
979*0Sstevel@tonic-gate 					(void) strlcpy(buffer, str, BUFSIZ);
980*0Sstevel@tonic-gate 					free(str);
981*0Sstevel@tonic-gate 				}
982*0Sstevel@tonic-gate 			}
983*0Sstevel@tonic-gate 
984*0Sstevel@tonic-gate 			if (!(found_entry && delete_it)) {
985*0Sstevel@tonic-gate 				/* This is the entry to be updated/reserved */
986*0Sstevel@tonic-gate 				if (fputs(buffer, pfile_tmp) == EOF) {
987*0Sstevel@tonic-gate 					err = errno;
988*0Sstevel@tonic-gate 					cryptoerror(LOG_STDERR, gettext(
989*0Sstevel@tonic-gate 					    "failed to write to a temp file: "
990*0Sstevel@tonic-gate 					    "%s."), strerror(err));
991*0Sstevel@tonic-gate 					rc = FAILURE;
992*0Sstevel@tonic-gate 					break;
993*0Sstevel@tonic-gate 				}
994*0Sstevel@tonic-gate 			}
995*0Sstevel@tonic-gate 		}
996*0Sstevel@tonic-gate 	}
997*0Sstevel@tonic-gate 
998*0Sstevel@tonic-gate 	if (add_it) {
999*0Sstevel@tonic-gate 		free(new_str);
1000*0Sstevel@tonic-gate 	}
1001*0Sstevel@tonic-gate 
1002*0Sstevel@tonic-gate 	if ((add_it && !found_package) || (rc == FAILURE)) {
1003*0Sstevel@tonic-gate 		if (add_it && !found_package) {
1004*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR,
1005*0Sstevel@tonic-gate 			    gettext("failed to update configuration - no "
1006*0Sstevel@tonic-gate 			    "driver package information."));
1007*0Sstevel@tonic-gate 		}
1008*0Sstevel@tonic-gate 
1009*0Sstevel@tonic-gate 		(void) fclose(pfile);
1010*0Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
1011*0Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
1012*0Sstevel@tonic-gate 			err = errno;
1013*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
1014*0Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
1015*0Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
1016*0Sstevel@tonic-gate 		}
1017*0Sstevel@tonic-gate 		return (FAILURE);
1018*0Sstevel@tonic-gate 	}
1019*0Sstevel@tonic-gate 
1020*0Sstevel@tonic-gate 	(void) fclose(pfile);
1021*0Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
1022*0Sstevel@tonic-gate 		err = errno;
1023*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
1024*0Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
1025*0Sstevel@tonic-gate 		    strerror(err));
1026*0Sstevel@tonic-gate 		return (FAILURE);
1027*0Sstevel@tonic-gate 	}
1028*0Sstevel@tonic-gate 
1029*0Sstevel@tonic-gate 	/* Copy the temporary file to the kcf.conf file */
1030*0Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
1031*0Sstevel@tonic-gate 		err = errno;
1032*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
1033*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
1034*0Sstevel@tonic-gate 		    strerror(err));
1035*0Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile,
1036*0Sstevel@tonic-gate 		    _PATH_KCF_CONF, strerror(err));
1037*0Sstevel@tonic-gate 		rc = FAILURE;
1038*0Sstevel@tonic-gate 	} else if (chmod(_PATH_KCF_CONF,
1039*0Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1040*0Sstevel@tonic-gate 		err = errno;
1041*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
1042*0Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
1043*0Sstevel@tonic-gate 		    strerror(err));
1044*0Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
1045*0Sstevel@tonic-gate 		    strerror(err));
1046*0Sstevel@tonic-gate 		rc = FAILURE;
1047*0Sstevel@tonic-gate 	} else {
1048*0Sstevel@tonic-gate 		rc = SUCCESS;
1049*0Sstevel@tonic-gate 	}
1050*0Sstevel@tonic-gate 
1051*0Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
1052*0Sstevel@tonic-gate 		err = errno;
1053*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
1054*0Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"),
1055*0Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
1056*0Sstevel@tonic-gate 	}
1057*0Sstevel@tonic-gate 
1058*0Sstevel@tonic-gate 	return (rc);
1059*0Sstevel@tonic-gate }
1060*0Sstevel@tonic-gate 
1061*0Sstevel@tonic-gate 
1062*0Sstevel@tonic-gate /*
1063*0Sstevel@tonic-gate  * Disable the mechanisms for the provider pointed by *ppent.  If allflag is
1064*0Sstevel@tonic-gate  * TRUE, disable all.  Otherwise, disable the mechanisms specified in the
1065*0Sstevel@tonic-gate  * dislist argument.  The "infolist" argument contains the mechanism list
1066*0Sstevel@tonic-gate  * supported by this provider.
1067*0Sstevel@tonic-gate  */
1068*0Sstevel@tonic-gate int
1069*0Sstevel@tonic-gate disable_mechs(entry_t **ppent, mechlist_t *infolist, boolean_t allflag,
1070*0Sstevel@tonic-gate mechlist_t *dislist)
1071*0Sstevel@tonic-gate {
1072*0Sstevel@tonic-gate 	entry_t *pent;
1073*0Sstevel@tonic-gate 	mechlist_t *plist;
1074*0Sstevel@tonic-gate 	mechlist_t *phead;
1075*0Sstevel@tonic-gate 	mechlist_t *pmech;
1076*0Sstevel@tonic-gate 	int rc = SUCCESS;
1077*0Sstevel@tonic-gate 
1078*0Sstevel@tonic-gate 	pent = *ppent;
1079*0Sstevel@tonic-gate 	if (pent == NULL) {
1080*0Sstevel@tonic-gate 		return (FAILURE);
1081*0Sstevel@tonic-gate 	}
1082*0Sstevel@tonic-gate 
1083*0Sstevel@tonic-gate 	if (allflag) {
1084*0Sstevel@tonic-gate 		free_mechlist(pent->dislist);
1085*0Sstevel@tonic-gate 		pent->dis_count = get_mech_count(infolist);
1086*0Sstevel@tonic-gate 		if (!(pent->dislist = dup_mechlist(infolist))) {
1087*0Sstevel@tonic-gate 			return (FAILURE);
1088*0Sstevel@tonic-gate 		} else {
1089*0Sstevel@tonic-gate 			return (SUCCESS);
1090*0Sstevel@tonic-gate 		}
1091*0Sstevel@tonic-gate 	}
1092*0Sstevel@tonic-gate 
1093*0Sstevel@tonic-gate 	/*
1094*0Sstevel@tonic-gate 	 * Not disable all. Now loop thru the mechanisms specified in the
1095*0Sstevel@tonic-gate 	 * dislist.  If the mechanism is not supported by the provider,
1096*0Sstevel@tonic-gate 	 * ignore it with a warning.  If the mechanism is disabled already,
1097*0Sstevel@tonic-gate 	 * do nothing. Otherwise, prepend it to the beginning of the disabled
1098*0Sstevel@tonic-gate 	 * list of the provider.
1099*0Sstevel@tonic-gate 	 */
1100*0Sstevel@tonic-gate 	plist = dislist;
1101*0Sstevel@tonic-gate 	while (plist != NULL) {
1102*0Sstevel@tonic-gate 		if (!is_in_list(plist->name, infolist)) {
1103*0Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext("(Warning) "
1104*0Sstevel@tonic-gate 			    "%1$s is not a valid mechanism for %2$s."),
1105*0Sstevel@tonic-gate 			    plist->name, pent->name);
1106*0Sstevel@tonic-gate 		} else if (!is_in_list(plist->name, pent->dislist)) {
1107*0Sstevel@tonic-gate 			/* Add this mechanism into the disabled list */
1108*0Sstevel@tonic-gate 			if ((pmech = create_mech(plist->name)) == NULL) {
1109*0Sstevel@tonic-gate 				rc = FAILURE;
1110*0Sstevel@tonic-gate 				break;
1111*0Sstevel@tonic-gate 			}
1112*0Sstevel@tonic-gate 
1113*0Sstevel@tonic-gate 			if (pent->dislist == NULL) {
1114*0Sstevel@tonic-gate 				pent->dislist = pmech;
1115*0Sstevel@tonic-gate 			} else {
1116*0Sstevel@tonic-gate 				phead = pent->dislist;
1117*0Sstevel@tonic-gate 				pent->dislist = pmech;
1118*0Sstevel@tonic-gate 				pmech->next = phead;
1119*0Sstevel@tonic-gate 			}
1120*0Sstevel@tonic-gate 			pent->dis_count++;
1121*0Sstevel@tonic-gate 		}
1122*0Sstevel@tonic-gate 		plist = plist->next;
1123*0Sstevel@tonic-gate 	}
1124*0Sstevel@tonic-gate 
1125*0Sstevel@tonic-gate 	return (rc);
1126*0Sstevel@tonic-gate }
1127*0Sstevel@tonic-gate 
1128*0Sstevel@tonic-gate /*
1129*0Sstevel@tonic-gate  * Remove the mechanism passed, specified by mech, from the list of
1130*0Sstevel@tonic-gate  * mechanisms, if present in the list. Else, do nothing.
1131*0Sstevel@tonic-gate  *
1132*0Sstevel@tonic-gate  * Returns B_TRUE if mechanism is present in the list.
1133*0Sstevel@tonic-gate  */
1134*0Sstevel@tonic-gate boolean_t
1135*0Sstevel@tonic-gate filter_mechlist(mechlist_t **pmechlist, const char *mech)
1136*0Sstevel@tonic-gate {
1137*0Sstevel@tonic-gate 	int cnt = 0;
1138*0Sstevel@tonic-gate 	mechlist_t *ptr, *pptr;
1139*0Sstevel@tonic-gate 	boolean_t mech_present = B_FALSE;
1140*0Sstevel@tonic-gate 
1141*0Sstevel@tonic-gate 	ptr = pptr = *pmechlist;
1142*0Sstevel@tonic-gate 
1143*0Sstevel@tonic-gate 	while (ptr != NULL) {
1144*0Sstevel@tonic-gate 		if (strncmp(ptr->name, mech, sizeof (mech_name_t)) == 0) {
1145*0Sstevel@tonic-gate 			mech_present = B_TRUE;
1146*0Sstevel@tonic-gate 			if (ptr == *pmechlist) {
1147*0Sstevel@tonic-gate 				pptr = *pmechlist = ptr->next;
1148*0Sstevel@tonic-gate 				free(ptr);
1149*0Sstevel@tonic-gate 				ptr = pptr;
1150*0Sstevel@tonic-gate 			} else {
1151*0Sstevel@tonic-gate 				pptr->next = ptr->next;
1152*0Sstevel@tonic-gate 				free(ptr);
1153*0Sstevel@tonic-gate 				ptr = pptr->next;
1154*0Sstevel@tonic-gate 			}
1155*0Sstevel@tonic-gate 		} else {
1156*0Sstevel@tonic-gate 			pptr = ptr;
1157*0Sstevel@tonic-gate 			ptr = ptr->next;
1158*0Sstevel@tonic-gate 			cnt++;
1159*0Sstevel@tonic-gate 		}
1160*0Sstevel@tonic-gate 	}
1161*0Sstevel@tonic-gate 
1162*0Sstevel@tonic-gate 	/* Only one entry is present */
1163*0Sstevel@tonic-gate 	if (cnt == 0)
1164*0Sstevel@tonic-gate 		*pmechlist = NULL;
1165*0Sstevel@tonic-gate 
1166*0Sstevel@tonic-gate 	return (mech_present);
1167*0Sstevel@tonic-gate }
1168*0Sstevel@tonic-gate 
1169*0Sstevel@tonic-gate 
1170*0Sstevel@tonic-gate 
1171*0Sstevel@tonic-gate /*
1172*0Sstevel@tonic-gate  * Print out the mechanism policy for a kernel provider that has an entry
1173*0Sstevel@tonic-gate  * in the kcf.conf file.
1174*0Sstevel@tonic-gate  *
1175*0Sstevel@tonic-gate  * The flag has_random is set to B_TRUE if the provider does random
1176*0Sstevel@tonic-gate  * numbers. The flag has_mechs is set by the caller to B_TRUE if the provider
1177*0Sstevel@tonic-gate  * has some mechanisms.
1178*0Sstevel@tonic-gate  */
1179*0Sstevel@tonic-gate void
1180*0Sstevel@tonic-gate print_kef_policy(entry_t *pent, boolean_t has_random, boolean_t has_mechs)
1181*0Sstevel@tonic-gate {
1182*0Sstevel@tonic-gate 	mechlist_t *ptr;
1183*0Sstevel@tonic-gate 	boolean_t rnd_disabled = B_FALSE;
1184*0Sstevel@tonic-gate 
1185*0Sstevel@tonic-gate 	if (pent == NULL) {
1186*0Sstevel@tonic-gate 		return;
1187*0Sstevel@tonic-gate 	}
1188*0Sstevel@tonic-gate 
1189*0Sstevel@tonic-gate 	rnd_disabled = filter_mechlist(&pent->dislist, RANDOM);
1190*0Sstevel@tonic-gate 	ptr = pent->dislist;
1191*0Sstevel@tonic-gate 
1192*0Sstevel@tonic-gate 	(void) printf("%s:", pent->name);
1193*0Sstevel@tonic-gate 
1194*0Sstevel@tonic-gate 	if (has_mechs == B_TRUE) {
1195*0Sstevel@tonic-gate 		/*
1196*0Sstevel@tonic-gate 		 * TRANSLATION_NOTE:
1197*0Sstevel@tonic-gate 		 * This code block may need to be modified a bit to avoid
1198*0Sstevel@tonic-gate 		 * constructing the text message on the fly.
1199*0Sstevel@tonic-gate 		 */
1200*0Sstevel@tonic-gate 		(void) printf(gettext(" all mechanisms are enabled"));
1201*0Sstevel@tonic-gate 		if (ptr != NULL)
1202*0Sstevel@tonic-gate 			(void) printf(gettext(", except "));
1203*0Sstevel@tonic-gate 		while (ptr != NULL) {
1204*0Sstevel@tonic-gate 			(void) printf("%s", ptr->name);
1205*0Sstevel@tonic-gate 			ptr = ptr->next;
1206*0Sstevel@tonic-gate 			if (ptr != NULL)
1207*0Sstevel@tonic-gate 				(void) printf(",");
1208*0Sstevel@tonic-gate 		}
1209*0Sstevel@tonic-gate 		if (ptr == NULL)
1210*0Sstevel@tonic-gate 			(void) printf(".");
1211*0Sstevel@tonic-gate 	}
1212*0Sstevel@tonic-gate 
1213*0Sstevel@tonic-gate 	/*
1214*0Sstevel@tonic-gate 	 * TRANSLATION_NOTE:
1215*0Sstevel@tonic-gate 	 * "random" is a keyword and not to be translated.
1216*0Sstevel@tonic-gate 	 */
1217*0Sstevel@tonic-gate 	if (rnd_disabled)
1218*0Sstevel@tonic-gate 		(void) printf(gettext(" %s is disabled."), "random");
1219*0Sstevel@tonic-gate 	else if (has_random)
1220*0Sstevel@tonic-gate 		(void) printf(gettext(" %s is enabled."), "random");
1221*0Sstevel@tonic-gate 	(void) printf("\n");
1222*0Sstevel@tonic-gate }
1223*0Sstevel@tonic-gate 
1224*0Sstevel@tonic-gate /*
1225*0Sstevel@tonic-gate  * Check if a kernel software provider is in the kernel.
1226*0Sstevel@tonic-gate  */
1227*0Sstevel@tonic-gate int
1228*0Sstevel@tonic-gate check_active_for_soft(char *provname, boolean_t *is_active)
1229*0Sstevel@tonic-gate {
1230*0Sstevel@tonic-gate 	crypto_get_soft_list_t	*psoftlist_kernel = NULL;
1231*0Sstevel@tonic-gate 	char	*ptr;
1232*0Sstevel@tonic-gate 	int	i;
1233*0Sstevel@tonic-gate 
1234*0Sstevel@tonic-gate 	if (provname == NULL) {
1235*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
1236*0Sstevel@tonic-gate 		return (FAILURE);
1237*0Sstevel@tonic-gate 	}
1238*0Sstevel@tonic-gate 
1239*0Sstevel@tonic-gate 	if (get_soft_list(&psoftlist_kernel) == FAILURE) {
1240*0Sstevel@tonic-gate 		cryptodebug("failed to get the software provider list from"
1241*0Sstevel@tonic-gate 		    "kernel.");
1242*0Sstevel@tonic-gate 		return (FAILURE);
1243*0Sstevel@tonic-gate 	}
1244*0Sstevel@tonic-gate 
1245*0Sstevel@tonic-gate 	*is_active = B_FALSE;
1246*0Sstevel@tonic-gate 	ptr = psoftlist_kernel->sl_soft_names;
1247*0Sstevel@tonic-gate 	for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
1248*0Sstevel@tonic-gate 		if (strcmp(provname, ptr) == 0) {
1249*0Sstevel@tonic-gate 			*is_active = B_TRUE;
1250*0Sstevel@tonic-gate 			break;
1251*0Sstevel@tonic-gate 		}
1252*0Sstevel@tonic-gate 		ptr = ptr + strlen(ptr) + 1;
1253*0Sstevel@tonic-gate 	}
1254*0Sstevel@tonic-gate 	free(psoftlist_kernel);
1255*0Sstevel@tonic-gate 
1256*0Sstevel@tonic-gate 	return (SUCCESS);
1257*0Sstevel@tonic-gate }
1258*0Sstevel@tonic-gate 
1259*0Sstevel@tonic-gate 
1260*0Sstevel@tonic-gate /*
1261*0Sstevel@tonic-gate  * Check if a kernel hardware provider is in the kernel.
1262*0Sstevel@tonic-gate  */
1263*0Sstevel@tonic-gate int
1264*0Sstevel@tonic-gate check_active_for_hard(char *provname, boolean_t *is_active)
1265*0Sstevel@tonic-gate {
1266*0Sstevel@tonic-gate 	crypto_get_dev_list_t	*pdevlist = NULL;
1267*0Sstevel@tonic-gate 	char 	devname[MAXNAMELEN];
1268*0Sstevel@tonic-gate 	int	inst_num;
1269*0Sstevel@tonic-gate 	int	i;
1270*0Sstevel@tonic-gate 
1271*0Sstevel@tonic-gate 	if (provname == NULL) {
1272*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
1273*0Sstevel@tonic-gate 		return (FAILURE);
1274*0Sstevel@tonic-gate 	}
1275*0Sstevel@tonic-gate 
1276*0Sstevel@tonic-gate 	if (split_hw_provname(provname, devname, &inst_num) == FAILURE) {
1277*0Sstevel@tonic-gate 		return (FAILURE);
1278*0Sstevel@tonic-gate 	}
1279*0Sstevel@tonic-gate 
1280*0Sstevel@tonic-gate 	if (get_dev_list(&pdevlist) == FAILURE) {
1281*0Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
1282*0Sstevel@tonic-gate 		return (FAILURE);
1283*0Sstevel@tonic-gate 	}
1284*0Sstevel@tonic-gate 
1285*0Sstevel@tonic-gate 	*is_active = B_FALSE;
1286*0Sstevel@tonic-gate 	for (i = 0; i < pdevlist->dl_dev_count; i++) {
1287*0Sstevel@tonic-gate 		if ((strcmp(pdevlist->dl_devs[i].le_dev_name, devname) == 0) &&
1288*0Sstevel@tonic-gate 		    (pdevlist->dl_devs[i].le_dev_instance == inst_num)) {
1289*0Sstevel@tonic-gate 			*is_active = B_TRUE;
1290*0Sstevel@tonic-gate 			break;
1291*0Sstevel@tonic-gate 		}
1292*0Sstevel@tonic-gate 	}
1293*0Sstevel@tonic-gate 	free(pdevlist);
1294*0Sstevel@tonic-gate 
1295*0Sstevel@tonic-gate 	return (SUCCESS);
1296*0Sstevel@tonic-gate }
1297