17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50a85b835SDaniel Anderson  * Common Development and Distribution License (the "License").
60a85b835SDaniel Anderson  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22ddcb6370SDan OpenSolaris Anderson  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <errno.h>
277c478bd9Sstevel@tonic-gate #include <fcntl.h>
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <strings.h>
317c478bd9Sstevel@tonic-gate #include <time.h>
327c478bd9Sstevel@tonic-gate #include <unistd.h>
337c478bd9Sstevel@tonic-gate #include <locale.h>
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
351b22764fSDaniel OpenSolaris Anderson #include <zone.h>
367c478bd9Sstevel@tonic-gate #include <sys/stat.h>
377c478bd9Sstevel@tonic-gate #include "cryptoadm.h"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate static int err; /* To store errno which may be overwritten by gettext() */
40*0f5cc0e1SDan OpenSolaris Anderson static int build_entrylist(entry_t *pent, entrylist_t **pplist);
41*0f5cc0e1SDan OpenSolaris Anderson static entry_t *dup_entry(entry_t *pent1);
42*0f5cc0e1SDan OpenSolaris Anderson static mechlist_t *dup_mechlist(mechlist_t *plist);
43*0f5cc0e1SDan OpenSolaris Anderson static entry_t *getent(char *provname, entrylist_t *entrylist);
44*0f5cc0e1SDan OpenSolaris Anderson static int interpret(char *buf, entry_t **ppent);
45ddcb6370SDan OpenSolaris Anderson static int parse_sup_dis_list(const char *buf, entry_t *pent);
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /*
497c478bd9Sstevel@tonic-gate  * Duplicate the mechanism list.  A null pointer is returned if the storage
507c478bd9Sstevel@tonic-gate  * space available is insufficient or the input argument is NULL.
517c478bd9Sstevel@tonic-gate  */
527c478bd9Sstevel@tonic-gate static mechlist_t *
dup_mechlist(mechlist_t * plist)537c478bd9Sstevel@tonic-gate dup_mechlist(mechlist_t *plist)
547c478bd9Sstevel@tonic-gate {
551b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pres = NULL;
561b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pcur;
571b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*ptmp;
581b22764fSDaniel OpenSolaris Anderson 	int		rc = SUCCESS;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 	while (plist != NULL) {
617c478bd9Sstevel@tonic-gate 		if (!(ptmp = create_mech(plist->name))) {
627c478bd9Sstevel@tonic-gate 			rc = FAILURE;
637c478bd9Sstevel@tonic-gate 			break;
647c478bd9Sstevel@tonic-gate 		}
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 		if (pres == NULL) {
677c478bd9Sstevel@tonic-gate 			pres = pcur = ptmp;
687c478bd9Sstevel@tonic-gate 		} else {
697c478bd9Sstevel@tonic-gate 			pcur->next = ptmp;
707c478bd9Sstevel@tonic-gate 			pcur = pcur->next;
717c478bd9Sstevel@tonic-gate 		}
727c478bd9Sstevel@tonic-gate 		plist = plist->next;
737c478bd9Sstevel@tonic-gate 	}
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	if (rc != SUCCESS) {
767c478bd9Sstevel@tonic-gate 		free_mechlist(pres);
777c478bd9Sstevel@tonic-gate 		return (NULL);
787c478bd9Sstevel@tonic-gate 	}
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	return (pres);
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * Get the number of mechanisms in the mechanism list.
867c478bd9Sstevel@tonic-gate  */
877c478bd9Sstevel@tonic-gate int
get_mech_count(mechlist_t * plist)887c478bd9Sstevel@tonic-gate get_mech_count(mechlist_t *plist)
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate 	int count = 0;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	while (plist != NULL) {
937c478bd9Sstevel@tonic-gate 		count++;
947c478bd9Sstevel@tonic-gate 		plist = plist->next;
957c478bd9Sstevel@tonic-gate 	}
967c478bd9Sstevel@tonic-gate 	return (count);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate 
991b22764fSDaniel OpenSolaris Anderson /*
1001b22764fSDaniel OpenSolaris Anderson  * Create one item of type entry_t with the provider name.
1011b22764fSDaniel OpenSolaris Anderson  * Return NULL if there's not enough memory or provname is NULL.
1021b22764fSDaniel OpenSolaris Anderson  */
1031b22764fSDaniel OpenSolaris Anderson entry_t *
create_entry(char * provname)1041b22764fSDaniel OpenSolaris Anderson create_entry(char *provname)
1051b22764fSDaniel OpenSolaris Anderson {
1061b22764fSDaniel OpenSolaris Anderson 	entry_t		*pent = NULL;
1071b22764fSDaniel OpenSolaris Anderson 
1081b22764fSDaniel OpenSolaris Anderson 	if (provname == NULL) {
1091b22764fSDaniel OpenSolaris Anderson 		return (NULL);
1101b22764fSDaniel OpenSolaris Anderson 	}
1111b22764fSDaniel OpenSolaris Anderson 
1121b22764fSDaniel OpenSolaris Anderson 	pent = calloc(1, sizeof (entry_t));
1131b22764fSDaniel OpenSolaris Anderson 	if (pent == NULL) {
1141b22764fSDaniel OpenSolaris Anderson 		cryptodebug("out of memory.");
1151b22764fSDaniel OpenSolaris Anderson 		return (NULL);
1161b22764fSDaniel OpenSolaris Anderson 	}
1171b22764fSDaniel OpenSolaris Anderson 
1181b22764fSDaniel OpenSolaris Anderson 	(void) strlcpy(pent->name, provname, MAXNAMELEN);
1191b22764fSDaniel OpenSolaris Anderson 	pent->suplist = NULL;
1201b22764fSDaniel OpenSolaris Anderson 	pent->sup_count = 0;
1211b22764fSDaniel OpenSolaris Anderson 	pent->dislist = NULL;
1221b22764fSDaniel OpenSolaris Anderson 	pent->dis_count = 0;
1231b22764fSDaniel OpenSolaris Anderson 	pent->load = B_TRUE;
1241b22764fSDaniel OpenSolaris Anderson 
1251b22764fSDaniel OpenSolaris Anderson 	return (pent);
1261b22764fSDaniel OpenSolaris Anderson }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate /*
1291b22764fSDaniel OpenSolaris Anderson  * Duplicate an entry for a provider from kcf.conf.
1301b22764fSDaniel OpenSolaris Anderson  * Return NULL if memory is insufficient or the input argument is NULL.
1311b22764fSDaniel OpenSolaris Anderson  * Called by getent().
1327c478bd9Sstevel@tonic-gate  */
1337c478bd9Sstevel@tonic-gate static entry_t *
dup_entry(entry_t * pent1)1347c478bd9Sstevel@tonic-gate dup_entry(entry_t *pent1)
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	entry_t	*pent2 = NULL;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	if (pent1 == NULL) {
1397c478bd9Sstevel@tonic-gate 		return (NULL);
1407c478bd9Sstevel@tonic-gate 	}
1417c478bd9Sstevel@tonic-gate 
1421b22764fSDaniel OpenSolaris Anderson 	if ((pent2 = create_entry(pent1->name)) == NULL) {
1437c478bd9Sstevel@tonic-gate 		cryptodebug("out of memory.");
1447c478bd9Sstevel@tonic-gate 		return (NULL);
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	pent2->sup_count = pent1->sup_count;
1487c478bd9Sstevel@tonic-gate 	pent2->dis_count = pent1->dis_count;
1491b22764fSDaniel OpenSolaris Anderson 	pent2->load = pent1->load;
1507c478bd9Sstevel@tonic-gate 	if (pent1->suplist != NULL) {
1517c478bd9Sstevel@tonic-gate 		pent2->suplist = dup_mechlist(pent1->suplist);
1527c478bd9Sstevel@tonic-gate 		if (pent2->suplist == NULL) {
1537c478bd9Sstevel@tonic-gate 			free_entry(pent2);
1547c478bd9Sstevel@tonic-gate 			return (NULL);
1557c478bd9Sstevel@tonic-gate 		}
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 	if (pent1->dislist != NULL) {
1587c478bd9Sstevel@tonic-gate 		pent2->dislist = dup_mechlist(pent1->dislist);
1597c478bd9Sstevel@tonic-gate 		if (pent2->dislist == NULL) {
1607c478bd9Sstevel@tonic-gate 			free_entry(pent2);
1617c478bd9Sstevel@tonic-gate 			return (NULL);
1627c478bd9Sstevel@tonic-gate 		}
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	return (pent2);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate /*
1707c478bd9Sstevel@tonic-gate  * This routine parses the disabledlist or the supportedlist of an entry
1717c478bd9Sstevel@tonic-gate  * in the kcf.conf configuration file.
1727c478bd9Sstevel@tonic-gate  *
1737c478bd9Sstevel@tonic-gate  * Arguments:
1741b22764fSDaniel OpenSolaris Anderson  *	buf: an input argument which is a char string with the format of
1757c478bd9Sstevel@tonic-gate  *	     "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
1767c478bd9Sstevel@tonic-gate  *	pent: the entry for the disabledlist.  This is an IN/OUT argument.
1777c478bd9Sstevel@tonic-gate  *
1787c478bd9Sstevel@tonic-gate  * Return value: SUCCESS or FAILURE.
1797c478bd9Sstevel@tonic-gate  */
1807c478bd9Sstevel@tonic-gate static int
parse_sup_dis_list(const char * buf,entry_t * pent)181ddcb6370SDan OpenSolaris Anderson parse_sup_dis_list(const char *buf, entry_t *pent)
1827c478bd9Sstevel@tonic-gate {
1831b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pmech = NULL;
1841b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*phead = NULL;
1851b22764fSDaniel OpenSolaris Anderson 	char		*next_token;
1861b22764fSDaniel OpenSolaris Anderson 	char		*value;
1871b22764fSDaniel OpenSolaris Anderson 	int		count;
1881b22764fSDaniel OpenSolaris Anderson 	int		supflag = B_FALSE;
1891b22764fSDaniel OpenSolaris Anderson 	int		disflag = B_FALSE;
1901b22764fSDaniel OpenSolaris Anderson 	int		rc = SUCCESS;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	if (strncmp(buf, EF_SUPPORTED, strlen(EF_SUPPORTED)) == 0) {
1937c478bd9Sstevel@tonic-gate 		supflag = B_TRUE;
1947c478bd9Sstevel@tonic-gate 	} else if (strncmp(buf, EF_DISABLED, strlen(EF_DISABLED)) == 0) {
1957c478bd9Sstevel@tonic-gate 		disflag = B_TRUE;
1967c478bd9Sstevel@tonic-gate 	} else {
1977c478bd9Sstevel@tonic-gate 		/* should not come here */
1987c478bd9Sstevel@tonic-gate 		return (FAILURE);
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	if (value = strpbrk(buf, SEP_EQUAL)) {
2027c478bd9Sstevel@tonic-gate 		value++; /* get rid of = */
2037c478bd9Sstevel@tonic-gate 	} else {
2047c478bd9Sstevel@tonic-gate 		cryptodebug("failed to parse the kcf.conf file.");
2057c478bd9Sstevel@tonic-gate 		return (FAILURE);
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	if ((next_token = strtok(value, SEP_COMMA)) == NULL) {
2097c478bd9Sstevel@tonic-gate 		cryptodebug("failed to parse the kcf.conf file.");
2107c478bd9Sstevel@tonic-gate 		return (FAILURE);
2117c478bd9Sstevel@tonic-gate 	}
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	if ((pmech = create_mech(next_token)) == NULL) {
2147c478bd9Sstevel@tonic-gate 		return (FAILURE);
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	if (supflag) {
218ddcb6370SDan OpenSolaris Anderson 			if (pent->suplist != NULL) {
219ddcb6370SDan OpenSolaris Anderson 				cryptodebug("multiple supportedlist entries "
220ddcb6370SDan OpenSolaris Anderson 				    "for a mechanism in file kcf.conf.");
221ddcb6370SDan OpenSolaris Anderson 				return (FAILURE);
222ddcb6370SDan OpenSolaris Anderson 			} else {
223ddcb6370SDan OpenSolaris Anderson 				pent->suplist = phead = pmech;
224ddcb6370SDan OpenSolaris Anderson 			}
2257c478bd9Sstevel@tonic-gate 	} else if (disflag) {
226ddcb6370SDan OpenSolaris Anderson 			if (pent->dislist != NULL) {
227ddcb6370SDan OpenSolaris Anderson 				cryptodebug("multiple disabledlist entries "
228ddcb6370SDan OpenSolaris Anderson 				    "for a mechanism in file kcf.conf.");
229ddcb6370SDan OpenSolaris Anderson 				return (FAILURE);
230ddcb6370SDan OpenSolaris Anderson 			} else {
231ddcb6370SDan OpenSolaris Anderson 				pent->dislist = phead = pmech;
232ddcb6370SDan OpenSolaris Anderson 			}
2337c478bd9Sstevel@tonic-gate 	}
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	count = 1;
2367c478bd9Sstevel@tonic-gate 	while (next_token) {
2377c478bd9Sstevel@tonic-gate 		if (next_token = strtok(NULL, SEP_COMMA)) {
2387c478bd9Sstevel@tonic-gate 			if ((pmech = create_mech(next_token)) == NULL) {
2397c478bd9Sstevel@tonic-gate 				rc = FAILURE;
2407c478bd9Sstevel@tonic-gate 				break;
2417c478bd9Sstevel@tonic-gate 			}
2427c478bd9Sstevel@tonic-gate 			count++;
2437c478bd9Sstevel@tonic-gate 			phead->next = pmech;
2447c478bd9Sstevel@tonic-gate 			phead = phead->next;
2457c478bd9Sstevel@tonic-gate 		}
2467c478bd9Sstevel@tonic-gate 	}
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	if (rc == SUCCESS) {
2497c478bd9Sstevel@tonic-gate 		if (supflag) {
2507c478bd9Sstevel@tonic-gate 			pent->sup_count = count;
2517c478bd9Sstevel@tonic-gate 		} else if (disflag) {
2527c478bd9Sstevel@tonic-gate 			pent->dis_count = count;
2537c478bd9Sstevel@tonic-gate 		}
2547c478bd9Sstevel@tonic-gate 	} else {
2557c478bd9Sstevel@tonic-gate 		free_mechlist(phead);
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	return (rc);
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate /*
2631b22764fSDaniel OpenSolaris Anderson  * Convert a char string containing a line about a provider
2641b22764fSDaniel OpenSolaris Anderson  * from kcf.conf into an entry_t structure.
2651b22764fSDaniel OpenSolaris Anderson  *
266ddcb6370SDan OpenSolaris Anderson  * Note: the input string, buf, may be modified by this function.
267ddcb6370SDan OpenSolaris Anderson  *
2681b22764fSDaniel OpenSolaris Anderson  * See ent2str(), the reverse of this function, for the format of
2691b22764fSDaniel OpenSolaris Anderson  * kcf.conf lines.
2707c478bd9Sstevel@tonic-gate  */
2717c478bd9Sstevel@tonic-gate static int
interpret(char * buf,entry_t ** ppent)2727c478bd9Sstevel@tonic-gate interpret(char *buf, entry_t **ppent)
2737c478bd9Sstevel@tonic-gate {
2741b22764fSDaniel OpenSolaris Anderson 	entry_t	*pent = NULL;
2751b22764fSDaniel OpenSolaris Anderson 	char	*token1;
2761b22764fSDaniel OpenSolaris Anderson 	char	*token2;
2771b22764fSDaniel OpenSolaris Anderson 	char	*token3;
2781b22764fSDaniel OpenSolaris Anderson 	int	rc;
2797c478bd9Sstevel@tonic-gate 
2801b22764fSDaniel OpenSolaris Anderson 	/* Get provider name */
2817c478bd9Sstevel@tonic-gate 	if ((token1 = strtok(buf, SEP_COLON)) == NULL) { /* buf is NULL */
2827c478bd9Sstevel@tonic-gate 		return (FAILURE);
2837c478bd9Sstevel@tonic-gate 	};
2847c478bd9Sstevel@tonic-gate 
2851b22764fSDaniel OpenSolaris Anderson 	pent = create_entry(token1);
2867c478bd9Sstevel@tonic-gate 	if (pent == NULL) {
2877c478bd9Sstevel@tonic-gate 		cryptodebug("out of memory.");
2887c478bd9Sstevel@tonic-gate 		return (FAILURE);
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
2927c478bd9Sstevel@tonic-gate 		/* The entry contains a provider name only */
2937c478bd9Sstevel@tonic-gate 		free_entry(pent);
2947c478bd9Sstevel@tonic-gate 		return (FAILURE);
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 
2971b22764fSDaniel OpenSolaris Anderson 	if (strncmp(token2, EF_UNLOAD, strlen(EF_UNLOAD)) == 0) {
2981b22764fSDaniel OpenSolaris Anderson 		pent->load = B_FALSE; /* cryptoadm unload */
299ddcb6370SDan OpenSolaris Anderson 		token2 = strtok(NULL, SEP_SEMICOLON);
300ddcb6370SDan OpenSolaris Anderson 		/*
301ddcb6370SDan OpenSolaris Anderson 		 * If token2 is NULL, the entry contains a
302ddcb6370SDan OpenSolaris Anderson 		 * provider name:unload only
303ddcb6370SDan OpenSolaris Anderson 		 */
3041b22764fSDaniel OpenSolaris Anderson 	}
3051b22764fSDaniel OpenSolaris Anderson 
306ddcb6370SDan OpenSolaris Anderson 	if (token2 != NULL) {
307ddcb6370SDan OpenSolaris Anderson 		/*
308ddcb6370SDan OpenSolaris Anderson 		 * Either supportedlist or disabledlist or both are present.
309ddcb6370SDan OpenSolaris Anderson 		 * Need to call strtok() to get token3 first, as function
310ddcb6370SDan OpenSolaris Anderson 		 * parse_sup_dis_list() makes strtok() calls on the
311ddcb6370SDan OpenSolaris Anderson 		 * token2 substring.
312ddcb6370SDan OpenSolaris Anderson 		 */
313ddcb6370SDan OpenSolaris Anderson 		token3 = strtok(NULL, SEP_SEMICOLON); /* optional */
314ddcb6370SDan OpenSolaris Anderson 
315ddcb6370SDan OpenSolaris Anderson 		/* parse supportedlist (or disabledlist if no supportedlist) */
316ddcb6370SDan OpenSolaris Anderson 		if ((rc = parse_sup_dis_list(token2, pent)) != SUCCESS) {
317ddcb6370SDan OpenSolaris Anderson 			free_entry(pent);
318ddcb6370SDan OpenSolaris Anderson 			return (rc);
319ddcb6370SDan OpenSolaris Anderson 		}
3207c478bd9Sstevel@tonic-gate 
321ddcb6370SDan OpenSolaris Anderson 		/* parse disabledlist (if there's a supportedlist) */
322ddcb6370SDan OpenSolaris Anderson 		if ((token3 != NULL) && ((rc = parse_sup_dis_list(token3,
323ddcb6370SDan OpenSolaris Anderson 		    pent)) != SUCCESS)) {
324ddcb6370SDan OpenSolaris Anderson 			free_entry(pent);
325ddcb6370SDan OpenSolaris Anderson 			return (rc);
326ddcb6370SDan OpenSolaris Anderson 		}
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	*ppent = pent;
3307c478bd9Sstevel@tonic-gate 	return (SUCCESS);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate /*
3351b22764fSDaniel OpenSolaris Anderson  * Add an entry about a provider from kcf.conf to the end of an entry list.
3361b22764fSDaniel OpenSolaris Anderson  * If the entry list pplist is NULL, create the linked list with pent as the
3371b22764fSDaniel OpenSolaris Anderson  * first element.
3387c478bd9Sstevel@tonic-gate  */
3397c478bd9Sstevel@tonic-gate static int
build_entrylist(entry_t * pent,entrylist_t ** pplist)3407c478bd9Sstevel@tonic-gate build_entrylist(entry_t *pent, entrylist_t **pplist)
3417c478bd9Sstevel@tonic-gate {
3421b22764fSDaniel OpenSolaris Anderson 	entrylist_t	*pentlist;
3431b22764fSDaniel OpenSolaris Anderson 	entrylist_t	*pcur = NULL;
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 	pentlist = malloc(sizeof (entrylist_t));
3467c478bd9Sstevel@tonic-gate 	if (pentlist == NULL) {
3477c478bd9Sstevel@tonic-gate 		cryptodebug("out of memory.");
3487c478bd9Sstevel@tonic-gate 		return (FAILURE);
3497c478bd9Sstevel@tonic-gate 	}
3507c478bd9Sstevel@tonic-gate 	pentlist->pent = pent;
3517c478bd9Sstevel@tonic-gate 	pentlist->next = NULL;
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	if (*pplist) {
3547c478bd9Sstevel@tonic-gate 		pcur = *pplist;
3557c478bd9Sstevel@tonic-gate 		while (pcur->next != NULL)
3567c478bd9Sstevel@tonic-gate 			pcur = pcur->next;
3577c478bd9Sstevel@tonic-gate 		pcur->next = pentlist;
3587c478bd9Sstevel@tonic-gate 	} else { /* empty list */
3597c478bd9Sstevel@tonic-gate 		*pplist = pentlist;
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	return (SUCCESS);
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /*
3687c478bd9Sstevel@tonic-gate  * Find the entry with the "provname" name from the entry list and duplicate
3691b22764fSDaniel OpenSolaris Anderson  * it.  Called by getent_kef().
3707c478bd9Sstevel@tonic-gate  */
3717c478bd9Sstevel@tonic-gate static entry_t *
getent(char * provname,entrylist_t * entrylist)3727c478bd9Sstevel@tonic-gate getent(char *provname, entrylist_t *entrylist)
3737c478bd9Sstevel@tonic-gate {
3747c478bd9Sstevel@tonic-gate 	boolean_t	found = B_FALSE;
3757c478bd9Sstevel@tonic-gate 	entry_t		*pent1 = NULL;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	if ((provname == NULL) || (entrylist == NULL)) {
3787c478bd9Sstevel@tonic-gate 		return (NULL);
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	while (!found && entrylist) {
3827c478bd9Sstevel@tonic-gate 		if (strcmp(entrylist->pent->name, provname) == 0) {
3837c478bd9Sstevel@tonic-gate 			found = B_TRUE;
3847c478bd9Sstevel@tonic-gate 			pent1 = entrylist->pent;
3857c478bd9Sstevel@tonic-gate 		} else {
3867c478bd9Sstevel@tonic-gate 			entrylist = entrylist->next;
3877c478bd9Sstevel@tonic-gate 		}
3887c478bd9Sstevel@tonic-gate 	}
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	if (!found) {
3917c478bd9Sstevel@tonic-gate 		return (NULL);
3927c478bd9Sstevel@tonic-gate 	}
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 	/* duplicate the entry to be returned */
3957c478bd9Sstevel@tonic-gate 	return (dup_entry(pent1));
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 
3991b22764fSDaniel OpenSolaris Anderson /*
4001b22764fSDaniel OpenSolaris Anderson  * Free memory in entry_t.
4011b22764fSDaniel OpenSolaris Anderson  * That is, the supported and disabled lists for a provider
4021b22764fSDaniel OpenSolaris Anderson  * from kcf.conf.
4031b22764fSDaniel OpenSolaris Anderson  */
4047c478bd9Sstevel@tonic-gate void
free_entry(entry_t * pent)4057c478bd9Sstevel@tonic-gate free_entry(entry_t  *pent)
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate 	if (pent == NULL) {
4087c478bd9Sstevel@tonic-gate 		return;
4097c478bd9Sstevel@tonic-gate 	} else {
4107c478bd9Sstevel@tonic-gate 		free_mechlist(pent->suplist);
4117c478bd9Sstevel@tonic-gate 		free_mechlist(pent->dislist);
4127c478bd9Sstevel@tonic-gate 		free(pent);
4137c478bd9Sstevel@tonic-gate 	}
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 
4171b22764fSDaniel OpenSolaris Anderson /*
4181b22764fSDaniel OpenSolaris Anderson  * Free elements in a entrylist_t linked list,
4191b22764fSDaniel OpenSolaris Anderson  * which lists providers in kcf.conf.
4201b22764fSDaniel OpenSolaris Anderson  */
4217c478bd9Sstevel@tonic-gate void
free_entrylist(entrylist_t * entrylist)4227c478bd9Sstevel@tonic-gate free_entrylist(entrylist_t *entrylist)
4237c478bd9Sstevel@tonic-gate {
4247c478bd9Sstevel@tonic-gate 	entrylist_t *pnext;
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	while (entrylist != NULL) {
4277c478bd9Sstevel@tonic-gate 		pnext = entrylist->next;
4287c478bd9Sstevel@tonic-gate 		free_entry(entrylist->pent);
4297c478bd9Sstevel@tonic-gate 		entrylist = pnext;
4307c478bd9Sstevel@tonic-gate 	}
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate /*
435*0f5cc0e1SDan OpenSolaris Anderson  * Convert an entry_t to a kcf.conf line string.  Build a string to insert
436*0f5cc0e1SDan OpenSolaris Anderson  * as a line in file kcf.conf.  Based on the content of an entry_t,
437*0f5cc0e1SDan OpenSolaris Anderson  * the result string is one of these 8 forms:
4387c478bd9Sstevel@tonic-gate  *  - name:supportedlist=m1,m2,...,mj
4397c478bd9Sstevel@tonic-gate  *  - name:disabledlist=m1,m2,...,mj
4407c478bd9Sstevel@tonic-gate  *  - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
4417c478bd9Sstevel@tonic-gate  *
442ddcb6370SDan OpenSolaris Anderson  *  - name:unload
4431b22764fSDaniel OpenSolaris Anderson  *  - name:unload;supportedlist=m1,m2,...,mj
4441b22764fSDaniel OpenSolaris Anderson  *  - name:unload;disabledlist=m1,m2,...,mj
4451b22764fSDaniel OpenSolaris Anderson  *  - name:unload;supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
4461b22764fSDaniel OpenSolaris Anderson  *
447*0f5cc0e1SDan OpenSolaris Anderson  *  - (NUL character or 0-length string)
448*0f5cc0e1SDan OpenSolaris Anderson  *
449*0f5cc0e1SDan OpenSolaris Anderson  * Return a 0-length empty string if no keyword is present (that is,
450*0f5cc0e1SDan OpenSolaris Anderson  * supportedlist, disabledlist, or unload).  A kcf.conf line with just the
451*0f5cc0e1SDan OpenSolaris Anderson  * provider name with no keyword is invalid.
452*0f5cc0e1SDan OpenSolaris Anderson  *
4531b22764fSDaniel OpenSolaris Anderson  * Note that the caller is responsible for freeing the returned string
4541b22764fSDaniel OpenSolaris Anderson  * (with free_entry()).
4551b22764fSDaniel OpenSolaris Anderson  * See interpret() for the reverse of this function: converting a string
4561b22764fSDaniel OpenSolaris Anderson  * to an entry_t.
4577c478bd9Sstevel@tonic-gate  */
4587c478bd9Sstevel@tonic-gate char *
ent2str(entry_t * pent)4597c478bd9Sstevel@tonic-gate ent2str(entry_t *pent)
4607c478bd9Sstevel@tonic-gate {
4611b22764fSDaniel OpenSolaris Anderson 	char		*buf;
4621b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pcur = NULL;
463*0f5cc0e1SDan OpenSolaris Anderson 	boolean_t	keyword_already_present = B_FALSE;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	if (pent == NULL) {
4667c478bd9Sstevel@tonic-gate 		return (NULL);
4677c478bd9Sstevel@tonic-gate 	}
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	if ((buf = malloc(BUFSIZ)) == NULL) {
4707c478bd9Sstevel@tonic-gate 		return (NULL);
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	/* convert the provider name */
4747c478bd9Sstevel@tonic-gate 	if (strlcpy(buf, pent->name, BUFSIZ) >= BUFSIZ) {
4757c478bd9Sstevel@tonic-gate 		free(buf);
4767c478bd9Sstevel@tonic-gate 		return (NULL);
4777c478bd9Sstevel@tonic-gate 	}
4787c478bd9Sstevel@tonic-gate 
4791b22764fSDaniel OpenSolaris Anderson 	if (!pent->load) { /* add "unload" keyword */
4807c478bd9Sstevel@tonic-gate 		if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
4817c478bd9Sstevel@tonic-gate 			free(buf);
4827c478bd9Sstevel@tonic-gate 			return (NULL);
4837c478bd9Sstevel@tonic-gate 		}
4847c478bd9Sstevel@tonic-gate 
4851b22764fSDaniel OpenSolaris Anderson 		if (strlcat(buf, EF_UNLOAD, BUFSIZ) >= BUFSIZ) {
4861b22764fSDaniel OpenSolaris Anderson 			free(buf);
4871b22764fSDaniel OpenSolaris Anderson 			return (NULL);
4881b22764fSDaniel OpenSolaris Anderson 		}
4891b22764fSDaniel OpenSolaris Anderson 
490*0f5cc0e1SDan OpenSolaris Anderson 		keyword_already_present = B_TRUE;
4911b22764fSDaniel OpenSolaris Anderson 	}
4921b22764fSDaniel OpenSolaris Anderson 
4931b22764fSDaniel OpenSolaris Anderson 	/* convert the supported list if any */
4941b22764fSDaniel OpenSolaris Anderson 	pcur = pent->suplist;
4951b22764fSDaniel OpenSolaris Anderson 	if (pcur != NULL) {
4961b22764fSDaniel OpenSolaris Anderson 		if (strlcat(buf,
497*0f5cc0e1SDan OpenSolaris Anderson 		    keyword_already_present ? SEP_SEMICOLON : SEP_COLON,
4981b22764fSDaniel OpenSolaris Anderson 		    BUFSIZ) >= BUFSIZ) {
4991b22764fSDaniel OpenSolaris Anderson 			free(buf);
5001b22764fSDaniel OpenSolaris Anderson 			return (NULL);
5011b22764fSDaniel OpenSolaris Anderson 		}
5021b22764fSDaniel OpenSolaris Anderson 
5037c478bd9Sstevel@tonic-gate 		if (strlcat(buf, EF_SUPPORTED, BUFSIZ) >= BUFSIZ) {
5047c478bd9Sstevel@tonic-gate 			free(buf);
5057c478bd9Sstevel@tonic-gate 			return (NULL);
5067c478bd9Sstevel@tonic-gate 		}
5077c478bd9Sstevel@tonic-gate 
5081b22764fSDaniel OpenSolaris Anderson 		while (pcur != NULL) {
5091b22764fSDaniel OpenSolaris Anderson 			if (strlcat(buf, pcur->name, BUFSIZ) >= BUFSIZ) {
5107c478bd9Sstevel@tonic-gate 				free(buf);
5117c478bd9Sstevel@tonic-gate 				return (NULL);
5127c478bd9Sstevel@tonic-gate 			}
5137c478bd9Sstevel@tonic-gate 
5141b22764fSDaniel OpenSolaris Anderson 			pcur = pcur->next;
5151b22764fSDaniel OpenSolaris Anderson 			if (pcur != NULL) {
5167c478bd9Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
5177c478bd9Sstevel@tonic-gate 				    >= BUFSIZ) {
5187c478bd9Sstevel@tonic-gate 					free(buf);
5197c478bd9Sstevel@tonic-gate 					return (NULL);
5207c478bd9Sstevel@tonic-gate 				}
5217c478bd9Sstevel@tonic-gate 			}
5227c478bd9Sstevel@tonic-gate 		}
523*0f5cc0e1SDan OpenSolaris Anderson 		keyword_already_present = B_TRUE;
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	/* convert the disabled list if any */
5271b22764fSDaniel OpenSolaris Anderson 	pcur = pent->dislist;
5281b22764fSDaniel OpenSolaris Anderson 	if (pcur != NULL) {
5291b22764fSDaniel OpenSolaris Anderson 		if (strlcat(buf,
530*0f5cc0e1SDan OpenSolaris Anderson 		    keyword_already_present ? SEP_SEMICOLON : SEP_COLON,
5311b22764fSDaniel OpenSolaris Anderson 		    BUFSIZ) >= BUFSIZ) {
5321b22764fSDaniel OpenSolaris Anderson 			free(buf);
5331b22764fSDaniel OpenSolaris Anderson 			return (NULL);
5341b22764fSDaniel OpenSolaris Anderson 		}
5351b22764fSDaniel OpenSolaris Anderson 
5361b22764fSDaniel OpenSolaris Anderson 		if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) {
5371b22764fSDaniel OpenSolaris Anderson 			free(buf);
5381b22764fSDaniel OpenSolaris Anderson 			return (NULL);
5397c478bd9Sstevel@tonic-gate 		}
5407c478bd9Sstevel@tonic-gate 
5411b22764fSDaniel OpenSolaris Anderson 		while (pcur != NULL) {
5421b22764fSDaniel OpenSolaris Anderson 			if (strlcat(buf, pcur->name, BUFSIZ) >= BUFSIZ) {
5437c478bd9Sstevel@tonic-gate 				free(buf);
5447c478bd9Sstevel@tonic-gate 				return (NULL);
5457c478bd9Sstevel@tonic-gate 			}
5467c478bd9Sstevel@tonic-gate 
5471b22764fSDaniel OpenSolaris Anderson 			pcur = pcur->next;
5481b22764fSDaniel OpenSolaris Anderson 			if (pcur != NULL) {
5497c478bd9Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
5507c478bd9Sstevel@tonic-gate 				    >= BUFSIZ) {
5517c478bd9Sstevel@tonic-gate 					free(buf);
5527c478bd9Sstevel@tonic-gate 					return (NULL);
5537c478bd9Sstevel@tonic-gate 				}
5547c478bd9Sstevel@tonic-gate 			}
5557c478bd9Sstevel@tonic-gate 		}
556*0f5cc0e1SDan OpenSolaris Anderson 		keyword_already_present = B_TRUE;
5577c478bd9Sstevel@tonic-gate 	}
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
5607c478bd9Sstevel@tonic-gate 		free(buf);
5617c478bd9Sstevel@tonic-gate 		return (NULL);
5627c478bd9Sstevel@tonic-gate 	}
5637c478bd9Sstevel@tonic-gate 
564*0f5cc0e1SDan OpenSolaris Anderson 	if (!keyword_already_present) {
565*0f5cc0e1SDan OpenSolaris Anderson 		/* Only the provider name, without a keyword, is on the line */
566*0f5cc0e1SDan OpenSolaris Anderson 		buf[0] = '\0';
567*0f5cc0e1SDan OpenSolaris Anderson 	}
5687c478bd9Sstevel@tonic-gate 	return (buf);
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate /*
5737c478bd9Sstevel@tonic-gate  * Enable the mechanisms for the provider pointed by *ppent.  If allflag is
5747c478bd9Sstevel@tonic-gate  * TRUE, enable all.  Otherwise, enable the mechanisms specified in the 3rd
5757c478bd9Sstevel@tonic-gate  * argument "mlist".  The result will be stored in ppent also.
5767c478bd9Sstevel@tonic-gate  */
5777c478bd9Sstevel@tonic-gate int
enable_mechs(entry_t ** ppent,boolean_t allflag,mechlist_t * mlist)5787c478bd9Sstevel@tonic-gate enable_mechs(entry_t **ppent, boolean_t allflag, mechlist_t *mlist)
5797c478bd9Sstevel@tonic-gate {
5801b22764fSDaniel OpenSolaris Anderson 	entry_t		*pent;
5811b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*phead; /* the current and resulting disabled list */
5821b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*ptr = NULL;
5831b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pcur = NULL;
5841b22764fSDaniel OpenSolaris Anderson 	boolean_t	found;
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	pent = *ppent;
5877c478bd9Sstevel@tonic-gate 	if (pent == NULL) {
5887c478bd9Sstevel@tonic-gate 		return (FAILURE);
5897c478bd9Sstevel@tonic-gate 	}
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	if (allflag) {
5927c478bd9Sstevel@tonic-gate 		free_mechlist(pent->dislist);
5937c478bd9Sstevel@tonic-gate 		pent->dis_count = 0;
5947c478bd9Sstevel@tonic-gate 		pent->dislist = NULL;
5957c478bd9Sstevel@tonic-gate 		return (SUCCESS);
5967c478bd9Sstevel@tonic-gate 	}
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	/*
5997c478bd9Sstevel@tonic-gate 	 * for each mechanism in the to-be-enabled mechanism list,
6007c478bd9Sstevel@tonic-gate 	 * -	check if it is in the current disabled list
6017c478bd9Sstevel@tonic-gate 	 * -	if found, delete it from the disabled list
6021b22764fSDaniel OpenSolaris Anderson 	 *	otherwise, give a warning.
6037c478bd9Sstevel@tonic-gate 	 */
6047c478bd9Sstevel@tonic-gate 	ptr = mlist;
6057c478bd9Sstevel@tonic-gate 	while (ptr != NULL) {
6067c478bd9Sstevel@tonic-gate 		found = B_FALSE;
6077c478bd9Sstevel@tonic-gate 		phead = pcur =  pent->dislist;
6087c478bd9Sstevel@tonic-gate 		while (!found && pcur) {
6097c478bd9Sstevel@tonic-gate 			if (strcmp(pcur->name, ptr->name) == 0) {
6107c478bd9Sstevel@tonic-gate 				found = B_TRUE;
6117c478bd9Sstevel@tonic-gate 			} else {
6127c478bd9Sstevel@tonic-gate 				phead = pcur;
6137c478bd9Sstevel@tonic-gate 				pcur = pcur->next;
6147c478bd9Sstevel@tonic-gate 			}
6157c478bd9Sstevel@tonic-gate 		}
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 		if (found) {
6187c478bd9Sstevel@tonic-gate 			if (phead == pcur) {
6197c478bd9Sstevel@tonic-gate 				pent->dislist = pent->dislist->next;
6207c478bd9Sstevel@tonic-gate 				free(pcur);
6217c478bd9Sstevel@tonic-gate 			} else {
6227c478bd9Sstevel@tonic-gate 				phead->next = pcur->next;
6237c478bd9Sstevel@tonic-gate 				free(pcur);
6247c478bd9Sstevel@tonic-gate 			}
6257c478bd9Sstevel@tonic-gate 			pent->dis_count--;
6267c478bd9Sstevel@tonic-gate 		} else {
6277c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
6287c478bd9Sstevel@tonic-gate 			    "(Warning) %1$s is either enabled already or not "
6297c478bd9Sstevel@tonic-gate 			    "a valid mechanism for %2$s"), ptr->name,
6307c478bd9Sstevel@tonic-gate 			    pent->name);
6317c478bd9Sstevel@tonic-gate 		}
6327c478bd9Sstevel@tonic-gate 		ptr = ptr->next;
6337c478bd9Sstevel@tonic-gate 	}
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 	if (pent->dis_count == 0) {
6367c478bd9Sstevel@tonic-gate 		pent->dislist = NULL;
6377c478bd9Sstevel@tonic-gate 	}
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate 	return (SUCCESS);
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 
6441b22764fSDaniel OpenSolaris Anderson /*
6451b22764fSDaniel OpenSolaris Anderson  * Determine if the kernel provider name, path, is a device
6461b22764fSDaniel OpenSolaris Anderson  * (that is, it contains a slash character (e.g., "mca/0").
6471b22764fSDaniel OpenSolaris Anderson  * If so, it is a hardware provider; otherwise it is a software provider.
6481b22764fSDaniel OpenSolaris Anderson  */
6497c478bd9Sstevel@tonic-gate boolean_t
is_device(char * path)6507c478bd9Sstevel@tonic-gate is_device(char *path)
6517c478bd9Sstevel@tonic-gate {
6527c478bd9Sstevel@tonic-gate 	if (strchr(path, SEP_SLASH) != NULL) {
6537c478bd9Sstevel@tonic-gate 		return (B_TRUE);
6547c478bd9Sstevel@tonic-gate 	} else {
6557c478bd9Sstevel@tonic-gate 		return (B_FALSE);
6567c478bd9Sstevel@tonic-gate 	}
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate /*
6607c478bd9Sstevel@tonic-gate  * Split a hardware provider name with the "name/inst_num" format into
6611b22764fSDaniel OpenSolaris Anderson  * a name and a number (e.g., split "mca/0" into "mca" instance 0).
6627c478bd9Sstevel@tonic-gate  */
6637c478bd9Sstevel@tonic-gate int
split_hw_provname(char * provname,char * pname,int * inst_num)6647c478bd9Sstevel@tonic-gate split_hw_provname(char *provname, char *pname, int *inst_num)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate 	char	name[MAXNAMELEN];
6677c478bd9Sstevel@tonic-gate 	char	*inst_str;
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
6707c478bd9Sstevel@tonic-gate 		return (FAILURE);
6717c478bd9Sstevel@tonic-gate 	}
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	(void) strlcpy(name, provname, MAXNAMELEN);
6747c478bd9Sstevel@tonic-gate 	if (strtok(name, "/") == NULL) {
6757c478bd9Sstevel@tonic-gate 		return (FAILURE);
6767c478bd9Sstevel@tonic-gate 	}
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	if ((inst_str = strtok(NULL, "/")) == NULL) {
6797c478bd9Sstevel@tonic-gate 		return (FAILURE);
6807c478bd9Sstevel@tonic-gate 	}
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	(void) strlcpy(pname, name, MAXNAMELEN);
6837c478bd9Sstevel@tonic-gate 	*inst_num = atoi(inst_str);
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	return (SUCCESS);
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate /*
6901b22764fSDaniel OpenSolaris Anderson  * Retrieve information from kcf.conf and build a hardware device entry list
6911b22764fSDaniel OpenSolaris Anderson  * and a software entry list of kernel crypto providers.
6921b22764fSDaniel OpenSolaris Anderson  *
6931b22764fSDaniel OpenSolaris Anderson  * This list is usually incomplete, as kernel crypto providers only have to
6941b22764fSDaniel OpenSolaris Anderson  * be listed in kcf.conf if a mechanism is disabled (by cryptoadm) or
6951b22764fSDaniel OpenSolaris Anderson  * if the kernel provider module is not one of the default kernel providers.
6961b22764fSDaniel OpenSolaris Anderson  *
6971b22764fSDaniel OpenSolaris Anderson  * The kcf.conf file is available only in the global zone.
6987c478bd9Sstevel@tonic-gate  */
6997c478bd9Sstevel@tonic-gate int
get_kcfconf_info(entrylist_t ** ppdevlist,entrylist_t ** ppsoftlist)700d616ad8eSHai-May Chao get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
7017c478bd9Sstevel@tonic-gate {
7021b22764fSDaniel OpenSolaris Anderson 	FILE	*pfile = NULL;
7031b22764fSDaniel OpenSolaris Anderson 	char	buffer[BUFSIZ];
7041b22764fSDaniel OpenSolaris Anderson 	int	len;
7051b22764fSDaniel OpenSolaris Anderson 	entry_t	*pent = NULL;
7061b22764fSDaniel OpenSolaris Anderson 	int	rc = SUCCESS;
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) {
7097c478bd9Sstevel@tonic-gate 		cryptodebug("failed to open the kcf.conf file for read only");
7107c478bd9Sstevel@tonic-gate 		return (FAILURE);
7117c478bd9Sstevel@tonic-gate 	}
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 	*ppdevlist = NULL;
7147c478bd9Sstevel@tonic-gate 	*ppsoftlist = NULL;
7157c478bd9Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
7167c478bd9Sstevel@tonic-gate 		if (buffer[0] == '#' || buffer[0] == ' ' ||
7177c478bd9Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t') {
7187c478bd9Sstevel@tonic-gate 			continue;   /* ignore comment lines */
7197c478bd9Sstevel@tonic-gate 		}
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 		len = strlen(buffer);
7221b22764fSDaniel OpenSolaris Anderson 		if (buffer[len - 1] == '\n') { /* get rid of trailing '\n' */
7237c478bd9Sstevel@tonic-gate 			len--;
7247c478bd9Sstevel@tonic-gate 		}
7257c478bd9Sstevel@tonic-gate 		buffer[len] = '\0';
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 		if ((rc = interpret(buffer,  &pent)) == SUCCESS) {
728d616ad8eSHai-May Chao 			if (is_device(pent->name)) {
7297c478bd9Sstevel@tonic-gate 				rc = build_entrylist(pent, ppdevlist);
7307c478bd9Sstevel@tonic-gate 			} else {
7317c478bd9Sstevel@tonic-gate 				rc = build_entrylist(pent, ppsoftlist);
7327c478bd9Sstevel@tonic-gate 			}
7337c478bd9Sstevel@tonic-gate 		} else {
7347c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
7357c478bd9Sstevel@tonic-gate 			    "failed to parse configuration."));
7367c478bd9Sstevel@tonic-gate 		}
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 		if (rc != SUCCESS) {
7397c478bd9Sstevel@tonic-gate 			free_entrylist(*ppdevlist);
7407c478bd9Sstevel@tonic-gate 			free_entrylist(*ppsoftlist);
7417c478bd9Sstevel@tonic-gate 			free_entry(pent);
7427c478bd9Sstevel@tonic-gate 			break;
7437c478bd9Sstevel@tonic-gate 		}
7447c478bd9Sstevel@tonic-gate 	}
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 	(void) fclose(pfile);
7477c478bd9Sstevel@tonic-gate 	return (rc);
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate /*
7517c478bd9Sstevel@tonic-gate  * Retrieve information from admin device and build a device entry list and
7521b22764fSDaniel OpenSolaris Anderson  * a software entry list.  This is used where there is no kcf.conf, e.g., the
7537c478bd9Sstevel@tonic-gate  * non-global zone.
7547c478bd9Sstevel@tonic-gate  */
7557c478bd9Sstevel@tonic-gate int
get_admindev_info(entrylist_t ** ppdevlist,entrylist_t ** ppsoftlist)7567c478bd9Sstevel@tonic-gate get_admindev_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
7577c478bd9Sstevel@tonic-gate {
7581b22764fSDaniel OpenSolaris Anderson 	crypto_get_dev_list_t	*pdevlist_kernel = NULL;
7591b22764fSDaniel OpenSolaris Anderson 	crypto_get_soft_list_t	*psoftlist_kernel = NULL;
7601b22764fSDaniel OpenSolaris Anderson 	char			*devname;
7611b22764fSDaniel OpenSolaris Anderson 	int			inst_num;
7621b22764fSDaniel OpenSolaris Anderson 	int			mcount;
7631b22764fSDaniel OpenSolaris Anderson 	mechlist_t		*pmech = NULL;
7641b22764fSDaniel OpenSolaris Anderson 	entry_t			*pent_dev = NULL, *pent_soft = NULL;
7651b22764fSDaniel OpenSolaris Anderson 	int			i;
7661b22764fSDaniel OpenSolaris Anderson 	char			*psoftname;
7671b22764fSDaniel OpenSolaris Anderson 	entrylist_t		*tmp_pdev = NULL;
7681b22764fSDaniel OpenSolaris Anderson 	entrylist_t		*tmp_psoft = NULL;
7691b22764fSDaniel OpenSolaris Anderson 	entrylist_t		*phardlist = NULL, *psoftlist = NULL;
7707c478bd9Sstevel@tonic-gate 
7711b22764fSDaniel OpenSolaris Anderson 	/*
7721b22764fSDaniel OpenSolaris Anderson 	 * Get hardware providers
7731b22764fSDaniel OpenSolaris Anderson 	 */
7747c478bd9Sstevel@tonic-gate 	if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
7757c478bd9Sstevel@tonic-gate 		cryptodebug("failed to get hardware provider list from kernel");
7767c478bd9Sstevel@tonic-gate 		return (FAILURE);
7777c478bd9Sstevel@tonic-gate 	}
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
7807c478bd9Sstevel@tonic-gate 		devname = pdevlist_kernel->dl_devs[i].le_dev_name;
7817c478bd9Sstevel@tonic-gate 		inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance;
7827c478bd9Sstevel@tonic-gate 		mcount = pdevlist_kernel->dl_devs[i].le_mechanism_count;
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate 		pmech = NULL;
7857c478bd9Sstevel@tonic-gate 		if (get_dev_info(devname, inst_num, mcount, &pmech) !=
7867c478bd9Sstevel@tonic-gate 		    SUCCESS) {
7877c478bd9Sstevel@tonic-gate 			cryptodebug(
7887c478bd9Sstevel@tonic-gate 			    "failed to retrieve the mechanism list for %s/%d.",
7897c478bd9Sstevel@tonic-gate 			    devname, inst_num);
7907c478bd9Sstevel@tonic-gate 			goto fail_out;
7917c478bd9Sstevel@tonic-gate 		}
7927c478bd9Sstevel@tonic-gate 
7931b22764fSDaniel OpenSolaris Anderson 		if ((pent_dev = create_entry(devname)) == NULL) {
7947c478bd9Sstevel@tonic-gate 			cryptodebug("out of memory.");
7957c478bd9Sstevel@tonic-gate 			free_mechlist(pmech);
7967c478bd9Sstevel@tonic-gate 			goto fail_out;
7977c478bd9Sstevel@tonic-gate 		}
7981b22764fSDaniel OpenSolaris Anderson 		pent_dev->suplist = pmech;
7991b22764fSDaniel OpenSolaris Anderson 		pent_dev->sup_count = mcount;
8007c478bd9Sstevel@tonic-gate 
8011b22764fSDaniel OpenSolaris Anderson 		if (build_entrylist(pent_dev, &tmp_pdev) != SUCCESS) {
8027c478bd9Sstevel@tonic-gate 			goto fail_out;
8037c478bd9Sstevel@tonic-gate 		}
8047c478bd9Sstevel@tonic-gate 	}
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	free(pdevlist_kernel);
8077c478bd9Sstevel@tonic-gate 	pdevlist_kernel = NULL;
8087c478bd9Sstevel@tonic-gate 
8091b22764fSDaniel OpenSolaris Anderson 	/*
8101b22764fSDaniel OpenSolaris Anderson 	 * Get software providers
8111b22764fSDaniel OpenSolaris Anderson 	 */
8121b22764fSDaniel OpenSolaris Anderson 	if (getzoneid() == GLOBAL_ZONEID) {
813d616ad8eSHai-May Chao 		if (get_kcfconf_info(&phardlist, &psoftlist) != SUCCESS) {
8141b22764fSDaniel OpenSolaris Anderson 			goto fail_out;
8151b22764fSDaniel OpenSolaris Anderson 		}
8161b22764fSDaniel OpenSolaris Anderson 	}
8171b22764fSDaniel OpenSolaris Anderson 
8187c478bd9Sstevel@tonic-gate 	if (get_soft_list(&psoftlist_kernel) != SUCCESS) {
8197c478bd9Sstevel@tonic-gate 		cryptodebug("failed to get software provider list from kernel");
8207c478bd9Sstevel@tonic-gate 		goto fail_out;
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
8247c478bd9Sstevel@tonic-gate 	    i < psoftlist_kernel->sl_soft_count;
8257c478bd9Sstevel@tonic-gate 	    i++, psoftname = psoftname + strlen(psoftname) + 1) {
8267c478bd9Sstevel@tonic-gate 		pmech = NULL;
827d616ad8eSHai-May Chao 		if (get_soft_info(psoftname, &pmech, phardlist, psoftlist) !=
828d616ad8eSHai-May Chao 		    SUCCESS) {
8297c478bd9Sstevel@tonic-gate 			cryptodebug(
8307c478bd9Sstevel@tonic-gate 			    "failed to retrieve the mechanism list for %s.",
8317c478bd9Sstevel@tonic-gate 			    psoftname);
8327c478bd9Sstevel@tonic-gate 			goto fail_out;
8337c478bd9Sstevel@tonic-gate 		}
8347c478bd9Sstevel@tonic-gate 
8351b22764fSDaniel OpenSolaris Anderson 		if ((pent_soft = create_entry(psoftname)) == NULL) {
8367c478bd9Sstevel@tonic-gate 			cryptodebug("out of memory.");
8377c478bd9Sstevel@tonic-gate 			free_mechlist(pmech);
8387c478bd9Sstevel@tonic-gate 			goto fail_out;
8397c478bd9Sstevel@tonic-gate 		}
8401b22764fSDaniel OpenSolaris Anderson 		pent_soft->suplist = pmech;
8411b22764fSDaniel OpenSolaris Anderson 		pent_soft->sup_count = get_mech_count(pmech);
8427c478bd9Sstevel@tonic-gate 
8431b22764fSDaniel OpenSolaris Anderson 		if (build_entrylist(pent_soft, &tmp_psoft) != SUCCESS) {
8447c478bd9Sstevel@tonic-gate 			goto fail_out;
8457c478bd9Sstevel@tonic-gate 		}
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate 	free(psoftlist_kernel);
8497c478bd9Sstevel@tonic-gate 	psoftlist_kernel = NULL;
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	*ppdevlist = tmp_pdev;
8527c478bd9Sstevel@tonic-gate 	*ppsoftlist = tmp_psoft;
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	return (SUCCESS);
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate fail_out:
8571b22764fSDaniel OpenSolaris Anderson 	if (pent_dev != NULL)
8581b22764fSDaniel OpenSolaris Anderson 		free_entry(pent_dev);
8591b22764fSDaniel OpenSolaris Anderson 	if (pent_soft != NULL)
8601b22764fSDaniel OpenSolaris Anderson 		free_entry(pent_soft);
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 	free_entrylist(tmp_pdev);
8637c478bd9Sstevel@tonic-gate 	free_entrylist(tmp_psoft);
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	if (pdevlist_kernel != NULL)
8667c478bd9Sstevel@tonic-gate 		free(pdevlist_kernel);
8677c478bd9Sstevel@tonic-gate 	if (psoftlist_kernel != NULL)
8687c478bd9Sstevel@tonic-gate 		free(psoftlist_kernel);
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	return (FAILURE);
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate /*
8741b22764fSDaniel OpenSolaris Anderson  * Return configuration information for a kernel provider from kcf.conf.
8751b22764fSDaniel OpenSolaris Anderson  * For kernel software providers return a enabled list and disabled list.
8761b22764fSDaniel OpenSolaris Anderson  * For kernel hardware providers return just a disabled list.
8771b22764fSDaniel OpenSolaris Anderson  *
8781b22764fSDaniel OpenSolaris Anderson  * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
8791b22764fSDaniel OpenSolaris Anderson  * If NULL, this function calls get_kcfconf_info() internally.
8807c478bd9Sstevel@tonic-gate  */
8817c478bd9Sstevel@tonic-gate entry_t *
getent_kef(char * provname,entrylist_t * phardlist,entrylist_t * psoftlist)882d616ad8eSHai-May Chao getent_kef(char *provname, entrylist_t *phardlist, entrylist_t *psoftlist)
8837c478bd9Sstevel@tonic-gate {
8841b22764fSDaniel OpenSolaris Anderson 	entry_t		*pent = NULL;
8851b22764fSDaniel OpenSolaris Anderson 	boolean_t	memory_allocated = B_FALSE;
8867c478bd9Sstevel@tonic-gate 
887d616ad8eSHai-May Chao 	if ((phardlist == NULL) || (psoftlist == NULL)) {
888d616ad8eSHai-May Chao 		if (get_kcfconf_info(&phardlist, &psoftlist) != SUCCESS) {
8891b22764fSDaniel OpenSolaris Anderson 			return (NULL);
8901b22764fSDaniel OpenSolaris Anderson 		}
8911b22764fSDaniel OpenSolaris Anderson 		memory_allocated = B_TRUE;
8927c478bd9Sstevel@tonic-gate 	}
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate 	if (is_device(provname)) {
8951b22764fSDaniel OpenSolaris Anderson 		pent = getent(provname, phardlist);
8967c478bd9Sstevel@tonic-gate 	} else {
8977c478bd9Sstevel@tonic-gate 		pent = getent(provname, psoftlist);
8987c478bd9Sstevel@tonic-gate 	}
8997c478bd9Sstevel@tonic-gate 
9001b22764fSDaniel OpenSolaris Anderson 	if (memory_allocated) {
9011b22764fSDaniel OpenSolaris Anderson 		free_entrylist(phardlist);
9021b22764fSDaniel OpenSolaris Anderson 		free_entrylist(psoftlist);
9031b22764fSDaniel OpenSolaris Anderson 	}
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 	return (pent);
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate /*
9097c478bd9Sstevel@tonic-gate  * Print out the provider name and the mechanism list.
9107c478bd9Sstevel@tonic-gate  */
9117c478bd9Sstevel@tonic-gate void
print_mechlist(char * provname,mechlist_t * pmechlist)9127c478bd9Sstevel@tonic-gate print_mechlist(char *provname, mechlist_t *pmechlist)
9137c478bd9Sstevel@tonic-gate {
9141b22764fSDaniel OpenSolaris Anderson 	mechlist_t *ptr = NULL;
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
9177c478bd9Sstevel@tonic-gate 		return;
9187c478bd9Sstevel@tonic-gate 	}
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	(void) printf("%s: ", provname);
9217c478bd9Sstevel@tonic-gate 	if (pmechlist == NULL) {
9227c478bd9Sstevel@tonic-gate 		(void) printf(gettext("No mechanisms presented.\n"));
9237c478bd9Sstevel@tonic-gate 		return;
9247c478bd9Sstevel@tonic-gate 	}
9257c478bd9Sstevel@tonic-gate 
9267c478bd9Sstevel@tonic-gate 	ptr = pmechlist;
9277c478bd9Sstevel@tonic-gate 	while (ptr != NULL) {
9287c478bd9Sstevel@tonic-gate 		(void) printf("%s", ptr->name);
9297c478bd9Sstevel@tonic-gate 		ptr = ptr->next;
9307c478bd9Sstevel@tonic-gate 		if (ptr == NULL) {
9317c478bd9Sstevel@tonic-gate 			(void) printf("\n");
9327c478bd9Sstevel@tonic-gate 		} else {
9337c478bd9Sstevel@tonic-gate 			(void) printf(",");
9347c478bd9Sstevel@tonic-gate 		}
9357c478bd9Sstevel@tonic-gate 	}
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 
9397c478bd9Sstevel@tonic-gate /*
9401b22764fSDaniel OpenSolaris Anderson  * Update the kcf.conf file based on the update mode:
9411b22764fSDaniel OpenSolaris Anderson  * - If update_mode is MODIFY_MODE, modify the entry with the same name.
9421b22764fSDaniel OpenSolaris Anderson  *   If not found, append a new entry to the kcf.conf file.
9431b22764fSDaniel OpenSolaris Anderson  * - If update_mode is DELETE_MODE, delete the entry with the same name.
9441b22764fSDaniel OpenSolaris Anderson  * - If update_mode is ADD_MODE, append a new entry to the kcf.conf file.
9457c478bd9Sstevel@tonic-gate  */
9467c478bd9Sstevel@tonic-gate int
update_kcfconf(entry_t * pent,int update_mode)9477c478bd9Sstevel@tonic-gate update_kcfconf(entry_t *pent, int update_mode)
9487c478bd9Sstevel@tonic-gate {
9497c478bd9Sstevel@tonic-gate 	boolean_t	add_it = B_FALSE;
9507c478bd9Sstevel@tonic-gate 	boolean_t	delete_it = B_FALSE;
951b50892d1SDan OpenSolaris Anderson 	boolean_t	this_entry_matches = B_FALSE;
9527c478bd9Sstevel@tonic-gate 	boolean_t	found_entry = B_FALSE;
9531b22764fSDaniel OpenSolaris Anderson 	FILE		*pfile = NULL;
9541b22764fSDaniel OpenSolaris Anderson 	FILE		*pfile_tmp = NULL;
9551b22764fSDaniel OpenSolaris Anderson 	char		buffer[BUFSIZ];
9561b22764fSDaniel OpenSolaris Anderson 	char		buffer2[BUFSIZ];
9571b22764fSDaniel OpenSolaris Anderson 	char		tmpfile_name[MAXPATHLEN];
9581b22764fSDaniel OpenSolaris Anderson 	char		*name;
9591b22764fSDaniel OpenSolaris Anderson 	char		*new_str = NULL;
9601b22764fSDaniel OpenSolaris Anderson 	int		rc = SUCCESS;
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 	if (pent == NULL) {
9637c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
9647c478bd9Sstevel@tonic-gate 		return (FAILURE);
9657c478bd9Sstevel@tonic-gate 	}
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 	/* Check the update_mode */
9681b22764fSDaniel OpenSolaris Anderson 	switch (update_mode) {
9691b22764fSDaniel OpenSolaris Anderson 	case ADD_MODE:
9707c478bd9Sstevel@tonic-gate 		add_it = B_TRUE;
9711b22764fSDaniel OpenSolaris Anderson 		/* FALLTHROUGH */
9721b22764fSDaniel OpenSolaris Anderson 	case MODIFY_MODE:
9731b22764fSDaniel OpenSolaris Anderson 		/* Convert the entry a string to add to kcf.conf  */
9747c478bd9Sstevel@tonic-gate 		if ((new_str = ent2str(pent)) == NULL) {
9757c478bd9Sstevel@tonic-gate 			return (FAILURE);
9767c478bd9Sstevel@tonic-gate 		}
977*0f5cc0e1SDan OpenSolaris Anderson 		if (strlen(new_str) == 0) {
978*0f5cc0e1SDan OpenSolaris Anderson 			free(new_str);
979*0f5cc0e1SDan OpenSolaris Anderson 			delete_it = B_TRUE;
980*0f5cc0e1SDan OpenSolaris Anderson 		}
9811b22764fSDaniel OpenSolaris Anderson 		break;
9821b22764fSDaniel OpenSolaris Anderson 	case DELETE_MODE:
9837c478bd9Sstevel@tonic-gate 		delete_it = B_TRUE;
9841b22764fSDaniel OpenSolaris Anderson 		break;
9851b22764fSDaniel OpenSolaris Anderson 	default:
9867c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
9877c478bd9Sstevel@tonic-gate 		return (FAILURE);
9887c478bd9Sstevel@tonic-gate 	}
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 	/* Open the kcf.conf file */
9917c478bd9Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
9927c478bd9Sstevel@tonic-gate 		err = errno;
9937c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
9947c478bd9Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
9957c478bd9Sstevel@tonic-gate 		    strerror(err));
9967c478bd9Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
9977c478bd9Sstevel@tonic-gate 		return (FAILURE);
9987c478bd9Sstevel@tonic-gate 	}
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 	/* Lock the kcf.conf file */
10017c478bd9Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
10027c478bd9Sstevel@tonic-gate 		err = errno;
10037c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10047c478bd9Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
10051b22764fSDaniel OpenSolaris Anderson 		    strerror(err));
10067c478bd9Sstevel@tonic-gate 		(void) fclose(pfile);
10077c478bd9Sstevel@tonic-gate 		return (FAILURE);
10087c478bd9Sstevel@tonic-gate 	}
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 	/*
10117c478bd9Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
10127c478bd9Sstevel@tonic-gate 	 * updated configuration file first.
10137c478bd9Sstevel@tonic-gate 	 */
10147c478bd9Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
10157c478bd9Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
10167c478bd9Sstevel@tonic-gate 		err = errno;
10177c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10187c478bd9Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
10197c478bd9Sstevel@tonic-gate 		    strerror(err));
10207c478bd9Sstevel@tonic-gate 		(void) fclose(pfile);
10217c478bd9Sstevel@tonic-gate 		return (FAILURE);
10227c478bd9Sstevel@tonic-gate 	}
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
10257c478bd9Sstevel@tonic-gate 		err = errno;
10267c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
10277c478bd9Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
10287c478bd9Sstevel@tonic-gate 		(void) fclose(pfile);
10297c478bd9Sstevel@tonic-gate 		return (FAILURE);
10307c478bd9Sstevel@tonic-gate 	}
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	/*
10337c478bd9Sstevel@tonic-gate 	 * Loop thru the entire kcf.conf file, insert, modify or delete
10347c478bd9Sstevel@tonic-gate 	 * an entry.
10357c478bd9Sstevel@tonic-gate 	 */
10367c478bd9Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
10377c478bd9Sstevel@tonic-gate 		if (add_it) {
10387c478bd9Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
10397c478bd9Sstevel@tonic-gate 				err = errno;
10407c478bd9Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
10417c478bd9Sstevel@tonic-gate 				    "failed to write to a temp file: %s."),
10427c478bd9Sstevel@tonic-gate 				    strerror(err));
10437c478bd9Sstevel@tonic-gate 				rc = FAILURE;
10447c478bd9Sstevel@tonic-gate 				break;
10457c478bd9Sstevel@tonic-gate 			}
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 		} else { /* modify or delete */
1048b50892d1SDan OpenSolaris Anderson 			this_entry_matches = B_FALSE;
10491b22764fSDaniel OpenSolaris Anderson 
10507c478bd9Sstevel@tonic-gate 			if (!(buffer[0] == '#' || buffer[0] == ' ' ||
10517c478bd9Sstevel@tonic-gate 			    buffer[0] == '\n'|| buffer[0] == '\t')) {
10527c478bd9Sstevel@tonic-gate 				/*
10537c478bd9Sstevel@tonic-gate 				 * Get the provider name from this line and
10547c478bd9Sstevel@tonic-gate 				 * check if this is the entry to be updated
10557c478bd9Sstevel@tonic-gate 				 * or deleted. Note: can not use "buffer"
10567c478bd9Sstevel@tonic-gate 				 * directly because strtok will change its
10577c478bd9Sstevel@tonic-gate 				 * value.
10587c478bd9Sstevel@tonic-gate 				 */
10597c478bd9Sstevel@tonic-gate 				(void) strlcpy(buffer2, buffer, BUFSIZ);
10607c478bd9Sstevel@tonic-gate 				if ((name = strtok(buffer2, SEP_COLON)) ==
10617c478bd9Sstevel@tonic-gate 				    NULL) {
10627c478bd9Sstevel@tonic-gate 					rc = FAILURE;
10637c478bd9Sstevel@tonic-gate 					break;
10647c478bd9Sstevel@tonic-gate 				}
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 				if (strcmp(pent->name, name) == 0) {
1067b50892d1SDan OpenSolaris Anderson 					this_entry_matches = B_TRUE;
10687c478bd9Sstevel@tonic-gate 					found_entry = B_TRUE;
10697c478bd9Sstevel@tonic-gate 				}
10707c478bd9Sstevel@tonic-gate 			}
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 
1073b50892d1SDan OpenSolaris Anderson 			if (!this_entry_matches || !delete_it) {
1074b50892d1SDan OpenSolaris Anderson 				/* write this entry */
1075b50892d1SDan OpenSolaris Anderson 				if (this_entry_matches) {
1076b50892d1SDan OpenSolaris Anderson 					/*
1077b50892d1SDan OpenSolaris Anderson 					 * Modify this entry: get the
1078b50892d1SDan OpenSolaris Anderson 					 * updated string and place into buffer.
1079b50892d1SDan OpenSolaris Anderson 					 */
1080b50892d1SDan OpenSolaris Anderson 					(void) strlcpy(buffer, new_str, BUFSIZ);
1081b50892d1SDan OpenSolaris Anderson 					free(new_str);
1082b50892d1SDan OpenSolaris Anderson 				}
1083b50892d1SDan OpenSolaris Anderson 				/* write the (unchanged or modified) entry */
10847c478bd9Sstevel@tonic-gate 				if (fputs(buffer, pfile_tmp) == EOF) {
10857c478bd9Sstevel@tonic-gate 					err = errno;
10867c478bd9Sstevel@tonic-gate 					cryptoerror(LOG_STDERR, gettext(
10877c478bd9Sstevel@tonic-gate 					    "failed to write to a temp file: "
10887c478bd9Sstevel@tonic-gate 					    "%s."), strerror(err));
10897c478bd9Sstevel@tonic-gate 					rc = FAILURE;
10907c478bd9Sstevel@tonic-gate 					break;
10917c478bd9Sstevel@tonic-gate 				}
10927c478bd9Sstevel@tonic-gate 			}
10937c478bd9Sstevel@tonic-gate 		}
10947c478bd9Sstevel@tonic-gate 	}
10957c478bd9Sstevel@tonic-gate 
10961b22764fSDaniel OpenSolaris Anderson 	if ((!delete_it) && (rc != FAILURE)) {
10971b22764fSDaniel OpenSolaris Anderson 		if (add_it || !found_entry) {
10981b22764fSDaniel OpenSolaris Anderson 			/* append new entry to end of file */
10991b22764fSDaniel OpenSolaris Anderson 			if (fputs(new_str, pfile_tmp) == EOF) {
11001b22764fSDaniel OpenSolaris Anderson 				err = errno;
11011b22764fSDaniel OpenSolaris Anderson 				cryptoerror(LOG_STDERR, gettext(
11021b22764fSDaniel OpenSolaris Anderson 				    "failed to write to a temp file: %s."),
11031b22764fSDaniel OpenSolaris Anderson 				    strerror(err));
11041b22764fSDaniel OpenSolaris Anderson 				rc = FAILURE;
11051b22764fSDaniel OpenSolaris Anderson 			}
11061b22764fSDaniel OpenSolaris Anderson 			free(new_str);
11077c478bd9Sstevel@tonic-gate 		}
11087c478bd9Sstevel@tonic-gate 	}
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	(void) fclose(pfile);
11117c478bd9Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
11127c478bd9Sstevel@tonic-gate 		err = errno;
11137c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11147c478bd9Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
11157c478bd9Sstevel@tonic-gate 		    strerror(err));
11167c478bd9Sstevel@tonic-gate 		return (FAILURE);
11177c478bd9Sstevel@tonic-gate 	}
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	/* Copy the temporary file to the kcf.conf file */
11207c478bd9Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
11217c478bd9Sstevel@tonic-gate 		err = errno;
11227c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11237c478bd9Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
11247c478bd9Sstevel@tonic-gate 		    strerror(err));
11257c478bd9Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile,
11267c478bd9Sstevel@tonic-gate 		    _PATH_KCF_CONF, strerror(err));
11277c478bd9Sstevel@tonic-gate 		rc = FAILURE;
11287c478bd9Sstevel@tonic-gate 	} else if (chmod(_PATH_KCF_CONF,
11297c478bd9Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
11307c478bd9Sstevel@tonic-gate 		err = errno;
11317c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
11327c478bd9Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
11337c478bd9Sstevel@tonic-gate 		    strerror(err));
11347c478bd9Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
11357c478bd9Sstevel@tonic-gate 		    strerror(err));
11367c478bd9Sstevel@tonic-gate 		rc = FAILURE;
11377c478bd9Sstevel@tonic-gate 	} else {
11387c478bd9Sstevel@tonic-gate 		rc = SUCCESS;
11397c478bd9Sstevel@tonic-gate 	}
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
11427c478bd9Sstevel@tonic-gate 		err = errno;
11437c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
11447c478bd9Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"),
11457c478bd9Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
11467c478bd9Sstevel@tonic-gate 	}
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate 	return (rc);
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate /*
11537c478bd9Sstevel@tonic-gate  * Disable the mechanisms for the provider pointed by *ppent.  If allflag is
11547c478bd9Sstevel@tonic-gate  * TRUE, disable all.  Otherwise, disable the mechanisms specified in the
11557c478bd9Sstevel@tonic-gate  * dislist argument.  The "infolist" argument contains the mechanism list
11567c478bd9Sstevel@tonic-gate  * supported by this provider.
11577c478bd9Sstevel@tonic-gate  */
11587c478bd9Sstevel@tonic-gate int
disable_mechs(entry_t ** ppent,mechlist_t * infolist,boolean_t allflag,mechlist_t * dislist)11597c478bd9Sstevel@tonic-gate disable_mechs(entry_t **ppent, mechlist_t *infolist, boolean_t allflag,
11607c478bd9Sstevel@tonic-gate mechlist_t *dislist)
11617c478bd9Sstevel@tonic-gate {
11621b22764fSDaniel OpenSolaris Anderson 	entry_t		*pent;
11631b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*plist = NULL;
11641b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*phead = NULL;
11651b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*pmech = NULL;
11661b22764fSDaniel OpenSolaris Anderson 	int		rc = SUCCESS;
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	pent = *ppent;
11697c478bd9Sstevel@tonic-gate 	if (pent == NULL) {
11707c478bd9Sstevel@tonic-gate 		return (FAILURE);
11717c478bd9Sstevel@tonic-gate 	}
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	if (allflag) {
11747c478bd9Sstevel@tonic-gate 		free_mechlist(pent->dislist);
11757c478bd9Sstevel@tonic-gate 		pent->dis_count = get_mech_count(infolist);
11767c478bd9Sstevel@tonic-gate 		if (!(pent->dislist = dup_mechlist(infolist))) {
11777c478bd9Sstevel@tonic-gate 			return (FAILURE);
11787c478bd9Sstevel@tonic-gate 		} else {
11797c478bd9Sstevel@tonic-gate 			return (SUCCESS);
11807c478bd9Sstevel@tonic-gate 		}
11817c478bd9Sstevel@tonic-gate 	}
11827c478bd9Sstevel@tonic-gate 
11837c478bd9Sstevel@tonic-gate 	/*
11847c478bd9Sstevel@tonic-gate 	 * Not disable all. Now loop thru the mechanisms specified in the
11857c478bd9Sstevel@tonic-gate 	 * dislist.  If the mechanism is not supported by the provider,
11867c478bd9Sstevel@tonic-gate 	 * ignore it with a warning.  If the mechanism is disabled already,
11877c478bd9Sstevel@tonic-gate 	 * do nothing. Otherwise, prepend it to the beginning of the disabled
11887c478bd9Sstevel@tonic-gate 	 * list of the provider.
11897c478bd9Sstevel@tonic-gate 	 */
11907c478bd9Sstevel@tonic-gate 	plist = dislist;
11917c478bd9Sstevel@tonic-gate 	while (plist != NULL) {
11927c478bd9Sstevel@tonic-gate 		if (!is_in_list(plist->name, infolist)) {
11937c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext("(Warning) "
11947c478bd9Sstevel@tonic-gate 			    "%1$s is not a valid mechanism for %2$s."),
11957c478bd9Sstevel@tonic-gate 			    plist->name, pent->name);
11967c478bd9Sstevel@tonic-gate 		} else if (!is_in_list(plist->name, pent->dislist)) {
11977c478bd9Sstevel@tonic-gate 			/* Add this mechanism into the disabled list */
11987c478bd9Sstevel@tonic-gate 			if ((pmech = create_mech(plist->name)) == NULL) {
11997c478bd9Sstevel@tonic-gate 				rc = FAILURE;
12007c478bd9Sstevel@tonic-gate 				break;
12017c478bd9Sstevel@tonic-gate 			}
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 			if (pent->dislist == NULL) {
12047c478bd9Sstevel@tonic-gate 				pent->dislist = pmech;
12057c478bd9Sstevel@tonic-gate 			} else {
12067c478bd9Sstevel@tonic-gate 				phead = pent->dislist;
12077c478bd9Sstevel@tonic-gate 				pent->dislist = pmech;
12087c478bd9Sstevel@tonic-gate 				pmech->next = phead;
12097c478bd9Sstevel@tonic-gate 			}
12107c478bd9Sstevel@tonic-gate 			pent->dis_count++;
12117c478bd9Sstevel@tonic-gate 		}
12127c478bd9Sstevel@tonic-gate 		plist = plist->next;
12137c478bd9Sstevel@tonic-gate 	}
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	return (rc);
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate /*
12197c478bd9Sstevel@tonic-gate  * Remove the mechanism passed, specified by mech, from the list of
12207c478bd9Sstevel@tonic-gate  * mechanisms, if present in the list. Else, do nothing.
12217c478bd9Sstevel@tonic-gate  *
12227c478bd9Sstevel@tonic-gate  * Returns B_TRUE if mechanism is present in the list.
12237c478bd9Sstevel@tonic-gate  */
12247c478bd9Sstevel@tonic-gate boolean_t
filter_mechlist(mechlist_t ** pmechlist,const char * mech)12257c478bd9Sstevel@tonic-gate filter_mechlist(mechlist_t **pmechlist, const char *mech)
12267c478bd9Sstevel@tonic-gate {
12271b22764fSDaniel OpenSolaris Anderson 	int		cnt = 0;
12281b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*ptr, *pptr;
12291b22764fSDaniel OpenSolaris Anderson 	boolean_t	mech_present = B_FALSE;
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate 	ptr = pptr = *pmechlist;
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 	while (ptr != NULL) {
12347c478bd9Sstevel@tonic-gate 		if (strncmp(ptr->name, mech, sizeof (mech_name_t)) == 0) {
12357c478bd9Sstevel@tonic-gate 			mech_present = B_TRUE;
12367c478bd9Sstevel@tonic-gate 			if (ptr == *pmechlist) {
12377c478bd9Sstevel@tonic-gate 				pptr = *pmechlist = ptr->next;
12387c478bd9Sstevel@tonic-gate 				free(ptr);
12397c478bd9Sstevel@tonic-gate 				ptr = pptr;
12407c478bd9Sstevel@tonic-gate 			} else {
12417c478bd9Sstevel@tonic-gate 				pptr->next = ptr->next;
12427c478bd9Sstevel@tonic-gate 				free(ptr);
12437c478bd9Sstevel@tonic-gate 				ptr = pptr->next;
12447c478bd9Sstevel@tonic-gate 			}
12457c478bd9Sstevel@tonic-gate 		} else {
12467c478bd9Sstevel@tonic-gate 			pptr = ptr;
12477c478bd9Sstevel@tonic-gate 			ptr = ptr->next;
12487c478bd9Sstevel@tonic-gate 			cnt++;
12497c478bd9Sstevel@tonic-gate 		}
12507c478bd9Sstevel@tonic-gate 	}
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate 	/* Only one entry is present */
12537c478bd9Sstevel@tonic-gate 	if (cnt == 0)
12547c478bd9Sstevel@tonic-gate 		*pmechlist = NULL;
12557c478bd9Sstevel@tonic-gate 
12567c478bd9Sstevel@tonic-gate 	return (mech_present);
12577c478bd9Sstevel@tonic-gate }
12587c478bd9Sstevel@tonic-gate 
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate /*
12627c478bd9Sstevel@tonic-gate  * Print out the mechanism policy for a kernel provider that has an entry
12637c478bd9Sstevel@tonic-gate  * in the kcf.conf file.
12647c478bd9Sstevel@tonic-gate  *
12657c478bd9Sstevel@tonic-gate  * The flag has_random is set to B_TRUE if the provider does random
12667c478bd9Sstevel@tonic-gate  * numbers. The flag has_mechs is set by the caller to B_TRUE if the provider
12677c478bd9Sstevel@tonic-gate  * has some mechanisms.
12681b22764fSDaniel OpenSolaris Anderson  *
12691b22764fSDaniel OpenSolaris Anderson  * If pent is NULL, the provider doesn't have a kcf.conf entry.
12707c478bd9Sstevel@tonic-gate  */
12717c478bd9Sstevel@tonic-gate void
print_kef_policy(char * provname,entry_t * pent,boolean_t has_random,boolean_t has_mechs)12721b22764fSDaniel OpenSolaris Anderson print_kef_policy(char *provname, entry_t *pent, boolean_t has_random,
12731b22764fSDaniel OpenSolaris Anderson     boolean_t has_mechs)
12747c478bd9Sstevel@tonic-gate {
12751b22764fSDaniel OpenSolaris Anderson 	mechlist_t	*ptr = NULL;
12761b22764fSDaniel OpenSolaris Anderson 	boolean_t	rnd_disabled = B_FALSE;
12777c478bd9Sstevel@tonic-gate 
12781b22764fSDaniel OpenSolaris Anderson 	if (pent != NULL) {
12791b22764fSDaniel OpenSolaris Anderson 		rnd_disabled = filter_mechlist(&pent->dislist, RANDOM);
12801b22764fSDaniel OpenSolaris Anderson 		ptr = pent->dislist;
12817c478bd9Sstevel@tonic-gate 	}
12827c478bd9Sstevel@tonic-gate 
12831b22764fSDaniel OpenSolaris Anderson 	(void) printf("%s:", provname);
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	if (has_mechs == B_TRUE) {
12867c478bd9Sstevel@tonic-gate 		/*
12870a85b835SDaniel Anderson 		 * TRANSLATION_NOTE
12887c478bd9Sstevel@tonic-gate 		 * This code block may need to be modified a bit to avoid
12897c478bd9Sstevel@tonic-gate 		 * constructing the text message on the fly.
12907c478bd9Sstevel@tonic-gate 		 */
12917c478bd9Sstevel@tonic-gate 		(void) printf(gettext(" all mechanisms are enabled"));
12927c478bd9Sstevel@tonic-gate 		if (ptr != NULL)
12937c478bd9Sstevel@tonic-gate 			(void) printf(gettext(", except "));
12947c478bd9Sstevel@tonic-gate 		while (ptr != NULL) {
12957c478bd9Sstevel@tonic-gate 			(void) printf("%s", ptr->name);
12967c478bd9Sstevel@tonic-gate 			ptr = ptr->next;
12977c478bd9Sstevel@tonic-gate 			if (ptr != NULL)
12987c478bd9Sstevel@tonic-gate 				(void) printf(",");
12997c478bd9Sstevel@tonic-gate 		}
13007c478bd9Sstevel@tonic-gate 		if (ptr == NULL)
13017c478bd9Sstevel@tonic-gate 			(void) printf(".");
13027c478bd9Sstevel@tonic-gate 	}
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 	/*
13050a85b835SDaniel Anderson 	 * TRANSLATION_NOTE
13067c478bd9Sstevel@tonic-gate 	 * "random" is a keyword and not to be translated.
13077c478bd9Sstevel@tonic-gate 	 */
13087c478bd9Sstevel@tonic-gate 	if (rnd_disabled)
13097c478bd9Sstevel@tonic-gate 		(void) printf(gettext(" %s is disabled."), "random");
13107c478bd9Sstevel@tonic-gate 	else if (has_random)
13117c478bd9Sstevel@tonic-gate 		(void) printf(gettext(" %s is enabled."), "random");
13127c478bd9Sstevel@tonic-gate 	(void) printf("\n");
13137c478bd9Sstevel@tonic-gate }
13147c478bd9Sstevel@tonic-gate 
13151b22764fSDaniel OpenSolaris Anderson 
13167c478bd9Sstevel@tonic-gate /*
13177c478bd9Sstevel@tonic-gate  * Check if a kernel software provider is in the kernel.
13181b22764fSDaniel OpenSolaris Anderson  *
13191b22764fSDaniel OpenSolaris Anderson  * Parameters:
13201b22764fSDaniel OpenSolaris Anderson  * provname		Provider name
13211b22764fSDaniel OpenSolaris Anderson  * psoftlist_kernel	Optional software provider list.  If NULL, it will be
13221b22764fSDaniel OpenSolaris Anderson  *			obtained from get_soft_list().
13231b22764fSDaniel OpenSolaris Anderson  * in_kernel		Set to B_TRUE if device is in the kernel, else B_FALSE
13247c478bd9Sstevel@tonic-gate  */
13257c478bd9Sstevel@tonic-gate int
check_kernel_for_soft(char * provname,crypto_get_soft_list_t * psoftlist_kernel,boolean_t * in_kernel)13261b22764fSDaniel OpenSolaris Anderson check_kernel_for_soft(char *provname, crypto_get_soft_list_t *psoftlist_kernel,
13271b22764fSDaniel OpenSolaris Anderson     boolean_t *in_kernel)
13287c478bd9Sstevel@tonic-gate {
13291b22764fSDaniel OpenSolaris Anderson 	char		*ptr;
13301b22764fSDaniel OpenSolaris Anderson 	int		i;
13311b22764fSDaniel OpenSolaris Anderson 	boolean_t	psoftlist_allocated = B_FALSE;
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
13347c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
13357c478bd9Sstevel@tonic-gate 		return (FAILURE);
13367c478bd9Sstevel@tonic-gate 	}
13377c478bd9Sstevel@tonic-gate 
13381b22764fSDaniel OpenSolaris Anderson 	if (psoftlist_kernel == NULL) {
13391b22764fSDaniel OpenSolaris Anderson 		if (get_soft_list(&psoftlist_kernel) == FAILURE) {
13401b22764fSDaniel OpenSolaris Anderson 			cryptodebug("failed to get the software provider list"
13411b22764fSDaniel OpenSolaris Anderson 			" from kernel.");
13421b22764fSDaniel OpenSolaris Anderson 			return (FAILURE);
13431b22764fSDaniel OpenSolaris Anderson 		}
13441b22764fSDaniel OpenSolaris Anderson 		psoftlist_allocated = B_TRUE;
13457c478bd9Sstevel@tonic-gate 	}
13467c478bd9Sstevel@tonic-gate 
13471b22764fSDaniel OpenSolaris Anderson 	*in_kernel = B_FALSE;
13487c478bd9Sstevel@tonic-gate 	ptr = psoftlist_kernel->sl_soft_names;
13497c478bd9Sstevel@tonic-gate 	for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
13507c478bd9Sstevel@tonic-gate 		if (strcmp(provname, ptr) == 0) {
13511b22764fSDaniel OpenSolaris Anderson 			*in_kernel = B_TRUE;
13527c478bd9Sstevel@tonic-gate 			break;
13537c478bd9Sstevel@tonic-gate 		}
13547c478bd9Sstevel@tonic-gate 		ptr = ptr + strlen(ptr) + 1;
13557c478bd9Sstevel@tonic-gate 	}
13561b22764fSDaniel OpenSolaris Anderson 
13571b22764fSDaniel OpenSolaris Anderson 	if (psoftlist_allocated)
13581b22764fSDaniel OpenSolaris Anderson 		free(psoftlist_kernel);
13597c478bd9Sstevel@tonic-gate 
13607c478bd9Sstevel@tonic-gate 	return (SUCCESS);
13617c478bd9Sstevel@tonic-gate }
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate /*
13657c478bd9Sstevel@tonic-gate  * Check if a kernel hardware provider is in the kernel.
13661b22764fSDaniel OpenSolaris Anderson  *
13671b22764fSDaniel OpenSolaris Anderson  * Parameters:
13681b22764fSDaniel OpenSolaris Anderson  * provname	Provider name
13691b22764fSDaniel OpenSolaris Anderson  * pdevlist	Optional Hardware Crypto Device List.  If NULL, it will be
13701b22764fSDaniel OpenSolaris Anderson  *		obtained from get_dev_list().
13711b22764fSDaniel OpenSolaris Anderson  * in_kernel	Set to B_TRUE if device is in the kernel, otherwise B_FALSE
13727c478bd9Sstevel@tonic-gate  */
13737c478bd9Sstevel@tonic-gate int
check_kernel_for_hard(char * provname,crypto_get_dev_list_t * pdevlist,boolean_t * in_kernel)13741b22764fSDaniel OpenSolaris Anderson check_kernel_for_hard(char *provname,
13751b22764fSDaniel OpenSolaris Anderson     crypto_get_dev_list_t *pdevlist, boolean_t *in_kernel)
13767c478bd9Sstevel@tonic-gate {
13771b22764fSDaniel OpenSolaris Anderson 	char		devname[MAXNAMELEN];
13781b22764fSDaniel OpenSolaris Anderson 	int		inst_num;
13791b22764fSDaniel OpenSolaris Anderson 	int		i;
13801b22764fSDaniel OpenSolaris Anderson 	boolean_t	dev_list_allocated = B_FALSE;
13817c478bd9Sstevel@tonic-gate 
13827c478bd9Sstevel@tonic-gate 	if (provname == NULL) {
13837c478bd9Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
13847c478bd9Sstevel@tonic-gate 		return (FAILURE);
13857c478bd9Sstevel@tonic-gate 	}
13867c478bd9Sstevel@tonic-gate 
13877c478bd9Sstevel@tonic-gate 	if (split_hw_provname(provname, devname, &inst_num) == FAILURE) {
13887c478bd9Sstevel@tonic-gate 		return (FAILURE);
13897c478bd9Sstevel@tonic-gate 	}
13907c478bd9Sstevel@tonic-gate 
13911b22764fSDaniel OpenSolaris Anderson 	if (pdevlist == NULL) {
13921b22764fSDaniel OpenSolaris Anderson 		if (get_dev_list(&pdevlist) == FAILURE) {
13931b22764fSDaniel OpenSolaris Anderson 			cryptoerror(LOG_STDERR, gettext("internal error."));
13941b22764fSDaniel OpenSolaris Anderson 			return (FAILURE);
13951b22764fSDaniel OpenSolaris Anderson 		}
13961b22764fSDaniel OpenSolaris Anderson 		dev_list_allocated = B_TRUE;
13977c478bd9Sstevel@tonic-gate 	}
13987c478bd9Sstevel@tonic-gate 
13991b22764fSDaniel OpenSolaris Anderson 	*in_kernel = B_FALSE;
14007c478bd9Sstevel@tonic-gate 	for (i = 0; i < pdevlist->dl_dev_count; i++) {
14017c478bd9Sstevel@tonic-gate 		if ((strcmp(pdevlist->dl_devs[i].le_dev_name, devname) == 0) &&
14027c478bd9Sstevel@tonic-gate 		    (pdevlist->dl_devs[i].le_dev_instance == inst_num)) {
14031b22764fSDaniel OpenSolaris Anderson 			*in_kernel = B_TRUE;
14047c478bd9Sstevel@tonic-gate 			break;
14057c478bd9Sstevel@tonic-gate 		}
14067c478bd9Sstevel@tonic-gate 	}
14071b22764fSDaniel OpenSolaris Anderson 
14081b22764fSDaniel OpenSolaris Anderson 	if (dev_list_allocated)
14091b22764fSDaniel OpenSolaris Anderson 		free(pdevlist);
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 	return (SUCCESS);
14127c478bd9Sstevel@tonic-gate }
1413