10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7334SDaniel.Anderson@Sun.COM  * Common Development and Distribution License (the "License").
6*7334SDaniel.Anderson@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*7334SDaniel.Anderson@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <errno.h>
270Sstevel@tonic-gate #include <fcntl.h>
280Sstevel@tonic-gate #include <stdio.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <strings.h>
310Sstevel@tonic-gate #include <time.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <locale.h>
340Sstevel@tonic-gate #include <sys/types.h>
350Sstevel@tonic-gate #include <sys/stat.h>
360Sstevel@tonic-gate #include "cryptoadm.h"
370Sstevel@tonic-gate 
380Sstevel@tonic-gate static int err; /* To store errno which may be overwritten by gettext() */
390Sstevel@tonic-gate static int build_entrylist(entry_t *, entrylist_t **);
400Sstevel@tonic-gate static entry_t *dup_entry(entry_t *);
410Sstevel@tonic-gate static mechlist_t *dup_mechlist(mechlist_t *);
420Sstevel@tonic-gate static entry_t *getent(char *, entrylist_t *);
430Sstevel@tonic-gate static int interpret(char *, entry_t **);
440Sstevel@tonic-gate static int parse_dislist(char *, entry_t *);
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate  * Duplicate the mechanism list.  A null pointer is returned if the storage
490Sstevel@tonic-gate  * space available is insufficient or the input argument is NULL.
500Sstevel@tonic-gate  */
510Sstevel@tonic-gate static mechlist_t *
520Sstevel@tonic-gate dup_mechlist(mechlist_t *plist)
530Sstevel@tonic-gate {
540Sstevel@tonic-gate 	mechlist_t *pres = NULL;
550Sstevel@tonic-gate 	mechlist_t *pcur;
560Sstevel@tonic-gate 	mechlist_t *ptmp;
570Sstevel@tonic-gate 	int rc = SUCCESS;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	while (plist != NULL) {
600Sstevel@tonic-gate 		if (!(ptmp = create_mech(plist->name))) {
610Sstevel@tonic-gate 			rc = FAILURE;
620Sstevel@tonic-gate 			break;
630Sstevel@tonic-gate 		}
640Sstevel@tonic-gate 
650Sstevel@tonic-gate 		if (pres == NULL) {
660Sstevel@tonic-gate 			pres = pcur = ptmp;
670Sstevel@tonic-gate 		} else {
680Sstevel@tonic-gate 			pcur->next = ptmp;
690Sstevel@tonic-gate 			pcur = pcur->next;
700Sstevel@tonic-gate 		}
710Sstevel@tonic-gate 		plist = plist->next;
720Sstevel@tonic-gate 	}
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	if (rc != SUCCESS) {
750Sstevel@tonic-gate 		free_mechlist(pres);
760Sstevel@tonic-gate 		return (NULL);
770Sstevel@tonic-gate 	}
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 	return (pres);
800Sstevel@tonic-gate }
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate  * Get the number of mechanisms in the mechanism list.
850Sstevel@tonic-gate  */
860Sstevel@tonic-gate int
870Sstevel@tonic-gate get_mech_count(mechlist_t *plist)
880Sstevel@tonic-gate {
890Sstevel@tonic-gate 	int count = 0;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	while (plist != NULL) {
920Sstevel@tonic-gate 		count++;
930Sstevel@tonic-gate 		plist = plist->next;
940Sstevel@tonic-gate 	}
950Sstevel@tonic-gate 	return (count);
960Sstevel@tonic-gate }
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 
990Sstevel@tonic-gate /*
1000Sstevel@tonic-gate  * Duplicate an entry.  A null pointer is returned if the storage space
1010Sstevel@tonic-gate  * available is insufficient or the input argument is NULL.
1020Sstevel@tonic-gate  */
1030Sstevel@tonic-gate static entry_t *
1040Sstevel@tonic-gate dup_entry(entry_t *pent1)
1050Sstevel@tonic-gate {
1060Sstevel@tonic-gate 	entry_t	*pent2 = NULL;
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate 	if (pent1 == NULL) {
1090Sstevel@tonic-gate 		return (NULL);
1100Sstevel@tonic-gate 	}
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	if ((pent2 = malloc(sizeof (entry_t))) == NULL) {
1130Sstevel@tonic-gate 		cryptodebug("out of memory.");
1140Sstevel@tonic-gate 		return (NULL);
1150Sstevel@tonic-gate 	}
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	(void) strlcpy(pent2->name, pent1->name, sizeof (pent2->name));
1180Sstevel@tonic-gate 	pent2->sup_count = pent1->sup_count;
1190Sstevel@tonic-gate 	pent2->dis_count = pent1->dis_count;
1200Sstevel@tonic-gate 	pent2->suplist = NULL;
1210Sstevel@tonic-gate 	pent2->dislist = NULL;
1220Sstevel@tonic-gate 	if (pent1->suplist != NULL) {
1230Sstevel@tonic-gate 		pent2->suplist = dup_mechlist(pent1->suplist);
1240Sstevel@tonic-gate 		if (pent2->suplist == NULL) {
1250Sstevel@tonic-gate 			free_entry(pent2);
1260Sstevel@tonic-gate 			return (NULL);
1270Sstevel@tonic-gate 		}
1280Sstevel@tonic-gate 	}
1290Sstevel@tonic-gate 	if (pent1->dislist != NULL) {
1300Sstevel@tonic-gate 		pent2->dislist = dup_mechlist(pent1->dislist);
1310Sstevel@tonic-gate 		if (pent2->dislist == NULL) {
1320Sstevel@tonic-gate 			free_entry(pent2);
1330Sstevel@tonic-gate 			return (NULL);
1340Sstevel@tonic-gate 		}
1350Sstevel@tonic-gate 	}
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	return (pent2);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate /*
1420Sstevel@tonic-gate  * This routine parses the disabledlist or the supportedlist of an entry
1430Sstevel@tonic-gate  * in the kcf.conf configuration file.
1440Sstevel@tonic-gate  *
1450Sstevel@tonic-gate  * Arguments:
1460Sstevel@tonic-gate  * 	buf: an input argument which is a char string with the format of
1470Sstevel@tonic-gate  *	     "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
1480Sstevel@tonic-gate  *	pent: the entry for the disabledlist.  This is an IN/OUT argument.
1490Sstevel@tonic-gate  *
1500Sstevel@tonic-gate  * Return value: SUCCESS or FAILURE.
1510Sstevel@tonic-gate  */
1520Sstevel@tonic-gate static int
1530Sstevel@tonic-gate parse_dislist(char *buf, entry_t *pent)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate 	mechlist_t *pmech;
1560Sstevel@tonic-gate 	mechlist_t *phead;
1570Sstevel@tonic-gate 	char *next_token;
1580Sstevel@tonic-gate 	char *value;
1590Sstevel@tonic-gate 	int count;
1600Sstevel@tonic-gate 	int supflag = B_FALSE;
1610Sstevel@tonic-gate 	int disflag = B_FALSE;
1620Sstevel@tonic-gate 	int rc = SUCCESS;
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	if (strncmp(buf, EF_SUPPORTED, strlen(EF_SUPPORTED)) == 0) {
1650Sstevel@tonic-gate 		supflag = B_TRUE;
1660Sstevel@tonic-gate 	} else if (strncmp(buf, EF_DISABLED, strlen(EF_DISABLED)) == 0) {
1670Sstevel@tonic-gate 		disflag = B_TRUE;
1680Sstevel@tonic-gate 	} else {
1690Sstevel@tonic-gate 		/* should not come here */
1700Sstevel@tonic-gate 		return (FAILURE);
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	if (value = strpbrk(buf, SEP_EQUAL)) {
1740Sstevel@tonic-gate 		value++; /* get rid of = */
1750Sstevel@tonic-gate 	} else {
1760Sstevel@tonic-gate 		cryptodebug("failed to parse the kcf.conf file.");
1770Sstevel@tonic-gate 		return (FAILURE);
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	if ((next_token = strtok(value, SEP_COMMA)) == NULL) {
1810Sstevel@tonic-gate 		cryptodebug("failed to parse the kcf.conf file.");
1820Sstevel@tonic-gate 		return (FAILURE);
1830Sstevel@tonic-gate 	}
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	if ((pmech = create_mech(next_token)) == NULL) {
1860Sstevel@tonic-gate 		return (FAILURE);
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	if (supflag) {
1900Sstevel@tonic-gate 		pent->suplist = phead = pmech;
1910Sstevel@tonic-gate 	} else if (disflag) {
1920Sstevel@tonic-gate 		pent->dislist = phead = pmech;
1930Sstevel@tonic-gate 	}
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	count = 1;
1960Sstevel@tonic-gate 	while (next_token) {
1970Sstevel@tonic-gate 		if (next_token = strtok(NULL, SEP_COMMA)) {
1980Sstevel@tonic-gate 			if ((pmech = create_mech(next_token)) == NULL) {
1990Sstevel@tonic-gate 				rc = FAILURE;
2000Sstevel@tonic-gate 				break;
2010Sstevel@tonic-gate 			}
2020Sstevel@tonic-gate 			count++;
2030Sstevel@tonic-gate 			phead->next = pmech;
2040Sstevel@tonic-gate 			phead = phead->next;
2050Sstevel@tonic-gate 		}
2060Sstevel@tonic-gate 	}
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	if (rc == SUCCESS) {
2090Sstevel@tonic-gate 		if (supflag) {
2100Sstevel@tonic-gate 			pent->sup_count = count;
2110Sstevel@tonic-gate 		} else if (disflag) {
2120Sstevel@tonic-gate 			pent->dis_count = count;
2130Sstevel@tonic-gate 		}
2140Sstevel@tonic-gate 	} else {
2150Sstevel@tonic-gate 		free_mechlist(phead);
2160Sstevel@tonic-gate 	}
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	return (rc);
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate /*
2240Sstevel@tonic-gate  * This routine converts a char string into an entry_t structure
2250Sstevel@tonic-gate  */
2260Sstevel@tonic-gate static int
2270Sstevel@tonic-gate interpret(char *buf, entry_t **ppent)
2280Sstevel@tonic-gate {
2290Sstevel@tonic-gate 	entry_t *pent;
2300Sstevel@tonic-gate 	char *token1;
2310Sstevel@tonic-gate 	char *token2;
2320Sstevel@tonic-gate 	char *token3;
2330Sstevel@tonic-gate 	int rc;
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	if ((token1 = strtok(buf, SEP_COLON)) == NULL) { /* buf is NULL */
2360Sstevel@tonic-gate 		return (FAILURE);
2370Sstevel@tonic-gate 	};
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	pent = malloc(sizeof (entry_t));
2400Sstevel@tonic-gate 	if (pent == NULL) {
2410Sstevel@tonic-gate 		cryptodebug("out of memory.");
2420Sstevel@tonic-gate 		return (FAILURE);
2430Sstevel@tonic-gate 	}
2440Sstevel@tonic-gate 	(void) strlcpy(pent->name, token1, sizeof (pent->name));
2450Sstevel@tonic-gate 	pent->suplist = NULL;
2460Sstevel@tonic-gate 	pent->dislist = NULL;
2470Sstevel@tonic-gate 	pent->sup_count = 0;
2480Sstevel@tonic-gate 	pent->dis_count = 0;
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
2510Sstevel@tonic-gate 		/* The entry contains a provider name only */
2520Sstevel@tonic-gate 		free_entry(pent);
2530Sstevel@tonic-gate 		return (FAILURE);
2540Sstevel@tonic-gate 	}
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	/* need to get token3 first to satisfy nested strtok invocations */
2570Sstevel@tonic-gate 	token3 = strtok(NULL, SEP_SEMICOLON);
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	if (token2 && ((rc = parse_dislist(token2, pent)) != SUCCESS)) {
2600Sstevel@tonic-gate 		free_entry(pent);
2610Sstevel@tonic-gate 		return (rc);
2620Sstevel@tonic-gate 	}
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	if (token3 && ((rc = parse_dislist(token3, pent)) != SUCCESS)) {
2650Sstevel@tonic-gate 		free_entry(pent);
2660Sstevel@tonic-gate 		return (rc);
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	*ppent = pent;
2700Sstevel@tonic-gate 	return (SUCCESS);
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate /*
2750Sstevel@tonic-gate  * Add an entry to the end of an entry list. If the entry list is NULL, will
2760Sstevel@tonic-gate  * create an entry list with the pent.
2770Sstevel@tonic-gate  */
2780Sstevel@tonic-gate static int
2790Sstevel@tonic-gate build_entrylist(entry_t *pent, entrylist_t **pplist)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate 	entrylist_t *pentlist;
2820Sstevel@tonic-gate 	entrylist_t *pcur;
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	pentlist = malloc(sizeof (entrylist_t));
2850Sstevel@tonic-gate 	if (pentlist == NULL) {
2860Sstevel@tonic-gate 		cryptodebug("out of memory.");
2870Sstevel@tonic-gate 		return (FAILURE);
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 	pentlist->pent = pent;
2900Sstevel@tonic-gate 	pentlist->next = NULL;
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	if (*pplist) {
2930Sstevel@tonic-gate 		pcur = *pplist;
2940Sstevel@tonic-gate 		while (pcur->next != NULL)
2950Sstevel@tonic-gate 			pcur = pcur->next;
2960Sstevel@tonic-gate 		pcur->next = pentlist;
2970Sstevel@tonic-gate 	} else { /* empty list */
2980Sstevel@tonic-gate 		*pplist = pentlist;
2990Sstevel@tonic-gate 	}
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	return (SUCCESS);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate /*
3070Sstevel@tonic-gate  * Find the entry with the "provname" name from the entry list and duplicate
3080Sstevel@tonic-gate  * it.
3090Sstevel@tonic-gate  */
3100Sstevel@tonic-gate static entry_t *
3110Sstevel@tonic-gate getent(char *provname, entrylist_t *entrylist)
3120Sstevel@tonic-gate {
3130Sstevel@tonic-gate 	boolean_t	found = B_FALSE;
3140Sstevel@tonic-gate 	entry_t		*pent1 = NULL;
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	if ((provname == NULL) || (entrylist == NULL)) {
3170Sstevel@tonic-gate 		return (NULL);
3180Sstevel@tonic-gate 	}
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	while (!found && entrylist) {
3210Sstevel@tonic-gate 		if (strcmp(entrylist->pent->name, provname) == 0) {
3220Sstevel@tonic-gate 			found = B_TRUE;
3230Sstevel@tonic-gate 			pent1 = entrylist->pent;
3240Sstevel@tonic-gate 		} else {
3250Sstevel@tonic-gate 			entrylist = entrylist->next;
3260Sstevel@tonic-gate 		}
3270Sstevel@tonic-gate 	}
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	if (!found) {
3300Sstevel@tonic-gate 		return (NULL);
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	/* duplicate the entry to be returned */
3340Sstevel@tonic-gate 	return (dup_entry(pent1));
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate void
3400Sstevel@tonic-gate free_entry(entry_t  *pent)
3410Sstevel@tonic-gate {
3420Sstevel@tonic-gate 	if (pent == NULL) {
3430Sstevel@tonic-gate 		return;
3440Sstevel@tonic-gate 	} else {
3450Sstevel@tonic-gate 		free_mechlist(pent->suplist);
3460Sstevel@tonic-gate 		free_mechlist(pent->dislist);
3470Sstevel@tonic-gate 		free(pent);
3480Sstevel@tonic-gate 	}
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate void
3530Sstevel@tonic-gate free_entrylist(entrylist_t *entrylist)
3540Sstevel@tonic-gate {
3550Sstevel@tonic-gate 	entrylist_t *pnext;
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	while (entrylist != NULL) {
3580Sstevel@tonic-gate 		pnext = entrylist->next;
3590Sstevel@tonic-gate 		free_entry(entrylist->pent);
3600Sstevel@tonic-gate 		entrylist = pnext;
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate }
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate /*
3660Sstevel@tonic-gate  * Convert an entry to a string.  This routine builds a string for the entry
3670Sstevel@tonic-gate  * to be inserted in the config file.  Based on the content of each entry,
3680Sstevel@tonic-gate  * the result string can be one of the 4 forms:
3690Sstevel@tonic-gate  *  - name
3700Sstevel@tonic-gate  *  - name:supportedlist=m1,m2,...,mj
3710Sstevel@tonic-gate  *  - name:disabledlist=m1,m2,...,mj
3720Sstevel@tonic-gate  *  - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
3730Sstevel@tonic-gate  *
3740Sstevel@tonic-gate  * Note that the caller is responsible for freeing the returned string.
3750Sstevel@tonic-gate  */
3760Sstevel@tonic-gate char *
3770Sstevel@tonic-gate ent2str(entry_t *pent)
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate 	char	*buf;
3800Sstevel@tonic-gate 	mechlist_t  *phead;
3810Sstevel@tonic-gate 	boolean_t supflag = B_FALSE;
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	if (pent == NULL) {
3850Sstevel@tonic-gate 		return (NULL);
3860Sstevel@tonic-gate 	}
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate 	if ((buf = malloc(BUFSIZ)) == NULL) {
3890Sstevel@tonic-gate 		return (NULL);
3900Sstevel@tonic-gate 	}
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	/* convert the provider name */
3930Sstevel@tonic-gate 	if (strlcpy(buf, pent->name, BUFSIZ) >= BUFSIZ) {
3940Sstevel@tonic-gate 		free(buf);
3950Sstevel@tonic-gate 		return (NULL);
3960Sstevel@tonic-gate 	}
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	/* convert the supported list if any */
3990Sstevel@tonic-gate 	phead = pent->suplist;
4000Sstevel@tonic-gate 	if (phead != NULL) {
4010Sstevel@tonic-gate 		supflag = B_TRUE;
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 		if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
4040Sstevel@tonic-gate 			free(buf);
4050Sstevel@tonic-gate 			return (NULL);
4060Sstevel@tonic-gate 		}
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 		if (strlcat(buf, EF_SUPPORTED, BUFSIZ) >= BUFSIZ) {
4090Sstevel@tonic-gate 			free(buf);
4100Sstevel@tonic-gate 			return (NULL);
4110Sstevel@tonic-gate 		}
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 		while (phead != NULL) {
4140Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
4150Sstevel@tonic-gate 				free(buf);
4160Sstevel@tonic-gate 				return (NULL);
4170Sstevel@tonic-gate 			}
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 			phead = phead->next;
4200Sstevel@tonic-gate 			if (phead != NULL) {
4210Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
4220Sstevel@tonic-gate 				    >= BUFSIZ) {
4230Sstevel@tonic-gate 					free(buf);
4240Sstevel@tonic-gate 					return (NULL);
4250Sstevel@tonic-gate 				}
4260Sstevel@tonic-gate 			}
4270Sstevel@tonic-gate 		}
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 	/* convert the disabled list if any */
4310Sstevel@tonic-gate 	phead = pent->dislist;
4320Sstevel@tonic-gate 	if (phead != NULL) {
4330Sstevel@tonic-gate 		if (supflag) {
4340Sstevel@tonic-gate 			if (strlcat(buf, ";disabledlist=", BUFSIZ) >= BUFSIZ) {
4350Sstevel@tonic-gate 				free(buf);
4360Sstevel@tonic-gate 				return (NULL);
4370Sstevel@tonic-gate 			}
4380Sstevel@tonic-gate 		} else {
4390Sstevel@tonic-gate 			if (strlcat(buf, ":disabledlist=", BUFSIZ) >= BUFSIZ) {
4400Sstevel@tonic-gate 				free(buf);
4410Sstevel@tonic-gate 				return (NULL);
4420Sstevel@tonic-gate 			}
4430Sstevel@tonic-gate 		}
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 		while (phead != NULL) {
4460Sstevel@tonic-gate 			if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
4470Sstevel@tonic-gate 				free(buf);
4480Sstevel@tonic-gate 				return (NULL);
4490Sstevel@tonic-gate 			}
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 			phead = phead->next;
4520Sstevel@tonic-gate 			if (phead != NULL) {
4530Sstevel@tonic-gate 				if (strlcat(buf, SEP_COMMA, BUFSIZ)
4540Sstevel@tonic-gate 				    >= BUFSIZ) {
4550Sstevel@tonic-gate 					free(buf);
4560Sstevel@tonic-gate 					return (NULL);
4570Sstevel@tonic-gate 				}
4580Sstevel@tonic-gate 			}
4590Sstevel@tonic-gate 		}
4600Sstevel@tonic-gate 	}
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
4630Sstevel@tonic-gate 		free(buf);
4640Sstevel@tonic-gate 		return (NULL);
4650Sstevel@tonic-gate 	}
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	return (buf);
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate /*
4720Sstevel@tonic-gate  * Enable the mechanisms for the provider pointed by *ppent.  If allflag is
4730Sstevel@tonic-gate  * TRUE, enable all.  Otherwise, enable the mechanisms specified in the 3rd
4740Sstevel@tonic-gate  * argument "mlist".  The result will be stored in ppent also.
4750Sstevel@tonic-gate  */
4760Sstevel@tonic-gate int
4770Sstevel@tonic-gate enable_mechs(entry_t **ppent, boolean_t allflag, mechlist_t *mlist)
4780Sstevel@tonic-gate {
4790Sstevel@tonic-gate 	entry_t *pent;
4800Sstevel@tonic-gate 	mechlist_t *phead; /* the current and resulting disabled list */
4810Sstevel@tonic-gate 	mechlist_t *ptr;
4820Sstevel@tonic-gate 	mechlist_t *pcur;
4830Sstevel@tonic-gate 	boolean_t found;
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 	pent = *ppent;
4860Sstevel@tonic-gate 	if (pent == NULL) {
4870Sstevel@tonic-gate 		return (FAILURE);
4880Sstevel@tonic-gate 	}
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	if (allflag) {
4910Sstevel@tonic-gate 		free_mechlist(pent->dislist);
4920Sstevel@tonic-gate 		pent->dis_count = 0;
4930Sstevel@tonic-gate 		pent->dislist = NULL;
4940Sstevel@tonic-gate 		return (SUCCESS);
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	/*
4980Sstevel@tonic-gate 	 * for each mechanism in the to-be-enabled mechanism list,
4990Sstevel@tonic-gate 	 * -	check if it is in the current disabled list
5000Sstevel@tonic-gate 	 * -	if found, delete it from the disabled list
5010Sstevel@tonic-gate 	 * 	otherwise, give a warning.
5020Sstevel@tonic-gate 	 */
5030Sstevel@tonic-gate 	ptr = mlist;
5040Sstevel@tonic-gate 	while (ptr != NULL) {
5050Sstevel@tonic-gate 		found = B_FALSE;
5060Sstevel@tonic-gate 		phead = pcur =  pent->dislist;
5070Sstevel@tonic-gate 		while (!found && pcur) {
5080Sstevel@tonic-gate 			if (strcmp(pcur->name, ptr->name) == 0) {
5090Sstevel@tonic-gate 				found = B_TRUE;
5100Sstevel@tonic-gate 			} else {
5110Sstevel@tonic-gate 				phead = pcur;
5120Sstevel@tonic-gate 				pcur = pcur->next;
5130Sstevel@tonic-gate 			}
5140Sstevel@tonic-gate 		}
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 		if (found) {
5170Sstevel@tonic-gate 			if (phead == pcur) {
5180Sstevel@tonic-gate 				pent->dislist = pent->dislist->next;
5190Sstevel@tonic-gate 				free(pcur);
5200Sstevel@tonic-gate 			} else {
5210Sstevel@tonic-gate 				phead->next = pcur->next;
5220Sstevel@tonic-gate 				free(pcur);
5230Sstevel@tonic-gate 			}
5240Sstevel@tonic-gate 			pent->dis_count--;
5250Sstevel@tonic-gate 		} else {
5260Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
5270Sstevel@tonic-gate 			    "(Warning) %1$s is either enabled already or not "
5280Sstevel@tonic-gate 			    "a valid mechanism for %2$s"), ptr->name,
5290Sstevel@tonic-gate 			    pent->name);
5300Sstevel@tonic-gate 		}
5310Sstevel@tonic-gate 		ptr = ptr->next;
5320Sstevel@tonic-gate 	}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	if (pent->dis_count == 0) {
5350Sstevel@tonic-gate 		pent->dislist = NULL;
5360Sstevel@tonic-gate 	}
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 	return (SUCCESS);
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate boolean_t
5440Sstevel@tonic-gate is_device(char *path)
5450Sstevel@tonic-gate {
5460Sstevel@tonic-gate 	if (strchr(path, SEP_SLASH) != NULL) {
5470Sstevel@tonic-gate 		return (B_TRUE);
5480Sstevel@tonic-gate 	} else {
5490Sstevel@tonic-gate 		return (B_FALSE);
5500Sstevel@tonic-gate 	}
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate /*
5540Sstevel@tonic-gate  * Split a hardware provider name with the "name/inst_num" format into
5550Sstevel@tonic-gate  * a name and a number.
5560Sstevel@tonic-gate  */
5570Sstevel@tonic-gate int
5580Sstevel@tonic-gate split_hw_provname(char *provname, char *pname, int *inst_num)
5590Sstevel@tonic-gate {
5600Sstevel@tonic-gate 	char	name[MAXNAMELEN];
5610Sstevel@tonic-gate 	char	*inst_str;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	if (provname == NULL) {
5640Sstevel@tonic-gate 		return (FAILURE);
5650Sstevel@tonic-gate 	}
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 	(void) strlcpy(name, provname, MAXNAMELEN);
5680Sstevel@tonic-gate 	if (strtok(name, "/") == NULL) {
5690Sstevel@tonic-gate 		return (FAILURE);
5700Sstevel@tonic-gate 	}
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	if ((inst_str = strtok(NULL, "/")) == NULL) {
5730Sstevel@tonic-gate 		return (FAILURE);
5740Sstevel@tonic-gate 	}
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 	(void) strlcpy(pname, name, MAXNAMELEN);
5770Sstevel@tonic-gate 	*inst_num = atoi(inst_str);
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	return (SUCCESS);
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate /*
5840Sstevel@tonic-gate  * Retrieve information from kcf.conf and build a device entry list and
5850Sstevel@tonic-gate  * a software entry list
5860Sstevel@tonic-gate  */
5870Sstevel@tonic-gate int
5880Sstevel@tonic-gate get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
5890Sstevel@tonic-gate {
5900Sstevel@tonic-gate 	FILE *pfile;
5910Sstevel@tonic-gate 	char buffer[BUFSIZ];
5920Sstevel@tonic-gate 	int len;
5930Sstevel@tonic-gate 	entry_t *pent = NULL;
5940Sstevel@tonic-gate 	int rc = SUCCESS;
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) {
5970Sstevel@tonic-gate 		cryptodebug("failed to open the kcf.conf file for read only");
5980Sstevel@tonic-gate 		return (FAILURE);
5990Sstevel@tonic-gate 	}
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	*ppdevlist = NULL;
6020Sstevel@tonic-gate 	*ppsoftlist = NULL;
6030Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
6040Sstevel@tonic-gate 		if (buffer[0] == '#' || buffer[0] == ' ' ||
6050Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t') {
6060Sstevel@tonic-gate 			continue;   /* ignore comment lines */
6070Sstevel@tonic-gate 		}
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 		len = strlen(buffer);
6100Sstevel@tonic-gate 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
6110Sstevel@tonic-gate 			len--;
6120Sstevel@tonic-gate 		}
6130Sstevel@tonic-gate 		buffer[len] = '\0';
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 		if ((rc = interpret(buffer,  &pent)) == SUCCESS) {
6160Sstevel@tonic-gate 			if (is_device(pent->name)) {
6170Sstevel@tonic-gate 				rc = build_entrylist(pent, ppdevlist);
6180Sstevel@tonic-gate 			} else {
6190Sstevel@tonic-gate 				rc = build_entrylist(pent, ppsoftlist);
6200Sstevel@tonic-gate 			}
6210Sstevel@tonic-gate 		} else {
6220Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
6230Sstevel@tonic-gate 			    "failed to parse configuration."));
6240Sstevel@tonic-gate 		}
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 		if (rc != SUCCESS) {
6270Sstevel@tonic-gate 			free_entrylist(*ppdevlist);
6280Sstevel@tonic-gate 			free_entrylist(*ppsoftlist);
6290Sstevel@tonic-gate 			free_entry(pent);
6300Sstevel@tonic-gate 			break;
6310Sstevel@tonic-gate 		}
6320Sstevel@tonic-gate 	}
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	(void) fclose(pfile);
6350Sstevel@tonic-gate 	return (rc);
6360Sstevel@tonic-gate }
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate /*
6390Sstevel@tonic-gate  * Retrieve information from admin device and build a device entry list and
6400Sstevel@tonic-gate  * a software entry list.  This is used where there is no kcf.conf, e.g.
6410Sstevel@tonic-gate  * non-global zone.
6420Sstevel@tonic-gate  */
6430Sstevel@tonic-gate int
6440Sstevel@tonic-gate get_admindev_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
6450Sstevel@tonic-gate {
6460Sstevel@tonic-gate 	crypto_get_dev_list_t *pdevlist_kernel = NULL;
6470Sstevel@tonic-gate 	crypto_get_soft_list_t *psoftlist_kernel = NULL;
6480Sstevel@tonic-gate 	char *devname;
6490Sstevel@tonic-gate 	int inst_num;
6500Sstevel@tonic-gate 	int mcount;
6510Sstevel@tonic-gate 	mechlist_t *pmech;
6520Sstevel@tonic-gate 	entry_t *pent = NULL;
6530Sstevel@tonic-gate 	int i;
6540Sstevel@tonic-gate 	char *psoftname;
6550Sstevel@tonic-gate 	entrylist_t *tmp_pdev = NULL;
6560Sstevel@tonic-gate 	entrylist_t *tmp_psoft = NULL;
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 	if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
6590Sstevel@tonic-gate 		cryptodebug("failed to get hardware provider list from kernel");
6600Sstevel@tonic-gate 		return (FAILURE);
6610Sstevel@tonic-gate 	}
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
6640Sstevel@tonic-gate 		devname = pdevlist_kernel->dl_devs[i].le_dev_name;
6650Sstevel@tonic-gate 		inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance;
6660Sstevel@tonic-gate 		mcount = pdevlist_kernel->dl_devs[i].le_mechanism_count;
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 		pmech = NULL;
6690Sstevel@tonic-gate 		if (get_dev_info(devname, inst_num, mcount, &pmech) !=
6700Sstevel@tonic-gate 		    SUCCESS) {
6710Sstevel@tonic-gate 			cryptodebug(
6720Sstevel@tonic-gate 			    "failed to retrieve the mechanism list for %s/%d.",
6730Sstevel@tonic-gate 			    devname, inst_num);
6740Sstevel@tonic-gate 			goto fail_out;
6750Sstevel@tonic-gate 		}
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 		if ((pent = malloc(sizeof (entry_t))) == NULL) {
6780Sstevel@tonic-gate 			cryptodebug("out of memory.");
6790Sstevel@tonic-gate 			free_mechlist(pmech);
6800Sstevel@tonic-gate 			goto fail_out;
6810Sstevel@tonic-gate 		}
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 		(void) strlcpy(pent->name, devname, MAXNAMELEN);
6840Sstevel@tonic-gate 		pent->suplist = pmech;
6850Sstevel@tonic-gate 		pent->sup_count = mcount;
6860Sstevel@tonic-gate 		pent->dislist = NULL;
6870Sstevel@tonic-gate 		pent->dis_count = 0;
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 		if (build_entrylist(pent, &tmp_pdev) != SUCCESS) {
6900Sstevel@tonic-gate 			goto fail_out;
6910Sstevel@tonic-gate 		}
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 		/* because incorporated in tmp_pdev */
6940Sstevel@tonic-gate 		pent = NULL;
6950Sstevel@tonic-gate 	}
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate 	free(pdevlist_kernel);
6980Sstevel@tonic-gate 	pdevlist_kernel = NULL;
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate 	if (get_soft_list(&psoftlist_kernel) != SUCCESS) {
7010Sstevel@tonic-gate 		cryptodebug("failed to get software provider list from kernel");
7020Sstevel@tonic-gate 		goto fail_out;
7030Sstevel@tonic-gate 	}
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
7060Sstevel@tonic-gate 	    i < psoftlist_kernel->sl_soft_count;
7070Sstevel@tonic-gate 	    i++, psoftname = psoftname + strlen(psoftname) + 1) {
7080Sstevel@tonic-gate 		pmech = NULL;
7090Sstevel@tonic-gate 		if (get_soft_info(psoftname, &pmech) != SUCCESS) {
7100Sstevel@tonic-gate 			cryptodebug(
7110Sstevel@tonic-gate 			    "failed to retrieve the mechanism list for %s.",
7120Sstevel@tonic-gate 			    psoftname);
7130Sstevel@tonic-gate 			goto fail_out;
7140Sstevel@tonic-gate 		}
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 		if ((pent = malloc(sizeof (entry_t))) == NULL) {
7170Sstevel@tonic-gate 			cryptodebug("out of memory.");
7180Sstevel@tonic-gate 			free_mechlist(pmech);
7190Sstevel@tonic-gate 			goto fail_out;
7200Sstevel@tonic-gate 		}
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 		(void) strlcpy(pent->name, psoftname, MAXNAMELEN);
7230Sstevel@tonic-gate 		pent->suplist = pmech;
7240Sstevel@tonic-gate 		pent->sup_count = get_mech_count(pmech);
7250Sstevel@tonic-gate 		pent->dislist = NULL;
7260Sstevel@tonic-gate 		pent->dis_count = 0;
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 		if (build_entrylist(pent, &tmp_psoft) != SUCCESS) {
7290Sstevel@tonic-gate 			goto fail_out;
7300Sstevel@tonic-gate 		}
7310Sstevel@tonic-gate 	}
7320Sstevel@tonic-gate 
7330Sstevel@tonic-gate 	free(psoftlist_kernel);
7340Sstevel@tonic-gate 	psoftlist_kernel = NULL;
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 	*ppdevlist = tmp_pdev;
7370Sstevel@tonic-gate 	*ppsoftlist = tmp_psoft;
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate 	return (SUCCESS);
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate fail_out:
7420Sstevel@tonic-gate 	if (pent != NULL)
7430Sstevel@tonic-gate 		free_entry(pent);
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 	free_entrylist(tmp_pdev);
7460Sstevel@tonic-gate 	free_entrylist(tmp_psoft);
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 	if (pdevlist_kernel != NULL)
7490Sstevel@tonic-gate 		free(pdevlist_kernel);
7500Sstevel@tonic-gate 	if (psoftlist_kernel != NULL)
7510Sstevel@tonic-gate 		free(psoftlist_kernel);
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 	return (FAILURE);
7540Sstevel@tonic-gate }
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate /*
7570Sstevel@tonic-gate  * Find the entry in the "kcf.conf" file with "provname" as the provider name.
7580Sstevel@tonic-gate  * Return the entry if found, otherwise return NULL.
7590Sstevel@tonic-gate  */
7600Sstevel@tonic-gate entry_t *
7610Sstevel@tonic-gate getent_kef(char *provname)
7620Sstevel@tonic-gate {
7630Sstevel@tonic-gate 	entrylist_t *pdevlist = NULL;
7640Sstevel@tonic-gate 	entrylist_t *psoftlist = NULL;
7650Sstevel@tonic-gate 	entry_t *pent = NULL;
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 	if (get_kcfconf_info(&pdevlist, &psoftlist) != SUCCESS) {
7680Sstevel@tonic-gate 		return (NULL);
7690Sstevel@tonic-gate 	}
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 	if (is_device(provname)) {
7720Sstevel@tonic-gate 		pent = getent(provname, pdevlist);
7730Sstevel@tonic-gate 	} else {
7740Sstevel@tonic-gate 		pent = getent(provname, psoftlist);
7750Sstevel@tonic-gate 	}
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 	free_entrylist(pdevlist);
7780Sstevel@tonic-gate 	free_entrylist(psoftlist);
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	return (pent);
7810Sstevel@tonic-gate }
7820Sstevel@tonic-gate 
7830Sstevel@tonic-gate /*
7840Sstevel@tonic-gate  * Print out the provider name and the mechanism list.
7850Sstevel@tonic-gate  */
7860Sstevel@tonic-gate void
7870Sstevel@tonic-gate print_mechlist(char *provname, mechlist_t *pmechlist)
7880Sstevel@tonic-gate {
7890Sstevel@tonic-gate 	mechlist_t *ptr;
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 	if (provname == NULL) {
7920Sstevel@tonic-gate 		return;
7930Sstevel@tonic-gate 	}
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	(void) printf("%s: ", provname);
7960Sstevel@tonic-gate 	if (pmechlist == NULL) {
7970Sstevel@tonic-gate 		(void) printf(gettext("No mechanisms presented.\n"));
7980Sstevel@tonic-gate 		return;
7990Sstevel@tonic-gate 	}
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate 	ptr = pmechlist;
8020Sstevel@tonic-gate 	while (ptr != NULL) {
8030Sstevel@tonic-gate 		(void) printf("%s", ptr->name);
8040Sstevel@tonic-gate 		ptr = ptr->next;
8050Sstevel@tonic-gate 		if (ptr == NULL) {
8060Sstevel@tonic-gate 			(void) printf("\n");
8070Sstevel@tonic-gate 		} else {
8080Sstevel@tonic-gate 			(void) printf(",");
8090Sstevel@tonic-gate 		}
8100Sstevel@tonic-gate 	}
8110Sstevel@tonic-gate }
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate  * Update the kcf.conf file based on the specified entry and the update mode.
8160Sstevel@tonic-gate  * - If update_mode is MODIFY_MODE or DELETE_MODE, the entry with the same
8170Sstevel@tonic-gate  *   provider name will be modified or deleted.
8180Sstevel@tonic-gate  * - If update_mode is ADD_MODE, this must be a hardware provider without
8190Sstevel@tonic-gate  *   an entry in the kcf.conf file yet.  Need to locate its driver package
8200Sstevel@tonic-gate  *   bracket and insert an entry into the bracket.
8210Sstevel@tonic-gate  */
8220Sstevel@tonic-gate int
8230Sstevel@tonic-gate update_kcfconf(entry_t *pent, int update_mode)
8240Sstevel@tonic-gate {
8250Sstevel@tonic-gate 	boolean_t	add_it = B_FALSE;
8260Sstevel@tonic-gate 	boolean_t	delete_it = B_FALSE;
8270Sstevel@tonic-gate 	boolean_t	found_package = B_FALSE;
8280Sstevel@tonic-gate 	boolean_t	found_entry = B_FALSE;
8290Sstevel@tonic-gate 	FILE	*pfile;
8300Sstevel@tonic-gate 	FILE	*pfile_tmp;
8310Sstevel@tonic-gate 	char	buffer[BUFSIZ];
8320Sstevel@tonic-gate 	char	buffer2[BUFSIZ];
8330Sstevel@tonic-gate 	char	devname[MAXNAMELEN];
8340Sstevel@tonic-gate 	char	tmpfile_name[MAXPATHLEN];
8350Sstevel@tonic-gate 	char	*name;
8360Sstevel@tonic-gate 	char	*str;
8370Sstevel@tonic-gate 	char	*new_str = NULL;
8380Sstevel@tonic-gate 	int	inst_num;
8390Sstevel@tonic-gate 	int rc = SUCCESS;
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 
8420Sstevel@tonic-gate 	if (pent == NULL) {
8430Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
8440Sstevel@tonic-gate 		return (FAILURE);
8450Sstevel@tonic-gate 	}
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 	/* Check the update_mode */
8480Sstevel@tonic-gate 	if (update_mode == ADD_MODE) {
8490Sstevel@tonic-gate 		add_it = B_TRUE;
8500Sstevel@tonic-gate 		/* Get the hardware provider name first */
8510Sstevel@tonic-gate 		if (split_hw_provname(pent->name, devname, &inst_num) ==
8520Sstevel@tonic-gate 		    FAILURE) {
8530Sstevel@tonic-gate 			return (FAILURE);
8540Sstevel@tonic-gate 		}
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 		/* Convert the entry to be a string  */
8570Sstevel@tonic-gate 		if ((new_str = ent2str(pent)) == NULL) {
8580Sstevel@tonic-gate 			return (FAILURE);
8590Sstevel@tonic-gate 		}
8600Sstevel@tonic-gate 	} else if (update_mode == DELETE_MODE) {
8610Sstevel@tonic-gate 		delete_it = B_TRUE;
8620Sstevel@tonic-gate 	} else if (update_mode != MODIFY_MODE) {
8630Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
8640Sstevel@tonic-gate 		return (FAILURE);
8650Sstevel@tonic-gate 	}
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	/* Open the kcf.conf file */
8690Sstevel@tonic-gate 	if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
8700Sstevel@tonic-gate 		err = errno;
8710Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8720Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
8730Sstevel@tonic-gate 		    strerror(err));
8740Sstevel@tonic-gate 		cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
8750Sstevel@tonic-gate 		return (FAILURE);
8760Sstevel@tonic-gate 	}
8770Sstevel@tonic-gate 
8780Sstevel@tonic-gate 	/* Lock the kcf.conf file */
8790Sstevel@tonic-gate 	if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
8800Sstevel@tonic-gate 		err = errno;
8810Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8820Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
8830Sstevel@tonic-gate 			strerror(err));
8840Sstevel@tonic-gate 		(void) fclose(pfile);
8850Sstevel@tonic-gate 		return (FAILURE);
8860Sstevel@tonic-gate 	}
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate 	/*
8890Sstevel@tonic-gate 	 * Create a temporary file in the /etc/crypto directory to save
8900Sstevel@tonic-gate 	 * updated configuration file first.
8910Sstevel@tonic-gate 	 */
8920Sstevel@tonic-gate 	(void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
8930Sstevel@tonic-gate 	if (mkstemp(tmpfile_name) == -1) {
8940Sstevel@tonic-gate 		err = errno;
8950Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
8960Sstevel@tonic-gate 		    gettext("failed to create a temporary file - %s"),
8970Sstevel@tonic-gate 		    strerror(err));
8980Sstevel@tonic-gate 		(void) fclose(pfile);
8990Sstevel@tonic-gate 		return (FAILURE);
9000Sstevel@tonic-gate 	}
9010Sstevel@tonic-gate 
9020Sstevel@tonic-gate 	if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
9030Sstevel@tonic-gate 		err = errno;
9040Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
9050Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
9060Sstevel@tonic-gate 		(void) fclose(pfile);
9070Sstevel@tonic-gate 		return (FAILURE);
9080Sstevel@tonic-gate 	}
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 	/*
9110Sstevel@tonic-gate 	 * Loop thru the entire kcf.conf file, insert, modify or delete
9120Sstevel@tonic-gate 	 * an entry.
9130Sstevel@tonic-gate 	 */
9140Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
9150Sstevel@tonic-gate 		if (add_it) {
9160Sstevel@tonic-gate 			/* always keep the current line */
9170Sstevel@tonic-gate 			if (fputs(buffer, pfile_tmp) == EOF) {
9180Sstevel@tonic-gate 				err = errno;
9190Sstevel@tonic-gate 				cryptoerror(LOG_STDERR, gettext(
9200Sstevel@tonic-gate 				    "failed to write to a temp file: %s."),
9210Sstevel@tonic-gate 				    strerror(err));
9220Sstevel@tonic-gate 				rc = FAILURE;
9230Sstevel@tonic-gate 				break;
9240Sstevel@tonic-gate 			}
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 			/*
9270Sstevel@tonic-gate 			 * If the current position is the beginning of a driver
9280Sstevel@tonic-gate 			 * package and if the driver name matches the hardware
9290Sstevel@tonic-gate 			 * provider name, then we want to insert the entry
9300Sstevel@tonic-gate 			 * here.
9310Sstevel@tonic-gate 			 */
9320Sstevel@tonic-gate 			if ((strstr(buffer, HW_DRIVER_STRING) != NULL) &&
9330Sstevel@tonic-gate 			    (strstr(buffer, devname) != NULL)) {
9340Sstevel@tonic-gate 				found_package = B_TRUE;
9350Sstevel@tonic-gate 				if (fputs(new_str, pfile_tmp) == EOF) {
9360Sstevel@tonic-gate 					err = errno;
9370Sstevel@tonic-gate 					cryptoerror(LOG_STDERR, gettext(
9380Sstevel@tonic-gate 					    "failed to write to a temp file: "
9390Sstevel@tonic-gate 					    "%s."), strerror(err));
9400Sstevel@tonic-gate 					rc = FAILURE;
9410Sstevel@tonic-gate 					break;
9420Sstevel@tonic-gate 				}
9430Sstevel@tonic-gate 			}
9440Sstevel@tonic-gate 		} else { /* modify or delete */
9450Sstevel@tonic-gate 			found_entry = B_FALSE;
9460Sstevel@tonic-gate 			if (!(buffer[0] == '#' || buffer[0] == ' ' ||
9470Sstevel@tonic-gate 			    buffer[0] == '\n'|| buffer[0] == '\t')) {
9480Sstevel@tonic-gate 				/*
9490Sstevel@tonic-gate 				 * Get the provider name from this line and
9500Sstevel@tonic-gate 				 * check if this is the entry to be updated
9510Sstevel@tonic-gate 				 * or deleted. Note: can not use "buffer"
9520Sstevel@tonic-gate 				 * directly because strtok will change its
9530Sstevel@tonic-gate 				 * value.
9540Sstevel@tonic-gate 				 */
9550Sstevel@tonic-gate 				(void) strlcpy(buffer2, buffer, BUFSIZ);
9560Sstevel@tonic-gate 				if ((name = strtok(buffer2, SEP_COLON)) ==
9570Sstevel@tonic-gate 				    NULL) {
9580Sstevel@tonic-gate 					rc = FAILURE;
9590Sstevel@tonic-gate 					break;
9600Sstevel@tonic-gate 				}
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate 				if (strcmp(pent->name, name) == 0) {
9630Sstevel@tonic-gate 					found_entry = B_TRUE;
9640Sstevel@tonic-gate 				}
9650Sstevel@tonic-gate 			}
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 			if (found_entry && !delete_it) {
9680Sstevel@tonic-gate 				/*
9690Sstevel@tonic-gate 				 * This is the entry to be updated; get the
9700Sstevel@tonic-gate 				 * updated string and place into buffer.
9710Sstevel@tonic-gate 				 */
9720Sstevel@tonic-gate 				if ((str = ent2str(pent)) == NULL) {
9730Sstevel@tonic-gate 					rc = FAILURE;
9740Sstevel@tonic-gate 					break;
9750Sstevel@tonic-gate 				} else {
9760Sstevel@tonic-gate 					(void) strlcpy(buffer, str, BUFSIZ);
9770Sstevel@tonic-gate 					free(str);
9780Sstevel@tonic-gate 				}
9790Sstevel@tonic-gate 			}
9800Sstevel@tonic-gate 
9810Sstevel@tonic-gate 			if (!(found_entry && delete_it)) {
9820Sstevel@tonic-gate 				/* This is the entry to be updated/reserved */
9830Sstevel@tonic-gate 				if (fputs(buffer, pfile_tmp) == EOF) {
9840Sstevel@tonic-gate 					err = errno;
9850Sstevel@tonic-gate 					cryptoerror(LOG_STDERR, gettext(
9860Sstevel@tonic-gate 					    "failed to write to a temp file: "
9870Sstevel@tonic-gate 					    "%s."), strerror(err));
9880Sstevel@tonic-gate 					rc = FAILURE;
9890Sstevel@tonic-gate 					break;
9900Sstevel@tonic-gate 				}
9910Sstevel@tonic-gate 			}
9920Sstevel@tonic-gate 		}
9930Sstevel@tonic-gate 	}
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 	if (add_it) {
9960Sstevel@tonic-gate 		free(new_str);
9970Sstevel@tonic-gate 	}
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate 	if ((add_it && !found_package) || (rc == FAILURE)) {
10000Sstevel@tonic-gate 		if (add_it && !found_package) {
10010Sstevel@tonic-gate 			cryptoerror(LOG_STDERR,
10020Sstevel@tonic-gate 			    gettext("failed to update configuration - no "
10030Sstevel@tonic-gate 			    "driver package information."));
10040Sstevel@tonic-gate 		}
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate 		(void) fclose(pfile);
10070Sstevel@tonic-gate 		(void) fclose(pfile_tmp);
10080Sstevel@tonic-gate 		if (unlink(tmpfile_name) != 0) {
10090Sstevel@tonic-gate 			err = errno;
10100Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext(
10110Sstevel@tonic-gate 			    "(Warning) failed to remove %s: %s"),
10120Sstevel@tonic-gate 			    tmpfile_name, strerror(err));
10130Sstevel@tonic-gate 		}
10140Sstevel@tonic-gate 		return (FAILURE);
10150Sstevel@tonic-gate 	}
10160Sstevel@tonic-gate 
10170Sstevel@tonic-gate 	(void) fclose(pfile);
10180Sstevel@tonic-gate 	if (fclose(pfile_tmp) != 0) {
10190Sstevel@tonic-gate 		err = errno;
10200Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10210Sstevel@tonic-gate 		    gettext("failed to close %s: %s"), tmpfile_name,
10220Sstevel@tonic-gate 		    strerror(err));
10230Sstevel@tonic-gate 		return (FAILURE);
10240Sstevel@tonic-gate 	}
10250Sstevel@tonic-gate 
10260Sstevel@tonic-gate 	/* Copy the temporary file to the kcf.conf file */
10270Sstevel@tonic-gate 	if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
10280Sstevel@tonic-gate 		err = errno;
10290Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10300Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
10310Sstevel@tonic-gate 		    strerror(err));
10320Sstevel@tonic-gate 		cryptodebug("failed to rename %s to %s: %s", tmpfile,
10330Sstevel@tonic-gate 		    _PATH_KCF_CONF, strerror(err));
10340Sstevel@tonic-gate 		rc = FAILURE;
10350Sstevel@tonic-gate 	} else if (chmod(_PATH_KCF_CONF,
10360Sstevel@tonic-gate 	    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
10370Sstevel@tonic-gate 		err = errno;
10380Sstevel@tonic-gate 		cryptoerror(LOG_STDERR,
10390Sstevel@tonic-gate 		    gettext("failed to update the configuration - %s"),
10400Sstevel@tonic-gate 		    strerror(err));
10410Sstevel@tonic-gate 		cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
10420Sstevel@tonic-gate 		    strerror(err));
10430Sstevel@tonic-gate 		rc = FAILURE;
10440Sstevel@tonic-gate 	} else {
10450Sstevel@tonic-gate 		rc = SUCCESS;
10460Sstevel@tonic-gate 	}
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 	if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
10490Sstevel@tonic-gate 		err = errno;
10500Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext(
10510Sstevel@tonic-gate 		    "(Warning) failed to remove %s: %s"),
10520Sstevel@tonic-gate 		    tmpfile_name, strerror(err));
10530Sstevel@tonic-gate 	}
10540Sstevel@tonic-gate 
10550Sstevel@tonic-gate 	return (rc);
10560Sstevel@tonic-gate }
10570Sstevel@tonic-gate 
10580Sstevel@tonic-gate 
10590Sstevel@tonic-gate /*
10600Sstevel@tonic-gate  * Disable the mechanisms for the provider pointed by *ppent.  If allflag is
10610Sstevel@tonic-gate  * TRUE, disable all.  Otherwise, disable the mechanisms specified in the
10620Sstevel@tonic-gate  * dislist argument.  The "infolist" argument contains the mechanism list
10630Sstevel@tonic-gate  * supported by this provider.
10640Sstevel@tonic-gate  */
10650Sstevel@tonic-gate int
10660Sstevel@tonic-gate disable_mechs(entry_t **ppent, mechlist_t *infolist, boolean_t allflag,
10670Sstevel@tonic-gate mechlist_t *dislist)
10680Sstevel@tonic-gate {
10690Sstevel@tonic-gate 	entry_t *pent;
10700Sstevel@tonic-gate 	mechlist_t *plist;
10710Sstevel@tonic-gate 	mechlist_t *phead;
10720Sstevel@tonic-gate 	mechlist_t *pmech;
10730Sstevel@tonic-gate 	int rc = SUCCESS;
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 	pent = *ppent;
10760Sstevel@tonic-gate 	if (pent == NULL) {
10770Sstevel@tonic-gate 		return (FAILURE);
10780Sstevel@tonic-gate 	}
10790Sstevel@tonic-gate 
10800Sstevel@tonic-gate 	if (allflag) {
10810Sstevel@tonic-gate 		free_mechlist(pent->dislist);
10820Sstevel@tonic-gate 		pent->dis_count = get_mech_count(infolist);
10830Sstevel@tonic-gate 		if (!(pent->dislist = dup_mechlist(infolist))) {
10840Sstevel@tonic-gate 			return (FAILURE);
10850Sstevel@tonic-gate 		} else {
10860Sstevel@tonic-gate 			return (SUCCESS);
10870Sstevel@tonic-gate 		}
10880Sstevel@tonic-gate 	}
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 	/*
10910Sstevel@tonic-gate 	 * Not disable all. Now loop thru the mechanisms specified in the
10920Sstevel@tonic-gate 	 * dislist.  If the mechanism is not supported by the provider,
10930Sstevel@tonic-gate 	 * ignore it with a warning.  If the mechanism is disabled already,
10940Sstevel@tonic-gate 	 * do nothing. Otherwise, prepend it to the beginning of the disabled
10950Sstevel@tonic-gate 	 * list of the provider.
10960Sstevel@tonic-gate 	 */
10970Sstevel@tonic-gate 	plist = dislist;
10980Sstevel@tonic-gate 	while (plist != NULL) {
10990Sstevel@tonic-gate 		if (!is_in_list(plist->name, infolist)) {
11000Sstevel@tonic-gate 			cryptoerror(LOG_STDERR, gettext("(Warning) "
11010Sstevel@tonic-gate 			    "%1$s is not a valid mechanism for %2$s."),
11020Sstevel@tonic-gate 			    plist->name, pent->name);
11030Sstevel@tonic-gate 		} else if (!is_in_list(plist->name, pent->dislist)) {
11040Sstevel@tonic-gate 			/* Add this mechanism into the disabled list */
11050Sstevel@tonic-gate 			if ((pmech = create_mech(plist->name)) == NULL) {
11060Sstevel@tonic-gate 				rc = FAILURE;
11070Sstevel@tonic-gate 				break;
11080Sstevel@tonic-gate 			}
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 			if (pent->dislist == NULL) {
11110Sstevel@tonic-gate 				pent->dislist = pmech;
11120Sstevel@tonic-gate 			} else {
11130Sstevel@tonic-gate 				phead = pent->dislist;
11140Sstevel@tonic-gate 				pent->dislist = pmech;
11150Sstevel@tonic-gate 				pmech->next = phead;
11160Sstevel@tonic-gate 			}
11170Sstevel@tonic-gate 			pent->dis_count++;
11180Sstevel@tonic-gate 		}
11190Sstevel@tonic-gate 		plist = plist->next;
11200Sstevel@tonic-gate 	}
11210Sstevel@tonic-gate 
11220Sstevel@tonic-gate 	return (rc);
11230Sstevel@tonic-gate }
11240Sstevel@tonic-gate 
11250Sstevel@tonic-gate /*
11260Sstevel@tonic-gate  * Remove the mechanism passed, specified by mech, from the list of
11270Sstevel@tonic-gate  * mechanisms, if present in the list. Else, do nothing.
11280Sstevel@tonic-gate  *
11290Sstevel@tonic-gate  * Returns B_TRUE if mechanism is present in the list.
11300Sstevel@tonic-gate  */
11310Sstevel@tonic-gate boolean_t
11320Sstevel@tonic-gate filter_mechlist(mechlist_t **pmechlist, const char *mech)
11330Sstevel@tonic-gate {
11340Sstevel@tonic-gate 	int cnt = 0;
11350Sstevel@tonic-gate 	mechlist_t *ptr, *pptr;
11360Sstevel@tonic-gate 	boolean_t mech_present = B_FALSE;
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate 	ptr = pptr = *pmechlist;
11390Sstevel@tonic-gate 
11400Sstevel@tonic-gate 	while (ptr != NULL) {
11410Sstevel@tonic-gate 		if (strncmp(ptr->name, mech, sizeof (mech_name_t)) == 0) {
11420Sstevel@tonic-gate 			mech_present = B_TRUE;
11430Sstevel@tonic-gate 			if (ptr == *pmechlist) {
11440Sstevel@tonic-gate 				pptr = *pmechlist = ptr->next;
11450Sstevel@tonic-gate 				free(ptr);
11460Sstevel@tonic-gate 				ptr = pptr;
11470Sstevel@tonic-gate 			} else {
11480Sstevel@tonic-gate 				pptr->next = ptr->next;
11490Sstevel@tonic-gate 				free(ptr);
11500Sstevel@tonic-gate 				ptr = pptr->next;
11510Sstevel@tonic-gate 			}
11520Sstevel@tonic-gate 		} else {
11530Sstevel@tonic-gate 			pptr = ptr;
11540Sstevel@tonic-gate 			ptr = ptr->next;
11550Sstevel@tonic-gate 			cnt++;
11560Sstevel@tonic-gate 		}
11570Sstevel@tonic-gate 	}
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate 	/* Only one entry is present */
11600Sstevel@tonic-gate 	if (cnt == 0)
11610Sstevel@tonic-gate 		*pmechlist = NULL;
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate 	return (mech_present);
11640Sstevel@tonic-gate }
11650Sstevel@tonic-gate 
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate /*
11690Sstevel@tonic-gate  * Print out the mechanism policy for a kernel provider that has an entry
11700Sstevel@tonic-gate  * in the kcf.conf file.
11710Sstevel@tonic-gate  *
11720Sstevel@tonic-gate  * The flag has_random is set to B_TRUE if the provider does random
11730Sstevel@tonic-gate  * numbers. The flag has_mechs is set by the caller to B_TRUE if the provider
11740Sstevel@tonic-gate  * has some mechanisms.
11750Sstevel@tonic-gate  */
11760Sstevel@tonic-gate void
11770Sstevel@tonic-gate print_kef_policy(entry_t *pent, boolean_t has_random, boolean_t has_mechs)
11780Sstevel@tonic-gate {
11790Sstevel@tonic-gate 	mechlist_t *ptr;
11800Sstevel@tonic-gate 	boolean_t rnd_disabled = B_FALSE;
11810Sstevel@tonic-gate 
11820Sstevel@tonic-gate 	if (pent == NULL) {
11830Sstevel@tonic-gate 		return;
11840Sstevel@tonic-gate 	}
11850Sstevel@tonic-gate 
11860Sstevel@tonic-gate 	rnd_disabled = filter_mechlist(&pent->dislist, RANDOM);
11870Sstevel@tonic-gate 	ptr = pent->dislist;
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	(void) printf("%s:", pent->name);
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	if (has_mechs == B_TRUE) {
11920Sstevel@tonic-gate 		/*
1193*7334SDaniel.Anderson@Sun.COM 		 * TRANSLATION_NOTE
11940Sstevel@tonic-gate 		 * This code block may need to be modified a bit to avoid
11950Sstevel@tonic-gate 		 * constructing the text message on the fly.
11960Sstevel@tonic-gate 		 */
11970Sstevel@tonic-gate 		(void) printf(gettext(" all mechanisms are enabled"));
11980Sstevel@tonic-gate 		if (ptr != NULL)
11990Sstevel@tonic-gate 			(void) printf(gettext(", except "));
12000Sstevel@tonic-gate 		while (ptr != NULL) {
12010Sstevel@tonic-gate 			(void) printf("%s", ptr->name);
12020Sstevel@tonic-gate 			ptr = ptr->next;
12030Sstevel@tonic-gate 			if (ptr != NULL)
12040Sstevel@tonic-gate 				(void) printf(",");
12050Sstevel@tonic-gate 		}
12060Sstevel@tonic-gate 		if (ptr == NULL)
12070Sstevel@tonic-gate 			(void) printf(".");
12080Sstevel@tonic-gate 	}
12090Sstevel@tonic-gate 
12100Sstevel@tonic-gate 	/*
1211*7334SDaniel.Anderson@Sun.COM 	 * TRANSLATION_NOTE
12120Sstevel@tonic-gate 	 * "random" is a keyword and not to be translated.
12130Sstevel@tonic-gate 	 */
12140Sstevel@tonic-gate 	if (rnd_disabled)
12150Sstevel@tonic-gate 		(void) printf(gettext(" %s is disabled."), "random");
12160Sstevel@tonic-gate 	else if (has_random)
12170Sstevel@tonic-gate 		(void) printf(gettext(" %s is enabled."), "random");
12180Sstevel@tonic-gate 	(void) printf("\n");
12190Sstevel@tonic-gate }
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate /*
12220Sstevel@tonic-gate  * Check if a kernel software provider is in the kernel.
12230Sstevel@tonic-gate  */
12240Sstevel@tonic-gate int
12250Sstevel@tonic-gate check_active_for_soft(char *provname, boolean_t *is_active)
12260Sstevel@tonic-gate {
12270Sstevel@tonic-gate 	crypto_get_soft_list_t	*psoftlist_kernel = NULL;
12280Sstevel@tonic-gate 	char	*ptr;
12290Sstevel@tonic-gate 	int	i;
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 	if (provname == NULL) {
12320Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
12330Sstevel@tonic-gate 		return (FAILURE);
12340Sstevel@tonic-gate 	}
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate 	if (get_soft_list(&psoftlist_kernel) == FAILURE) {
12370Sstevel@tonic-gate 		cryptodebug("failed to get the software provider list from"
12380Sstevel@tonic-gate 		    "kernel.");
12390Sstevel@tonic-gate 		return (FAILURE);
12400Sstevel@tonic-gate 	}
12410Sstevel@tonic-gate 
12420Sstevel@tonic-gate 	*is_active = B_FALSE;
12430Sstevel@tonic-gate 	ptr = psoftlist_kernel->sl_soft_names;
12440Sstevel@tonic-gate 	for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
12450Sstevel@tonic-gate 		if (strcmp(provname, ptr) == 0) {
12460Sstevel@tonic-gate 			*is_active = B_TRUE;
12470Sstevel@tonic-gate 			break;
12480Sstevel@tonic-gate 		}
12490Sstevel@tonic-gate 		ptr = ptr + strlen(ptr) + 1;
12500Sstevel@tonic-gate 	}
12510Sstevel@tonic-gate 	free(psoftlist_kernel);
12520Sstevel@tonic-gate 
12530Sstevel@tonic-gate 	return (SUCCESS);
12540Sstevel@tonic-gate }
12550Sstevel@tonic-gate 
12560Sstevel@tonic-gate 
12570Sstevel@tonic-gate /*
12580Sstevel@tonic-gate  * Check if a kernel hardware provider is in the kernel.
12590Sstevel@tonic-gate  */
12600Sstevel@tonic-gate int
12610Sstevel@tonic-gate check_active_for_hard(char *provname, boolean_t *is_active)
12620Sstevel@tonic-gate {
12630Sstevel@tonic-gate 	crypto_get_dev_list_t	*pdevlist = NULL;
12640Sstevel@tonic-gate 	char 	devname[MAXNAMELEN];
12650Sstevel@tonic-gate 	int	inst_num;
12660Sstevel@tonic-gate 	int	i;
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate 	if (provname == NULL) {
12690Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
12700Sstevel@tonic-gate 		return (FAILURE);
12710Sstevel@tonic-gate 	}
12720Sstevel@tonic-gate 
12730Sstevel@tonic-gate 	if (split_hw_provname(provname, devname, &inst_num) == FAILURE) {
12740Sstevel@tonic-gate 		return (FAILURE);
12750Sstevel@tonic-gate 	}
12760Sstevel@tonic-gate 
12770Sstevel@tonic-gate 	if (get_dev_list(&pdevlist) == FAILURE) {
12780Sstevel@tonic-gate 		cryptoerror(LOG_STDERR, gettext("internal error."));
12790Sstevel@tonic-gate 		return (FAILURE);
12800Sstevel@tonic-gate 	}
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 	*is_active = B_FALSE;
12830Sstevel@tonic-gate 	for (i = 0; i < pdevlist->dl_dev_count; i++) {
12840Sstevel@tonic-gate 		if ((strcmp(pdevlist->dl_devs[i].le_dev_name, devname) == 0) &&
12850Sstevel@tonic-gate 		    (pdevlist->dl_devs[i].le_dev_instance == inst_num)) {
12860Sstevel@tonic-gate 			*is_active = B_TRUE;
12870Sstevel@tonic-gate 			break;
12880Sstevel@tonic-gate 		}
12890Sstevel@tonic-gate 	}
12900Sstevel@tonic-gate 	free(pdevlist);
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate 	return (SUCCESS);
12930Sstevel@tonic-gate }
1294