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