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
57334SDaniel.Anderson@Sun.COM * Common Development and Distribution License (the "License").
67334SDaniel.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 /*
2211458Sopensolaris@drydog.com * Copyright 2010 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>
357968Sopensolaris@drydog.com #include <zone.h>
360Sstevel@tonic-gate #include <sys/stat.h>
370Sstevel@tonic-gate #include "cryptoadm.h"
380Sstevel@tonic-gate
390Sstevel@tonic-gate static int err; /* To store errno which may be overwritten by gettext() */
40*11775Sopensolaris@drydog.com static int build_entrylist(entry_t *pent, entrylist_t **pplist);
41*11775Sopensolaris@drydog.com static entry_t *dup_entry(entry_t *pent1);
42*11775Sopensolaris@drydog.com static mechlist_t *dup_mechlist(mechlist_t *plist);
43*11775Sopensolaris@drydog.com static entry_t *getent(char *provname, entrylist_t *entrylist);
44*11775Sopensolaris@drydog.com static int interpret(char *buf, entry_t **ppent);
4511458Sopensolaris@drydog.com static int parse_sup_dis_list(const char *buf, entry_t *pent);
460Sstevel@tonic-gate
470Sstevel@tonic-gate
480Sstevel@tonic-gate /*
490Sstevel@tonic-gate * Duplicate the mechanism list. A null pointer is returned if the storage
500Sstevel@tonic-gate * space available is insufficient or the input argument is NULL.
510Sstevel@tonic-gate */
520Sstevel@tonic-gate static mechlist_t *
dup_mechlist(mechlist_t * plist)530Sstevel@tonic-gate dup_mechlist(mechlist_t *plist)
540Sstevel@tonic-gate {
557968Sopensolaris@drydog.com mechlist_t *pres = NULL;
567968Sopensolaris@drydog.com mechlist_t *pcur;
577968Sopensolaris@drydog.com mechlist_t *ptmp;
587968Sopensolaris@drydog.com int rc = SUCCESS;
590Sstevel@tonic-gate
600Sstevel@tonic-gate while (plist != NULL) {
610Sstevel@tonic-gate if (!(ptmp = create_mech(plist->name))) {
620Sstevel@tonic-gate rc = FAILURE;
630Sstevel@tonic-gate break;
640Sstevel@tonic-gate }
650Sstevel@tonic-gate
660Sstevel@tonic-gate if (pres == NULL) {
670Sstevel@tonic-gate pres = pcur = ptmp;
680Sstevel@tonic-gate } else {
690Sstevel@tonic-gate pcur->next = ptmp;
700Sstevel@tonic-gate pcur = pcur->next;
710Sstevel@tonic-gate }
720Sstevel@tonic-gate plist = plist->next;
730Sstevel@tonic-gate }
740Sstevel@tonic-gate
750Sstevel@tonic-gate if (rc != SUCCESS) {
760Sstevel@tonic-gate free_mechlist(pres);
770Sstevel@tonic-gate return (NULL);
780Sstevel@tonic-gate }
790Sstevel@tonic-gate
800Sstevel@tonic-gate return (pres);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
830Sstevel@tonic-gate
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate * Get the number of mechanisms in the mechanism list.
860Sstevel@tonic-gate */
870Sstevel@tonic-gate int
get_mech_count(mechlist_t * plist)880Sstevel@tonic-gate get_mech_count(mechlist_t *plist)
890Sstevel@tonic-gate {
900Sstevel@tonic-gate int count = 0;
910Sstevel@tonic-gate
920Sstevel@tonic-gate while (plist != NULL) {
930Sstevel@tonic-gate count++;
940Sstevel@tonic-gate plist = plist->next;
950Sstevel@tonic-gate }
960Sstevel@tonic-gate return (count);
970Sstevel@tonic-gate }
980Sstevel@tonic-gate
997968Sopensolaris@drydog.com /*
1007968Sopensolaris@drydog.com * Create one item of type entry_t with the provider name.
1017968Sopensolaris@drydog.com * Return NULL if there's not enough memory or provname is NULL.
1027968Sopensolaris@drydog.com */
1037968Sopensolaris@drydog.com entry_t *
create_entry(char * provname)1047968Sopensolaris@drydog.com create_entry(char *provname)
1057968Sopensolaris@drydog.com {
1067968Sopensolaris@drydog.com entry_t *pent = NULL;
1077968Sopensolaris@drydog.com
1087968Sopensolaris@drydog.com if (provname == NULL) {
1097968Sopensolaris@drydog.com return (NULL);
1107968Sopensolaris@drydog.com }
1117968Sopensolaris@drydog.com
1127968Sopensolaris@drydog.com pent = calloc(1, sizeof (entry_t));
1137968Sopensolaris@drydog.com if (pent == NULL) {
1147968Sopensolaris@drydog.com cryptodebug("out of memory.");
1157968Sopensolaris@drydog.com return (NULL);
1167968Sopensolaris@drydog.com }
1177968Sopensolaris@drydog.com
1187968Sopensolaris@drydog.com (void) strlcpy(pent->name, provname, MAXNAMELEN);
1197968Sopensolaris@drydog.com pent->suplist = NULL;
1207968Sopensolaris@drydog.com pent->sup_count = 0;
1217968Sopensolaris@drydog.com pent->dislist = NULL;
1227968Sopensolaris@drydog.com pent->dis_count = 0;
1237968Sopensolaris@drydog.com pent->load = B_TRUE;
1247968Sopensolaris@drydog.com
1257968Sopensolaris@drydog.com return (pent);
1267968Sopensolaris@drydog.com }
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate /*
1297968Sopensolaris@drydog.com * Duplicate an entry for a provider from kcf.conf.
1307968Sopensolaris@drydog.com * Return NULL if memory is insufficient or the input argument is NULL.
1317968Sopensolaris@drydog.com * Called by getent().
1320Sstevel@tonic-gate */
1330Sstevel@tonic-gate static entry_t *
dup_entry(entry_t * pent1)1340Sstevel@tonic-gate dup_entry(entry_t *pent1)
1350Sstevel@tonic-gate {
1360Sstevel@tonic-gate entry_t *pent2 = NULL;
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate if (pent1 == NULL) {
1390Sstevel@tonic-gate return (NULL);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1427968Sopensolaris@drydog.com if ((pent2 = create_entry(pent1->name)) == NULL) {
1430Sstevel@tonic-gate cryptodebug("out of memory.");
1440Sstevel@tonic-gate return (NULL);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate pent2->sup_count = pent1->sup_count;
1480Sstevel@tonic-gate pent2->dis_count = pent1->dis_count;
1497968Sopensolaris@drydog.com pent2->load = pent1->load;
1500Sstevel@tonic-gate if (pent1->suplist != NULL) {
1510Sstevel@tonic-gate pent2->suplist = dup_mechlist(pent1->suplist);
1520Sstevel@tonic-gate if (pent2->suplist == NULL) {
1530Sstevel@tonic-gate free_entry(pent2);
1540Sstevel@tonic-gate return (NULL);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate if (pent1->dislist != NULL) {
1580Sstevel@tonic-gate pent2->dislist = dup_mechlist(pent1->dislist);
1590Sstevel@tonic-gate if (pent2->dislist == NULL) {
1600Sstevel@tonic-gate free_entry(pent2);
1610Sstevel@tonic-gate return (NULL);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate return (pent2);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate * This routine parses the disabledlist or the supportedlist of an entry
1710Sstevel@tonic-gate * in the kcf.conf configuration file.
1720Sstevel@tonic-gate *
1730Sstevel@tonic-gate * Arguments:
1747968Sopensolaris@drydog.com * buf: an input argument which is a char string with the format of
1750Sstevel@tonic-gate * "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
1760Sstevel@tonic-gate * pent: the entry for the disabledlist. This is an IN/OUT argument.
1770Sstevel@tonic-gate *
1780Sstevel@tonic-gate * Return value: SUCCESS or FAILURE.
1790Sstevel@tonic-gate */
1800Sstevel@tonic-gate static int
parse_sup_dis_list(const char * buf,entry_t * pent)18111458Sopensolaris@drydog.com parse_sup_dis_list(const char *buf, entry_t *pent)
1820Sstevel@tonic-gate {
1837968Sopensolaris@drydog.com mechlist_t *pmech = NULL;
1847968Sopensolaris@drydog.com mechlist_t *phead = NULL;
1857968Sopensolaris@drydog.com char *next_token;
1867968Sopensolaris@drydog.com char *value;
1877968Sopensolaris@drydog.com int count;
1887968Sopensolaris@drydog.com int supflag = B_FALSE;
1897968Sopensolaris@drydog.com int disflag = B_FALSE;
1907968Sopensolaris@drydog.com int rc = SUCCESS;
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate if (strncmp(buf, EF_SUPPORTED, strlen(EF_SUPPORTED)) == 0) {
1930Sstevel@tonic-gate supflag = B_TRUE;
1940Sstevel@tonic-gate } else if (strncmp(buf, EF_DISABLED, strlen(EF_DISABLED)) == 0) {
1950Sstevel@tonic-gate disflag = B_TRUE;
1960Sstevel@tonic-gate } else {
1970Sstevel@tonic-gate /* should not come here */
1980Sstevel@tonic-gate return (FAILURE);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) {
2020Sstevel@tonic-gate value++; /* get rid of = */
2030Sstevel@tonic-gate } else {
2040Sstevel@tonic-gate cryptodebug("failed to parse the kcf.conf file.");
2050Sstevel@tonic-gate return (FAILURE);
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate if ((next_token = strtok(value, SEP_COMMA)) == NULL) {
2090Sstevel@tonic-gate cryptodebug("failed to parse the kcf.conf file.");
2100Sstevel@tonic-gate return (FAILURE);
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate if ((pmech = create_mech(next_token)) == NULL) {
2140Sstevel@tonic-gate return (FAILURE);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate if (supflag) {
21811458Sopensolaris@drydog.com if (pent->suplist != NULL) {
21911458Sopensolaris@drydog.com cryptodebug("multiple supportedlist entries "
22011458Sopensolaris@drydog.com "for a mechanism in file kcf.conf.");
22111458Sopensolaris@drydog.com return (FAILURE);
22211458Sopensolaris@drydog.com } else {
22311458Sopensolaris@drydog.com pent->suplist = phead = pmech;
22411458Sopensolaris@drydog.com }
2250Sstevel@tonic-gate } else if (disflag) {
22611458Sopensolaris@drydog.com if (pent->dislist != NULL) {
22711458Sopensolaris@drydog.com cryptodebug("multiple disabledlist entries "
22811458Sopensolaris@drydog.com "for a mechanism in file kcf.conf.");
22911458Sopensolaris@drydog.com return (FAILURE);
23011458Sopensolaris@drydog.com } else {
23111458Sopensolaris@drydog.com pent->dislist = phead = pmech;
23211458Sopensolaris@drydog.com }
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate count = 1;
2360Sstevel@tonic-gate while (next_token) {
2370Sstevel@tonic-gate if (next_token = strtok(NULL, SEP_COMMA)) {
2380Sstevel@tonic-gate if ((pmech = create_mech(next_token)) == NULL) {
2390Sstevel@tonic-gate rc = FAILURE;
2400Sstevel@tonic-gate break;
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate count++;
2430Sstevel@tonic-gate phead->next = pmech;
2440Sstevel@tonic-gate phead = phead->next;
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate if (rc == SUCCESS) {
2490Sstevel@tonic-gate if (supflag) {
2500Sstevel@tonic-gate pent->sup_count = count;
2510Sstevel@tonic-gate } else if (disflag) {
2520Sstevel@tonic-gate pent->dis_count = count;
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate } else {
2550Sstevel@tonic-gate free_mechlist(phead);
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate return (rc);
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate /*
2637968Sopensolaris@drydog.com * Convert a char string containing a line about a provider
2647968Sopensolaris@drydog.com * from kcf.conf into an entry_t structure.
2657968Sopensolaris@drydog.com *
26611458Sopensolaris@drydog.com * Note: the input string, buf, may be modified by this function.
26711458Sopensolaris@drydog.com *
2687968Sopensolaris@drydog.com * See ent2str(), the reverse of this function, for the format of
2697968Sopensolaris@drydog.com * kcf.conf lines.
2700Sstevel@tonic-gate */
2710Sstevel@tonic-gate static int
interpret(char * buf,entry_t ** ppent)2720Sstevel@tonic-gate interpret(char *buf, entry_t **ppent)
2730Sstevel@tonic-gate {
2747968Sopensolaris@drydog.com entry_t *pent = NULL;
2757968Sopensolaris@drydog.com char *token1;
2767968Sopensolaris@drydog.com char *token2;
2777968Sopensolaris@drydog.com char *token3;
2787968Sopensolaris@drydog.com int rc;
2790Sstevel@tonic-gate
2807968Sopensolaris@drydog.com /* Get provider name */
2810Sstevel@tonic-gate if ((token1 = strtok(buf, SEP_COLON)) == NULL) { /* buf is NULL */
2820Sstevel@tonic-gate return (FAILURE);
2830Sstevel@tonic-gate };
2840Sstevel@tonic-gate
2857968Sopensolaris@drydog.com pent = create_entry(token1);
2860Sstevel@tonic-gate if (pent == NULL) {
2870Sstevel@tonic-gate cryptodebug("out of memory.");
2880Sstevel@tonic-gate return (FAILURE);
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
2920Sstevel@tonic-gate /* The entry contains a provider name only */
2930Sstevel@tonic-gate free_entry(pent);
2940Sstevel@tonic-gate return (FAILURE);
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate
2977968Sopensolaris@drydog.com if (strncmp(token2, EF_UNLOAD, strlen(EF_UNLOAD)) == 0) {
2987968Sopensolaris@drydog.com pent->load = B_FALSE; /* cryptoadm unload */
29911458Sopensolaris@drydog.com token2 = strtok(NULL, SEP_SEMICOLON);
30011458Sopensolaris@drydog.com /*
30111458Sopensolaris@drydog.com * If token2 is NULL, the entry contains a
30211458Sopensolaris@drydog.com * provider name:unload only
30311458Sopensolaris@drydog.com */
3047968Sopensolaris@drydog.com }
3057968Sopensolaris@drydog.com
30611458Sopensolaris@drydog.com if (token2 != NULL) {
30711458Sopensolaris@drydog.com /*
30811458Sopensolaris@drydog.com * Either supportedlist or disabledlist or both are present.
30911458Sopensolaris@drydog.com * Need to call strtok() to get token3 first, as function
31011458Sopensolaris@drydog.com * parse_sup_dis_list() makes strtok() calls on the
31111458Sopensolaris@drydog.com * token2 substring.
31211458Sopensolaris@drydog.com */
31311458Sopensolaris@drydog.com token3 = strtok(NULL, SEP_SEMICOLON); /* optional */
3140Sstevel@tonic-gate
31511458Sopensolaris@drydog.com /* parse supportedlist (or disabledlist if no supportedlist) */
31611458Sopensolaris@drydog.com if ((rc = parse_sup_dis_list(token2, pent)) != SUCCESS) {
31711458Sopensolaris@drydog.com free_entry(pent);
31811458Sopensolaris@drydog.com return (rc);
31911458Sopensolaris@drydog.com }
3200Sstevel@tonic-gate
32111458Sopensolaris@drydog.com /* parse disabledlist (if there's a supportedlist) */
32211458Sopensolaris@drydog.com if ((token3 != NULL) && ((rc = parse_sup_dis_list(token3,
32311458Sopensolaris@drydog.com pent)) != SUCCESS)) {
32411458Sopensolaris@drydog.com free_entry(pent);
32511458Sopensolaris@drydog.com return (rc);
32611458Sopensolaris@drydog.com }
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate *ppent = pent;
3300Sstevel@tonic-gate return (SUCCESS);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate /*
3357968Sopensolaris@drydog.com * Add an entry about a provider from kcf.conf to the end of an entry list.
3367968Sopensolaris@drydog.com * If the entry list pplist is NULL, create the linked list with pent as the
3377968Sopensolaris@drydog.com * first element.
3380Sstevel@tonic-gate */
3390Sstevel@tonic-gate static int
build_entrylist(entry_t * pent,entrylist_t ** pplist)3400Sstevel@tonic-gate build_entrylist(entry_t *pent, entrylist_t **pplist)
3410Sstevel@tonic-gate {
3427968Sopensolaris@drydog.com entrylist_t *pentlist;
3437968Sopensolaris@drydog.com entrylist_t *pcur = NULL;
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate pentlist = malloc(sizeof (entrylist_t));
3460Sstevel@tonic-gate if (pentlist == NULL) {
3470Sstevel@tonic-gate cryptodebug("out of memory.");
3480Sstevel@tonic-gate return (FAILURE);
3490Sstevel@tonic-gate }
3500Sstevel@tonic-gate pentlist->pent = pent;
3510Sstevel@tonic-gate pentlist->next = NULL;
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate if (*pplist) {
3540Sstevel@tonic-gate pcur = *pplist;
3550Sstevel@tonic-gate while (pcur->next != NULL)
3560Sstevel@tonic-gate pcur = pcur->next;
3570Sstevel@tonic-gate pcur->next = pentlist;
3580Sstevel@tonic-gate } else { /* empty list */
3590Sstevel@tonic-gate *pplist = pentlist;
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate return (SUCCESS);
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate /*
3680Sstevel@tonic-gate * Find the entry with the "provname" name from the entry list and duplicate
3697968Sopensolaris@drydog.com * it. Called by getent_kef().
3700Sstevel@tonic-gate */
3710Sstevel@tonic-gate static entry_t *
getent(char * provname,entrylist_t * entrylist)3720Sstevel@tonic-gate getent(char *provname, entrylist_t *entrylist)
3730Sstevel@tonic-gate {
3740Sstevel@tonic-gate boolean_t found = B_FALSE;
3750Sstevel@tonic-gate entry_t *pent1 = NULL;
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate if ((provname == NULL) || (entrylist == NULL)) {
3780Sstevel@tonic-gate return (NULL);
3790Sstevel@tonic-gate }
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate while (!found && entrylist) {
3820Sstevel@tonic-gate if (strcmp(entrylist->pent->name, provname) == 0) {
3830Sstevel@tonic-gate found = B_TRUE;
3840Sstevel@tonic-gate pent1 = entrylist->pent;
3850Sstevel@tonic-gate } else {
3860Sstevel@tonic-gate entrylist = entrylist->next;
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate }
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate if (!found) {
3910Sstevel@tonic-gate return (NULL);
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate /* duplicate the entry to be returned */
3950Sstevel@tonic-gate return (dup_entry(pent1));
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate
3997968Sopensolaris@drydog.com /*
4007968Sopensolaris@drydog.com * Free memory in entry_t.
4017968Sopensolaris@drydog.com * That is, the supported and disabled lists for a provider
4027968Sopensolaris@drydog.com * from kcf.conf.
4037968Sopensolaris@drydog.com */
4040Sstevel@tonic-gate void
free_entry(entry_t * pent)4050Sstevel@tonic-gate free_entry(entry_t *pent)
4060Sstevel@tonic-gate {
4070Sstevel@tonic-gate if (pent == NULL) {
4080Sstevel@tonic-gate return;
4090Sstevel@tonic-gate } else {
4100Sstevel@tonic-gate free_mechlist(pent->suplist);
4110Sstevel@tonic-gate free_mechlist(pent->dislist);
4120Sstevel@tonic-gate free(pent);
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate
4177968Sopensolaris@drydog.com /*
4187968Sopensolaris@drydog.com * Free elements in a entrylist_t linked list,
4197968Sopensolaris@drydog.com * which lists providers in kcf.conf.
4207968Sopensolaris@drydog.com */
4210Sstevel@tonic-gate void
free_entrylist(entrylist_t * entrylist)4220Sstevel@tonic-gate free_entrylist(entrylist_t *entrylist)
4230Sstevel@tonic-gate {
4240Sstevel@tonic-gate entrylist_t *pnext;
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate while (entrylist != NULL) {
4270Sstevel@tonic-gate pnext = entrylist->next;
4280Sstevel@tonic-gate free_entry(entrylist->pent);
4290Sstevel@tonic-gate entrylist = pnext;
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate /*
435*11775Sopensolaris@drydog.com * Convert an entry_t to a kcf.conf line string. Build a string to insert
436*11775Sopensolaris@drydog.com * as a line in file kcf.conf. Based on the content of an entry_t,
437*11775Sopensolaris@drydog.com * the result string is one of these 8 forms:
4380Sstevel@tonic-gate * - name:supportedlist=m1,m2,...,mj
4390Sstevel@tonic-gate * - name:disabledlist=m1,m2,...,mj
4400Sstevel@tonic-gate * - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
4410Sstevel@tonic-gate *
44211458Sopensolaris@drydog.com * - name:unload
4437968Sopensolaris@drydog.com * - name:unload;supportedlist=m1,m2,...,mj
4447968Sopensolaris@drydog.com * - name:unload;disabledlist=m1,m2,...,mj
4457968Sopensolaris@drydog.com * - name:unload;supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
4467968Sopensolaris@drydog.com *
447*11775Sopensolaris@drydog.com * - (NUL character or 0-length string)
448*11775Sopensolaris@drydog.com *
449*11775Sopensolaris@drydog.com * Return a 0-length empty string if no keyword is present (that is,
450*11775Sopensolaris@drydog.com * supportedlist, disabledlist, or unload). A kcf.conf line with just the
451*11775Sopensolaris@drydog.com * provider name with no keyword is invalid.
452*11775Sopensolaris@drydog.com *
4537968Sopensolaris@drydog.com * Note that the caller is responsible for freeing the returned string
4547968Sopensolaris@drydog.com * (with free_entry()).
4557968Sopensolaris@drydog.com * See interpret() for the reverse of this function: converting a string
4567968Sopensolaris@drydog.com * to an entry_t.
4570Sstevel@tonic-gate */
4580Sstevel@tonic-gate char *
ent2str(entry_t * pent)4590Sstevel@tonic-gate ent2str(entry_t *pent)
4600Sstevel@tonic-gate {
4617968Sopensolaris@drydog.com char *buf;
4627968Sopensolaris@drydog.com mechlist_t *pcur = NULL;
463*11775Sopensolaris@drydog.com boolean_t keyword_already_present = B_FALSE;
4640Sstevel@tonic-gate
4650Sstevel@tonic-gate if (pent == NULL) {
4660Sstevel@tonic-gate return (NULL);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate if ((buf = malloc(BUFSIZ)) == NULL) {
4700Sstevel@tonic-gate return (NULL);
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /* convert the provider name */
4740Sstevel@tonic-gate if (strlcpy(buf, pent->name, BUFSIZ) >= BUFSIZ) {
4750Sstevel@tonic-gate free(buf);
4760Sstevel@tonic-gate return (NULL);
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate
4797968Sopensolaris@drydog.com if (!pent->load) { /* add "unload" keyword */
4807968Sopensolaris@drydog.com if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
4817968Sopensolaris@drydog.com free(buf);
4827968Sopensolaris@drydog.com return (NULL);
4837968Sopensolaris@drydog.com }
4847968Sopensolaris@drydog.com
4857968Sopensolaris@drydog.com if (strlcat(buf, EF_UNLOAD, BUFSIZ) >= BUFSIZ) {
4867968Sopensolaris@drydog.com free(buf);
4877968Sopensolaris@drydog.com return (NULL);
4887968Sopensolaris@drydog.com }
4897968Sopensolaris@drydog.com
490*11775Sopensolaris@drydog.com keyword_already_present = B_TRUE;
4917968Sopensolaris@drydog.com }
4927968Sopensolaris@drydog.com
4930Sstevel@tonic-gate /* convert the supported list if any */
4947968Sopensolaris@drydog.com pcur = pent->suplist;
4957968Sopensolaris@drydog.com if (pcur != NULL) {
4967968Sopensolaris@drydog.com if (strlcat(buf,
497*11775Sopensolaris@drydog.com keyword_already_present ? SEP_SEMICOLON : SEP_COLON,
4987968Sopensolaris@drydog.com BUFSIZ) >= BUFSIZ) {
4990Sstevel@tonic-gate free(buf);
5000Sstevel@tonic-gate return (NULL);
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate if (strlcat(buf, EF_SUPPORTED, BUFSIZ) >= BUFSIZ) {
5040Sstevel@tonic-gate free(buf);
5050Sstevel@tonic-gate return (NULL);
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate
5087968Sopensolaris@drydog.com while (pcur != NULL) {
5097968Sopensolaris@drydog.com if (strlcat(buf, pcur->name, BUFSIZ) >= BUFSIZ) {
5100Sstevel@tonic-gate free(buf);
5110Sstevel@tonic-gate return (NULL);
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate
5147968Sopensolaris@drydog.com pcur = pcur->next;
5157968Sopensolaris@drydog.com if (pcur != NULL) {
5160Sstevel@tonic-gate if (strlcat(buf, SEP_COMMA, BUFSIZ)
5170Sstevel@tonic-gate >= BUFSIZ) {
5180Sstevel@tonic-gate free(buf);
5190Sstevel@tonic-gate return (NULL);
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate }
523*11775Sopensolaris@drydog.com keyword_already_present = B_TRUE;
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate /* convert the disabled list if any */
5277968Sopensolaris@drydog.com pcur = pent->dislist;
5287968Sopensolaris@drydog.com if (pcur != NULL) {
5297968Sopensolaris@drydog.com if (strlcat(buf,
530*11775Sopensolaris@drydog.com keyword_already_present ? SEP_SEMICOLON : SEP_COLON,
5317968Sopensolaris@drydog.com BUFSIZ) >= BUFSIZ) {
5327968Sopensolaris@drydog.com free(buf);
5337968Sopensolaris@drydog.com return (NULL);
5340Sstevel@tonic-gate }
5350Sstevel@tonic-gate
5367968Sopensolaris@drydog.com if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) {
5377968Sopensolaris@drydog.com free(buf);
5387968Sopensolaris@drydog.com return (NULL);
5397968Sopensolaris@drydog.com }
5407968Sopensolaris@drydog.com
5417968Sopensolaris@drydog.com while (pcur != NULL) {
5427968Sopensolaris@drydog.com if (strlcat(buf, pcur->name, BUFSIZ) >= BUFSIZ) {
5430Sstevel@tonic-gate free(buf);
5440Sstevel@tonic-gate return (NULL);
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate
5477968Sopensolaris@drydog.com pcur = pcur->next;
5487968Sopensolaris@drydog.com if (pcur != NULL) {
5490Sstevel@tonic-gate if (strlcat(buf, SEP_COMMA, BUFSIZ)
5500Sstevel@tonic-gate >= BUFSIZ) {
5510Sstevel@tonic-gate free(buf);
5520Sstevel@tonic-gate return (NULL);
5530Sstevel@tonic-gate }
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate }
556*11775Sopensolaris@drydog.com keyword_already_present = B_TRUE;
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
5600Sstevel@tonic-gate free(buf);
5610Sstevel@tonic-gate return (NULL);
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate
564*11775Sopensolaris@drydog.com if (!keyword_already_present) {
565*11775Sopensolaris@drydog.com /* Only the provider name, without a keyword, is on the line */
566*11775Sopensolaris@drydog.com buf[0] = '\0';
567*11775Sopensolaris@drydog.com }
5680Sstevel@tonic-gate return (buf);
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate /*
5730Sstevel@tonic-gate * Enable the mechanisms for the provider pointed by *ppent. If allflag is
5740Sstevel@tonic-gate * TRUE, enable all. Otherwise, enable the mechanisms specified in the 3rd
5750Sstevel@tonic-gate * argument "mlist". The result will be stored in ppent also.
5760Sstevel@tonic-gate */
5770Sstevel@tonic-gate int
enable_mechs(entry_t ** ppent,boolean_t allflag,mechlist_t * mlist)5780Sstevel@tonic-gate enable_mechs(entry_t **ppent, boolean_t allflag, mechlist_t *mlist)
5790Sstevel@tonic-gate {
5807968Sopensolaris@drydog.com entry_t *pent;
5817968Sopensolaris@drydog.com mechlist_t *phead; /* the current and resulting disabled list */
5827968Sopensolaris@drydog.com mechlist_t *ptr = NULL;
5837968Sopensolaris@drydog.com mechlist_t *pcur = NULL;
5847968Sopensolaris@drydog.com boolean_t found;
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate pent = *ppent;
5870Sstevel@tonic-gate if (pent == NULL) {
5880Sstevel@tonic-gate return (FAILURE);
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate if (allflag) {
5920Sstevel@tonic-gate free_mechlist(pent->dislist);
5930Sstevel@tonic-gate pent->dis_count = 0;
5940Sstevel@tonic-gate pent->dislist = NULL;
5950Sstevel@tonic-gate return (SUCCESS);
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate /*
5990Sstevel@tonic-gate * for each mechanism in the to-be-enabled mechanism list,
6000Sstevel@tonic-gate * - check if it is in the current disabled list
6010Sstevel@tonic-gate * - if found, delete it from the disabled list
6027968Sopensolaris@drydog.com * otherwise, give a warning.
6030Sstevel@tonic-gate */
6040Sstevel@tonic-gate ptr = mlist;
6050Sstevel@tonic-gate while (ptr != NULL) {
6060Sstevel@tonic-gate found = B_FALSE;
6070Sstevel@tonic-gate phead = pcur = pent->dislist;
6080Sstevel@tonic-gate while (!found && pcur) {
6090Sstevel@tonic-gate if (strcmp(pcur->name, ptr->name) == 0) {
6100Sstevel@tonic-gate found = B_TRUE;
6110Sstevel@tonic-gate } else {
6120Sstevel@tonic-gate phead = pcur;
6130Sstevel@tonic-gate pcur = pcur->next;
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate if (found) {
6180Sstevel@tonic-gate if (phead == pcur) {
6190Sstevel@tonic-gate pent->dislist = pent->dislist->next;
6200Sstevel@tonic-gate free(pcur);
6210Sstevel@tonic-gate } else {
6220Sstevel@tonic-gate phead->next = pcur->next;
6230Sstevel@tonic-gate free(pcur);
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate pent->dis_count--;
6260Sstevel@tonic-gate } else {
6270Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext(
6280Sstevel@tonic-gate "(Warning) %1$s is either enabled already or not "
6290Sstevel@tonic-gate "a valid mechanism for %2$s"), ptr->name,
6300Sstevel@tonic-gate pent->name);
6310Sstevel@tonic-gate }
6320Sstevel@tonic-gate ptr = ptr->next;
6330Sstevel@tonic-gate }
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate if (pent->dis_count == 0) {
6360Sstevel@tonic-gate pent->dislist = NULL;
6370Sstevel@tonic-gate }
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate return (SUCCESS);
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate }
6420Sstevel@tonic-gate
6430Sstevel@tonic-gate
6447968Sopensolaris@drydog.com /*
6457968Sopensolaris@drydog.com * Determine if the kernel provider name, path, is a device
6467968Sopensolaris@drydog.com * (that is, it contains a slash character (e.g., "mca/0").
6477968Sopensolaris@drydog.com * If so, it is a hardware provider; otherwise it is a software provider.
6487968Sopensolaris@drydog.com */
6490Sstevel@tonic-gate boolean_t
is_device(char * path)6500Sstevel@tonic-gate is_device(char *path)
6510Sstevel@tonic-gate {
6520Sstevel@tonic-gate if (strchr(path, SEP_SLASH) != NULL) {
6530Sstevel@tonic-gate return (B_TRUE);
6540Sstevel@tonic-gate } else {
6550Sstevel@tonic-gate return (B_FALSE);
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate /*
6600Sstevel@tonic-gate * Split a hardware provider name with the "name/inst_num" format into
6617968Sopensolaris@drydog.com * a name and a number (e.g., split "mca/0" into "mca" instance 0).
6620Sstevel@tonic-gate */
6630Sstevel@tonic-gate int
split_hw_provname(char * provname,char * pname,int * inst_num)6640Sstevel@tonic-gate split_hw_provname(char *provname, char *pname, int *inst_num)
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate char name[MAXNAMELEN];
6670Sstevel@tonic-gate char *inst_str;
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate if (provname == NULL) {
6700Sstevel@tonic-gate return (FAILURE);
6710Sstevel@tonic-gate }
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate (void) strlcpy(name, provname, MAXNAMELEN);
6740Sstevel@tonic-gate if (strtok(name, "/") == NULL) {
6750Sstevel@tonic-gate return (FAILURE);
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate if ((inst_str = strtok(NULL, "/")) == NULL) {
6790Sstevel@tonic-gate return (FAILURE);
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate (void) strlcpy(pname, name, MAXNAMELEN);
6830Sstevel@tonic-gate *inst_num = atoi(inst_str);
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate return (SUCCESS);
6860Sstevel@tonic-gate }
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate /*
6907968Sopensolaris@drydog.com * Retrieve information from kcf.conf and build a hardware device entry list
6917968Sopensolaris@drydog.com * and a software entry list of kernel crypto providers.
6927968Sopensolaris@drydog.com *
6937968Sopensolaris@drydog.com * This list is usually incomplete, as kernel crypto providers only have to
6947968Sopensolaris@drydog.com * be listed in kcf.conf if a mechanism is disabled (by cryptoadm) or
6957968Sopensolaris@drydog.com * if the kernel provider module is not one of the default kernel providers.
6967968Sopensolaris@drydog.com *
6977968Sopensolaris@drydog.com * The kcf.conf file is available only in the global zone.
6980Sstevel@tonic-gate */
6990Sstevel@tonic-gate int
get_kcfconf_info(entrylist_t ** ppdevlist,entrylist_t ** ppsoftlist)70010979SHai-May.Chao@Sun.COM get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
7010Sstevel@tonic-gate {
7027968Sopensolaris@drydog.com FILE *pfile = NULL;
7037968Sopensolaris@drydog.com char buffer[BUFSIZ];
7047968Sopensolaris@drydog.com int len;
7057968Sopensolaris@drydog.com entry_t *pent = NULL;
7067968Sopensolaris@drydog.com int rc = SUCCESS;
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) {
7090Sstevel@tonic-gate cryptodebug("failed to open the kcf.conf file for read only");
7100Sstevel@tonic-gate return (FAILURE);
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate
7130Sstevel@tonic-gate *ppdevlist = NULL;
7140Sstevel@tonic-gate *ppsoftlist = NULL;
7150Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) {
7160Sstevel@tonic-gate if (buffer[0] == '#' || buffer[0] == ' ' ||
7170Sstevel@tonic-gate buffer[0] == '\n'|| buffer[0] == '\t') {
7180Sstevel@tonic-gate continue; /* ignore comment lines */
7190Sstevel@tonic-gate }
7200Sstevel@tonic-gate
7210Sstevel@tonic-gate len = strlen(buffer);
7227968Sopensolaris@drydog.com if (buffer[len - 1] == '\n') { /* get rid of trailing '\n' */
7230Sstevel@tonic-gate len--;
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate buffer[len] = '\0';
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate if ((rc = interpret(buffer, &pent)) == SUCCESS) {
72810979SHai-May.Chao@Sun.COM if (is_device(pent->name)) {
7290Sstevel@tonic-gate rc = build_entrylist(pent, ppdevlist);
7300Sstevel@tonic-gate } else {
7310Sstevel@tonic-gate rc = build_entrylist(pent, ppsoftlist);
7320Sstevel@tonic-gate }
7330Sstevel@tonic-gate } else {
7340Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext(
7350Sstevel@tonic-gate "failed to parse configuration."));
7360Sstevel@tonic-gate }
7370Sstevel@tonic-gate
7380Sstevel@tonic-gate if (rc != SUCCESS) {
7390Sstevel@tonic-gate free_entrylist(*ppdevlist);
7400Sstevel@tonic-gate free_entrylist(*ppsoftlist);
7410Sstevel@tonic-gate free_entry(pent);
7420Sstevel@tonic-gate break;
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate }
7450Sstevel@tonic-gate
7460Sstevel@tonic-gate (void) fclose(pfile);
7470Sstevel@tonic-gate return (rc);
7480Sstevel@tonic-gate }
7490Sstevel@tonic-gate
7500Sstevel@tonic-gate /*
7510Sstevel@tonic-gate * Retrieve information from admin device and build a device entry list and
7527968Sopensolaris@drydog.com * a software entry list. This is used where there is no kcf.conf, e.g., the
7530Sstevel@tonic-gate * non-global zone.
7540Sstevel@tonic-gate */
7550Sstevel@tonic-gate int
get_admindev_info(entrylist_t ** ppdevlist,entrylist_t ** ppsoftlist)7560Sstevel@tonic-gate get_admindev_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist)
7570Sstevel@tonic-gate {
7587968Sopensolaris@drydog.com crypto_get_dev_list_t *pdevlist_kernel = NULL;
7597968Sopensolaris@drydog.com crypto_get_soft_list_t *psoftlist_kernel = NULL;
7607968Sopensolaris@drydog.com char *devname;
7617968Sopensolaris@drydog.com int inst_num;
7627968Sopensolaris@drydog.com int mcount;
7637968Sopensolaris@drydog.com mechlist_t *pmech = NULL;
7647968Sopensolaris@drydog.com entry_t *pent_dev = NULL, *pent_soft = NULL;
7657968Sopensolaris@drydog.com int i;
7667968Sopensolaris@drydog.com char *psoftname;
7677968Sopensolaris@drydog.com entrylist_t *tmp_pdev = NULL;
7687968Sopensolaris@drydog.com entrylist_t *tmp_psoft = NULL;
7697968Sopensolaris@drydog.com entrylist_t *phardlist = NULL, *psoftlist = NULL;
7700Sstevel@tonic-gate
7717968Sopensolaris@drydog.com /*
7727968Sopensolaris@drydog.com * Get hardware providers
7737968Sopensolaris@drydog.com */
7740Sstevel@tonic-gate if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
7750Sstevel@tonic-gate cryptodebug("failed to get hardware provider list from kernel");
7760Sstevel@tonic-gate return (FAILURE);
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
7800Sstevel@tonic-gate devname = pdevlist_kernel->dl_devs[i].le_dev_name;
7810Sstevel@tonic-gate inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance;
7820Sstevel@tonic-gate mcount = pdevlist_kernel->dl_devs[i].le_mechanism_count;
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate pmech = NULL;
7850Sstevel@tonic-gate if (get_dev_info(devname, inst_num, mcount, &pmech) !=
7860Sstevel@tonic-gate SUCCESS) {
7870Sstevel@tonic-gate cryptodebug(
7880Sstevel@tonic-gate "failed to retrieve the mechanism list for %s/%d.",
7890Sstevel@tonic-gate devname, inst_num);
7900Sstevel@tonic-gate goto fail_out;
7910Sstevel@tonic-gate }
7920Sstevel@tonic-gate
7937968Sopensolaris@drydog.com if ((pent_dev = create_entry(devname)) == NULL) {
7940Sstevel@tonic-gate cryptodebug("out of memory.");
7950Sstevel@tonic-gate free_mechlist(pmech);
7960Sstevel@tonic-gate goto fail_out;
7970Sstevel@tonic-gate }
7987968Sopensolaris@drydog.com pent_dev->suplist = pmech;
7997968Sopensolaris@drydog.com pent_dev->sup_count = mcount;
8000Sstevel@tonic-gate
8017968Sopensolaris@drydog.com if (build_entrylist(pent_dev, &tmp_pdev) != SUCCESS) {
8020Sstevel@tonic-gate goto fail_out;
8030Sstevel@tonic-gate }
8040Sstevel@tonic-gate }
8050Sstevel@tonic-gate
8060Sstevel@tonic-gate free(pdevlist_kernel);
8070Sstevel@tonic-gate pdevlist_kernel = NULL;
8080Sstevel@tonic-gate
8097968Sopensolaris@drydog.com /*
8107968Sopensolaris@drydog.com * Get software providers
8117968Sopensolaris@drydog.com */
8127968Sopensolaris@drydog.com if (getzoneid() == GLOBAL_ZONEID) {
81310979SHai-May.Chao@Sun.COM if (get_kcfconf_info(&phardlist, &psoftlist) != SUCCESS) {
8147968Sopensolaris@drydog.com goto fail_out;
8157968Sopensolaris@drydog.com }
8167968Sopensolaris@drydog.com }
8177968Sopensolaris@drydog.com
8180Sstevel@tonic-gate if (get_soft_list(&psoftlist_kernel) != SUCCESS) {
8190Sstevel@tonic-gate cryptodebug("failed to get software provider list from kernel");
8200Sstevel@tonic-gate goto fail_out;
8210Sstevel@tonic-gate }
8220Sstevel@tonic-gate
8230Sstevel@tonic-gate for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
8240Sstevel@tonic-gate i < psoftlist_kernel->sl_soft_count;
8250Sstevel@tonic-gate i++, psoftname = psoftname + strlen(psoftname) + 1) {
8260Sstevel@tonic-gate pmech = NULL;
82710979SHai-May.Chao@Sun.COM if (get_soft_info(psoftname, &pmech, phardlist, psoftlist) !=
82810979SHai-May.Chao@Sun.COM SUCCESS) {
8290Sstevel@tonic-gate cryptodebug(
8300Sstevel@tonic-gate "failed to retrieve the mechanism list for %s.",
8310Sstevel@tonic-gate psoftname);
8320Sstevel@tonic-gate goto fail_out;
8330Sstevel@tonic-gate }
8340Sstevel@tonic-gate
8357968Sopensolaris@drydog.com if ((pent_soft = create_entry(psoftname)) == NULL) {
8360Sstevel@tonic-gate cryptodebug("out of memory.");
8370Sstevel@tonic-gate free_mechlist(pmech);
8380Sstevel@tonic-gate goto fail_out;
8390Sstevel@tonic-gate }
8407968Sopensolaris@drydog.com pent_soft->suplist = pmech;
8417968Sopensolaris@drydog.com pent_soft->sup_count = get_mech_count(pmech);
8420Sstevel@tonic-gate
8437968Sopensolaris@drydog.com if (build_entrylist(pent_soft, &tmp_psoft) != SUCCESS) {
8440Sstevel@tonic-gate goto fail_out;
8450Sstevel@tonic-gate }
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate free(psoftlist_kernel);
8490Sstevel@tonic-gate psoftlist_kernel = NULL;
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate *ppdevlist = tmp_pdev;
8520Sstevel@tonic-gate *ppsoftlist = tmp_psoft;
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate return (SUCCESS);
8550Sstevel@tonic-gate
8560Sstevel@tonic-gate fail_out:
8577968Sopensolaris@drydog.com if (pent_dev != NULL)
8587968Sopensolaris@drydog.com free_entry(pent_dev);
8597968Sopensolaris@drydog.com if (pent_soft != NULL)
8607968Sopensolaris@drydog.com free_entry(pent_soft);
8610Sstevel@tonic-gate
8620Sstevel@tonic-gate free_entrylist(tmp_pdev);
8630Sstevel@tonic-gate free_entrylist(tmp_psoft);
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate if (pdevlist_kernel != NULL)
8660Sstevel@tonic-gate free(pdevlist_kernel);
8670Sstevel@tonic-gate if (psoftlist_kernel != NULL)
8680Sstevel@tonic-gate free(psoftlist_kernel);
8690Sstevel@tonic-gate
8700Sstevel@tonic-gate return (FAILURE);
8710Sstevel@tonic-gate }
8720Sstevel@tonic-gate
8730Sstevel@tonic-gate /*
8747968Sopensolaris@drydog.com * Return configuration information for a kernel provider from kcf.conf.
8757968Sopensolaris@drydog.com * For kernel software providers return a enabled list and disabled list.
8767968Sopensolaris@drydog.com * For kernel hardware providers return just a disabled list.
8777968Sopensolaris@drydog.com *
8787968Sopensolaris@drydog.com * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
8797968Sopensolaris@drydog.com * If NULL, this function calls get_kcfconf_info() internally.
8800Sstevel@tonic-gate */
8810Sstevel@tonic-gate entry_t *
getent_kef(char * provname,entrylist_t * phardlist,entrylist_t * psoftlist)88210979SHai-May.Chao@Sun.COM getent_kef(char *provname, entrylist_t *phardlist, entrylist_t *psoftlist)
8830Sstevel@tonic-gate {
8847968Sopensolaris@drydog.com entry_t *pent = NULL;
8857968Sopensolaris@drydog.com boolean_t memory_allocated = B_FALSE;
8860Sstevel@tonic-gate
88710979SHai-May.Chao@Sun.COM if ((phardlist == NULL) || (psoftlist == NULL)) {
88810979SHai-May.Chao@Sun.COM if (get_kcfconf_info(&phardlist, &psoftlist) != SUCCESS) {
8897968Sopensolaris@drydog.com return (NULL);
8907968Sopensolaris@drydog.com }
8917968Sopensolaris@drydog.com memory_allocated = B_TRUE;
8920Sstevel@tonic-gate }
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate if (is_device(provname)) {
8957968Sopensolaris@drydog.com pent = getent(provname, phardlist);
8960Sstevel@tonic-gate } else {
8970Sstevel@tonic-gate pent = getent(provname, psoftlist);
8980Sstevel@tonic-gate }
8990Sstevel@tonic-gate
9007968Sopensolaris@drydog.com if (memory_allocated) {
9017968Sopensolaris@drydog.com free_entrylist(phardlist);
9027968Sopensolaris@drydog.com free_entrylist(psoftlist);
9037968Sopensolaris@drydog.com }
9040Sstevel@tonic-gate
9050Sstevel@tonic-gate return (pent);
9060Sstevel@tonic-gate }
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate /*
9090Sstevel@tonic-gate * Print out the provider name and the mechanism list.
9100Sstevel@tonic-gate */
9110Sstevel@tonic-gate void
print_mechlist(char * provname,mechlist_t * pmechlist)9120Sstevel@tonic-gate print_mechlist(char *provname, mechlist_t *pmechlist)
9130Sstevel@tonic-gate {
9147968Sopensolaris@drydog.com mechlist_t *ptr = NULL;
9150Sstevel@tonic-gate
9160Sstevel@tonic-gate if (provname == NULL) {
9170Sstevel@tonic-gate return;
9180Sstevel@tonic-gate }
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate (void) printf("%s: ", provname);
9210Sstevel@tonic-gate if (pmechlist == NULL) {
9220Sstevel@tonic-gate (void) printf(gettext("No mechanisms presented.\n"));
9230Sstevel@tonic-gate return;
9240Sstevel@tonic-gate }
9250Sstevel@tonic-gate
9260Sstevel@tonic-gate ptr = pmechlist;
9270Sstevel@tonic-gate while (ptr != NULL) {
9280Sstevel@tonic-gate (void) printf("%s", ptr->name);
9290Sstevel@tonic-gate ptr = ptr->next;
9300Sstevel@tonic-gate if (ptr == NULL) {
9310Sstevel@tonic-gate (void) printf("\n");
9320Sstevel@tonic-gate } else {
9330Sstevel@tonic-gate (void) printf(",");
9340Sstevel@tonic-gate }
9350Sstevel@tonic-gate }
9360Sstevel@tonic-gate }
9370Sstevel@tonic-gate
9380Sstevel@tonic-gate
9390Sstevel@tonic-gate /*
9407968Sopensolaris@drydog.com * Update the kcf.conf file based on the update mode:
9417968Sopensolaris@drydog.com * - If update_mode is MODIFY_MODE, modify the entry with the same name.
9427968Sopensolaris@drydog.com * If not found, append a new entry to the kcf.conf file.
9437968Sopensolaris@drydog.com * - If update_mode is DELETE_MODE, delete the entry with the same name.
9447968Sopensolaris@drydog.com * - If update_mode is ADD_MODE, append a new entry to the kcf.conf file.
9450Sstevel@tonic-gate */
9460Sstevel@tonic-gate int
update_kcfconf(entry_t * pent,int update_mode)9470Sstevel@tonic-gate update_kcfconf(entry_t *pent, int update_mode)
9480Sstevel@tonic-gate {
9490Sstevel@tonic-gate boolean_t add_it = B_FALSE;
9500Sstevel@tonic-gate boolean_t delete_it = B_FALSE;
9518273Sopensolaris@drydog.com boolean_t this_entry_matches = B_FALSE;
9520Sstevel@tonic-gate boolean_t found_entry = B_FALSE;
9537968Sopensolaris@drydog.com FILE *pfile = NULL;
9547968Sopensolaris@drydog.com FILE *pfile_tmp = NULL;
9557968Sopensolaris@drydog.com char buffer[BUFSIZ];
9567968Sopensolaris@drydog.com char buffer2[BUFSIZ];
9577968Sopensolaris@drydog.com char tmpfile_name[MAXPATHLEN];
9587968Sopensolaris@drydog.com char *name;
9597968Sopensolaris@drydog.com char *new_str = NULL;
9607968Sopensolaris@drydog.com int rc = SUCCESS;
9610Sstevel@tonic-gate
9620Sstevel@tonic-gate if (pent == NULL) {
9630Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error."));
9640Sstevel@tonic-gate return (FAILURE);
9650Sstevel@tonic-gate }
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate /* Check the update_mode */
9687968Sopensolaris@drydog.com switch (update_mode) {
9697968Sopensolaris@drydog.com case ADD_MODE:
9700Sstevel@tonic-gate add_it = B_TRUE;
9717968Sopensolaris@drydog.com /* FALLTHROUGH */
9727968Sopensolaris@drydog.com case MODIFY_MODE:
9737968Sopensolaris@drydog.com /* Convert the entry a string to add to kcf.conf */
9740Sstevel@tonic-gate if ((new_str = ent2str(pent)) == NULL) {
9750Sstevel@tonic-gate return (FAILURE);
9760Sstevel@tonic-gate }
977*11775Sopensolaris@drydog.com if (strlen(new_str) == 0) {
978*11775Sopensolaris@drydog.com free(new_str);
979*11775Sopensolaris@drydog.com delete_it = B_TRUE;
980*11775Sopensolaris@drydog.com }
9817968Sopensolaris@drydog.com break;
9827968Sopensolaris@drydog.com case DELETE_MODE:
9830Sstevel@tonic-gate delete_it = B_TRUE;
9847968Sopensolaris@drydog.com break;
9857968Sopensolaris@drydog.com default:
9860Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error."));
9870Sstevel@tonic-gate return (FAILURE);
9880Sstevel@tonic-gate }
9890Sstevel@tonic-gate
9900Sstevel@tonic-gate /* Open the kcf.conf file */
9910Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
9920Sstevel@tonic-gate err = errno;
9930Sstevel@tonic-gate cryptoerror(LOG_STDERR,
9940Sstevel@tonic-gate gettext("failed to update the configuration - %s"),
9950Sstevel@tonic-gate strerror(err));
9960Sstevel@tonic-gate cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
9970Sstevel@tonic-gate return (FAILURE);
9980Sstevel@tonic-gate }
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate /* Lock the kcf.conf file */
10010Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
10020Sstevel@tonic-gate err = errno;
10030Sstevel@tonic-gate cryptoerror(LOG_STDERR,
10040Sstevel@tonic-gate gettext("failed to update the configuration - %s"),
10057968Sopensolaris@drydog.com strerror(err));
10060Sstevel@tonic-gate (void) fclose(pfile);
10070Sstevel@tonic-gate return (FAILURE);
10080Sstevel@tonic-gate }
10090Sstevel@tonic-gate
10100Sstevel@tonic-gate /*
10110Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory to save
10120Sstevel@tonic-gate * updated configuration file first.
10130Sstevel@tonic-gate */
10140Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
10150Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) {
10160Sstevel@tonic-gate err = errno;
10170Sstevel@tonic-gate cryptoerror(LOG_STDERR,
10180Sstevel@tonic-gate gettext("failed to create a temporary file - %s"),
10190Sstevel@tonic-gate strerror(err));
10200Sstevel@tonic-gate (void) fclose(pfile);
10210Sstevel@tonic-gate return (FAILURE);
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
10250Sstevel@tonic-gate err = errno;
10260Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
10270Sstevel@tonic-gate tmpfile_name, strerror(err));
10280Sstevel@tonic-gate (void) fclose(pfile);
10290Sstevel@tonic-gate return (FAILURE);
10300Sstevel@tonic-gate }
10310Sstevel@tonic-gate
10320Sstevel@tonic-gate /*
10330Sstevel@tonic-gate * Loop thru the entire kcf.conf file, insert, modify or delete
10340Sstevel@tonic-gate * an entry.
10350Sstevel@tonic-gate */
10360Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) {
10370Sstevel@tonic-gate if (add_it) {
10380Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) {
10390Sstevel@tonic-gate err = errno;
10400Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext(
10410Sstevel@tonic-gate "failed to write to a temp file: %s."),
10420Sstevel@tonic-gate strerror(err));
10430Sstevel@tonic-gate rc = FAILURE;
10440Sstevel@tonic-gate break;
10450Sstevel@tonic-gate }
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate } else { /* modify or delete */
10488273Sopensolaris@drydog.com this_entry_matches = B_FALSE;
10497968Sopensolaris@drydog.com
10500Sstevel@tonic-gate if (!(buffer[0] == '#' || buffer[0] == ' ' ||
10510Sstevel@tonic-gate buffer[0] == '\n'|| buffer[0] == '\t')) {
10520Sstevel@tonic-gate /*
10530Sstevel@tonic-gate * Get the provider name from this line and
10540Sstevel@tonic-gate * check if this is the entry to be updated
10550Sstevel@tonic-gate * or deleted. Note: can not use "buffer"
10560Sstevel@tonic-gate * directly because strtok will change its
10570Sstevel@tonic-gate * value.
10580Sstevel@tonic-gate */
10590Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ);
10600Sstevel@tonic-gate if ((name = strtok(buffer2, SEP_COLON)) ==
10610Sstevel@tonic-gate NULL) {
10620Sstevel@tonic-gate rc = FAILURE;
10630Sstevel@tonic-gate break;
10640Sstevel@tonic-gate }
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate if (strcmp(pent->name, name) == 0) {
10678273Sopensolaris@drydog.com this_entry_matches = B_TRUE;
10680Sstevel@tonic-gate found_entry = B_TRUE;
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate }
10710Sstevel@tonic-gate
10720Sstevel@tonic-gate
10738273Sopensolaris@drydog.com if (!this_entry_matches || !delete_it) {
10748273Sopensolaris@drydog.com /* write this entry */
10758273Sopensolaris@drydog.com if (this_entry_matches) {
10768273Sopensolaris@drydog.com /*
10778273Sopensolaris@drydog.com * Modify this entry: get the
10788273Sopensolaris@drydog.com * updated string and place into buffer.
10798273Sopensolaris@drydog.com */
10808273Sopensolaris@drydog.com (void) strlcpy(buffer, new_str, BUFSIZ);
10818273Sopensolaris@drydog.com free(new_str);
10828273Sopensolaris@drydog.com }
10838273Sopensolaris@drydog.com /* write the (unchanged or modified) entry */
10840Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) {
10850Sstevel@tonic-gate err = errno;
10860Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext(
10870Sstevel@tonic-gate "failed to write to a temp file: "
10880Sstevel@tonic-gate "%s."), strerror(err));
10890Sstevel@tonic-gate rc = FAILURE;
10900Sstevel@tonic-gate break;
10910Sstevel@tonic-gate }
10920Sstevel@tonic-gate }
10930Sstevel@tonic-gate }
10940Sstevel@tonic-gate }
10950Sstevel@tonic-gate
10967968Sopensolaris@drydog.com if ((!delete_it) && (rc != FAILURE)) {
10977968Sopensolaris@drydog.com if (add_it || !found_entry) {
10987968Sopensolaris@drydog.com /* append new entry to end of file */
10997968Sopensolaris@drydog.com if (fputs(new_str, pfile_tmp) == EOF) {
11007968Sopensolaris@drydog.com err = errno;
11017968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext(
11027968Sopensolaris@drydog.com "failed to write to a temp file: %s."),
11037968Sopensolaris@drydog.com strerror(err));
11047968Sopensolaris@drydog.com rc = FAILURE;
11057968Sopensolaris@drydog.com }
11067968Sopensolaris@drydog.com free(new_str);
11070Sstevel@tonic-gate }
11080Sstevel@tonic-gate }
11090Sstevel@tonic-gate
11100Sstevel@tonic-gate (void) fclose(pfile);
11110Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) {
11120Sstevel@tonic-gate err = errno;
11130Sstevel@tonic-gate cryptoerror(LOG_STDERR,
11140Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name,
11150Sstevel@tonic-gate strerror(err));
11160Sstevel@tonic-gate return (FAILURE);
11170Sstevel@tonic-gate }
11180Sstevel@tonic-gate
11190Sstevel@tonic-gate /* Copy the temporary file to the kcf.conf file */
11200Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
11210Sstevel@tonic-gate err = errno;
11220Sstevel@tonic-gate cryptoerror(LOG_STDERR,
11230Sstevel@tonic-gate gettext("failed to update the configuration - %s"),
11240Sstevel@tonic-gate strerror(err));
11250Sstevel@tonic-gate cryptodebug("failed to rename %s to %s: %s", tmpfile,
11260Sstevel@tonic-gate _PATH_KCF_CONF, strerror(err));
11270Sstevel@tonic-gate rc = FAILURE;
11280Sstevel@tonic-gate } else if (chmod(_PATH_KCF_CONF,
11290Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
11300Sstevel@tonic-gate err = errno;
11310Sstevel@tonic-gate cryptoerror(LOG_STDERR,
11320Sstevel@tonic-gate gettext("failed to update the configuration - %s"),
11330Sstevel@tonic-gate strerror(err));
11340Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
11350Sstevel@tonic-gate strerror(err));
11360Sstevel@tonic-gate rc = FAILURE;
11370Sstevel@tonic-gate } else {
11380Sstevel@tonic-gate rc = SUCCESS;
11390Sstevel@tonic-gate }
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
11420Sstevel@tonic-gate err = errno;
11430Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext(
11440Sstevel@tonic-gate "(Warning) failed to remove %s: %s"),
11450Sstevel@tonic-gate tmpfile_name, strerror(err));
11460Sstevel@tonic-gate }
11470Sstevel@tonic-gate
11480Sstevel@tonic-gate return (rc);
11490Sstevel@tonic-gate }
11500Sstevel@tonic-gate
11510Sstevel@tonic-gate
11520Sstevel@tonic-gate /*
11530Sstevel@tonic-gate * Disable the mechanisms for the provider pointed by *ppent. If allflag is
11540Sstevel@tonic-gate * TRUE, disable all. Otherwise, disable the mechanisms specified in the
11550Sstevel@tonic-gate * dislist argument. The "infolist" argument contains the mechanism list
11560Sstevel@tonic-gate * supported by this provider.
11570Sstevel@tonic-gate */
11580Sstevel@tonic-gate int
disable_mechs(entry_t ** ppent,mechlist_t * infolist,boolean_t allflag,mechlist_t * dislist)11590Sstevel@tonic-gate disable_mechs(entry_t **ppent, mechlist_t *infolist, boolean_t allflag,
11600Sstevel@tonic-gate mechlist_t *dislist)
11610Sstevel@tonic-gate {
11627968Sopensolaris@drydog.com entry_t *pent;
11637968Sopensolaris@drydog.com mechlist_t *plist = NULL;
11647968Sopensolaris@drydog.com mechlist_t *phead = NULL;
11657968Sopensolaris@drydog.com mechlist_t *pmech = NULL;
11667968Sopensolaris@drydog.com int rc = SUCCESS;
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate pent = *ppent;
11690Sstevel@tonic-gate if (pent == NULL) {
11700Sstevel@tonic-gate return (FAILURE);
11710Sstevel@tonic-gate }
11720Sstevel@tonic-gate
11730Sstevel@tonic-gate if (allflag) {
11740Sstevel@tonic-gate free_mechlist(pent->dislist);
11750Sstevel@tonic-gate pent->dis_count = get_mech_count(infolist);
11760Sstevel@tonic-gate if (!(pent->dislist = dup_mechlist(infolist))) {
11770Sstevel@tonic-gate return (FAILURE);
11780Sstevel@tonic-gate } else {
11790Sstevel@tonic-gate return (SUCCESS);
11800Sstevel@tonic-gate }
11810Sstevel@tonic-gate }
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate /*
11840Sstevel@tonic-gate * Not disable all. Now loop thru the mechanisms specified in the
11850Sstevel@tonic-gate * dislist. If the mechanism is not supported by the provider,
11860Sstevel@tonic-gate * ignore it with a warning. If the mechanism is disabled already,
11870Sstevel@tonic-gate * do nothing. Otherwise, prepend it to the beginning of the disabled
11880Sstevel@tonic-gate * list of the provider.
11890Sstevel@tonic-gate */
11900Sstevel@tonic-gate plist = dislist;
11910Sstevel@tonic-gate while (plist != NULL) {
11920Sstevel@tonic-gate if (!is_in_list(plist->name, infolist)) {
11930Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("(Warning) "
11940Sstevel@tonic-gate "%1$s is not a valid mechanism for %2$s."),
11950Sstevel@tonic-gate plist->name, pent->name);
11960Sstevel@tonic-gate } else if (!is_in_list(plist->name, pent->dislist)) {
11970Sstevel@tonic-gate /* Add this mechanism into the disabled list */
11980Sstevel@tonic-gate if ((pmech = create_mech(plist->name)) == NULL) {
11990Sstevel@tonic-gate rc = FAILURE;
12000Sstevel@tonic-gate break;
12010Sstevel@tonic-gate }
12020Sstevel@tonic-gate
12030Sstevel@tonic-gate if (pent->dislist == NULL) {
12040Sstevel@tonic-gate pent->dislist = pmech;
12050Sstevel@tonic-gate } else {
12060Sstevel@tonic-gate phead = pent->dislist;
12070Sstevel@tonic-gate pent->dislist = pmech;
12080Sstevel@tonic-gate pmech->next = phead;
12090Sstevel@tonic-gate }
12100Sstevel@tonic-gate pent->dis_count++;
12110Sstevel@tonic-gate }
12120Sstevel@tonic-gate plist = plist->next;
12130Sstevel@tonic-gate }
12140Sstevel@tonic-gate
12150Sstevel@tonic-gate return (rc);
12160Sstevel@tonic-gate }
12170Sstevel@tonic-gate
12180Sstevel@tonic-gate /*
12190Sstevel@tonic-gate * Remove the mechanism passed, specified by mech, from the list of
12200Sstevel@tonic-gate * mechanisms, if present in the list. Else, do nothing.
12210Sstevel@tonic-gate *
12220Sstevel@tonic-gate * Returns B_TRUE if mechanism is present in the list.
12230Sstevel@tonic-gate */
12240Sstevel@tonic-gate boolean_t
filter_mechlist(mechlist_t ** pmechlist,const char * mech)12250Sstevel@tonic-gate filter_mechlist(mechlist_t **pmechlist, const char *mech)
12260Sstevel@tonic-gate {
12277968Sopensolaris@drydog.com int cnt = 0;
12287968Sopensolaris@drydog.com mechlist_t *ptr, *pptr;
12297968Sopensolaris@drydog.com boolean_t mech_present = B_FALSE;
12300Sstevel@tonic-gate
12310Sstevel@tonic-gate ptr = pptr = *pmechlist;
12320Sstevel@tonic-gate
12330Sstevel@tonic-gate while (ptr != NULL) {
12340Sstevel@tonic-gate if (strncmp(ptr->name, mech, sizeof (mech_name_t)) == 0) {
12350Sstevel@tonic-gate mech_present = B_TRUE;
12360Sstevel@tonic-gate if (ptr == *pmechlist) {
12370Sstevel@tonic-gate pptr = *pmechlist = ptr->next;
12380Sstevel@tonic-gate free(ptr);
12390Sstevel@tonic-gate ptr = pptr;
12400Sstevel@tonic-gate } else {
12410Sstevel@tonic-gate pptr->next = ptr->next;
12420Sstevel@tonic-gate free(ptr);
12430Sstevel@tonic-gate ptr = pptr->next;
12440Sstevel@tonic-gate }
12450Sstevel@tonic-gate } else {
12460Sstevel@tonic-gate pptr = ptr;
12470Sstevel@tonic-gate ptr = ptr->next;
12480Sstevel@tonic-gate cnt++;
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate }
12510Sstevel@tonic-gate
12520Sstevel@tonic-gate /* Only one entry is present */
12530Sstevel@tonic-gate if (cnt == 0)
12540Sstevel@tonic-gate *pmechlist = NULL;
12550Sstevel@tonic-gate
12560Sstevel@tonic-gate return (mech_present);
12570Sstevel@tonic-gate }
12580Sstevel@tonic-gate
12590Sstevel@tonic-gate
12600Sstevel@tonic-gate
12610Sstevel@tonic-gate /*
12620Sstevel@tonic-gate * Print out the mechanism policy for a kernel provider that has an entry
12630Sstevel@tonic-gate * in the kcf.conf file.
12640Sstevel@tonic-gate *
12650Sstevel@tonic-gate * The flag has_random is set to B_TRUE if the provider does random
12660Sstevel@tonic-gate * numbers. The flag has_mechs is set by the caller to B_TRUE if the provider
12670Sstevel@tonic-gate * has some mechanisms.
12687968Sopensolaris@drydog.com *
12697968Sopensolaris@drydog.com * If pent is NULL, the provider doesn't have a kcf.conf entry.
12700Sstevel@tonic-gate */
12710Sstevel@tonic-gate void
print_kef_policy(char * provname,entry_t * pent,boolean_t has_random,boolean_t has_mechs)12727968Sopensolaris@drydog.com print_kef_policy(char *provname, entry_t *pent, boolean_t has_random,
12737968Sopensolaris@drydog.com boolean_t has_mechs)
12740Sstevel@tonic-gate {
12757968Sopensolaris@drydog.com mechlist_t *ptr = NULL;
12767968Sopensolaris@drydog.com boolean_t rnd_disabled = B_FALSE;
12770Sstevel@tonic-gate
12787968Sopensolaris@drydog.com if (pent != NULL) {
12797968Sopensolaris@drydog.com rnd_disabled = filter_mechlist(&pent->dislist, RANDOM);
12807968Sopensolaris@drydog.com ptr = pent->dislist;
12810Sstevel@tonic-gate }
12820Sstevel@tonic-gate
12837968Sopensolaris@drydog.com (void) printf("%s:", provname);
12840Sstevel@tonic-gate
12850Sstevel@tonic-gate if (has_mechs == B_TRUE) {
12860Sstevel@tonic-gate /*
12877334SDaniel.Anderson@Sun.COM * TRANSLATION_NOTE
12880Sstevel@tonic-gate * This code block may need to be modified a bit to avoid
12890Sstevel@tonic-gate * constructing the text message on the fly.
12900Sstevel@tonic-gate */
12910Sstevel@tonic-gate (void) printf(gettext(" all mechanisms are enabled"));
12920Sstevel@tonic-gate if (ptr != NULL)
12930Sstevel@tonic-gate (void) printf(gettext(", except "));
12940Sstevel@tonic-gate while (ptr != NULL) {
12950Sstevel@tonic-gate (void) printf("%s", ptr->name);
12960Sstevel@tonic-gate ptr = ptr->next;
12970Sstevel@tonic-gate if (ptr != NULL)
12980Sstevel@tonic-gate (void) printf(",");
12990Sstevel@tonic-gate }
13000Sstevel@tonic-gate if (ptr == NULL)
13010Sstevel@tonic-gate (void) printf(".");
13020Sstevel@tonic-gate }
13030Sstevel@tonic-gate
13040Sstevel@tonic-gate /*
13057334SDaniel.Anderson@Sun.COM * TRANSLATION_NOTE
13060Sstevel@tonic-gate * "random" is a keyword and not to be translated.
13070Sstevel@tonic-gate */
13080Sstevel@tonic-gate if (rnd_disabled)
13090Sstevel@tonic-gate (void) printf(gettext(" %s is disabled."), "random");
13100Sstevel@tonic-gate else if (has_random)
13110Sstevel@tonic-gate (void) printf(gettext(" %s is enabled."), "random");
13120Sstevel@tonic-gate (void) printf("\n");
13130Sstevel@tonic-gate }
13140Sstevel@tonic-gate
13157968Sopensolaris@drydog.com
13160Sstevel@tonic-gate /*
13170Sstevel@tonic-gate * Check if a kernel software provider is in the kernel.
13187968Sopensolaris@drydog.com *
13197968Sopensolaris@drydog.com * Parameters:
13207968Sopensolaris@drydog.com * provname Provider name
13217968Sopensolaris@drydog.com * psoftlist_kernel Optional software provider list. If NULL, it will be
13227968Sopensolaris@drydog.com * obtained from get_soft_list().
13237968Sopensolaris@drydog.com * in_kernel Set to B_TRUE if device is in the kernel, else B_FALSE
13240Sstevel@tonic-gate */
13250Sstevel@tonic-gate int
check_kernel_for_soft(char * provname,crypto_get_soft_list_t * psoftlist_kernel,boolean_t * in_kernel)13267968Sopensolaris@drydog.com check_kernel_for_soft(char *provname, crypto_get_soft_list_t *psoftlist_kernel,
13277968Sopensolaris@drydog.com boolean_t *in_kernel)
13280Sstevel@tonic-gate {
13297968Sopensolaris@drydog.com char *ptr;
13307968Sopensolaris@drydog.com int i;
13317968Sopensolaris@drydog.com boolean_t psoftlist_allocated = B_FALSE;
13320Sstevel@tonic-gate
13330Sstevel@tonic-gate if (provname == NULL) {
13340Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error."));
13350Sstevel@tonic-gate return (FAILURE);
13360Sstevel@tonic-gate }
13370Sstevel@tonic-gate
13387968Sopensolaris@drydog.com if (psoftlist_kernel == NULL) {
13397968Sopensolaris@drydog.com if (get_soft_list(&psoftlist_kernel) == FAILURE) {
13407968Sopensolaris@drydog.com cryptodebug("failed to get the software provider list"
13417968Sopensolaris@drydog.com " from kernel.");
13427968Sopensolaris@drydog.com return (FAILURE);
13437968Sopensolaris@drydog.com }
13447968Sopensolaris@drydog.com psoftlist_allocated = B_TRUE;
13450Sstevel@tonic-gate }
13460Sstevel@tonic-gate
13477968Sopensolaris@drydog.com *in_kernel = B_FALSE;
13480Sstevel@tonic-gate ptr = psoftlist_kernel->sl_soft_names;
13490Sstevel@tonic-gate for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
13500Sstevel@tonic-gate if (strcmp(provname, ptr) == 0) {
13517968Sopensolaris@drydog.com *in_kernel = B_TRUE;
13520Sstevel@tonic-gate break;
13530Sstevel@tonic-gate }
13540Sstevel@tonic-gate ptr = ptr + strlen(ptr) + 1;
13550Sstevel@tonic-gate }
13567968Sopensolaris@drydog.com
13577968Sopensolaris@drydog.com if (psoftlist_allocated)
13587968Sopensolaris@drydog.com free(psoftlist_kernel);
13590Sstevel@tonic-gate
13600Sstevel@tonic-gate return (SUCCESS);
13610Sstevel@tonic-gate }
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate
13640Sstevel@tonic-gate /*
13650Sstevel@tonic-gate * Check if a kernel hardware provider is in the kernel.
13667968Sopensolaris@drydog.com *
13677968Sopensolaris@drydog.com * Parameters:
13687968Sopensolaris@drydog.com * provname Provider name
13697968Sopensolaris@drydog.com * pdevlist Optional Hardware Crypto Device List. If NULL, it will be
13707968Sopensolaris@drydog.com * obtained from get_dev_list().
13717968Sopensolaris@drydog.com * in_kernel Set to B_TRUE if device is in the kernel, otherwise B_FALSE
13720Sstevel@tonic-gate */
13730Sstevel@tonic-gate int
check_kernel_for_hard(char * provname,crypto_get_dev_list_t * pdevlist,boolean_t * in_kernel)13747968Sopensolaris@drydog.com check_kernel_for_hard(char *provname,
13757968Sopensolaris@drydog.com crypto_get_dev_list_t *pdevlist, boolean_t *in_kernel)
13760Sstevel@tonic-gate {
13777968Sopensolaris@drydog.com char devname[MAXNAMELEN];
13787968Sopensolaris@drydog.com int inst_num;
13797968Sopensolaris@drydog.com int i;
13807968Sopensolaris@drydog.com boolean_t dev_list_allocated = B_FALSE;
13810Sstevel@tonic-gate
13820Sstevel@tonic-gate if (provname == NULL) {
13830Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error."));
13840Sstevel@tonic-gate return (FAILURE);
13850Sstevel@tonic-gate }
13860Sstevel@tonic-gate
13870Sstevel@tonic-gate if (split_hw_provname(provname, devname, &inst_num) == FAILURE) {
13880Sstevel@tonic-gate return (FAILURE);
13890Sstevel@tonic-gate }
13900Sstevel@tonic-gate
13917968Sopensolaris@drydog.com if (pdevlist == NULL) {
13927968Sopensolaris@drydog.com if (get_dev_list(&pdevlist) == FAILURE) {
13937968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("internal error."));
13947968Sopensolaris@drydog.com return (FAILURE);
13957968Sopensolaris@drydog.com }
13967968Sopensolaris@drydog.com dev_list_allocated = B_TRUE;
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate
13997968Sopensolaris@drydog.com *in_kernel = B_FALSE;
14000Sstevel@tonic-gate for (i = 0; i < pdevlist->dl_dev_count; i++) {
14010Sstevel@tonic-gate if ((strcmp(pdevlist->dl_devs[i].le_dev_name, devname) == 0) &&
14020Sstevel@tonic-gate (pdevlist->dl_devs[i].le_dev_instance == inst_num)) {
14037968Sopensolaris@drydog.com *in_kernel = B_TRUE;
14040Sstevel@tonic-gate break;
14050Sstevel@tonic-gate }
14060Sstevel@tonic-gate }
14077968Sopensolaris@drydog.com
14087968Sopensolaris@drydog.com if (dev_list_allocated)
14097968Sopensolaris@drydog.com free(pdevlist);
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate return (SUCCESS);
14120Sstevel@tonic-gate }
1413