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