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 2004 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 <stdio.h>
30*0Sstevel@tonic-gate #include <errno.h>
31*0Sstevel@tonic-gate #include <strings.h>
32*0Sstevel@tonic-gate #include <locale.h>
33*0Sstevel@tonic-gate #include <stdlib.h>
34*0Sstevel@tonic-gate #include "cryptoutil.h"
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate static int uef_interpret(char *, uentry_t **);
37*0Sstevel@tonic-gate static int parse_policylist(char *, uentry_t *);
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate /*
40*0Sstevel@tonic-gate  * Retrieve the user-level provider info from the pkcs11.conf file.
41*0Sstevel@tonic-gate  * If successful, the result is returned from the ppliblist argument.
42*0Sstevel@tonic-gate  * This function returns SUCCESS if successfully done; otherwise it returns
43*0Sstevel@tonic-gate  * FAILURE.
44*0Sstevel@tonic-gate  */
45*0Sstevel@tonic-gate int
46*0Sstevel@tonic-gate get_pkcs11conf_info(uentrylist_t **ppliblist)
47*0Sstevel@tonic-gate {
48*0Sstevel@tonic-gate 	FILE *pfile;
49*0Sstevel@tonic-gate 	char buffer[BUFSIZ];
50*0Sstevel@tonic-gate 	size_t len;
51*0Sstevel@tonic-gate 	uentry_t *pent;
52*0Sstevel@tonic-gate 	uentrylist_t *pentlist;
53*0Sstevel@tonic-gate 	uentrylist_t *pcur;
54*0Sstevel@tonic-gate 	int rc = SUCCESS;
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate 	*ppliblist = NULL;
57*0Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_PKCS11_CONF, "r")) == NULL) {
58*0Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_PKCS11_CONF);
59*0Sstevel@tonic-gate 		return (FAILURE);
60*0Sstevel@tonic-gate 	}
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
63*0Sstevel@tonic-gate 		if (buffer[0] == '#' || buffer[0] == ' ' ||
64*0Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t') {
65*0Sstevel@tonic-gate 			continue;   /* ignore comment lines */
66*0Sstevel@tonic-gate 		}
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate 		len = strlen(buffer);
69*0Sstevel@tonic-gate 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
70*0Sstevel@tonic-gate 			len--;
71*0Sstevel@tonic-gate 		}
72*0Sstevel@tonic-gate 		buffer[len] = '\0';
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 		if ((rc = uef_interpret(buffer,  &pent)) != SUCCESS) {
75*0Sstevel@tonic-gate 			break;
76*0Sstevel@tonic-gate 		}
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 		/* append pent into ppliblist */
79*0Sstevel@tonic-gate 		pentlist = malloc(sizeof (uentrylist_t));
80*0Sstevel@tonic-gate 		if (pentlist == NULL) {
81*0Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
82*0Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
83*0Sstevel@tonic-gate 			free_uentry(pent);
84*0Sstevel@tonic-gate 			rc = FAILURE;
85*0Sstevel@tonic-gate 			break;
86*0Sstevel@tonic-gate 		}
87*0Sstevel@tonic-gate 		pentlist->puent = pent;
88*0Sstevel@tonic-gate 		pentlist->next = NULL;
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 		if (*ppliblist == NULL) {
91*0Sstevel@tonic-gate 			*ppliblist = pcur = pentlist;
92*0Sstevel@tonic-gate 		} else {
93*0Sstevel@tonic-gate 			pcur->next = pentlist;
94*0Sstevel@tonic-gate 			pcur = pcur->next;
95*0Sstevel@tonic-gate 		}
96*0Sstevel@tonic-gate 	}
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 	(void) fclose(pfile);
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 	if (rc != SUCCESS) {
101*0Sstevel@tonic-gate 		free_uentrylist(*ppliblist);
102*0Sstevel@tonic-gate 		*ppliblist = NULL;
103*0Sstevel@tonic-gate 	}
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate 	return (rc);
106*0Sstevel@tonic-gate }
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate /*
110*0Sstevel@tonic-gate  * This routine converts a char string into a uentry_t structure
111*0Sstevel@tonic-gate  * The input string "buf" should be one of the following:
112*0Sstevel@tonic-gate  *	library_name
113*0Sstevel@tonic-gate  *	library_name:NO_RANDOM
114*0Sstevel@tonic-gate  *	library_name:disabledlist=m1,m2,...,mk
115*0Sstevel@tonic-gate  *	library_name:disabledlist=m1,m2,...,mk;NO_RANDOM
116*0Sstevel@tonic-gate  *	library_name:enabledlist=
117*0Sstevel@tonic-gate  *	library_name:enabledlist=;NO_RANDOM
118*0Sstevel@tonic-gate  *	library_name:enabledlist=m1,m2,...,mk
119*0Sstevel@tonic-gate  *	library_name:enabledlist=m1,m2,...,mk;NO_RANDOM
120*0Sstevel@tonic-gate  *	metaslot:status=enabled;enabledlist=m1,m2,....;slot=<slot-description>;\
121*0Sstevel@tonic-gate  *	token=<token-label>
122*0Sstevel@tonic-gate  *
123*0Sstevel@tonic-gate  * Note:
124*0Sstevel@tonic-gate  *	The mechanisms m1,..mk are in hex form. For example, "0x00000210"
125*0Sstevel@tonic-gate  *	for CKM_MD5.
126*0Sstevel@tonic-gate  *
127*0Sstevel@tonic-gate  *	For the metaslot entry, "enabledlist", "slot", "auto_key_migrate"
128*0Sstevel@tonic-gate  * 	or "token" is optional
129*0Sstevel@tonic-gate  */
130*0Sstevel@tonic-gate static int
131*0Sstevel@tonic-gate uef_interpret(char *buf, uentry_t **ppent)
132*0Sstevel@tonic-gate {
133*0Sstevel@tonic-gate 	uentry_t *pent;
134*0Sstevel@tonic-gate 	char	*token1;
135*0Sstevel@tonic-gate 	char	*token2;
136*0Sstevel@tonic-gate 	char	*lasts;
137*0Sstevel@tonic-gate 	int	rc;
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	*ppent = NULL;
140*0Sstevel@tonic-gate 	if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) {
141*0Sstevel@tonic-gate 		/* buf is NULL */
142*0Sstevel@tonic-gate 		return (FAILURE);
143*0Sstevel@tonic-gate 	};
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 	pent = calloc(sizeof (uentry_t), 1);
146*0Sstevel@tonic-gate 	if (pent == NULL) {
147*0Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
148*0Sstevel@tonic-gate 		    _PATH_PKCS11_CONF);
149*0Sstevel@tonic-gate 		return (FAILURE);
150*0Sstevel@tonic-gate 	}
151*0Sstevel@tonic-gate 	(void) strlcpy(pent->name, token1, sizeof (pent->name));
152*0Sstevel@tonic-gate 	/*
153*0Sstevel@tonic-gate 	 * in case metaslot_auto_key_migrate is not specified, it should
154*0Sstevel@tonic-gate 	 * be default to true
155*0Sstevel@tonic-gate 	 */
156*0Sstevel@tonic-gate 	pent->flag_metaslot_auto_key_migrate = B_TRUE;
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	while ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) != NULL) {
159*0Sstevel@tonic-gate 		if ((rc = parse_policylist(token2, pent)) != SUCCESS) {
160*0Sstevel@tonic-gate 			free_uentry(pent);
161*0Sstevel@tonic-gate 			return (rc);
162*0Sstevel@tonic-gate 		}
163*0Sstevel@tonic-gate 	}
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate 	*ppent = pent;
166*0Sstevel@tonic-gate 	return (SUCCESS);
167*0Sstevel@tonic-gate }
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate /*
171*0Sstevel@tonic-gate  * This routine parses the policy list and stored the result in the argument
172*0Sstevel@tonic-gate  * pent.
173*0Sstevel@tonic-gate  *
174*0Sstevel@tonic-gate  * 	Arg buf: input only, its format should be one of the following:
175*0Sstevel@tonic-gate  *     		enabledlist=
176*0Sstevel@tonic-gate  *		enabledlist=m1,m2,...,mk
177*0Sstevel@tonic-gate  *		disabledlist=m1,m2,...,mk
178*0Sstevel@tonic-gate  *		NO_RANDOM
179*0Sstevel@tonic-gate  *		metaslot_status=enabled|disabled
180*0Sstevel@tonic-gate  *		metaslot_token=<token-label>
181*0Sstevel@tonic-gate  *		metaslot_slot=<slot-description.
182*0Sstevel@tonic-gate  *
183*0Sstevel@tonic-gate  *	Arg pent: input/output
184*0Sstevel@tonic-gate  *
185*0Sstevel@tonic-gate  *      return: SUCCESS or FAILURE
186*0Sstevel@tonic-gate  */
187*0Sstevel@tonic-gate static int
188*0Sstevel@tonic-gate parse_policylist(char *buf, uentry_t *pent)
189*0Sstevel@tonic-gate {
190*0Sstevel@tonic-gate 	umechlist_t *phead = NULL;
191*0Sstevel@tonic-gate 	umechlist_t *pcur = NULL;
192*0Sstevel@tonic-gate 	umechlist_t *pmech;
193*0Sstevel@tonic-gate 	char *next_token;
194*0Sstevel@tonic-gate 	char *value;
195*0Sstevel@tonic-gate 	char *lasts;
196*0Sstevel@tonic-gate 	int count = 0;
197*0Sstevel@tonic-gate 	int rc = SUCCESS;
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 	if (pent == NULL) {
200*0Sstevel@tonic-gate 		return (FAILURE);
201*0Sstevel@tonic-gate 	}
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 	if (strncmp(buf, EF_DISABLED, sizeof (EF_DISABLED) - 1) == 0) {
204*0Sstevel@tonic-gate 		pent->flag_enabledlist = B_FALSE;
205*0Sstevel@tonic-gate 	} else if (strncmp(buf, EF_ENABLED, sizeof (EF_ENABLED) - 1) == 0) {
206*0Sstevel@tonic-gate 		pent->flag_enabledlist = B_TRUE;
207*0Sstevel@tonic-gate 	} else if (strncmp(buf, EF_NORANDOM, sizeof (EF_NORANDOM) - 1) == 0) {
208*0Sstevel@tonic-gate 		pent->flag_norandom = B_TRUE;
209*0Sstevel@tonic-gate 		return (rc);
210*0Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_TOKEN,
211*0Sstevel@tonic-gate 	    sizeof (METASLOT_TOKEN) - 1) == 0) {
212*0Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
213*0Sstevel@tonic-gate 			value++; /* get rid of = */
214*0Sstevel@tonic-gate 			(void) strlcpy((char *)pent->metaslot_ks_token, value,
215*0Sstevel@tonic-gate 			    TOKEN_LABEL_SIZE);
216*0Sstevel@tonic-gate 			return (SUCCESS);
217*0Sstevel@tonic-gate 		} else {
218*0Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
219*0Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
220*0Sstevel@tonic-gate 			return (FAILURE);
221*0Sstevel@tonic-gate 		}
222*0Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_SLOT,
223*0Sstevel@tonic-gate 	    sizeof (METASLOT_SLOT) - 1) == 0) {
224*0Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
225*0Sstevel@tonic-gate 			value++; /* get rid of = */
226*0Sstevel@tonic-gate 			(void) strlcpy((char *)pent->metaslot_ks_slot, value,
227*0Sstevel@tonic-gate 			    SLOT_DESCRIPTION_SIZE);
228*0Sstevel@tonic-gate 			return (SUCCESS);
229*0Sstevel@tonic-gate 		} else {
230*0Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
231*0Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
232*0Sstevel@tonic-gate 			return (FAILURE);
233*0Sstevel@tonic-gate 		}
234*0Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_STATUS,
235*0Sstevel@tonic-gate 	    sizeof (METASLOT_STATUS) - 1) == 0) {
236*0Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
237*0Sstevel@tonic-gate 			value++; /* get rid of = */
238*0Sstevel@tonic-gate 			if (strcmp(value, METASLOT_DISABLED) == 0) {
239*0Sstevel@tonic-gate 				pent->flag_metaslot_enabled = B_FALSE;
240*0Sstevel@tonic-gate 			} else if (strcmp(value, METASLOT_ENABLED) == 0) {
241*0Sstevel@tonic-gate 				pent->flag_metaslot_enabled = B_TRUE;
242*0Sstevel@tonic-gate 			} else {
243*0Sstevel@tonic-gate 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
244*0Sstevel@tonic-gate 				    _PATH_PKCS11_CONF);
245*0Sstevel@tonic-gate 				return (FAILURE);
246*0Sstevel@tonic-gate 			}
247*0Sstevel@tonic-gate 			return (SUCCESS);
248*0Sstevel@tonic-gate 		} else {
249*0Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
250*0Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
251*0Sstevel@tonic-gate 			return (FAILURE);
252*0Sstevel@tonic-gate 		}
253*0Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_AUTO_KEY_MIGRATE,
254*0Sstevel@tonic-gate 	    sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) {
255*0Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
256*0Sstevel@tonic-gate 			value++; /* get rid of = */
257*0Sstevel@tonic-gate 			if (strcmp(value, METASLOT_DISABLED) == 0) {
258*0Sstevel@tonic-gate 				pent->flag_metaslot_auto_key_migrate = B_FALSE;
259*0Sstevel@tonic-gate 			} else if (strcmp(value, METASLOT_ENABLED) == 0) {
260*0Sstevel@tonic-gate 				pent->flag_metaslot_auto_key_migrate = B_TRUE;
261*0Sstevel@tonic-gate 			} else {
262*0Sstevel@tonic-gate 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
263*0Sstevel@tonic-gate 				    _PATH_PKCS11_CONF);
264*0Sstevel@tonic-gate 				return (FAILURE);
265*0Sstevel@tonic-gate 			}
266*0Sstevel@tonic-gate 			return (SUCCESS);
267*0Sstevel@tonic-gate 		} else {
268*0Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
269*0Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
270*0Sstevel@tonic-gate 			return (FAILURE);
271*0Sstevel@tonic-gate 		}
272*0Sstevel@tonic-gate 	} else {
273*0Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to parse %s.\n",
274*0Sstevel@tonic-gate 		    _PATH_PKCS11_CONF);
275*0Sstevel@tonic-gate 		return (FAILURE);
276*0Sstevel@tonic-gate 	}
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate 	if (value = strpbrk(buf, SEP_EQUAL)) {
279*0Sstevel@tonic-gate 		value++; /* get rid of = */
280*0Sstevel@tonic-gate 	}
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	if ((next_token = strtok_r(value, SEP_COMMA, &lasts)) == NULL) {
283*0Sstevel@tonic-gate 		if (pent->flag_enabledlist) {
284*0Sstevel@tonic-gate 			return (SUCCESS);
285*0Sstevel@tonic-gate 		} else {
286*0Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
287*0Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
288*0Sstevel@tonic-gate 			return (FAILURE);
289*0Sstevel@tonic-gate 		}
290*0Sstevel@tonic-gate 	}
291*0Sstevel@tonic-gate 
292*0Sstevel@tonic-gate 	while (next_token) {
293*0Sstevel@tonic-gate 		if ((pmech = create_umech(next_token)) == NULL) {
294*0Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
295*0Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
296*0Sstevel@tonic-gate 			rc = FAILURE;
297*0Sstevel@tonic-gate 			break;
298*0Sstevel@tonic-gate 		}
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 		if (phead == NULL) {
301*0Sstevel@tonic-gate 			phead = pcur = pmech;
302*0Sstevel@tonic-gate 		} else {
303*0Sstevel@tonic-gate 			pcur->next = pmech;
304*0Sstevel@tonic-gate 			pcur = pcur->next;
305*0Sstevel@tonic-gate 		}
306*0Sstevel@tonic-gate 		count++;
307*0Sstevel@tonic-gate 		next_token = strtok_r(NULL, SEP_COMMA, &lasts);
308*0Sstevel@tonic-gate 	}
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate 	if (rc == SUCCESS) {
311*0Sstevel@tonic-gate 		pent->policylist = phead;
312*0Sstevel@tonic-gate 		pent->count = count;
313*0Sstevel@tonic-gate 	} else {
314*0Sstevel@tonic-gate 		free_umechlist(phead);
315*0Sstevel@tonic-gate 	}
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	return (rc);
318*0Sstevel@tonic-gate }
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate /*
322*0Sstevel@tonic-gate  * Create one item of type umechlist_t with the mechanism name.  A NULL is
323*0Sstevel@tonic-gate  * returned when the input name is NULL or the heap memory is insufficient.
324*0Sstevel@tonic-gate  */
325*0Sstevel@tonic-gate umechlist_t *
326*0Sstevel@tonic-gate create_umech(char *name)
327*0Sstevel@tonic-gate {
328*0Sstevel@tonic-gate 	umechlist_t *pmech = NULL;
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 	if (name == NULL) {
331*0Sstevel@tonic-gate 		return (NULL);
332*0Sstevel@tonic-gate 	}
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 	if ((pmech = malloc(sizeof (umechlist_t))) != NULL) {
335*0Sstevel@tonic-gate 		(void) strlcpy(pmech->name, name, sizeof (pmech->name));
336*0Sstevel@tonic-gate 		pmech->next = NULL;
337*0Sstevel@tonic-gate 	}
338*0Sstevel@tonic-gate 
339*0Sstevel@tonic-gate 	return (pmech);
340*0Sstevel@tonic-gate }
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate void
344*0Sstevel@tonic-gate free_umechlist(umechlist_t *plist)
345*0Sstevel@tonic-gate {
346*0Sstevel@tonic-gate 	umechlist_t *pnext;
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	while (plist != NULL) {
349*0Sstevel@tonic-gate 		pnext = plist->next;
350*0Sstevel@tonic-gate 		free(plist);
351*0Sstevel@tonic-gate 		plist = pnext;
352*0Sstevel@tonic-gate 	}
353*0Sstevel@tonic-gate }
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate void
357*0Sstevel@tonic-gate free_uentry(uentry_t  *pent)
358*0Sstevel@tonic-gate {
359*0Sstevel@tonic-gate 	if (pent == NULL) {
360*0Sstevel@tonic-gate 		return;
361*0Sstevel@tonic-gate 	} else {
362*0Sstevel@tonic-gate 		free_umechlist(pent->policylist);
363*0Sstevel@tonic-gate 		free(pent);
364*0Sstevel@tonic-gate 	}
365*0Sstevel@tonic-gate }
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate void
369*0Sstevel@tonic-gate free_uentrylist(uentrylist_t *entrylist)
370*0Sstevel@tonic-gate {
371*0Sstevel@tonic-gate 	uentrylist_t *pnext;
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	while (entrylist != NULL) {
374*0Sstevel@tonic-gate 		pnext = entrylist->next;
375*0Sstevel@tonic-gate 		free_uentry(entrylist->puent);
376*0Sstevel@tonic-gate 		free(entrylist);
377*0Sstevel@tonic-gate 		entrylist = pnext;
378*0Sstevel@tonic-gate 	}
379*0Sstevel@tonic-gate }
380