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
51914Scasper  * Common Development and Distribution License (the "License").
61914Scasper  * 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 /*
221914Scasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <stdio.h>
290Sstevel@tonic-gate #include <errno.h>
300Sstevel@tonic-gate #include <strings.h>
310Sstevel@tonic-gate #include <locale.h>
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include "cryptoutil.h"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate static int uef_interpret(char *, uentry_t **);
360Sstevel@tonic-gate static int parse_policylist(char *, uentry_t *);
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate  * Retrieve the user-level provider info from the pkcs11.conf file.
400Sstevel@tonic-gate  * If successful, the result is returned from the ppliblist argument.
410Sstevel@tonic-gate  * This function returns SUCCESS if successfully done; otherwise it returns
420Sstevel@tonic-gate  * FAILURE.
430Sstevel@tonic-gate  */
440Sstevel@tonic-gate int
450Sstevel@tonic-gate get_pkcs11conf_info(uentrylist_t **ppliblist)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate 	FILE *pfile;
480Sstevel@tonic-gate 	char buffer[BUFSIZ];
490Sstevel@tonic-gate 	size_t len;
500Sstevel@tonic-gate 	uentry_t *pent;
510Sstevel@tonic-gate 	uentrylist_t *pentlist;
520Sstevel@tonic-gate 	uentrylist_t *pcur;
530Sstevel@tonic-gate 	int rc = SUCCESS;
540Sstevel@tonic-gate 
550Sstevel@tonic-gate 	*ppliblist = NULL;
561914Scasper 	if ((pfile = fopen(_PATH_PKCS11_CONF, "rF")) == NULL) {
570Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_PKCS11_CONF);
580Sstevel@tonic-gate 		return (FAILURE);
590Sstevel@tonic-gate 	}
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
620Sstevel@tonic-gate 		if (buffer[0] == '#' || buffer[0] == ' ' ||
630Sstevel@tonic-gate 		    buffer[0] == '\n'|| buffer[0] == '\t') {
640Sstevel@tonic-gate 			continue;   /* ignore comment lines */
650Sstevel@tonic-gate 		}
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 		len = strlen(buffer);
680Sstevel@tonic-gate 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
690Sstevel@tonic-gate 			len--;
700Sstevel@tonic-gate 		}
710Sstevel@tonic-gate 		buffer[len] = '\0';
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 		if ((rc = uef_interpret(buffer,  &pent)) != SUCCESS) {
740Sstevel@tonic-gate 			break;
750Sstevel@tonic-gate 		}
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 		/* append pent into ppliblist */
780Sstevel@tonic-gate 		pentlist = malloc(sizeof (uentrylist_t));
790Sstevel@tonic-gate 		if (pentlist == NULL) {
800Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
810Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
820Sstevel@tonic-gate 			free_uentry(pent);
830Sstevel@tonic-gate 			rc = FAILURE;
840Sstevel@tonic-gate 			break;
850Sstevel@tonic-gate 		}
860Sstevel@tonic-gate 		pentlist->puent = pent;
870Sstevel@tonic-gate 		pentlist->next = NULL;
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 		if (*ppliblist == NULL) {
900Sstevel@tonic-gate 			*ppliblist = pcur = pentlist;
910Sstevel@tonic-gate 		} else {
920Sstevel@tonic-gate 			pcur->next = pentlist;
930Sstevel@tonic-gate 			pcur = pcur->next;
940Sstevel@tonic-gate 		}
950Sstevel@tonic-gate 	}
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	(void) fclose(pfile);
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	if (rc != SUCCESS) {
1000Sstevel@tonic-gate 		free_uentrylist(*ppliblist);
1010Sstevel@tonic-gate 		*ppliblist = NULL;
1020Sstevel@tonic-gate 	}
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	return (rc);
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate /*
1090Sstevel@tonic-gate  * This routine converts a char string into a uentry_t structure
1100Sstevel@tonic-gate  * The input string "buf" should be one of the following:
1110Sstevel@tonic-gate  *	library_name
1120Sstevel@tonic-gate  *	library_name:NO_RANDOM
1130Sstevel@tonic-gate  *	library_name:disabledlist=m1,m2,...,mk
1140Sstevel@tonic-gate  *	library_name:disabledlist=m1,m2,...,mk;NO_RANDOM
1150Sstevel@tonic-gate  *	library_name:enabledlist=
1160Sstevel@tonic-gate  *	library_name:enabledlist=;NO_RANDOM
1170Sstevel@tonic-gate  *	library_name:enabledlist=m1,m2,...,mk
1180Sstevel@tonic-gate  *	library_name:enabledlist=m1,m2,...,mk;NO_RANDOM
1190Sstevel@tonic-gate  *	metaslot:status=enabled;enabledlist=m1,m2,....;slot=<slot-description>;\
1200Sstevel@tonic-gate  *	token=<token-label>
1210Sstevel@tonic-gate  *
1220Sstevel@tonic-gate  * Note:
1230Sstevel@tonic-gate  *	The mechanisms m1,..mk are in hex form. For example, "0x00000210"
1240Sstevel@tonic-gate  *	for CKM_MD5.
1250Sstevel@tonic-gate  *
1260Sstevel@tonic-gate  *	For the metaslot entry, "enabledlist", "slot", "auto_key_migrate"
1270Sstevel@tonic-gate  * 	or "token" is optional
1280Sstevel@tonic-gate  */
1290Sstevel@tonic-gate static int
1300Sstevel@tonic-gate uef_interpret(char *buf, uentry_t **ppent)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate 	uentry_t *pent;
1330Sstevel@tonic-gate 	char	*token1;
1340Sstevel@tonic-gate 	char	*token2;
1350Sstevel@tonic-gate 	char	*lasts;
1360Sstevel@tonic-gate 	int	rc;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	*ppent = NULL;
1390Sstevel@tonic-gate 	if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) {
1400Sstevel@tonic-gate 		/* buf is NULL */
1410Sstevel@tonic-gate 		return (FAILURE);
1420Sstevel@tonic-gate 	};
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	pent = calloc(sizeof (uentry_t), 1);
1450Sstevel@tonic-gate 	if (pent == NULL) {
1460Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
1470Sstevel@tonic-gate 		    _PATH_PKCS11_CONF);
1480Sstevel@tonic-gate 		return (FAILURE);
1490Sstevel@tonic-gate 	}
1500Sstevel@tonic-gate 	(void) strlcpy(pent->name, token1, sizeof (pent->name));
1510Sstevel@tonic-gate 	/*
1520Sstevel@tonic-gate 	 * in case metaslot_auto_key_migrate is not specified, it should
1530Sstevel@tonic-gate 	 * be default to true
1540Sstevel@tonic-gate 	 */
1550Sstevel@tonic-gate 	pent->flag_metaslot_auto_key_migrate = B_TRUE;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	while ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) != NULL) {
1580Sstevel@tonic-gate 		if ((rc = parse_policylist(token2, pent)) != SUCCESS) {
1590Sstevel@tonic-gate 			free_uentry(pent);
1600Sstevel@tonic-gate 			return (rc);
1610Sstevel@tonic-gate 		}
1620Sstevel@tonic-gate 	}
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	*ppent = pent;
1650Sstevel@tonic-gate 	return (SUCCESS);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * This routine parses the policy list and stored the result in the argument
1710Sstevel@tonic-gate  * pent.
1720Sstevel@tonic-gate  *
1730Sstevel@tonic-gate  * 	Arg buf: input only, its format should be one of the following:
1740Sstevel@tonic-gate  *     		enabledlist=
1750Sstevel@tonic-gate  *		enabledlist=m1,m2,...,mk
1760Sstevel@tonic-gate  *		disabledlist=m1,m2,...,mk
1770Sstevel@tonic-gate  *		NO_RANDOM
1780Sstevel@tonic-gate  *		metaslot_status=enabled|disabled
1790Sstevel@tonic-gate  *		metaslot_token=<token-label>
1800Sstevel@tonic-gate  *		metaslot_slot=<slot-description.
1810Sstevel@tonic-gate  *
1820Sstevel@tonic-gate  *	Arg pent: input/output
1830Sstevel@tonic-gate  *
1840Sstevel@tonic-gate  *      return: SUCCESS or FAILURE
1850Sstevel@tonic-gate  */
1860Sstevel@tonic-gate static int
1870Sstevel@tonic-gate parse_policylist(char *buf, uentry_t *pent)
1880Sstevel@tonic-gate {
1890Sstevel@tonic-gate 	umechlist_t *phead = NULL;
1900Sstevel@tonic-gate 	umechlist_t *pcur = NULL;
1910Sstevel@tonic-gate 	umechlist_t *pmech;
1920Sstevel@tonic-gate 	char *next_token;
1930Sstevel@tonic-gate 	char *value;
1940Sstevel@tonic-gate 	char *lasts;
1950Sstevel@tonic-gate 	int count = 0;
1960Sstevel@tonic-gate 	int rc = SUCCESS;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	if (pent == NULL) {
1990Sstevel@tonic-gate 		return (FAILURE);
2000Sstevel@tonic-gate 	}
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	if (strncmp(buf, EF_DISABLED, sizeof (EF_DISABLED) - 1) == 0) {
2030Sstevel@tonic-gate 		pent->flag_enabledlist = B_FALSE;
2040Sstevel@tonic-gate 	} else if (strncmp(buf, EF_ENABLED, sizeof (EF_ENABLED) - 1) == 0) {
2050Sstevel@tonic-gate 		pent->flag_enabledlist = B_TRUE;
2060Sstevel@tonic-gate 	} else if (strncmp(buf, EF_NORANDOM, sizeof (EF_NORANDOM) - 1) == 0) {
2070Sstevel@tonic-gate 		pent->flag_norandom = B_TRUE;
2080Sstevel@tonic-gate 		return (rc);
2090Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_TOKEN,
2100Sstevel@tonic-gate 	    sizeof (METASLOT_TOKEN) - 1) == 0) {
2110Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2120Sstevel@tonic-gate 			value++; /* get rid of = */
2130Sstevel@tonic-gate 			(void) strlcpy((char *)pent->metaslot_ks_token, value,
214*3089Swyllys 			    sizeof (pent->metaslot_ks_token));
2150Sstevel@tonic-gate 			return (SUCCESS);
2160Sstevel@tonic-gate 		} else {
2170Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2180Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2190Sstevel@tonic-gate 			return (FAILURE);
2200Sstevel@tonic-gate 		}
2210Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_SLOT,
2220Sstevel@tonic-gate 	    sizeof (METASLOT_SLOT) - 1) == 0) {
2230Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2240Sstevel@tonic-gate 			value++; /* get rid of = */
2250Sstevel@tonic-gate 			(void) strlcpy((char *)pent->metaslot_ks_slot, value,
226*3089Swyllys 			    sizeof (pent->metaslot_ks_slot));
2270Sstevel@tonic-gate 			return (SUCCESS);
2280Sstevel@tonic-gate 		} else {
2290Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2300Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2310Sstevel@tonic-gate 			return (FAILURE);
2320Sstevel@tonic-gate 		}
2330Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_STATUS,
2340Sstevel@tonic-gate 	    sizeof (METASLOT_STATUS) - 1) == 0) {
2350Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2360Sstevel@tonic-gate 			value++; /* get rid of = */
2370Sstevel@tonic-gate 			if (strcmp(value, METASLOT_DISABLED) == 0) {
2380Sstevel@tonic-gate 				pent->flag_metaslot_enabled = B_FALSE;
2390Sstevel@tonic-gate 			} else if (strcmp(value, METASLOT_ENABLED) == 0) {
2400Sstevel@tonic-gate 				pent->flag_metaslot_enabled = B_TRUE;
2410Sstevel@tonic-gate 			} else {
2420Sstevel@tonic-gate 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
2430Sstevel@tonic-gate 				    _PATH_PKCS11_CONF);
2440Sstevel@tonic-gate 				return (FAILURE);
2450Sstevel@tonic-gate 			}
2460Sstevel@tonic-gate 			return (SUCCESS);
2470Sstevel@tonic-gate 		} else {
2480Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2490Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2500Sstevel@tonic-gate 			return (FAILURE);
2510Sstevel@tonic-gate 		}
2520Sstevel@tonic-gate 	} else if (strncmp(buf, METASLOT_AUTO_KEY_MIGRATE,
2530Sstevel@tonic-gate 	    sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) {
2540Sstevel@tonic-gate 		if (value = strpbrk(buf, SEP_EQUAL)) {
2550Sstevel@tonic-gate 			value++; /* get rid of = */
2560Sstevel@tonic-gate 			if (strcmp(value, METASLOT_DISABLED) == 0) {
2570Sstevel@tonic-gate 				pent->flag_metaslot_auto_key_migrate = B_FALSE;
2580Sstevel@tonic-gate 			} else if (strcmp(value, METASLOT_ENABLED) == 0) {
2590Sstevel@tonic-gate 				pent->flag_metaslot_auto_key_migrate = B_TRUE;
2600Sstevel@tonic-gate 			} else {
2610Sstevel@tonic-gate 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
2620Sstevel@tonic-gate 				    _PATH_PKCS11_CONF);
2630Sstevel@tonic-gate 				return (FAILURE);
2640Sstevel@tonic-gate 			}
2650Sstevel@tonic-gate 			return (SUCCESS);
2660Sstevel@tonic-gate 		} else {
2670Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2680Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2690Sstevel@tonic-gate 			return (FAILURE);
2700Sstevel@tonic-gate 		}
2710Sstevel@tonic-gate 	} else {
2720Sstevel@tonic-gate 		cryptoerror(LOG_ERR, "failed to parse %s.\n",
2730Sstevel@tonic-gate 		    _PATH_PKCS11_CONF);
2740Sstevel@tonic-gate 		return (FAILURE);
2750Sstevel@tonic-gate 	}
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	if (value = strpbrk(buf, SEP_EQUAL)) {
2780Sstevel@tonic-gate 		value++; /* get rid of = */
2790Sstevel@tonic-gate 	}
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	if ((next_token = strtok_r(value, SEP_COMMA, &lasts)) == NULL) {
2820Sstevel@tonic-gate 		if (pent->flag_enabledlist) {
2830Sstevel@tonic-gate 			return (SUCCESS);
2840Sstevel@tonic-gate 		} else {
2850Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
2860Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2870Sstevel@tonic-gate 			return (FAILURE);
2880Sstevel@tonic-gate 		}
2890Sstevel@tonic-gate 	}
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	while (next_token) {
2920Sstevel@tonic-gate 		if ((pmech = create_umech(next_token)) == NULL) {
2930Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
2940Sstevel@tonic-gate 			    _PATH_PKCS11_CONF);
2950Sstevel@tonic-gate 			rc = FAILURE;
2960Sstevel@tonic-gate 			break;
2970Sstevel@tonic-gate 		}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 		if (phead == NULL) {
3000Sstevel@tonic-gate 			phead = pcur = pmech;
3010Sstevel@tonic-gate 		} else {
3020Sstevel@tonic-gate 			pcur->next = pmech;
3030Sstevel@tonic-gate 			pcur = pcur->next;
3040Sstevel@tonic-gate 		}
3050Sstevel@tonic-gate 		count++;
3060Sstevel@tonic-gate 		next_token = strtok_r(NULL, SEP_COMMA, &lasts);
3070Sstevel@tonic-gate 	}
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	if (rc == SUCCESS) {
3100Sstevel@tonic-gate 		pent->policylist = phead;
3110Sstevel@tonic-gate 		pent->count = count;
3120Sstevel@tonic-gate 	} else {
3130Sstevel@tonic-gate 		free_umechlist(phead);
3140Sstevel@tonic-gate 	}
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	return (rc);
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate /*
3210Sstevel@tonic-gate  * Create one item of type umechlist_t with the mechanism name.  A NULL is
3220Sstevel@tonic-gate  * returned when the input name is NULL or the heap memory is insufficient.
3230Sstevel@tonic-gate  */
3240Sstevel@tonic-gate umechlist_t *
3250Sstevel@tonic-gate create_umech(char *name)
3260Sstevel@tonic-gate {
3270Sstevel@tonic-gate 	umechlist_t *pmech = NULL;
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	if (name == NULL) {
3300Sstevel@tonic-gate 		return (NULL);
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	if ((pmech = malloc(sizeof (umechlist_t))) != NULL) {
3340Sstevel@tonic-gate 		(void) strlcpy(pmech->name, name, sizeof (pmech->name));
3350Sstevel@tonic-gate 		pmech->next = NULL;
3360Sstevel@tonic-gate 	}
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	return (pmech);
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate void
3430Sstevel@tonic-gate free_umechlist(umechlist_t *plist)
3440Sstevel@tonic-gate {
3450Sstevel@tonic-gate 	umechlist_t *pnext;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	while (plist != NULL) {
3480Sstevel@tonic-gate 		pnext = plist->next;
3490Sstevel@tonic-gate 		free(plist);
3500Sstevel@tonic-gate 		plist = pnext;
3510Sstevel@tonic-gate 	}
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate void
3560Sstevel@tonic-gate free_uentry(uentry_t  *pent)
3570Sstevel@tonic-gate {
3580Sstevel@tonic-gate 	if (pent == NULL) {
3590Sstevel@tonic-gate 		return;
3600Sstevel@tonic-gate 	} else {
3610Sstevel@tonic-gate 		free_umechlist(pent->policylist);
3620Sstevel@tonic-gate 		free(pent);
3630Sstevel@tonic-gate 	}
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate void
3680Sstevel@tonic-gate free_uentrylist(uentrylist_t *entrylist)
3690Sstevel@tonic-gate {
3700Sstevel@tonic-gate 	uentrylist_t *pnext;
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	while (entrylist != NULL) {
3730Sstevel@tonic-gate 		pnext = entrylist->next;
3740Sstevel@tonic-gate 		free_uentry(entrylist->puent);
3750Sstevel@tonic-gate 		free(entrylist);
3760Sstevel@tonic-gate 		entrylist = pnext;
3770Sstevel@tonic-gate 	}
3780Sstevel@tonic-gate }
379*3089Swyllys 
380*3089Swyllys 
381*3089Swyllys 
382*3089Swyllys /*
383*3089Swyllys  * Duplicate an UEF mechanism list.  A NULL pointer is returned if out of
384*3089Swyllys  * memory or the input argument is NULL.
385*3089Swyllys  */
386*3089Swyllys static umechlist_t *
387*3089Swyllys dup_umechlist(umechlist_t *plist)
388*3089Swyllys {
389*3089Swyllys 	umechlist_t *pres = NULL;
390*3089Swyllys 	umechlist_t *pcur;
391*3089Swyllys 	umechlist_t *ptmp;
392*3089Swyllys 	int rc = SUCCESS;
393*3089Swyllys 
394*3089Swyllys 	while (plist != NULL) {
395*3089Swyllys 		if (!(ptmp = create_umech(plist->name))) {
396*3089Swyllys 			rc = FAILURE;
397*3089Swyllys 			break;
398*3089Swyllys 		}
399*3089Swyllys 
400*3089Swyllys 		if (pres == NULL) {
401*3089Swyllys 			pres = pcur = ptmp;
402*3089Swyllys 		} else {
403*3089Swyllys 			pcur->next = ptmp;
404*3089Swyllys 			pcur = pcur->next;
405*3089Swyllys 		}
406*3089Swyllys 		plist = plist->next;
407*3089Swyllys 	}
408*3089Swyllys 
409*3089Swyllys 	if (rc != SUCCESS) {
410*3089Swyllys 		free_umechlist(pres);
411*3089Swyllys 		return (NULL);
412*3089Swyllys 	}
413*3089Swyllys 
414*3089Swyllys 	return (pres);
415*3089Swyllys }
416*3089Swyllys 
417*3089Swyllys 
418*3089Swyllys /*
419*3089Swyllys  * Duplicate an uentry.  A NULL pointer is returned if out of memory
420*3089Swyllys  * or the input argument is NULL.
421*3089Swyllys  */
422*3089Swyllys static uentry_t *
423*3089Swyllys dup_uentry(uentry_t *puent1)
424*3089Swyllys {
425*3089Swyllys 	uentry_t *puent2 = NULL;
426*3089Swyllys 
427*3089Swyllys 	if (puent1 == NULL) {
428*3089Swyllys 		return (NULL);
429*3089Swyllys 	}
430*3089Swyllys 
431*3089Swyllys 	if ((puent2 = malloc(sizeof (uentry_t))) == NULL) {
432*3089Swyllys 		cryptoerror(LOG_STDERR, gettext("out of memory."));
433*3089Swyllys 		return (NULL);
434*3089Swyllys 	} else {
435*3089Swyllys 		(void) strlcpy(puent2->name, puent1->name,
436*3089Swyllys 		    sizeof (puent2->name));
437*3089Swyllys 		puent2->flag_norandom = puent1->flag_norandom;
438*3089Swyllys 		puent2->flag_enabledlist = puent1->flag_enabledlist;
439*3089Swyllys 		puent2->policylist = dup_umechlist(puent1->policylist);
440*3089Swyllys 		puent2->flag_metaslot_enabled = puent1->flag_metaslot_enabled;
441*3089Swyllys 		puent2->flag_metaslot_auto_key_migrate
442*3089Swyllys 		    = puent1->flag_metaslot_auto_key_migrate;
443*3089Swyllys 		(void) memcpy(puent2->metaslot_ks_slot,
444*3089Swyllys 		    puent1->metaslot_ks_slot, SLOT_DESCRIPTION_SIZE);
445*3089Swyllys 		(void) memcpy(puent2->metaslot_ks_token,
446*3089Swyllys 		    puent1->metaslot_ks_token, TOKEN_LABEL_SIZE);
447*3089Swyllys 		puent2->count = puent1->count;
448*3089Swyllys 		return (puent2);
449*3089Swyllys 	}
450*3089Swyllys }
451*3089Swyllys 
452*3089Swyllys /*
453*3089Swyllys  * Find the entry in the "pkcs11.conf" file with "libname" as the provider
454*3089Swyllys  * name. Return the entry if found, otherwise return NULL.
455*3089Swyllys  */
456*3089Swyllys uentry_t *
457*3089Swyllys getent_uef(char *libname)
458*3089Swyllys {
459*3089Swyllys 	uentrylist_t	*pliblist = NULL;
460*3089Swyllys 	uentrylist_t	*plib = NULL;
461*3089Swyllys 	uentry_t	*puent = NULL;
462*3089Swyllys 	boolean_t	found = B_FALSE;
463*3089Swyllys 
464*3089Swyllys 	if (libname == NULL) {
465*3089Swyllys 		return (NULL);
466*3089Swyllys 	}
467*3089Swyllys 
468*3089Swyllys 	if ((get_pkcs11conf_info(&pliblist)) == FAILURE) {
469*3089Swyllys 		return (NULL);
470*3089Swyllys 	}
471*3089Swyllys 
472*3089Swyllys 	plib = pliblist;
473*3089Swyllys 	while (plib) {
474*3089Swyllys 		if (strcmp(plib->puent->name, libname) == 0) {
475*3089Swyllys 			found = B_TRUE;
476*3089Swyllys 			break;
477*3089Swyllys 		} else {
478*3089Swyllys 			plib = plib->next;
479*3089Swyllys 		}
480*3089Swyllys 	}
481*3089Swyllys 
482*3089Swyllys 	if (found) {
483*3089Swyllys 		puent = dup_uentry(plib->puent);
484*3089Swyllys 	}
485*3089Swyllys 
486*3089Swyllys 	free_uentrylist(pliblist);
487*3089Swyllys 	return (puent);
488*3089Swyllys }
489*3089Swyllys 
490*3089Swyllys 
491*3089Swyllys 
492*3089Swyllys /*
493*3089Swyllys  * Retrieve the metaslot information from the pkcs11.conf file.
494*3089Swyllys  * This function returns SUCCESS if successfully done; otherwise it returns
495*3089Swyllys  * FAILURE.   If successful, the caller is responsible to free the space
496*3089Swyllys  * allocated for objectstore_slot_info and objectstore_token_info.
497*3089Swyllys  */
498*3089Swyllys int
499*3089Swyllys get_metaslot_info(boolean_t  *status_enabled, boolean_t *migrate_enabled,
500*3089Swyllys     char **objectstore_slot_info, char **objectstore_token_info)
501*3089Swyllys {
502*3089Swyllys 
503*3089Swyllys 	int rc = SUCCESS;
504*3089Swyllys 	uentry_t *puent;
505*3089Swyllys 	char *buf1 = NULL;
506*3089Swyllys 	char *buf2 = NULL;
507*3089Swyllys 
508*3089Swyllys 	if ((puent = getent_uef(METASLOT_KEYWORD)) == NULL) {
509*3089Swyllys 		/* metaslot entry doesn't exist */
510*3089Swyllys 		return (FAILURE);
511*3089Swyllys 	}
512*3089Swyllys 
513*3089Swyllys 	*status_enabled = puent->flag_metaslot_enabled;
514*3089Swyllys 	*migrate_enabled = puent->flag_metaslot_auto_key_migrate;
515*3089Swyllys 
516*3089Swyllys 	buf1 = malloc(SLOT_DESCRIPTION_SIZE);
517*3089Swyllys 	if (buf1 == NULL) {
518*3089Swyllys 		cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n");
519*3089Swyllys 		rc = FAILURE;
520*3089Swyllys 		goto out;
521*3089Swyllys 	}
522*3089Swyllys 	(void) strcpy(buf1, (const char *) puent->metaslot_ks_slot);
523*3089Swyllys 	*objectstore_slot_info = buf1;
524*3089Swyllys 
525*3089Swyllys 	buf2 = malloc(TOKEN_LABEL_SIZE);
526*3089Swyllys 	if (objectstore_slot_info == NULL) {
527*3089Swyllys 		cryptoerror(LOG_ERR, "get_metaslot_info() - out of memory.\n");
528*3089Swyllys 		rc = FAILURE;
529*3089Swyllys 		goto out;
530*3089Swyllys 	}
531*3089Swyllys 	(void) strcpy(buf2, (const char *) puent->metaslot_ks_token);
532*3089Swyllys 	*objectstore_token_info = buf2;
533*3089Swyllys 
534*3089Swyllys out:
535*3089Swyllys 	if (puent != NULL) {
536*3089Swyllys 		free_uentry(puent);
537*3089Swyllys 	}
538*3089Swyllys 
539*3089Swyllys 	if (rc == FAILURE) {
540*3089Swyllys 		if (buf1 != NULL) {
541*3089Swyllys 			free(buf1);
542*3089Swyllys 		}
543*3089Swyllys 		if (buf2 != NULL) {
544*3089Swyllys 			free(buf2);
545*3089Swyllys 		}
546*3089Swyllys 	}
547*3089Swyllys 
548*3089Swyllys 	return (rc);
549*3089Swyllys }
550