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 /* 22*10500SHai-May.Chao@Sun.COM * Copyright 2009 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" 38*10500SHai-May.Chao@Sun.COM #include <cryptoutil.h> 390Sstevel@tonic-gate 400Sstevel@tonic-gate static int err; /* To store errno which may be overwritten by gettext() */ 410Sstevel@tonic-gate static int build_entrylist(entry_t *, entrylist_t **); 420Sstevel@tonic-gate static entry_t *dup_entry(entry_t *); 430Sstevel@tonic-gate static mechlist_t *dup_mechlist(mechlist_t *); 440Sstevel@tonic-gate static entry_t *getent(char *, entrylist_t *); 450Sstevel@tonic-gate static int interpret(char *, entry_t **); 467968Sopensolaris@drydog.com static int parse_sup_dis_list(char *, entry_t *); 470Sstevel@tonic-gate 480Sstevel@tonic-gate 490Sstevel@tonic-gate /* 500Sstevel@tonic-gate * Duplicate the mechanism list. A null pointer is returned if the storage 510Sstevel@tonic-gate * space available is insufficient or the input argument is NULL. 520Sstevel@tonic-gate */ 530Sstevel@tonic-gate static mechlist_t * 540Sstevel@tonic-gate dup_mechlist(mechlist_t *plist) 550Sstevel@tonic-gate { 567968Sopensolaris@drydog.com mechlist_t *pres = NULL; 577968Sopensolaris@drydog.com mechlist_t *pcur; 587968Sopensolaris@drydog.com mechlist_t *ptmp; 597968Sopensolaris@drydog.com int rc = SUCCESS; 600Sstevel@tonic-gate 610Sstevel@tonic-gate while (plist != NULL) { 620Sstevel@tonic-gate if (!(ptmp = create_mech(plist->name))) { 630Sstevel@tonic-gate rc = FAILURE; 640Sstevel@tonic-gate break; 650Sstevel@tonic-gate } 660Sstevel@tonic-gate 670Sstevel@tonic-gate if (pres == NULL) { 680Sstevel@tonic-gate pres = pcur = ptmp; 690Sstevel@tonic-gate } else { 700Sstevel@tonic-gate pcur->next = ptmp; 710Sstevel@tonic-gate pcur = pcur->next; 720Sstevel@tonic-gate } 730Sstevel@tonic-gate plist = plist->next; 740Sstevel@tonic-gate } 750Sstevel@tonic-gate 760Sstevel@tonic-gate if (rc != SUCCESS) { 770Sstevel@tonic-gate free_mechlist(pres); 780Sstevel@tonic-gate return (NULL); 790Sstevel@tonic-gate } 800Sstevel@tonic-gate 810Sstevel@tonic-gate return (pres); 820Sstevel@tonic-gate } 830Sstevel@tonic-gate 840Sstevel@tonic-gate 850Sstevel@tonic-gate /* 860Sstevel@tonic-gate * Get the number of mechanisms in the mechanism list. 870Sstevel@tonic-gate */ 880Sstevel@tonic-gate int 890Sstevel@tonic-gate get_mech_count(mechlist_t *plist) 900Sstevel@tonic-gate { 910Sstevel@tonic-gate int count = 0; 920Sstevel@tonic-gate 930Sstevel@tonic-gate while (plist != NULL) { 940Sstevel@tonic-gate count++; 950Sstevel@tonic-gate plist = plist->next; 960Sstevel@tonic-gate } 970Sstevel@tonic-gate return (count); 980Sstevel@tonic-gate } 990Sstevel@tonic-gate 1007968Sopensolaris@drydog.com /* 1017968Sopensolaris@drydog.com * Create one item of type entry_t with the provider name. 1027968Sopensolaris@drydog.com * Return NULL if there's not enough memory or provname is NULL. 1037968Sopensolaris@drydog.com */ 1047968Sopensolaris@drydog.com entry_t * 1057968Sopensolaris@drydog.com create_entry(char *provname) 1067968Sopensolaris@drydog.com { 1077968Sopensolaris@drydog.com entry_t *pent = NULL; 1087968Sopensolaris@drydog.com 1097968Sopensolaris@drydog.com if (provname == NULL) { 1107968Sopensolaris@drydog.com return (NULL); 1117968Sopensolaris@drydog.com } 1127968Sopensolaris@drydog.com 1137968Sopensolaris@drydog.com pent = calloc(1, sizeof (entry_t)); 1147968Sopensolaris@drydog.com if (pent == NULL) { 1157968Sopensolaris@drydog.com cryptodebug("out of memory."); 1167968Sopensolaris@drydog.com return (NULL); 1177968Sopensolaris@drydog.com } 1187968Sopensolaris@drydog.com 1197968Sopensolaris@drydog.com (void) strlcpy(pent->name, provname, MAXNAMELEN); 1207968Sopensolaris@drydog.com pent->suplist = NULL; 1217968Sopensolaris@drydog.com pent->sup_count = 0; 1227968Sopensolaris@drydog.com pent->dislist = NULL; 1237968Sopensolaris@drydog.com pent->dis_count = 0; 1247968Sopensolaris@drydog.com pent->load = B_TRUE; 1257968Sopensolaris@drydog.com 1267968Sopensolaris@drydog.com return (pent); 1277968Sopensolaris@drydog.com } 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate /* 1307968Sopensolaris@drydog.com * Duplicate an entry for a provider from kcf.conf. 1317968Sopensolaris@drydog.com * Return NULL if memory is insufficient or the input argument is NULL. 1327968Sopensolaris@drydog.com * Called by getent(). 1330Sstevel@tonic-gate */ 1340Sstevel@tonic-gate static entry_t * 1350Sstevel@tonic-gate dup_entry(entry_t *pent1) 1360Sstevel@tonic-gate { 1370Sstevel@tonic-gate entry_t *pent2 = NULL; 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate if (pent1 == NULL) { 1400Sstevel@tonic-gate return (NULL); 1410Sstevel@tonic-gate } 1420Sstevel@tonic-gate 1437968Sopensolaris@drydog.com if ((pent2 = create_entry(pent1->name)) == NULL) { 1440Sstevel@tonic-gate cryptodebug("out of memory."); 1450Sstevel@tonic-gate return (NULL); 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 148*10500SHai-May.Chao@Sun.COM pent2->flag_fips_enabled = pent1->flag_fips_enabled; 1490Sstevel@tonic-gate pent2->sup_count = pent1->sup_count; 1500Sstevel@tonic-gate pent2->dis_count = pent1->dis_count; 1517968Sopensolaris@drydog.com pent2->load = pent1->load; 1520Sstevel@tonic-gate if (pent1->suplist != NULL) { 1530Sstevel@tonic-gate pent2->suplist = dup_mechlist(pent1->suplist); 1540Sstevel@tonic-gate if (pent2->suplist == NULL) { 1550Sstevel@tonic-gate free_entry(pent2); 1560Sstevel@tonic-gate return (NULL); 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate if (pent1->dislist != NULL) { 1600Sstevel@tonic-gate pent2->dislist = dup_mechlist(pent1->dislist); 1610Sstevel@tonic-gate if (pent2->dislist == NULL) { 1620Sstevel@tonic-gate free_entry(pent2); 1630Sstevel@tonic-gate return (NULL); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate } 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate return (pent2); 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate /* 1720Sstevel@tonic-gate * This routine parses the disabledlist or the supportedlist of an entry 1730Sstevel@tonic-gate * in the kcf.conf configuration file. 1740Sstevel@tonic-gate * 1750Sstevel@tonic-gate * Arguments: 1767968Sopensolaris@drydog.com * buf: an input argument which is a char string with the format of 1770Sstevel@tonic-gate * "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..." 1780Sstevel@tonic-gate * pent: the entry for the disabledlist. This is an IN/OUT argument. 1790Sstevel@tonic-gate * 1800Sstevel@tonic-gate * Return value: SUCCESS or FAILURE. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate static int 1837968Sopensolaris@drydog.com parse_sup_dis_list(char *buf, entry_t *pent) 1840Sstevel@tonic-gate { 1857968Sopensolaris@drydog.com mechlist_t *pmech = NULL; 1867968Sopensolaris@drydog.com mechlist_t *phead = NULL; 1877968Sopensolaris@drydog.com char *next_token; 1887968Sopensolaris@drydog.com char *value; 1897968Sopensolaris@drydog.com int count; 1907968Sopensolaris@drydog.com int supflag = B_FALSE; 1917968Sopensolaris@drydog.com int disflag = B_FALSE; 1927968Sopensolaris@drydog.com int rc = SUCCESS; 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate if (strncmp(buf, EF_SUPPORTED, strlen(EF_SUPPORTED)) == 0) { 1950Sstevel@tonic-gate supflag = B_TRUE; 1960Sstevel@tonic-gate } else if (strncmp(buf, EF_DISABLED, strlen(EF_DISABLED)) == 0) { 1970Sstevel@tonic-gate disflag = B_TRUE; 1980Sstevel@tonic-gate } else { 1990Sstevel@tonic-gate /* should not come here */ 2000Sstevel@tonic-gate return (FAILURE); 2010Sstevel@tonic-gate } 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 2040Sstevel@tonic-gate value++; /* get rid of = */ 2050Sstevel@tonic-gate } else { 2060Sstevel@tonic-gate cryptodebug("failed to parse the kcf.conf file."); 2070Sstevel@tonic-gate return (FAILURE); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate if ((next_token = strtok(value, SEP_COMMA)) == NULL) { 2110Sstevel@tonic-gate cryptodebug("failed to parse the kcf.conf file."); 2120Sstevel@tonic-gate return (FAILURE); 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate if ((pmech = create_mech(next_token)) == NULL) { 2160Sstevel@tonic-gate return (FAILURE); 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate if (supflag) { 2200Sstevel@tonic-gate pent->suplist = phead = pmech; 2210Sstevel@tonic-gate } else if (disflag) { 2220Sstevel@tonic-gate pent->dislist = phead = pmech; 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate count = 1; 2260Sstevel@tonic-gate while (next_token) { 2270Sstevel@tonic-gate if (next_token = strtok(NULL, SEP_COMMA)) { 2280Sstevel@tonic-gate if ((pmech = create_mech(next_token)) == NULL) { 2290Sstevel@tonic-gate rc = FAILURE; 2300Sstevel@tonic-gate break; 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate count++; 2330Sstevel@tonic-gate phead->next = pmech; 2340Sstevel@tonic-gate phead = phead->next; 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate if (rc == SUCCESS) { 2390Sstevel@tonic-gate if (supflag) { 2400Sstevel@tonic-gate pent->sup_count = count; 2410Sstevel@tonic-gate } else if (disflag) { 2420Sstevel@tonic-gate pent->dis_count = count; 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate } else { 2450Sstevel@tonic-gate free_mechlist(phead); 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate return (rc); 2490Sstevel@tonic-gate } 2500Sstevel@tonic-gate 251*10500SHai-May.Chao@Sun.COM static int 252*10500SHai-May.Chao@Sun.COM parse_fips(char *buf, entry_t *pent) 253*10500SHai-May.Chao@Sun.COM { 254*10500SHai-May.Chao@Sun.COM char *value; 255*10500SHai-May.Chao@Sun.COM 256*10500SHai-May.Chao@Sun.COM if (strncmp(buf, EF_FIPS_STATUS, sizeof (EF_FIPS_STATUS) - 1) == 0) { 257*10500SHai-May.Chao@Sun.COM if (value = strpbrk(buf, SEP_EQUAL)) { 258*10500SHai-May.Chao@Sun.COM value++; /* get rid of = */ 259*10500SHai-May.Chao@Sun.COM if (strcmp(value, DISABLED_KEYWORD) == 0) { 260*10500SHai-May.Chao@Sun.COM pent->flag_fips_enabled = B_FALSE; 261*10500SHai-May.Chao@Sun.COM } else if (strcmp(value, ENABLED_KEYWORD) == 0) { 262*10500SHai-May.Chao@Sun.COM pent->flag_fips_enabled = B_TRUE; 263*10500SHai-May.Chao@Sun.COM } else { 264*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_ERR, gettext( 265*10500SHai-May.Chao@Sun.COM "Failed to parse kcf.conf file.\n")); 266*10500SHai-May.Chao@Sun.COM return (FAILURE); 267*10500SHai-May.Chao@Sun.COM } 268*10500SHai-May.Chao@Sun.COM return (SUCCESS); 269*10500SHai-May.Chao@Sun.COM } else { 270*10500SHai-May.Chao@Sun.COM return (FAILURE); 271*10500SHai-May.Chao@Sun.COM } 272*10500SHai-May.Chao@Sun.COM } else { 273*10500SHai-May.Chao@Sun.COM /* should not come here */ 274*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_ERR, gettext( 275*10500SHai-May.Chao@Sun.COM "Failed to parse kcf.conf file.\n")); 276*10500SHai-May.Chao@Sun.COM return (FAILURE); 277*10500SHai-May.Chao@Sun.COM } 278*10500SHai-May.Chao@Sun.COM 279*10500SHai-May.Chao@Sun.COM } 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate /* 2827968Sopensolaris@drydog.com * Convert a char string containing a line about a provider 2837968Sopensolaris@drydog.com * from kcf.conf into an entry_t structure. 2847968Sopensolaris@drydog.com * 2857968Sopensolaris@drydog.com * See ent2str(), the reverse of this function, for the format of 2867968Sopensolaris@drydog.com * kcf.conf lines. 2870Sstevel@tonic-gate */ 2880Sstevel@tonic-gate static int 2890Sstevel@tonic-gate interpret(char *buf, entry_t **ppent) 2900Sstevel@tonic-gate { 2917968Sopensolaris@drydog.com entry_t *pent = NULL; 2927968Sopensolaris@drydog.com char *token1; 2937968Sopensolaris@drydog.com char *token2; 2947968Sopensolaris@drydog.com char *token3; 2957968Sopensolaris@drydog.com int rc; 2960Sstevel@tonic-gate 2977968Sopensolaris@drydog.com /* Get provider name */ 2980Sstevel@tonic-gate if ((token1 = strtok(buf, SEP_COLON)) == NULL) { /* buf is NULL */ 2990Sstevel@tonic-gate return (FAILURE); 3000Sstevel@tonic-gate }; 3010Sstevel@tonic-gate 3027968Sopensolaris@drydog.com pent = create_entry(token1); 3030Sstevel@tonic-gate if (pent == NULL) { 3040Sstevel@tonic-gate cryptodebug("out of memory."); 3050Sstevel@tonic-gate return (FAILURE); 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate 308*10500SHai-May.Chao@Sun.COM if (is_fips(token1)) { 309*10500SHai-May.Chao@Sun.COM if ((rc = parse_fips(buf + strlen(token1) + 1, 310*10500SHai-May.Chao@Sun.COM pent)) != SUCCESS) { 311*10500SHai-May.Chao@Sun.COM free_entry(pent); 312*10500SHai-May.Chao@Sun.COM } 313*10500SHai-May.Chao@Sun.COM *ppent = pent; 314*10500SHai-May.Chao@Sun.COM return (rc); 315*10500SHai-May.Chao@Sun.COM } 316*10500SHai-May.Chao@Sun.COM 3170Sstevel@tonic-gate if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) { 3180Sstevel@tonic-gate /* The entry contains a provider name only */ 3190Sstevel@tonic-gate free_entry(pent); 3200Sstevel@tonic-gate return (FAILURE); 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate 3237968Sopensolaris@drydog.com if (strncmp(token2, EF_UNLOAD, strlen(EF_UNLOAD)) == 0) { 3247968Sopensolaris@drydog.com pent->load = B_FALSE; /* cryptoadm unload */ 3257968Sopensolaris@drydog.com if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) { 3267968Sopensolaris@drydog.com /* The entry contains a provider name:unload only */ 3277968Sopensolaris@drydog.com free_entry(pent); 3287968Sopensolaris@drydog.com return (FAILURE); 3297968Sopensolaris@drydog.com } 3307968Sopensolaris@drydog.com } 3317968Sopensolaris@drydog.com 3320Sstevel@tonic-gate /* need to get token3 first to satisfy nested strtok invocations */ 3337968Sopensolaris@drydog.com token3 = strtok(NULL, SEP_SEMICOLON); /* optional */ 3340Sstevel@tonic-gate 3357968Sopensolaris@drydog.com /* parse supportedlist (or disabledlist if no supportedlist) */ 3367968Sopensolaris@drydog.com if ((token2 != NULL) && ((rc = parse_sup_dis_list(token2, pent)) != 3377968Sopensolaris@drydog.com SUCCESS)) { 3380Sstevel@tonic-gate free_entry(pent); 3390Sstevel@tonic-gate return (rc); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 3427968Sopensolaris@drydog.com /* parse disabledlist (if there's a supportedlist) */ 3437968Sopensolaris@drydog.com if ((token3 != NULL) && ((rc = parse_sup_dis_list(token3, pent)) != 3447968Sopensolaris@drydog.com SUCCESS)) { 3450Sstevel@tonic-gate free_entry(pent); 3460Sstevel@tonic-gate return (rc); 3470Sstevel@tonic-gate } 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate *ppent = pent; 3500Sstevel@tonic-gate return (SUCCESS); 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate /* 3557968Sopensolaris@drydog.com * Add an entry about a provider from kcf.conf to the end of an entry list. 3567968Sopensolaris@drydog.com * If the entry list pplist is NULL, create the linked list with pent as the 3577968Sopensolaris@drydog.com * first element. 3580Sstevel@tonic-gate */ 3590Sstevel@tonic-gate static int 3600Sstevel@tonic-gate build_entrylist(entry_t *pent, entrylist_t **pplist) 3610Sstevel@tonic-gate { 3627968Sopensolaris@drydog.com entrylist_t *pentlist; 3637968Sopensolaris@drydog.com entrylist_t *pcur = NULL; 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate pentlist = malloc(sizeof (entrylist_t)); 3660Sstevel@tonic-gate if (pentlist == NULL) { 3670Sstevel@tonic-gate cryptodebug("out of memory."); 3680Sstevel@tonic-gate return (FAILURE); 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate pentlist->pent = pent; 3710Sstevel@tonic-gate pentlist->next = NULL; 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate if (*pplist) { 3740Sstevel@tonic-gate pcur = *pplist; 3750Sstevel@tonic-gate while (pcur->next != NULL) 3760Sstevel@tonic-gate pcur = pcur->next; 3770Sstevel@tonic-gate pcur->next = pentlist; 3780Sstevel@tonic-gate } else { /* empty list */ 3790Sstevel@tonic-gate *pplist = pentlist; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate return (SUCCESS); 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate /* 3880Sstevel@tonic-gate * Find the entry with the "provname" name from the entry list and duplicate 3897968Sopensolaris@drydog.com * it. Called by getent_kef(). 3900Sstevel@tonic-gate */ 3910Sstevel@tonic-gate static entry_t * 3920Sstevel@tonic-gate getent(char *provname, entrylist_t *entrylist) 3930Sstevel@tonic-gate { 3940Sstevel@tonic-gate boolean_t found = B_FALSE; 3950Sstevel@tonic-gate entry_t *pent1 = NULL; 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate if ((provname == NULL) || (entrylist == NULL)) { 3980Sstevel@tonic-gate return (NULL); 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate while (!found && entrylist) { 4020Sstevel@tonic-gate if (strcmp(entrylist->pent->name, provname) == 0) { 4030Sstevel@tonic-gate found = B_TRUE; 4040Sstevel@tonic-gate pent1 = entrylist->pent; 4050Sstevel@tonic-gate } else { 4060Sstevel@tonic-gate entrylist = entrylist->next; 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate } 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate if (!found) { 4110Sstevel@tonic-gate return (NULL); 4120Sstevel@tonic-gate } 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate /* duplicate the entry to be returned */ 4150Sstevel@tonic-gate return (dup_entry(pent1)); 4160Sstevel@tonic-gate } 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate 4197968Sopensolaris@drydog.com /* 4207968Sopensolaris@drydog.com * Free memory in entry_t. 4217968Sopensolaris@drydog.com * That is, the supported and disabled lists for a provider 4227968Sopensolaris@drydog.com * from kcf.conf. 4237968Sopensolaris@drydog.com */ 4240Sstevel@tonic-gate void 4250Sstevel@tonic-gate free_entry(entry_t *pent) 4260Sstevel@tonic-gate { 4270Sstevel@tonic-gate if (pent == NULL) { 4280Sstevel@tonic-gate return; 4290Sstevel@tonic-gate } else { 4300Sstevel@tonic-gate free_mechlist(pent->suplist); 4310Sstevel@tonic-gate free_mechlist(pent->dislist); 4320Sstevel@tonic-gate free(pent); 4330Sstevel@tonic-gate } 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate 4377968Sopensolaris@drydog.com /* 4387968Sopensolaris@drydog.com * Free elements in a entrylist_t linked list, 4397968Sopensolaris@drydog.com * which lists providers in kcf.conf. 4407968Sopensolaris@drydog.com */ 4410Sstevel@tonic-gate void 4420Sstevel@tonic-gate free_entrylist(entrylist_t *entrylist) 4430Sstevel@tonic-gate { 4440Sstevel@tonic-gate entrylist_t *pnext; 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate while (entrylist != NULL) { 4470Sstevel@tonic-gate pnext = entrylist->next; 4480Sstevel@tonic-gate free_entry(entrylist->pent); 4490Sstevel@tonic-gate entrylist = pnext; 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate /* 4550Sstevel@tonic-gate * Convert an entry to a string. This routine builds a string for the entry 4567968Sopensolaris@drydog.com * to be inserted in the kcf.conf file. Based on the content of each entry, 4577968Sopensolaris@drydog.com * the result string can be one of these 6 forms: 4580Sstevel@tonic-gate * - name:supportedlist=m1,m2,...,mj 4590Sstevel@tonic-gate * - name:disabledlist=m1,m2,...,mj 4600Sstevel@tonic-gate * - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk 4610Sstevel@tonic-gate * 4627968Sopensolaris@drydog.com * - name:unload;supportedlist=m1,m2,...,mj 4637968Sopensolaris@drydog.com * - name:unload;disabledlist=m1,m2,...,mj 4647968Sopensolaris@drydog.com * - name:unload;supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk 4657968Sopensolaris@drydog.com * 4667968Sopensolaris@drydog.com * Note that the caller is responsible for freeing the returned string 4677968Sopensolaris@drydog.com * (with free_entry()). 4687968Sopensolaris@drydog.com * See interpret() for the reverse of this function: converting a string 4697968Sopensolaris@drydog.com * to an entry_t. 4700Sstevel@tonic-gate */ 4710Sstevel@tonic-gate char * 4720Sstevel@tonic-gate ent2str(entry_t *pent) 4730Sstevel@tonic-gate { 4747968Sopensolaris@drydog.com char *buf; 4757968Sopensolaris@drydog.com mechlist_t *pcur = NULL; 4767968Sopensolaris@drydog.com boolean_t semicolon_separator = B_FALSE; 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate if (pent == NULL) { 4800Sstevel@tonic-gate return (NULL); 4810Sstevel@tonic-gate } 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate if ((buf = malloc(BUFSIZ)) == NULL) { 4840Sstevel@tonic-gate return (NULL); 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate /* convert the provider name */ 4880Sstevel@tonic-gate if (strlcpy(buf, pent->name, BUFSIZ) >= BUFSIZ) { 4890Sstevel@tonic-gate free(buf); 4900Sstevel@tonic-gate return (NULL); 4910Sstevel@tonic-gate } 4920Sstevel@tonic-gate 4937968Sopensolaris@drydog.com if (!pent->load) { /* add "unload" keyword */ 4947968Sopensolaris@drydog.com if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) { 4957968Sopensolaris@drydog.com free(buf); 4967968Sopensolaris@drydog.com return (NULL); 4977968Sopensolaris@drydog.com } 4987968Sopensolaris@drydog.com 4997968Sopensolaris@drydog.com if (strlcat(buf, EF_UNLOAD, BUFSIZ) >= BUFSIZ) { 5007968Sopensolaris@drydog.com free(buf); 5017968Sopensolaris@drydog.com return (NULL); 5027968Sopensolaris@drydog.com } 5037968Sopensolaris@drydog.com 5047968Sopensolaris@drydog.com semicolon_separator = B_TRUE; 5057968Sopensolaris@drydog.com } 5067968Sopensolaris@drydog.com 5070Sstevel@tonic-gate /* convert the supported list if any */ 5087968Sopensolaris@drydog.com pcur = pent->suplist; 5097968Sopensolaris@drydog.com if (pcur != NULL) { 5107968Sopensolaris@drydog.com if (strlcat(buf, 5117968Sopensolaris@drydog.com semicolon_separator ? SEP_SEMICOLON : SEP_COLON, 5127968Sopensolaris@drydog.com BUFSIZ) >= BUFSIZ) { 5130Sstevel@tonic-gate free(buf); 5140Sstevel@tonic-gate return (NULL); 5150Sstevel@tonic-gate } 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate if (strlcat(buf, EF_SUPPORTED, BUFSIZ) >= BUFSIZ) { 5180Sstevel@tonic-gate free(buf); 5190Sstevel@tonic-gate return (NULL); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5227968Sopensolaris@drydog.com while (pcur != NULL) { 5237968Sopensolaris@drydog.com if (strlcat(buf, pcur->name, BUFSIZ) >= BUFSIZ) { 5240Sstevel@tonic-gate free(buf); 5250Sstevel@tonic-gate return (NULL); 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate 5287968Sopensolaris@drydog.com pcur = pcur->next; 5297968Sopensolaris@drydog.com if (pcur != NULL) { 5300Sstevel@tonic-gate if (strlcat(buf, SEP_COMMA, BUFSIZ) 5310Sstevel@tonic-gate >= BUFSIZ) { 5320Sstevel@tonic-gate free(buf); 5330Sstevel@tonic-gate return (NULL); 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate } 5377968Sopensolaris@drydog.com semicolon_separator = B_TRUE; 5380Sstevel@tonic-gate } 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate /* convert the disabled list if any */ 5417968Sopensolaris@drydog.com pcur = pent->dislist; 5427968Sopensolaris@drydog.com if (pcur != NULL) { 5437968Sopensolaris@drydog.com if (strlcat(buf, 5447968Sopensolaris@drydog.com semicolon_separator ? SEP_SEMICOLON : SEP_COLON, 5457968Sopensolaris@drydog.com BUFSIZ) >= BUFSIZ) { 5467968Sopensolaris@drydog.com free(buf); 5477968Sopensolaris@drydog.com return (NULL); 5480Sstevel@tonic-gate } 5490Sstevel@tonic-gate 5507968Sopensolaris@drydog.com if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) { 5517968Sopensolaris@drydog.com free(buf); 5527968Sopensolaris@drydog.com return (NULL); 5537968Sopensolaris@drydog.com } 5547968Sopensolaris@drydog.com 5557968Sopensolaris@drydog.com while (pcur != NULL) { 5567968Sopensolaris@drydog.com if (strlcat(buf, pcur->name, BUFSIZ) >= BUFSIZ) { 5570Sstevel@tonic-gate free(buf); 5580Sstevel@tonic-gate return (NULL); 5590Sstevel@tonic-gate } 5600Sstevel@tonic-gate 5617968Sopensolaris@drydog.com pcur = pcur->next; 5627968Sopensolaris@drydog.com if (pcur != NULL) { 5630Sstevel@tonic-gate if (strlcat(buf, SEP_COMMA, BUFSIZ) 5640Sstevel@tonic-gate >= BUFSIZ) { 5650Sstevel@tonic-gate free(buf); 5660Sstevel@tonic-gate return (NULL); 5670Sstevel@tonic-gate } 5680Sstevel@tonic-gate } 5690Sstevel@tonic-gate } 5707968Sopensolaris@drydog.com semicolon_separator = B_TRUE; 5710Sstevel@tonic-gate } 5720Sstevel@tonic-gate 5730Sstevel@tonic-gate if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) { 5740Sstevel@tonic-gate free(buf); 5750Sstevel@tonic-gate return (NULL); 5760Sstevel@tonic-gate } 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate return (buf); 5790Sstevel@tonic-gate } 5800Sstevel@tonic-gate 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate /* 5830Sstevel@tonic-gate * Enable the mechanisms for the provider pointed by *ppent. If allflag is 5840Sstevel@tonic-gate * TRUE, enable all. Otherwise, enable the mechanisms specified in the 3rd 5850Sstevel@tonic-gate * argument "mlist". The result will be stored in ppent also. 5860Sstevel@tonic-gate */ 5870Sstevel@tonic-gate int 5880Sstevel@tonic-gate enable_mechs(entry_t **ppent, boolean_t allflag, mechlist_t *mlist) 5890Sstevel@tonic-gate { 5907968Sopensolaris@drydog.com entry_t *pent; 5917968Sopensolaris@drydog.com mechlist_t *phead; /* the current and resulting disabled list */ 5927968Sopensolaris@drydog.com mechlist_t *ptr = NULL; 5937968Sopensolaris@drydog.com mechlist_t *pcur = NULL; 5947968Sopensolaris@drydog.com boolean_t found; 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate pent = *ppent; 5970Sstevel@tonic-gate if (pent == NULL) { 5980Sstevel@tonic-gate return (FAILURE); 5990Sstevel@tonic-gate } 6000Sstevel@tonic-gate 6010Sstevel@tonic-gate if (allflag) { 6020Sstevel@tonic-gate free_mechlist(pent->dislist); 6030Sstevel@tonic-gate pent->dis_count = 0; 6040Sstevel@tonic-gate pent->dislist = NULL; 6050Sstevel@tonic-gate return (SUCCESS); 6060Sstevel@tonic-gate } 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate /* 6090Sstevel@tonic-gate * for each mechanism in the to-be-enabled mechanism list, 6100Sstevel@tonic-gate * - check if it is in the current disabled list 6110Sstevel@tonic-gate * - if found, delete it from the disabled list 6127968Sopensolaris@drydog.com * otherwise, give a warning. 6130Sstevel@tonic-gate */ 6140Sstevel@tonic-gate ptr = mlist; 6150Sstevel@tonic-gate while (ptr != NULL) { 6160Sstevel@tonic-gate found = B_FALSE; 6170Sstevel@tonic-gate phead = pcur = pent->dislist; 6180Sstevel@tonic-gate while (!found && pcur) { 6190Sstevel@tonic-gate if (strcmp(pcur->name, ptr->name) == 0) { 6200Sstevel@tonic-gate found = B_TRUE; 6210Sstevel@tonic-gate } else { 6220Sstevel@tonic-gate phead = pcur; 6230Sstevel@tonic-gate pcur = pcur->next; 6240Sstevel@tonic-gate } 6250Sstevel@tonic-gate } 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate if (found) { 6280Sstevel@tonic-gate if (phead == pcur) { 6290Sstevel@tonic-gate pent->dislist = pent->dislist->next; 6300Sstevel@tonic-gate free(pcur); 6310Sstevel@tonic-gate } else { 6320Sstevel@tonic-gate phead->next = pcur->next; 6330Sstevel@tonic-gate free(pcur); 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate pent->dis_count--; 6360Sstevel@tonic-gate } else { 6370Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 6380Sstevel@tonic-gate "(Warning) %1$s is either enabled already or not " 6390Sstevel@tonic-gate "a valid mechanism for %2$s"), ptr->name, 6400Sstevel@tonic-gate pent->name); 6410Sstevel@tonic-gate } 6420Sstevel@tonic-gate ptr = ptr->next; 6430Sstevel@tonic-gate } 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate if (pent->dis_count == 0) { 6460Sstevel@tonic-gate pent->dislist = NULL; 6470Sstevel@tonic-gate } 6480Sstevel@tonic-gate 6490Sstevel@tonic-gate return (SUCCESS); 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate } 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate 6547968Sopensolaris@drydog.com /* 6557968Sopensolaris@drydog.com * Determine if the kernel provider name, path, is a device 6567968Sopensolaris@drydog.com * (that is, it contains a slash character (e.g., "mca/0"). 6577968Sopensolaris@drydog.com * If so, it is a hardware provider; otherwise it is a software provider. 6587968Sopensolaris@drydog.com */ 6590Sstevel@tonic-gate boolean_t 6600Sstevel@tonic-gate is_device(char *path) 6610Sstevel@tonic-gate { 6620Sstevel@tonic-gate if (strchr(path, SEP_SLASH) != NULL) { 6630Sstevel@tonic-gate return (B_TRUE); 6640Sstevel@tonic-gate } else { 6650Sstevel@tonic-gate return (B_FALSE); 6660Sstevel@tonic-gate } 6670Sstevel@tonic-gate } 6680Sstevel@tonic-gate 669*10500SHai-May.Chao@Sun.COM boolean_t 670*10500SHai-May.Chao@Sun.COM is_fips(char *name) 671*10500SHai-May.Chao@Sun.COM { 672*10500SHai-May.Chao@Sun.COM if (strcmp(name, FIPS_KEYWORD) == 0) { 673*10500SHai-May.Chao@Sun.COM return (B_TRUE); 674*10500SHai-May.Chao@Sun.COM } else { 675*10500SHai-May.Chao@Sun.COM return (B_FALSE); 676*10500SHai-May.Chao@Sun.COM } 677*10500SHai-May.Chao@Sun.COM } 678*10500SHai-May.Chao@Sun.COM 6790Sstevel@tonic-gate /* 6800Sstevel@tonic-gate * Split a hardware provider name with the "name/inst_num" format into 6817968Sopensolaris@drydog.com * a name and a number (e.g., split "mca/0" into "mca" instance 0). 6820Sstevel@tonic-gate */ 6830Sstevel@tonic-gate int 6840Sstevel@tonic-gate split_hw_provname(char *provname, char *pname, int *inst_num) 6850Sstevel@tonic-gate { 6860Sstevel@tonic-gate char name[MAXNAMELEN]; 6870Sstevel@tonic-gate char *inst_str; 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate if (provname == NULL) { 6900Sstevel@tonic-gate return (FAILURE); 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate (void) strlcpy(name, provname, MAXNAMELEN); 6940Sstevel@tonic-gate if (strtok(name, "/") == NULL) { 6950Sstevel@tonic-gate return (FAILURE); 6960Sstevel@tonic-gate } 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate if ((inst_str = strtok(NULL, "/")) == NULL) { 6990Sstevel@tonic-gate return (FAILURE); 7000Sstevel@tonic-gate } 7010Sstevel@tonic-gate 7020Sstevel@tonic-gate (void) strlcpy(pname, name, MAXNAMELEN); 7030Sstevel@tonic-gate *inst_num = atoi(inst_str); 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate return (SUCCESS); 7060Sstevel@tonic-gate } 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate /* 7107968Sopensolaris@drydog.com * Retrieve information from kcf.conf and build a hardware device entry list 7117968Sopensolaris@drydog.com * and a software entry list of kernel crypto providers. 7127968Sopensolaris@drydog.com * 7137968Sopensolaris@drydog.com * This list is usually incomplete, as kernel crypto providers only have to 7147968Sopensolaris@drydog.com * be listed in kcf.conf if a mechanism is disabled (by cryptoadm) or 7157968Sopensolaris@drydog.com * if the kernel provider module is not one of the default kernel providers. 7167968Sopensolaris@drydog.com * 7177968Sopensolaris@drydog.com * The kcf.conf file is available only in the global zone. 7180Sstevel@tonic-gate */ 7190Sstevel@tonic-gate int 720*10500SHai-May.Chao@Sun.COM get_kcfconf_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist, 721*10500SHai-May.Chao@Sun.COM entrylist_t **ppfipslist) 7220Sstevel@tonic-gate { 7237968Sopensolaris@drydog.com FILE *pfile = NULL; 7247968Sopensolaris@drydog.com char buffer[BUFSIZ]; 7257968Sopensolaris@drydog.com int len; 7267968Sopensolaris@drydog.com entry_t *pent = NULL; 7277968Sopensolaris@drydog.com int rc = SUCCESS; 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r")) == NULL) { 7300Sstevel@tonic-gate cryptodebug("failed to open the kcf.conf file for read only"); 7310Sstevel@tonic-gate return (FAILURE); 7320Sstevel@tonic-gate } 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate *ppdevlist = NULL; 7350Sstevel@tonic-gate *ppsoftlist = NULL; 736*10500SHai-May.Chao@Sun.COM *ppfipslist = NULL; 737*10500SHai-May.Chao@Sun.COM 7380Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 7390Sstevel@tonic-gate if (buffer[0] == '#' || buffer[0] == ' ' || 7400Sstevel@tonic-gate buffer[0] == '\n'|| buffer[0] == '\t') { 7410Sstevel@tonic-gate continue; /* ignore comment lines */ 7420Sstevel@tonic-gate } 7430Sstevel@tonic-gate 7440Sstevel@tonic-gate len = strlen(buffer); 7457968Sopensolaris@drydog.com if (buffer[len - 1] == '\n') { /* get rid of trailing '\n' */ 7460Sstevel@tonic-gate len--; 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate buffer[len] = '\0'; 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate if ((rc = interpret(buffer, &pent)) == SUCCESS) { 751*10500SHai-May.Chao@Sun.COM if (is_fips(pent->name)) { 752*10500SHai-May.Chao@Sun.COM if (*ppfipslist != NULL) { 753*10500SHai-May.Chao@Sun.COM cryptoerror(LOG_STDERR, gettext( 754*10500SHai-May.Chao@Sun.COM "multiple fips entries.")); 755*10500SHai-May.Chao@Sun.COM rc = FAILURE; 756*10500SHai-May.Chao@Sun.COM } else { 757*10500SHai-May.Chao@Sun.COM rc = build_entrylist(pent, ppfipslist); 758*10500SHai-May.Chao@Sun.COM } 759*10500SHai-May.Chao@Sun.COM } else if (is_device(pent->name)) { 7600Sstevel@tonic-gate rc = build_entrylist(pent, ppdevlist); 7610Sstevel@tonic-gate } else { 7620Sstevel@tonic-gate rc = build_entrylist(pent, ppsoftlist); 7630Sstevel@tonic-gate } 7640Sstevel@tonic-gate } else { 7650Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 7660Sstevel@tonic-gate "failed to parse configuration.")); 767*10500SHai-May.Chao@Sun.COM rc = FAILURE; 7680Sstevel@tonic-gate } 7690Sstevel@tonic-gate 7700Sstevel@tonic-gate if (rc != SUCCESS) { 7710Sstevel@tonic-gate free_entrylist(*ppdevlist); 7720Sstevel@tonic-gate free_entrylist(*ppsoftlist); 773*10500SHai-May.Chao@Sun.COM free_entrylist(*ppfipslist); 7740Sstevel@tonic-gate free_entry(pent); 7750Sstevel@tonic-gate break; 7760Sstevel@tonic-gate } 7770Sstevel@tonic-gate } 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate (void) fclose(pfile); 7800Sstevel@tonic-gate return (rc); 7810Sstevel@tonic-gate } 7820Sstevel@tonic-gate 7830Sstevel@tonic-gate /* 7840Sstevel@tonic-gate * Retrieve information from admin device and build a device entry list and 7857968Sopensolaris@drydog.com * a software entry list. This is used where there is no kcf.conf, e.g., the 7860Sstevel@tonic-gate * non-global zone. 7870Sstevel@tonic-gate */ 7880Sstevel@tonic-gate int 7890Sstevel@tonic-gate get_admindev_info(entrylist_t **ppdevlist, entrylist_t **ppsoftlist) 7900Sstevel@tonic-gate { 7917968Sopensolaris@drydog.com crypto_get_dev_list_t *pdevlist_kernel = NULL; 7927968Sopensolaris@drydog.com crypto_get_soft_list_t *psoftlist_kernel = NULL; 7937968Sopensolaris@drydog.com char *devname; 7947968Sopensolaris@drydog.com int inst_num; 7957968Sopensolaris@drydog.com int mcount; 7967968Sopensolaris@drydog.com mechlist_t *pmech = NULL; 7977968Sopensolaris@drydog.com entry_t *pent_dev = NULL, *pent_soft = NULL; 7987968Sopensolaris@drydog.com int i; 7997968Sopensolaris@drydog.com char *psoftname; 8007968Sopensolaris@drydog.com entrylist_t *tmp_pdev = NULL; 8017968Sopensolaris@drydog.com entrylist_t *tmp_psoft = NULL; 8027968Sopensolaris@drydog.com entrylist_t *phardlist = NULL, *psoftlist = NULL; 803*10500SHai-May.Chao@Sun.COM entrylist_t *pfipslist = NULL; 8040Sstevel@tonic-gate 8057968Sopensolaris@drydog.com /* 8067968Sopensolaris@drydog.com * Get hardware providers 8077968Sopensolaris@drydog.com */ 8080Sstevel@tonic-gate if (get_dev_list(&pdevlist_kernel) != SUCCESS) { 8090Sstevel@tonic-gate cryptodebug("failed to get hardware provider list from kernel"); 8100Sstevel@tonic-gate return (FAILURE); 8110Sstevel@tonic-gate } 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) { 8140Sstevel@tonic-gate devname = pdevlist_kernel->dl_devs[i].le_dev_name; 8150Sstevel@tonic-gate inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance; 8160Sstevel@tonic-gate mcount = pdevlist_kernel->dl_devs[i].le_mechanism_count; 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate pmech = NULL; 8190Sstevel@tonic-gate if (get_dev_info(devname, inst_num, mcount, &pmech) != 8200Sstevel@tonic-gate SUCCESS) { 8210Sstevel@tonic-gate cryptodebug( 8220Sstevel@tonic-gate "failed to retrieve the mechanism list for %s/%d.", 8230Sstevel@tonic-gate devname, inst_num); 8240Sstevel@tonic-gate goto fail_out; 8250Sstevel@tonic-gate } 8260Sstevel@tonic-gate 8277968Sopensolaris@drydog.com if ((pent_dev = create_entry(devname)) == NULL) { 8280Sstevel@tonic-gate cryptodebug("out of memory."); 8290Sstevel@tonic-gate free_mechlist(pmech); 8300Sstevel@tonic-gate goto fail_out; 8310Sstevel@tonic-gate } 8327968Sopensolaris@drydog.com pent_dev->suplist = pmech; 8337968Sopensolaris@drydog.com pent_dev->sup_count = mcount; 8340Sstevel@tonic-gate 8357968Sopensolaris@drydog.com if (build_entrylist(pent_dev, &tmp_pdev) != SUCCESS) { 8360Sstevel@tonic-gate goto fail_out; 8370Sstevel@tonic-gate } 8380Sstevel@tonic-gate } 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate free(pdevlist_kernel); 8410Sstevel@tonic-gate pdevlist_kernel = NULL; 8420Sstevel@tonic-gate 8437968Sopensolaris@drydog.com /* 8447968Sopensolaris@drydog.com * Get software providers 8457968Sopensolaris@drydog.com */ 8467968Sopensolaris@drydog.com if (getzoneid() == GLOBAL_ZONEID) { 847*10500SHai-May.Chao@Sun.COM if (get_kcfconf_info(&phardlist, &psoftlist, &pfipslist) != 848*10500SHai-May.Chao@Sun.COM SUCCESS) { 8497968Sopensolaris@drydog.com goto fail_out; 8507968Sopensolaris@drydog.com } 8517968Sopensolaris@drydog.com } 8527968Sopensolaris@drydog.com 8530Sstevel@tonic-gate if (get_soft_list(&psoftlist_kernel) != SUCCESS) { 8540Sstevel@tonic-gate cryptodebug("failed to get software provider list from kernel"); 8550Sstevel@tonic-gate goto fail_out; 8560Sstevel@tonic-gate } 8570Sstevel@tonic-gate 8580Sstevel@tonic-gate for (i = 0, psoftname = psoftlist_kernel->sl_soft_names; 8590Sstevel@tonic-gate i < psoftlist_kernel->sl_soft_count; 8600Sstevel@tonic-gate i++, psoftname = psoftname + strlen(psoftname) + 1) { 8610Sstevel@tonic-gate pmech = NULL; 862*10500SHai-May.Chao@Sun.COM if (get_soft_info(psoftname, &pmech, phardlist, psoftlist, 863*10500SHai-May.Chao@Sun.COM pfipslist) != SUCCESS) { 8640Sstevel@tonic-gate cryptodebug( 8650Sstevel@tonic-gate "failed to retrieve the mechanism list for %s.", 8660Sstevel@tonic-gate psoftname); 8670Sstevel@tonic-gate goto fail_out; 8680Sstevel@tonic-gate } 8690Sstevel@tonic-gate 8707968Sopensolaris@drydog.com if ((pent_soft = create_entry(psoftname)) == NULL) { 8710Sstevel@tonic-gate cryptodebug("out of memory."); 8720Sstevel@tonic-gate free_mechlist(pmech); 8730Sstevel@tonic-gate goto fail_out; 8740Sstevel@tonic-gate } 8757968Sopensolaris@drydog.com pent_soft->suplist = pmech; 8767968Sopensolaris@drydog.com pent_soft->sup_count = get_mech_count(pmech); 8770Sstevel@tonic-gate 8787968Sopensolaris@drydog.com if (build_entrylist(pent_soft, &tmp_psoft) != SUCCESS) { 8790Sstevel@tonic-gate goto fail_out; 8800Sstevel@tonic-gate } 8810Sstevel@tonic-gate } 8820Sstevel@tonic-gate 8830Sstevel@tonic-gate free(psoftlist_kernel); 8840Sstevel@tonic-gate psoftlist_kernel = NULL; 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate *ppdevlist = tmp_pdev; 8870Sstevel@tonic-gate *ppsoftlist = tmp_psoft; 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate return (SUCCESS); 8900Sstevel@tonic-gate 8910Sstevel@tonic-gate fail_out: 8927968Sopensolaris@drydog.com if (pent_dev != NULL) 8937968Sopensolaris@drydog.com free_entry(pent_dev); 8947968Sopensolaris@drydog.com if (pent_soft != NULL) 8957968Sopensolaris@drydog.com free_entry(pent_soft); 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate free_entrylist(tmp_pdev); 8980Sstevel@tonic-gate free_entrylist(tmp_psoft); 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate if (pdevlist_kernel != NULL) 9010Sstevel@tonic-gate free(pdevlist_kernel); 9020Sstevel@tonic-gate if (psoftlist_kernel != NULL) 9030Sstevel@tonic-gate free(psoftlist_kernel); 9040Sstevel@tonic-gate 9050Sstevel@tonic-gate return (FAILURE); 9060Sstevel@tonic-gate } 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate /* 9097968Sopensolaris@drydog.com * Return configuration information for a kernel provider from kcf.conf. 9107968Sopensolaris@drydog.com * For kernel software providers return a enabled list and disabled list. 9117968Sopensolaris@drydog.com * For kernel hardware providers return just a disabled list. 9127968Sopensolaris@drydog.com * 9137968Sopensolaris@drydog.com * Parameters phardlist and psoftlist are supplied by get_kcfconf_info(). 9147968Sopensolaris@drydog.com * If NULL, this function calls get_kcfconf_info() internally. 9150Sstevel@tonic-gate */ 9160Sstevel@tonic-gate entry_t * 917*10500SHai-May.Chao@Sun.COM getent_kef(char *provname, entrylist_t *phardlist, entrylist_t *psoftlist, 918*10500SHai-May.Chao@Sun.COM entrylist_t *pfipslist) 9190Sstevel@tonic-gate { 9207968Sopensolaris@drydog.com entry_t *pent = NULL; 9217968Sopensolaris@drydog.com boolean_t memory_allocated = B_FALSE; 9220Sstevel@tonic-gate 923*10500SHai-May.Chao@Sun.COM if ((phardlist == NULL) || (psoftlist == NULL) || (pfipslist == NULL)) { 924*10500SHai-May.Chao@Sun.COM if (get_kcfconf_info(&phardlist, &psoftlist, &pfipslist) != 925*10500SHai-May.Chao@Sun.COM SUCCESS) { 9267968Sopensolaris@drydog.com return (NULL); 9277968Sopensolaris@drydog.com } 9287968Sopensolaris@drydog.com memory_allocated = B_TRUE; 9290Sstevel@tonic-gate } 9300Sstevel@tonic-gate 9310Sstevel@tonic-gate if (is_device(provname)) { 9327968Sopensolaris@drydog.com pent = getent(provname, phardlist); 933*10500SHai-May.Chao@Sun.COM } else if (is_fips(provname)) { 934*10500SHai-May.Chao@Sun.COM pent = getent(provname, pfipslist); 9350Sstevel@tonic-gate } else { 9360Sstevel@tonic-gate pent = getent(provname, psoftlist); 9370Sstevel@tonic-gate } 9380Sstevel@tonic-gate 9397968Sopensolaris@drydog.com if (memory_allocated) { 9407968Sopensolaris@drydog.com free_entrylist(phardlist); 9417968Sopensolaris@drydog.com free_entrylist(psoftlist); 942*10500SHai-May.Chao@Sun.COM free_entrylist(pfipslist); 9437968Sopensolaris@drydog.com } 9440Sstevel@tonic-gate 9450Sstevel@tonic-gate return (pent); 9460Sstevel@tonic-gate } 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate /* 9490Sstevel@tonic-gate * Print out the provider name and the mechanism list. 9500Sstevel@tonic-gate */ 9510Sstevel@tonic-gate void 9520Sstevel@tonic-gate print_mechlist(char *provname, mechlist_t *pmechlist) 9530Sstevel@tonic-gate { 9547968Sopensolaris@drydog.com mechlist_t *ptr = NULL; 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate if (provname == NULL) { 9570Sstevel@tonic-gate return; 9580Sstevel@tonic-gate } 9590Sstevel@tonic-gate 9600Sstevel@tonic-gate (void) printf("%s: ", provname); 9610Sstevel@tonic-gate if (pmechlist == NULL) { 9620Sstevel@tonic-gate (void) printf(gettext("No mechanisms presented.\n")); 9630Sstevel@tonic-gate return; 9640Sstevel@tonic-gate } 9650Sstevel@tonic-gate 9660Sstevel@tonic-gate ptr = pmechlist; 9670Sstevel@tonic-gate while (ptr != NULL) { 9680Sstevel@tonic-gate (void) printf("%s", ptr->name); 9690Sstevel@tonic-gate ptr = ptr->next; 9700Sstevel@tonic-gate if (ptr == NULL) { 9710Sstevel@tonic-gate (void) printf("\n"); 9720Sstevel@tonic-gate } else { 9730Sstevel@tonic-gate (void) printf(","); 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate } 9760Sstevel@tonic-gate } 9770Sstevel@tonic-gate 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate /* 9807968Sopensolaris@drydog.com * Update the kcf.conf file based on the update mode: 9817968Sopensolaris@drydog.com * - If update_mode is MODIFY_MODE, modify the entry with the same name. 9827968Sopensolaris@drydog.com * If not found, append a new entry to the kcf.conf file. 9837968Sopensolaris@drydog.com * - If update_mode is DELETE_MODE, delete the entry with the same name. 9847968Sopensolaris@drydog.com * - If update_mode is ADD_MODE, append a new entry to the kcf.conf file. 9850Sstevel@tonic-gate */ 9860Sstevel@tonic-gate int 9870Sstevel@tonic-gate update_kcfconf(entry_t *pent, int update_mode) 9880Sstevel@tonic-gate { 9890Sstevel@tonic-gate boolean_t add_it = B_FALSE; 9900Sstevel@tonic-gate boolean_t delete_it = B_FALSE; 9918273Sopensolaris@drydog.com boolean_t this_entry_matches = B_FALSE; 9920Sstevel@tonic-gate boolean_t found_entry = B_FALSE; 9937968Sopensolaris@drydog.com FILE *pfile = NULL; 9947968Sopensolaris@drydog.com FILE *pfile_tmp = NULL; 9957968Sopensolaris@drydog.com char buffer[BUFSIZ]; 9967968Sopensolaris@drydog.com char buffer2[BUFSIZ]; 9977968Sopensolaris@drydog.com char tmpfile_name[MAXPATHLEN]; 9987968Sopensolaris@drydog.com char *name; 9997968Sopensolaris@drydog.com char *new_str = NULL; 10007968Sopensolaris@drydog.com int rc = SUCCESS; 10010Sstevel@tonic-gate 10020Sstevel@tonic-gate if (pent == NULL) { 10030Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 10040Sstevel@tonic-gate return (FAILURE); 10050Sstevel@tonic-gate } 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate /* Check the update_mode */ 10087968Sopensolaris@drydog.com switch (update_mode) { 10097968Sopensolaris@drydog.com case ADD_MODE: 10100Sstevel@tonic-gate add_it = B_TRUE; 10117968Sopensolaris@drydog.com /* FALLTHROUGH */ 10127968Sopensolaris@drydog.com case MODIFY_MODE: 10137968Sopensolaris@drydog.com /* Convert the entry a string to add to kcf.conf */ 10140Sstevel@tonic-gate if ((new_str = ent2str(pent)) == NULL) { 10150Sstevel@tonic-gate return (FAILURE); 10160Sstevel@tonic-gate } 10177968Sopensolaris@drydog.com break; 10187968Sopensolaris@drydog.com case DELETE_MODE: 10190Sstevel@tonic-gate delete_it = B_TRUE; 10207968Sopensolaris@drydog.com break; 10217968Sopensolaris@drydog.com default: 10220Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 10230Sstevel@tonic-gate return (FAILURE); 10240Sstevel@tonic-gate } 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate /* Open the kcf.conf file */ 10270Sstevel@tonic-gate if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) { 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 open %s for write.", _PATH_KCF_CONF); 10330Sstevel@tonic-gate return (FAILURE); 10340Sstevel@tonic-gate } 10350Sstevel@tonic-gate 10360Sstevel@tonic-gate /* Lock the kcf.conf file */ 10370Sstevel@tonic-gate if (lockf(fileno(pfile), F_TLOCK, 0) == -1) { 10380Sstevel@tonic-gate err = errno; 10390Sstevel@tonic-gate cryptoerror(LOG_STDERR, 10400Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 10417968Sopensolaris@drydog.com strerror(err)); 10420Sstevel@tonic-gate (void) fclose(pfile); 10430Sstevel@tonic-gate return (FAILURE); 10440Sstevel@tonic-gate } 10450Sstevel@tonic-gate 10460Sstevel@tonic-gate /* 10470Sstevel@tonic-gate * Create a temporary file in the /etc/crypto directory to save 10480Sstevel@tonic-gate * updated configuration file first. 10490Sstevel@tonic-gate */ 10500Sstevel@tonic-gate (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name)); 10510Sstevel@tonic-gate if (mkstemp(tmpfile_name) == -1) { 10520Sstevel@tonic-gate err = errno; 10530Sstevel@tonic-gate cryptoerror(LOG_STDERR, 10540Sstevel@tonic-gate gettext("failed to create a temporary file - %s"), 10550Sstevel@tonic-gate strerror(err)); 10560Sstevel@tonic-gate (void) fclose(pfile); 10570Sstevel@tonic-gate return (FAILURE); 10580Sstevel@tonic-gate } 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) { 10610Sstevel@tonic-gate err = errno; 10620Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"), 10630Sstevel@tonic-gate tmpfile_name, strerror(err)); 10640Sstevel@tonic-gate (void) fclose(pfile); 10650Sstevel@tonic-gate return (FAILURE); 10660Sstevel@tonic-gate } 10670Sstevel@tonic-gate 10680Sstevel@tonic-gate /* 10690Sstevel@tonic-gate * Loop thru the entire kcf.conf file, insert, modify or delete 10700Sstevel@tonic-gate * an entry. 10710Sstevel@tonic-gate */ 10720Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 10730Sstevel@tonic-gate if (add_it) { 10740Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 10750Sstevel@tonic-gate err = errno; 10760Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 10770Sstevel@tonic-gate "failed to write to a temp file: %s."), 10780Sstevel@tonic-gate strerror(err)); 10790Sstevel@tonic-gate rc = FAILURE; 10800Sstevel@tonic-gate break; 10810Sstevel@tonic-gate } 10820Sstevel@tonic-gate 10830Sstevel@tonic-gate } else { /* modify or delete */ 10848273Sopensolaris@drydog.com this_entry_matches = B_FALSE; 10857968Sopensolaris@drydog.com 10860Sstevel@tonic-gate if (!(buffer[0] == '#' || buffer[0] == ' ' || 10870Sstevel@tonic-gate buffer[0] == '\n'|| buffer[0] == '\t')) { 10880Sstevel@tonic-gate /* 10890Sstevel@tonic-gate * Get the provider name from this line and 10900Sstevel@tonic-gate * check if this is the entry to be updated 10910Sstevel@tonic-gate * or deleted. Note: can not use "buffer" 10920Sstevel@tonic-gate * directly because strtok will change its 10930Sstevel@tonic-gate * value. 10940Sstevel@tonic-gate */ 10950Sstevel@tonic-gate (void) strlcpy(buffer2, buffer, BUFSIZ); 10960Sstevel@tonic-gate if ((name = strtok(buffer2, SEP_COLON)) == 10970Sstevel@tonic-gate NULL) { 10980Sstevel@tonic-gate rc = FAILURE; 10990Sstevel@tonic-gate break; 11000Sstevel@tonic-gate } 11010Sstevel@tonic-gate 11020Sstevel@tonic-gate if (strcmp(pent->name, name) == 0) { 11038273Sopensolaris@drydog.com this_entry_matches = B_TRUE; 11040Sstevel@tonic-gate found_entry = B_TRUE; 11050Sstevel@tonic-gate } 11060Sstevel@tonic-gate } 11070Sstevel@tonic-gate 11080Sstevel@tonic-gate 11098273Sopensolaris@drydog.com if (!this_entry_matches || !delete_it) { 11108273Sopensolaris@drydog.com /* write this entry */ 11118273Sopensolaris@drydog.com if (this_entry_matches) { 11128273Sopensolaris@drydog.com /* 11138273Sopensolaris@drydog.com * Modify this entry: get the 11148273Sopensolaris@drydog.com * updated string and place into buffer. 11158273Sopensolaris@drydog.com */ 11168273Sopensolaris@drydog.com (void) strlcpy(buffer, new_str, BUFSIZ); 11178273Sopensolaris@drydog.com free(new_str); 11188273Sopensolaris@drydog.com } 11198273Sopensolaris@drydog.com /* write the (unchanged or modified) entry */ 11200Sstevel@tonic-gate if (fputs(buffer, pfile_tmp) == EOF) { 11210Sstevel@tonic-gate err = errno; 11220Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 11230Sstevel@tonic-gate "failed to write to a temp file: " 11240Sstevel@tonic-gate "%s."), strerror(err)); 11250Sstevel@tonic-gate rc = FAILURE; 11260Sstevel@tonic-gate break; 11270Sstevel@tonic-gate } 11280Sstevel@tonic-gate } 11290Sstevel@tonic-gate } 11300Sstevel@tonic-gate } 11310Sstevel@tonic-gate 11327968Sopensolaris@drydog.com if ((!delete_it) && (rc != FAILURE)) { 11337968Sopensolaris@drydog.com if (add_it || !found_entry) { 11347968Sopensolaris@drydog.com /* append new entry to end of file */ 11357968Sopensolaris@drydog.com if (fputs(new_str, pfile_tmp) == EOF) { 11367968Sopensolaris@drydog.com err = errno; 11377968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext( 11387968Sopensolaris@drydog.com "failed to write to a temp file: %s."), 11397968Sopensolaris@drydog.com strerror(err)); 11407968Sopensolaris@drydog.com rc = FAILURE; 11417968Sopensolaris@drydog.com } 11427968Sopensolaris@drydog.com free(new_str); 11430Sstevel@tonic-gate } 11440Sstevel@tonic-gate } 11450Sstevel@tonic-gate 11460Sstevel@tonic-gate (void) fclose(pfile); 11470Sstevel@tonic-gate if (fclose(pfile_tmp) != 0) { 11480Sstevel@tonic-gate err = errno; 11490Sstevel@tonic-gate cryptoerror(LOG_STDERR, 11500Sstevel@tonic-gate gettext("failed to close %s: %s"), tmpfile_name, 11510Sstevel@tonic-gate strerror(err)); 11520Sstevel@tonic-gate return (FAILURE); 11530Sstevel@tonic-gate } 11540Sstevel@tonic-gate 11550Sstevel@tonic-gate /* Copy the temporary file to the kcf.conf file */ 11560Sstevel@tonic-gate if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) { 11570Sstevel@tonic-gate err = errno; 11580Sstevel@tonic-gate cryptoerror(LOG_STDERR, 11590Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 11600Sstevel@tonic-gate strerror(err)); 11610Sstevel@tonic-gate cryptodebug("failed to rename %s to %s: %s", tmpfile, 11620Sstevel@tonic-gate _PATH_KCF_CONF, strerror(err)); 11630Sstevel@tonic-gate rc = FAILURE; 11640Sstevel@tonic-gate } else if (chmod(_PATH_KCF_CONF, 11650Sstevel@tonic-gate S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 11660Sstevel@tonic-gate err = errno; 11670Sstevel@tonic-gate cryptoerror(LOG_STDERR, 11680Sstevel@tonic-gate gettext("failed to update the configuration - %s"), 11690Sstevel@tonic-gate strerror(err)); 11700Sstevel@tonic-gate cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF, 11710Sstevel@tonic-gate strerror(err)); 11720Sstevel@tonic-gate rc = FAILURE; 11730Sstevel@tonic-gate } else { 11740Sstevel@tonic-gate rc = SUCCESS; 11750Sstevel@tonic-gate } 11760Sstevel@tonic-gate 11770Sstevel@tonic-gate if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) { 11780Sstevel@tonic-gate err = errno; 11790Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext( 11800Sstevel@tonic-gate "(Warning) failed to remove %s: %s"), 11810Sstevel@tonic-gate tmpfile_name, strerror(err)); 11820Sstevel@tonic-gate } 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate return (rc); 11850Sstevel@tonic-gate } 11860Sstevel@tonic-gate 11870Sstevel@tonic-gate 11880Sstevel@tonic-gate /* 11890Sstevel@tonic-gate * Disable the mechanisms for the provider pointed by *ppent. If allflag is 11900Sstevel@tonic-gate * TRUE, disable all. Otherwise, disable the mechanisms specified in the 11910Sstevel@tonic-gate * dislist argument. The "infolist" argument contains the mechanism list 11920Sstevel@tonic-gate * supported by this provider. 11930Sstevel@tonic-gate */ 11940Sstevel@tonic-gate int 11950Sstevel@tonic-gate disable_mechs(entry_t **ppent, mechlist_t *infolist, boolean_t allflag, 11960Sstevel@tonic-gate mechlist_t *dislist) 11970Sstevel@tonic-gate { 11987968Sopensolaris@drydog.com entry_t *pent; 11997968Sopensolaris@drydog.com mechlist_t *plist = NULL; 12007968Sopensolaris@drydog.com mechlist_t *phead = NULL; 12017968Sopensolaris@drydog.com mechlist_t *pmech = NULL; 12027968Sopensolaris@drydog.com int rc = SUCCESS; 12030Sstevel@tonic-gate 12040Sstevel@tonic-gate pent = *ppent; 12050Sstevel@tonic-gate if (pent == NULL) { 12060Sstevel@tonic-gate return (FAILURE); 12070Sstevel@tonic-gate } 12080Sstevel@tonic-gate 12090Sstevel@tonic-gate if (allflag) { 12100Sstevel@tonic-gate free_mechlist(pent->dislist); 12110Sstevel@tonic-gate pent->dis_count = get_mech_count(infolist); 12120Sstevel@tonic-gate if (!(pent->dislist = dup_mechlist(infolist))) { 12130Sstevel@tonic-gate return (FAILURE); 12140Sstevel@tonic-gate } else { 12150Sstevel@tonic-gate return (SUCCESS); 12160Sstevel@tonic-gate } 12170Sstevel@tonic-gate } 12180Sstevel@tonic-gate 12190Sstevel@tonic-gate /* 12200Sstevel@tonic-gate * Not disable all. Now loop thru the mechanisms specified in the 12210Sstevel@tonic-gate * dislist. If the mechanism is not supported by the provider, 12220Sstevel@tonic-gate * ignore it with a warning. If the mechanism is disabled already, 12230Sstevel@tonic-gate * do nothing. Otherwise, prepend it to the beginning of the disabled 12240Sstevel@tonic-gate * list of the provider. 12250Sstevel@tonic-gate */ 12260Sstevel@tonic-gate plist = dislist; 12270Sstevel@tonic-gate while (plist != NULL) { 12280Sstevel@tonic-gate if (!is_in_list(plist->name, infolist)) { 12290Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("(Warning) " 12300Sstevel@tonic-gate "%1$s is not a valid mechanism for %2$s."), 12310Sstevel@tonic-gate plist->name, pent->name); 12320Sstevel@tonic-gate } else if (!is_in_list(plist->name, pent->dislist)) { 12330Sstevel@tonic-gate /* Add this mechanism into the disabled list */ 12340Sstevel@tonic-gate if ((pmech = create_mech(plist->name)) == NULL) { 12350Sstevel@tonic-gate rc = FAILURE; 12360Sstevel@tonic-gate break; 12370Sstevel@tonic-gate } 12380Sstevel@tonic-gate 12390Sstevel@tonic-gate if (pent->dislist == NULL) { 12400Sstevel@tonic-gate pent->dislist = pmech; 12410Sstevel@tonic-gate } else { 12420Sstevel@tonic-gate phead = pent->dislist; 12430Sstevel@tonic-gate pent->dislist = pmech; 12440Sstevel@tonic-gate pmech->next = phead; 12450Sstevel@tonic-gate } 12460Sstevel@tonic-gate pent->dis_count++; 12470Sstevel@tonic-gate } 12480Sstevel@tonic-gate plist = plist->next; 12490Sstevel@tonic-gate } 12500Sstevel@tonic-gate 12510Sstevel@tonic-gate return (rc); 12520Sstevel@tonic-gate } 12530Sstevel@tonic-gate 12540Sstevel@tonic-gate /* 12550Sstevel@tonic-gate * Remove the mechanism passed, specified by mech, from the list of 12560Sstevel@tonic-gate * mechanisms, if present in the list. Else, do nothing. 12570Sstevel@tonic-gate * 12580Sstevel@tonic-gate * Returns B_TRUE if mechanism is present in the list. 12590Sstevel@tonic-gate */ 12600Sstevel@tonic-gate boolean_t 12610Sstevel@tonic-gate filter_mechlist(mechlist_t **pmechlist, const char *mech) 12620Sstevel@tonic-gate { 12637968Sopensolaris@drydog.com int cnt = 0; 12647968Sopensolaris@drydog.com mechlist_t *ptr, *pptr; 12657968Sopensolaris@drydog.com boolean_t mech_present = B_FALSE; 12660Sstevel@tonic-gate 12670Sstevel@tonic-gate ptr = pptr = *pmechlist; 12680Sstevel@tonic-gate 12690Sstevel@tonic-gate while (ptr != NULL) { 12700Sstevel@tonic-gate if (strncmp(ptr->name, mech, sizeof (mech_name_t)) == 0) { 12710Sstevel@tonic-gate mech_present = B_TRUE; 12720Sstevel@tonic-gate if (ptr == *pmechlist) { 12730Sstevel@tonic-gate pptr = *pmechlist = ptr->next; 12740Sstevel@tonic-gate free(ptr); 12750Sstevel@tonic-gate ptr = pptr; 12760Sstevel@tonic-gate } else { 12770Sstevel@tonic-gate pptr->next = ptr->next; 12780Sstevel@tonic-gate free(ptr); 12790Sstevel@tonic-gate ptr = pptr->next; 12800Sstevel@tonic-gate } 12810Sstevel@tonic-gate } else { 12820Sstevel@tonic-gate pptr = ptr; 12830Sstevel@tonic-gate ptr = ptr->next; 12840Sstevel@tonic-gate cnt++; 12850Sstevel@tonic-gate } 12860Sstevel@tonic-gate } 12870Sstevel@tonic-gate 12880Sstevel@tonic-gate /* Only one entry is present */ 12890Sstevel@tonic-gate if (cnt == 0) 12900Sstevel@tonic-gate *pmechlist = NULL; 12910Sstevel@tonic-gate 12920Sstevel@tonic-gate return (mech_present); 12930Sstevel@tonic-gate } 12940Sstevel@tonic-gate 12950Sstevel@tonic-gate 12960Sstevel@tonic-gate 12970Sstevel@tonic-gate /* 12980Sstevel@tonic-gate * Print out the mechanism policy for a kernel provider that has an entry 12990Sstevel@tonic-gate * in the kcf.conf file. 13000Sstevel@tonic-gate * 13010Sstevel@tonic-gate * The flag has_random is set to B_TRUE if the provider does random 13020Sstevel@tonic-gate * numbers. The flag has_mechs is set by the caller to B_TRUE if the provider 13030Sstevel@tonic-gate * has some mechanisms. 13047968Sopensolaris@drydog.com * 13057968Sopensolaris@drydog.com * If pent is NULL, the provider doesn't have a kcf.conf entry. 13060Sstevel@tonic-gate */ 13070Sstevel@tonic-gate void 13087968Sopensolaris@drydog.com print_kef_policy(char *provname, entry_t *pent, boolean_t has_random, 13097968Sopensolaris@drydog.com boolean_t has_mechs) 13100Sstevel@tonic-gate { 13117968Sopensolaris@drydog.com mechlist_t *ptr = NULL; 13127968Sopensolaris@drydog.com boolean_t rnd_disabled = B_FALSE; 13130Sstevel@tonic-gate 13147968Sopensolaris@drydog.com if (pent != NULL) { 13157968Sopensolaris@drydog.com rnd_disabled = filter_mechlist(&pent->dislist, RANDOM); 13167968Sopensolaris@drydog.com ptr = pent->dislist; 13170Sstevel@tonic-gate } 13180Sstevel@tonic-gate 13197968Sopensolaris@drydog.com (void) printf("%s:", provname); 13200Sstevel@tonic-gate 13210Sstevel@tonic-gate if (has_mechs == B_TRUE) { 13220Sstevel@tonic-gate /* 13237334SDaniel.Anderson@Sun.COM * TRANSLATION_NOTE 13240Sstevel@tonic-gate * This code block may need to be modified a bit to avoid 13250Sstevel@tonic-gate * constructing the text message on the fly. 13260Sstevel@tonic-gate */ 13270Sstevel@tonic-gate (void) printf(gettext(" all mechanisms are enabled")); 13280Sstevel@tonic-gate if (ptr != NULL) 13290Sstevel@tonic-gate (void) printf(gettext(", except ")); 13300Sstevel@tonic-gate while (ptr != NULL) { 13310Sstevel@tonic-gate (void) printf("%s", ptr->name); 13320Sstevel@tonic-gate ptr = ptr->next; 13330Sstevel@tonic-gate if (ptr != NULL) 13340Sstevel@tonic-gate (void) printf(","); 13350Sstevel@tonic-gate } 13360Sstevel@tonic-gate if (ptr == NULL) 13370Sstevel@tonic-gate (void) printf("."); 13380Sstevel@tonic-gate } 13390Sstevel@tonic-gate 13400Sstevel@tonic-gate /* 13417334SDaniel.Anderson@Sun.COM * TRANSLATION_NOTE 13420Sstevel@tonic-gate * "random" is a keyword and not to be translated. 13430Sstevel@tonic-gate */ 13440Sstevel@tonic-gate if (rnd_disabled) 13450Sstevel@tonic-gate (void) printf(gettext(" %s is disabled."), "random"); 13460Sstevel@tonic-gate else if (has_random) 13470Sstevel@tonic-gate (void) printf(gettext(" %s is enabled."), "random"); 13480Sstevel@tonic-gate (void) printf("\n"); 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate 13517968Sopensolaris@drydog.com 13520Sstevel@tonic-gate /* 13530Sstevel@tonic-gate * Check if a kernel software provider is in the kernel. 13547968Sopensolaris@drydog.com * 13557968Sopensolaris@drydog.com * Parameters: 13567968Sopensolaris@drydog.com * provname Provider name 13577968Sopensolaris@drydog.com * psoftlist_kernel Optional software provider list. If NULL, it will be 13587968Sopensolaris@drydog.com * obtained from get_soft_list(). 13597968Sopensolaris@drydog.com * in_kernel Set to B_TRUE if device is in the kernel, else B_FALSE 13600Sstevel@tonic-gate */ 13610Sstevel@tonic-gate int 13627968Sopensolaris@drydog.com check_kernel_for_soft(char *provname, crypto_get_soft_list_t *psoftlist_kernel, 13637968Sopensolaris@drydog.com boolean_t *in_kernel) 13640Sstevel@tonic-gate { 13657968Sopensolaris@drydog.com char *ptr; 13667968Sopensolaris@drydog.com int i; 13677968Sopensolaris@drydog.com boolean_t psoftlist_allocated = B_FALSE; 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate if (provname == NULL) { 13700Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 13710Sstevel@tonic-gate return (FAILURE); 13720Sstevel@tonic-gate } 13730Sstevel@tonic-gate 13747968Sopensolaris@drydog.com if (psoftlist_kernel == NULL) { 13757968Sopensolaris@drydog.com if (get_soft_list(&psoftlist_kernel) == FAILURE) { 13767968Sopensolaris@drydog.com cryptodebug("failed to get the software provider list" 13777968Sopensolaris@drydog.com " from kernel."); 13787968Sopensolaris@drydog.com return (FAILURE); 13797968Sopensolaris@drydog.com } 13807968Sopensolaris@drydog.com psoftlist_allocated = B_TRUE; 13810Sstevel@tonic-gate } 13820Sstevel@tonic-gate 13837968Sopensolaris@drydog.com *in_kernel = B_FALSE; 13840Sstevel@tonic-gate ptr = psoftlist_kernel->sl_soft_names; 13850Sstevel@tonic-gate for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) { 13860Sstevel@tonic-gate if (strcmp(provname, ptr) == 0) { 13877968Sopensolaris@drydog.com *in_kernel = B_TRUE; 13880Sstevel@tonic-gate break; 13890Sstevel@tonic-gate } 13900Sstevel@tonic-gate ptr = ptr + strlen(ptr) + 1; 13910Sstevel@tonic-gate } 13927968Sopensolaris@drydog.com 13937968Sopensolaris@drydog.com if (psoftlist_allocated) 13947968Sopensolaris@drydog.com free(psoftlist_kernel); 13950Sstevel@tonic-gate 13960Sstevel@tonic-gate return (SUCCESS); 13970Sstevel@tonic-gate } 13980Sstevel@tonic-gate 13990Sstevel@tonic-gate 14000Sstevel@tonic-gate /* 14010Sstevel@tonic-gate * Check if a kernel hardware provider is in the kernel. 14027968Sopensolaris@drydog.com * 14037968Sopensolaris@drydog.com * Parameters: 14047968Sopensolaris@drydog.com * provname Provider name 14057968Sopensolaris@drydog.com * pdevlist Optional Hardware Crypto Device List. If NULL, it will be 14067968Sopensolaris@drydog.com * obtained from get_dev_list(). 14077968Sopensolaris@drydog.com * in_kernel Set to B_TRUE if device is in the kernel, otherwise B_FALSE 14080Sstevel@tonic-gate */ 14090Sstevel@tonic-gate int 14107968Sopensolaris@drydog.com check_kernel_for_hard(char *provname, 14117968Sopensolaris@drydog.com crypto_get_dev_list_t *pdevlist, boolean_t *in_kernel) 14120Sstevel@tonic-gate { 14137968Sopensolaris@drydog.com char devname[MAXNAMELEN]; 14147968Sopensolaris@drydog.com int inst_num; 14157968Sopensolaris@drydog.com int i; 14167968Sopensolaris@drydog.com boolean_t dev_list_allocated = B_FALSE; 14170Sstevel@tonic-gate 14180Sstevel@tonic-gate if (provname == NULL) { 14190Sstevel@tonic-gate cryptoerror(LOG_STDERR, gettext("internal error.")); 14200Sstevel@tonic-gate return (FAILURE); 14210Sstevel@tonic-gate } 14220Sstevel@tonic-gate 14230Sstevel@tonic-gate if (split_hw_provname(provname, devname, &inst_num) == FAILURE) { 14240Sstevel@tonic-gate return (FAILURE); 14250Sstevel@tonic-gate } 14260Sstevel@tonic-gate 14277968Sopensolaris@drydog.com if (pdevlist == NULL) { 14287968Sopensolaris@drydog.com if (get_dev_list(&pdevlist) == FAILURE) { 14297968Sopensolaris@drydog.com cryptoerror(LOG_STDERR, gettext("internal error.")); 14307968Sopensolaris@drydog.com return (FAILURE); 14317968Sopensolaris@drydog.com } 14327968Sopensolaris@drydog.com dev_list_allocated = B_TRUE; 14330Sstevel@tonic-gate } 14340Sstevel@tonic-gate 14357968Sopensolaris@drydog.com *in_kernel = B_FALSE; 14360Sstevel@tonic-gate for (i = 0; i < pdevlist->dl_dev_count; i++) { 14370Sstevel@tonic-gate if ((strcmp(pdevlist->dl_devs[i].le_dev_name, devname) == 0) && 14380Sstevel@tonic-gate (pdevlist->dl_devs[i].le_dev_instance == inst_num)) { 14397968Sopensolaris@drydog.com *in_kernel = B_TRUE; 14400Sstevel@tonic-gate break; 14410Sstevel@tonic-gate } 14420Sstevel@tonic-gate } 14437968Sopensolaris@drydog.com 14447968Sopensolaris@drydog.com if (dev_list_allocated) 14457968Sopensolaris@drydog.com free(pdevlist); 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate return (SUCCESS); 14480Sstevel@tonic-gate } 1449