1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <stdio.h> 30*0Sstevel@tonic-gate #include <errno.h> 31*0Sstevel@tonic-gate #include <strings.h> 32*0Sstevel@tonic-gate #include <locale.h> 33*0Sstevel@tonic-gate #include <stdlib.h> 34*0Sstevel@tonic-gate #include "cryptoutil.h" 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate static int uef_interpret(char *, uentry_t **); 37*0Sstevel@tonic-gate static int parse_policylist(char *, uentry_t *); 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate /* 40*0Sstevel@tonic-gate * Retrieve the user-level provider info from the pkcs11.conf file. 41*0Sstevel@tonic-gate * If successful, the result is returned from the ppliblist argument. 42*0Sstevel@tonic-gate * This function returns SUCCESS if successfully done; otherwise it returns 43*0Sstevel@tonic-gate * FAILURE. 44*0Sstevel@tonic-gate */ 45*0Sstevel@tonic-gate int 46*0Sstevel@tonic-gate get_pkcs11conf_info(uentrylist_t **ppliblist) 47*0Sstevel@tonic-gate { 48*0Sstevel@tonic-gate FILE *pfile; 49*0Sstevel@tonic-gate char buffer[BUFSIZ]; 50*0Sstevel@tonic-gate size_t len; 51*0Sstevel@tonic-gate uentry_t *pent; 52*0Sstevel@tonic-gate uentrylist_t *pentlist; 53*0Sstevel@tonic-gate uentrylist_t *pcur; 54*0Sstevel@tonic-gate int rc = SUCCESS; 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate *ppliblist = NULL; 57*0Sstevel@tonic-gate if ((pfile = fopen(_PATH_PKCS11_CONF, "r")) == NULL) { 58*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_PKCS11_CONF); 59*0Sstevel@tonic-gate return (FAILURE); 60*0Sstevel@tonic-gate } 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate while (fgets(buffer, BUFSIZ, pfile) != NULL) { 63*0Sstevel@tonic-gate if (buffer[0] == '#' || buffer[0] == ' ' || 64*0Sstevel@tonic-gate buffer[0] == '\n'|| buffer[0] == '\t') { 65*0Sstevel@tonic-gate continue; /* ignore comment lines */ 66*0Sstevel@tonic-gate } 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate len = strlen(buffer); 69*0Sstevel@tonic-gate if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */ 70*0Sstevel@tonic-gate len--; 71*0Sstevel@tonic-gate } 72*0Sstevel@tonic-gate buffer[len] = '\0'; 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate if ((rc = uef_interpret(buffer, &pent)) != SUCCESS) { 75*0Sstevel@tonic-gate break; 76*0Sstevel@tonic-gate } 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate /* append pent into ppliblist */ 79*0Sstevel@tonic-gate pentlist = malloc(sizeof (uentrylist_t)); 80*0Sstevel@tonic-gate if (pentlist == NULL) { 81*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "parsing %s, out of memory.\n", 82*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 83*0Sstevel@tonic-gate free_uentry(pent); 84*0Sstevel@tonic-gate rc = FAILURE; 85*0Sstevel@tonic-gate break; 86*0Sstevel@tonic-gate } 87*0Sstevel@tonic-gate pentlist->puent = pent; 88*0Sstevel@tonic-gate pentlist->next = NULL; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate if (*ppliblist == NULL) { 91*0Sstevel@tonic-gate *ppliblist = pcur = pentlist; 92*0Sstevel@tonic-gate } else { 93*0Sstevel@tonic-gate pcur->next = pentlist; 94*0Sstevel@tonic-gate pcur = pcur->next; 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate } 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate (void) fclose(pfile); 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate if (rc != SUCCESS) { 101*0Sstevel@tonic-gate free_uentrylist(*ppliblist); 102*0Sstevel@tonic-gate *ppliblist = NULL; 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate return (rc); 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate /* 110*0Sstevel@tonic-gate * This routine converts a char string into a uentry_t structure 111*0Sstevel@tonic-gate * The input string "buf" should be one of the following: 112*0Sstevel@tonic-gate * library_name 113*0Sstevel@tonic-gate * library_name:NO_RANDOM 114*0Sstevel@tonic-gate * library_name:disabledlist=m1,m2,...,mk 115*0Sstevel@tonic-gate * library_name:disabledlist=m1,m2,...,mk;NO_RANDOM 116*0Sstevel@tonic-gate * library_name:enabledlist= 117*0Sstevel@tonic-gate * library_name:enabledlist=;NO_RANDOM 118*0Sstevel@tonic-gate * library_name:enabledlist=m1,m2,...,mk 119*0Sstevel@tonic-gate * library_name:enabledlist=m1,m2,...,mk;NO_RANDOM 120*0Sstevel@tonic-gate * metaslot:status=enabled;enabledlist=m1,m2,....;slot=<slot-description>;\ 121*0Sstevel@tonic-gate * token=<token-label> 122*0Sstevel@tonic-gate * 123*0Sstevel@tonic-gate * Note: 124*0Sstevel@tonic-gate * The mechanisms m1,..mk are in hex form. For example, "0x00000210" 125*0Sstevel@tonic-gate * for CKM_MD5. 126*0Sstevel@tonic-gate * 127*0Sstevel@tonic-gate * For the metaslot entry, "enabledlist", "slot", "auto_key_migrate" 128*0Sstevel@tonic-gate * or "token" is optional 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate static int 131*0Sstevel@tonic-gate uef_interpret(char *buf, uentry_t **ppent) 132*0Sstevel@tonic-gate { 133*0Sstevel@tonic-gate uentry_t *pent; 134*0Sstevel@tonic-gate char *token1; 135*0Sstevel@tonic-gate char *token2; 136*0Sstevel@tonic-gate char *lasts; 137*0Sstevel@tonic-gate int rc; 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate *ppent = NULL; 140*0Sstevel@tonic-gate if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) { 141*0Sstevel@tonic-gate /* buf is NULL */ 142*0Sstevel@tonic-gate return (FAILURE); 143*0Sstevel@tonic-gate }; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate pent = calloc(sizeof (uentry_t), 1); 146*0Sstevel@tonic-gate if (pent == NULL) { 147*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "parsing %s, out of memory.\n", 148*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 149*0Sstevel@tonic-gate return (FAILURE); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate (void) strlcpy(pent->name, token1, sizeof (pent->name)); 152*0Sstevel@tonic-gate /* 153*0Sstevel@tonic-gate * in case metaslot_auto_key_migrate is not specified, it should 154*0Sstevel@tonic-gate * be default to true 155*0Sstevel@tonic-gate */ 156*0Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_TRUE; 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate while ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) != NULL) { 159*0Sstevel@tonic-gate if ((rc = parse_policylist(token2, pent)) != SUCCESS) { 160*0Sstevel@tonic-gate free_uentry(pent); 161*0Sstevel@tonic-gate return (rc); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate *ppent = pent; 166*0Sstevel@tonic-gate return (SUCCESS); 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate /* 171*0Sstevel@tonic-gate * This routine parses the policy list and stored the result in the argument 172*0Sstevel@tonic-gate * pent. 173*0Sstevel@tonic-gate * 174*0Sstevel@tonic-gate * Arg buf: input only, its format should be one of the following: 175*0Sstevel@tonic-gate * enabledlist= 176*0Sstevel@tonic-gate * enabledlist=m1,m2,...,mk 177*0Sstevel@tonic-gate * disabledlist=m1,m2,...,mk 178*0Sstevel@tonic-gate * NO_RANDOM 179*0Sstevel@tonic-gate * metaslot_status=enabled|disabled 180*0Sstevel@tonic-gate * metaslot_token=<token-label> 181*0Sstevel@tonic-gate * metaslot_slot=<slot-description. 182*0Sstevel@tonic-gate * 183*0Sstevel@tonic-gate * Arg pent: input/output 184*0Sstevel@tonic-gate * 185*0Sstevel@tonic-gate * return: SUCCESS or FAILURE 186*0Sstevel@tonic-gate */ 187*0Sstevel@tonic-gate static int 188*0Sstevel@tonic-gate parse_policylist(char *buf, uentry_t *pent) 189*0Sstevel@tonic-gate { 190*0Sstevel@tonic-gate umechlist_t *phead = NULL; 191*0Sstevel@tonic-gate umechlist_t *pcur = NULL; 192*0Sstevel@tonic-gate umechlist_t *pmech; 193*0Sstevel@tonic-gate char *next_token; 194*0Sstevel@tonic-gate char *value; 195*0Sstevel@tonic-gate char *lasts; 196*0Sstevel@tonic-gate int count = 0; 197*0Sstevel@tonic-gate int rc = SUCCESS; 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate if (pent == NULL) { 200*0Sstevel@tonic-gate return (FAILURE); 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate if (strncmp(buf, EF_DISABLED, sizeof (EF_DISABLED) - 1) == 0) { 204*0Sstevel@tonic-gate pent->flag_enabledlist = B_FALSE; 205*0Sstevel@tonic-gate } else if (strncmp(buf, EF_ENABLED, sizeof (EF_ENABLED) - 1) == 0) { 206*0Sstevel@tonic-gate pent->flag_enabledlist = B_TRUE; 207*0Sstevel@tonic-gate } else if (strncmp(buf, EF_NORANDOM, sizeof (EF_NORANDOM) - 1) == 0) { 208*0Sstevel@tonic-gate pent->flag_norandom = B_TRUE; 209*0Sstevel@tonic-gate return (rc); 210*0Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_TOKEN, 211*0Sstevel@tonic-gate sizeof (METASLOT_TOKEN) - 1) == 0) { 212*0Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 213*0Sstevel@tonic-gate value++; /* get rid of = */ 214*0Sstevel@tonic-gate (void) strlcpy((char *)pent->metaslot_ks_token, value, 215*0Sstevel@tonic-gate TOKEN_LABEL_SIZE); 216*0Sstevel@tonic-gate return (SUCCESS); 217*0Sstevel@tonic-gate } else { 218*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 219*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 220*0Sstevel@tonic-gate return (FAILURE); 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_SLOT, 223*0Sstevel@tonic-gate sizeof (METASLOT_SLOT) - 1) == 0) { 224*0Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 225*0Sstevel@tonic-gate value++; /* get rid of = */ 226*0Sstevel@tonic-gate (void) strlcpy((char *)pent->metaslot_ks_slot, value, 227*0Sstevel@tonic-gate SLOT_DESCRIPTION_SIZE); 228*0Sstevel@tonic-gate return (SUCCESS); 229*0Sstevel@tonic-gate } else { 230*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 231*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 232*0Sstevel@tonic-gate return (FAILURE); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_STATUS, 235*0Sstevel@tonic-gate sizeof (METASLOT_STATUS) - 1) == 0) { 236*0Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 237*0Sstevel@tonic-gate value++; /* get rid of = */ 238*0Sstevel@tonic-gate if (strcmp(value, METASLOT_DISABLED) == 0) { 239*0Sstevel@tonic-gate pent->flag_metaslot_enabled = B_FALSE; 240*0Sstevel@tonic-gate } else if (strcmp(value, METASLOT_ENABLED) == 0) { 241*0Sstevel@tonic-gate pent->flag_metaslot_enabled = B_TRUE; 242*0Sstevel@tonic-gate } else { 243*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 244*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 245*0Sstevel@tonic-gate return (FAILURE); 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate return (SUCCESS); 248*0Sstevel@tonic-gate } else { 249*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 250*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 251*0Sstevel@tonic-gate return (FAILURE); 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate } else if (strncmp(buf, METASLOT_AUTO_KEY_MIGRATE, 254*0Sstevel@tonic-gate sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) { 255*0Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 256*0Sstevel@tonic-gate value++; /* get rid of = */ 257*0Sstevel@tonic-gate if (strcmp(value, METASLOT_DISABLED) == 0) { 258*0Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_FALSE; 259*0Sstevel@tonic-gate } else if (strcmp(value, METASLOT_ENABLED) == 0) { 260*0Sstevel@tonic-gate pent->flag_metaslot_auto_key_migrate = B_TRUE; 261*0Sstevel@tonic-gate } else { 262*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 263*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 264*0Sstevel@tonic-gate return (FAILURE); 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate return (SUCCESS); 267*0Sstevel@tonic-gate } else { 268*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 269*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 270*0Sstevel@tonic-gate return (FAILURE); 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate } else { 273*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 274*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 275*0Sstevel@tonic-gate return (FAILURE); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate if (value = strpbrk(buf, SEP_EQUAL)) { 279*0Sstevel@tonic-gate value++; /* get rid of = */ 280*0Sstevel@tonic-gate } 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate if ((next_token = strtok_r(value, SEP_COMMA, &lasts)) == NULL) { 283*0Sstevel@tonic-gate if (pent->flag_enabledlist) { 284*0Sstevel@tonic-gate return (SUCCESS); 285*0Sstevel@tonic-gate } else { 286*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "failed to parse %s.\n", 287*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 288*0Sstevel@tonic-gate return (FAILURE); 289*0Sstevel@tonic-gate } 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate while (next_token) { 293*0Sstevel@tonic-gate if ((pmech = create_umech(next_token)) == NULL) { 294*0Sstevel@tonic-gate cryptoerror(LOG_ERR, "parsing %s, out of memory.\n", 295*0Sstevel@tonic-gate _PATH_PKCS11_CONF); 296*0Sstevel@tonic-gate rc = FAILURE; 297*0Sstevel@tonic-gate break; 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate if (phead == NULL) { 301*0Sstevel@tonic-gate phead = pcur = pmech; 302*0Sstevel@tonic-gate } else { 303*0Sstevel@tonic-gate pcur->next = pmech; 304*0Sstevel@tonic-gate pcur = pcur->next; 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate count++; 307*0Sstevel@tonic-gate next_token = strtok_r(NULL, SEP_COMMA, &lasts); 308*0Sstevel@tonic-gate } 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate if (rc == SUCCESS) { 311*0Sstevel@tonic-gate pent->policylist = phead; 312*0Sstevel@tonic-gate pent->count = count; 313*0Sstevel@tonic-gate } else { 314*0Sstevel@tonic-gate free_umechlist(phead); 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate return (rc); 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* 322*0Sstevel@tonic-gate * Create one item of type umechlist_t with the mechanism name. A NULL is 323*0Sstevel@tonic-gate * returned when the input name is NULL or the heap memory is insufficient. 324*0Sstevel@tonic-gate */ 325*0Sstevel@tonic-gate umechlist_t * 326*0Sstevel@tonic-gate create_umech(char *name) 327*0Sstevel@tonic-gate { 328*0Sstevel@tonic-gate umechlist_t *pmech = NULL; 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate if (name == NULL) { 331*0Sstevel@tonic-gate return (NULL); 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate if ((pmech = malloc(sizeof (umechlist_t))) != NULL) { 335*0Sstevel@tonic-gate (void) strlcpy(pmech->name, name, sizeof (pmech->name)); 336*0Sstevel@tonic-gate pmech->next = NULL; 337*0Sstevel@tonic-gate } 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate return (pmech); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate void 344*0Sstevel@tonic-gate free_umechlist(umechlist_t *plist) 345*0Sstevel@tonic-gate { 346*0Sstevel@tonic-gate umechlist_t *pnext; 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate while (plist != NULL) { 349*0Sstevel@tonic-gate pnext = plist->next; 350*0Sstevel@tonic-gate free(plist); 351*0Sstevel@tonic-gate plist = pnext; 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate void 357*0Sstevel@tonic-gate free_uentry(uentry_t *pent) 358*0Sstevel@tonic-gate { 359*0Sstevel@tonic-gate if (pent == NULL) { 360*0Sstevel@tonic-gate return; 361*0Sstevel@tonic-gate } else { 362*0Sstevel@tonic-gate free_umechlist(pent->policylist); 363*0Sstevel@tonic-gate free(pent); 364*0Sstevel@tonic-gate } 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate void 369*0Sstevel@tonic-gate free_uentrylist(uentrylist_t *entrylist) 370*0Sstevel@tonic-gate { 371*0Sstevel@tonic-gate uentrylist_t *pnext; 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate while (entrylist != NULL) { 374*0Sstevel@tonic-gate pnext = entrylist->next; 375*0Sstevel@tonic-gate free_uentry(entrylist->puent); 376*0Sstevel@tonic-gate free(entrylist); 377*0Sstevel@tonic-gate entrylist = pnext; 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate } 380