Print this page
10124 smatch fixes for cryptoadm
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c
+++ new/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24 /*
25 25 * Copyright 2010 Nexenta Systems, Inc. All rights resrved.
26 + * Copyright (c) 2018, Joyent, Inc.
26 27 */
27 28
28 29 #include <cryptoutil.h>
29 30 #include <fcntl.h>
30 31 #include <libintl.h>
31 32 #include <stdio.h>
32 33 #include <stdlib.h>
33 34 #include <strings.h>
34 35 #include <unistd.h>
35 36 #include <errno.h>
36 37 #include <dlfcn.h>
37 38 #include <link.h>
38 39 #include <sys/types.h>
39 40 #include <sys/stat.h>
40 41 #include <security/cryptoki.h>
41 42 #include "cryptoadm.h"
42 43
43 44 #define HDR1 " P\n"
44 45 #define HDR2 " S V K a U D\n"
45 46 #define HDR3 " i e e i n e\n"
46 47 #define HDR4 " S g V r y r W w r\n"
47 48 #define HDR5 " E D D i n e i G G r r i\n"
48 49 #define HDR6 " H n e i g + r + e e a a v E\n"
49 50 #define HDR7 "min max W c c g n R i R n n p p e C\n"
50 51
51 52
52 53 static int err; /* To store errno which may be overwritten by gettext() */
53 54 static boolean_t is_in_policylist(midstr_t, umechlist_t *);
54 55 static char *uent2str(uentry_t *);
55 56 static boolean_t check_random(CK_SLOT_ID, CK_FUNCTION_LIST_PTR);
56 57
57 58 static void display_slot_flags(CK_FLAGS flags)
58 59 {
59 60 (void) printf(gettext("Slot Flags: "));
60 61 if (flags & CKF_TOKEN_PRESENT)
61 62 (void) printf("CKF_TOKEN_PRESENT ");
62 63 if (flags & CKF_REMOVABLE_DEVICE)
63 64 (void) printf("CKF_REMOVABLE_DEVICE ");
64 65 if (flags & CKF_HW_SLOT)
65 66 (void) printf("CKF_HW_SLOT ");
66 67 (void) printf("\n");
67 68 }
68 69
69 70 void
70 71 display_token_flags(CK_FLAGS flags)
71 72 {
72 73 (void) printf(gettext("Flags: "));
73 74 if (flags & CKF_RNG)
74 75 (void) printf("CKF_RNG ");
75 76 if (flags & CKF_WRITE_PROTECTED)
76 77 (void) printf("CKF_WRITE_PROTECTED ");
77 78 if (flags & CKF_LOGIN_REQUIRED)
78 79 (void) printf("CKF_LOGIN_REQUIRED ");
79 80 if (flags & CKF_USER_PIN_INITIALIZED)
80 81 (void) printf("CKF_USER_PIN_INITIALIZED ");
81 82 if (flags & CKF_RESTORE_KEY_NOT_NEEDED)
82 83 (void) printf("CKF_RESTORE_KEY_NOT_NEEDED ");
83 84 if (flags & CKF_CLOCK_ON_TOKEN)
84 85 (void) printf("CKF_CLOCK_ON_TOKEN ");
85 86 if (flags & CKF_PROTECTED_AUTHENTICATION_PATH)
86 87 (void) printf("CKF_PROTECTED_AUTHENTICATION_PATH ");
87 88 if (flags & CKF_DUAL_CRYPTO_OPERATIONS)
88 89 (void) printf("CKF_DUAL_CRYPTO_OPERATIONS ");
89 90 if (flags & CKF_TOKEN_INITIALIZED)
90 91 (void) printf("CKF_TOKEN_INITIALIZED ");
91 92 if (flags & CKF_SECONDARY_AUTHENTICATION)
92 93 (void) printf("CKF_SECONDARY_AUTHENTICATION ");
93 94 if (flags & CKF_USER_PIN_COUNT_LOW)
94 95 (void) printf("CKF_USER_PIN_COUNT_LOW ");
95 96 if (flags & CKF_USER_PIN_FINAL_TRY)
96 97 (void) printf("CKF_USER_PIN_FINAL_TRY ");
97 98 if (flags & CKF_USER_PIN_LOCKED)
98 99 (void) printf("CKF_USER_PIN_LOCKED ");
99 100 if (flags & CKF_USER_PIN_TO_BE_CHANGED)
100 101 (void) printf("CKF_USER_PIN_TO_BE_CHANGED ");
101 102 if (flags & CKF_SO_PIN_COUNT_LOW)
102 103 (void) printf("CKF_SO_PIN_COUNT_LOW ");
103 104 if (flags & CKF_SO_PIN_FINAL_TRY)
104 105 (void) printf("CKF_SO_PIN_FINAL_TRY ");
105 106 if (flags & CKF_SO_PIN_LOCKED)
106 107 (void) printf("CKF_SO_PIN_LOCKED ");
107 108 if (flags & CKF_SO_PIN_TO_BE_CHANGED)
108 109 (void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
109 110 if (flags & CKF_SO_PIN_TO_BE_CHANGED)
110 111 (void) printf("CKF_SO_PIN_TO_BE_CHANGED ");
111 112 (void) printf("\n");
112 113 }
113 114
114 115 void
115 116 display_mech_info(CK_MECHANISM_INFO *mechInfo)
116 117 {
117 118 CK_FLAGS ec_flags = CKF_EC_F_P | CKF_EC_F_2M | CKF_EC_ECPARAMETERS |
118 119 CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS | CKF_EC_COMPRESS;
119 120
120 121 (void) printf("%-4ld %-4ld ", mechInfo->ulMinKeySize,
121 122 mechInfo->ulMaxKeySize);
122 123 (void) printf("%s %s %s %s %s %s %s %s %s %s %s %s "
123 124 "%s %s",
124 125 (mechInfo->flags & CKF_HW) ? "X" : ".",
125 126 (mechInfo->flags & CKF_ENCRYPT) ? "X" : ".",
126 127 (mechInfo->flags & CKF_DECRYPT) ? "X" : ".",
127 128 (mechInfo->flags & CKF_DIGEST) ? "X" : ".",
128 129 (mechInfo->flags & CKF_SIGN) ? "X" : ".",
129 130 (mechInfo->flags & CKF_SIGN_RECOVER) ? "X" : ".",
130 131 (mechInfo->flags & CKF_VERIFY) ? "X" : ".",
131 132 (mechInfo->flags & CKF_VERIFY_RECOVER) ? "X" : ".",
132 133 (mechInfo->flags & CKF_GENERATE) ? "X" : ".",
133 134 (mechInfo->flags & CKF_GENERATE_KEY_PAIR) ? "X" : ".",
134 135 (mechInfo->flags & CKF_WRAP) ? "X" : ".",
135 136 (mechInfo->flags & CKF_UNWRAP) ? "X" : ".",
136 137 (mechInfo->flags & CKF_DERIVE) ? "X" : ".",
137 138 (mechInfo->flags & ec_flags) ? "X" : ".");
138 139 }
139 140
140 141 /*
141 142 * Converts the provided list of mechanism names in their string format to
142 143 * their corresponding PKCS#11 mechanism IDs.
143 144 *
144 145 * The list of mechanism names to be converted is provided in the
145 146 * "mlist" argument. The list of converted mechanism IDs is returned
146 147 * in the "pmech_list" argument.
147 148 *
148 149 * This function is called by list_metaslot_info() and
149 150 * list_mechlist_for_lib() functions.
150 151 */
151 152 int
152 153 convert_mechlist(CK_MECHANISM_TYPE **pmech_list, CK_ULONG *mech_count,
153 154 mechlist_t *mlist)
↓ open down ↓ |
118 lines elided |
↑ open up ↑ |
154 155 {
155 156 int i, n = 0;
156 157 mechlist_t *p = mlist;
157 158
158 159 while (p != NULL) {
159 160 p = p->next;
160 161 n++;
161 162 }
162 163
163 164 *pmech_list = malloc(n * sizeof (CK_MECHANISM_TYPE));
164 - if (pmech_list == NULL) {
165 + if (*pmech_list == NULL) {
165 166 cryptodebug("out of memory");
166 167 return (FAILURE);
167 168 }
168 169 p = mlist;
169 170 for (i = 0; i < n; i++) {
170 171 if (pkcs11_str2mech(p->name, &(*pmech_list[i])) != CKR_OK) {
171 172 free(*pmech_list);
172 173 return (FAILURE);
173 174 }
174 175 p = p->next;
175 176 }
176 177 *mech_count = n;
177 178 return (SUCCESS);
178 179 }
179 180
180 181 /*
181 182 * Display the mechanism list for a user-level library
182 183 */
183 184 int
184 185 list_mechlist_for_lib(char *libname, mechlist_t *mlist,
185 186 flag_val_t *rng_flag, boolean_t no_warn,
186 187 boolean_t verbose, boolean_t show_mechs)
187 188 {
188 189 CK_RV rv = CKR_OK;
189 190 CK_RV (*Tmp_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR);
190 191 CK_FUNCTION_LIST_PTR prov_funcs; /* Provider's function list */
191 192 CK_SLOT_ID_PTR prov_slots = NULL; /* Provider's slot list */
192 193 CK_MECHANISM_TYPE_PTR pmech_list = NULL; /* mech list for a slot */
193 194 CK_SLOT_INFO slotinfo;
194 195 CK_ULONG slot_count;
195 196 CK_ULONG mech_count;
196 197 uentry_t *puent = NULL;
197 198 boolean_t lib_initialized = B_FALSE;
198 199 void *dldesc = NULL;
199 200 char *dl_error;
200 201 const char *mech_name;
201 202 char *isa;
202 203 char libpath[MAXPATHLEN];
203 204 char buf[MAXPATHLEN];
204 205 int i, j;
205 206 int rc = SUCCESS;
206 207
207 208 if (libname == NULL) {
208 209 /* should not happen */
209 210 cryptoerror(LOG_STDERR, gettext("internal error."));
210 211 cryptodebug("list_mechlist_for_lib() - libname is NULL.");
211 212 return (FAILURE);
212 213 }
213 214
214 215 /* Check if the library is in the pkcs11.conf file */
215 216 if ((puent = getent_uef(libname)) == NULL) {
216 217 cryptoerror(LOG_STDERR,
217 218 gettext("%s does not exist."), libname);
218 219 return (FAILURE);
219 220 }
220 221 free_uentry(puent);
221 222
222 223 /* Remove $ISA from the library name */
223 224 if (strlcpy(buf, libname, sizeof (buf)) >= sizeof (buf)) {
224 225 (void) printf(gettext("%s: the provider name is too long."),
225 226 libname);
226 227 return (FAILURE);
227 228 }
228 229
229 230 if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
230 231 *isa = '\000';
231 232 isa += strlen(PKCS11_ISA);
232 233 (void) snprintf(libpath, MAXPATHLEN, "%s%s%s", buf, "/", isa);
233 234 } else {
234 235 (void) strlcpy(libpath, libname, sizeof (libpath));
235 236 }
236 237
237 238 /*
238 239 * Open the provider. Use RTLD_NOW here, as a way to
239 240 * catch any providers with incomplete symbols that
240 241 * might otherwise cause problems during libpkcs11's
241 242 * execution.
242 243 */
243 244 dldesc = dlopen(libpath, RTLD_NOW);
244 245 if (dldesc == NULL) {
245 246 dl_error = dlerror();
246 247 cryptodebug("Cannot load PKCS#11 library %s. dlerror: %s",
247 248 libname, dl_error != NULL ? dl_error : "Unknown");
248 249 rc = FAILURE;
249 250 goto clean_exit;
250 251 }
251 252
252 253 /* Get the pointer to provider's C_GetFunctionList() */
253 254 Tmp_C_GetFunctionList = (CK_RV(*)())dlsym(dldesc, "C_GetFunctionList");
254 255 if (Tmp_C_GetFunctionList == NULL) {
255 256 cryptodebug("Cannot get the address of the C_GetFunctionList "
256 257 "from %s", libname);
257 258 rc = FAILURE;
258 259 goto clean_exit;
259 260 }
260 261
261 262 /* Get the provider's function list */
262 263 rv = Tmp_C_GetFunctionList(&prov_funcs);
263 264 if (rv != CKR_OK) {
264 265 cryptodebug("failed to call C_GetFunctionList from %s",
265 266 libname);
266 267 rc = FAILURE;
267 268 goto clean_exit;
268 269 }
269 270
270 271 /* Initialize this provider */
271 272 rv = prov_funcs->C_Initialize(NULL_PTR);
272 273 if (rv != CKR_OK) {
273 274 cryptodebug("failed to call C_Initialize from %s, "
274 275 "return code = %d", libname, rv);
275 276 rc = FAILURE;
276 277 goto clean_exit;
277 278 } else {
278 279 lib_initialized = B_TRUE;
279 280 }
280 281
281 282 /*
282 283 * Find out how many slots this provider has, call with tokenPresent
283 284 * set to FALSE so all potential slots are returned.
284 285 */
285 286 rv = prov_funcs->C_GetSlotList(FALSE, NULL_PTR, &slot_count);
286 287 if (rv != CKR_OK) {
287 288 cryptodebug("failed to get the slotlist from %s.", libname);
288 289 rc = FAILURE;
289 290 goto clean_exit;
290 291 } else if (slot_count == 0) {
291 292 if (!no_warn)
292 293 (void) printf(gettext("%s: no slots presented.\n"),
293 294 libname);
294 295 rc = SUCCESS;
295 296 goto clean_exit;
296 297 }
297 298
298 299 /* Allocate memory for the slot list */
299 300 prov_slots = malloc(slot_count * sizeof (CK_SLOT_ID));
300 301 if (prov_slots == NULL) {
301 302 cryptodebug("out of memory.");
302 303 rc = FAILURE;
303 304 goto clean_exit;
304 305 }
305 306
306 307 /* Get the slot list from provider */
307 308 rv = prov_funcs->C_GetSlotList(FALSE, prov_slots, &slot_count);
308 309 if (rv != CKR_OK) {
309 310 cryptodebug("failed to call C_GetSlotList() from %s.",
310 311 libname);
311 312 rc = FAILURE;
312 313 goto clean_exit;
313 314 }
314 315
315 316 if (verbose) {
316 317 (void) printf(gettext("Number of slots: %d\n"), slot_count);
317 318 }
318 319
319 320 /* Get the mechanism list for each slot */
320 321 for (i = 0; i < slot_count; i++) {
321 322 if (verbose)
322 323 /*
323 324 * TRANSLATION_NOTE
324 325 * In some languages, the # symbol should be
325 326 * converted to "no", an "n" followed by a
326 327 * superscript "o"..
327 328 */
328 329 (void) printf(gettext("\nSlot #%d\n"), i+1);
329 330
330 331 if ((rng_flag != NULL) && (*rng_flag == NO_RNG)) {
331 332 if (check_random(prov_slots[i], prov_funcs)) {
332 333 *rng_flag = HAS_RNG;
333 334 rc = SUCCESS;
334 335 goto clean_exit;
335 336 } else
336 337 continue;
337 338 }
338 339
339 340 rv = prov_funcs->C_GetSlotInfo(prov_slots[i], &slotinfo);
340 341 if (rv != CKR_OK) {
341 342 cryptodebug("failed to get slotinfo from %s", libname);
342 343 rc = FAILURE;
343 344 break;
344 345 }
345 346 if (verbose) {
346 347 CK_TOKEN_INFO tokeninfo;
347 348
348 349 (void) printf(gettext("Description: %.64s\n"
349 350 "Manufacturer: %.32s\n"
350 351 "PKCS#11 Version: %d.%d\n"),
351 352 slotinfo.slotDescription,
352 353 slotinfo.manufacturerID,
353 354 prov_funcs->version.major,
354 355 prov_funcs->version.minor);
355 356
356 357 (void) printf(gettext("Hardware Version: %d.%d\n"
357 358 "Firmware Version: %d.%d\n"),
358 359 slotinfo.hardwareVersion.major,
359 360 slotinfo.hardwareVersion.minor,
360 361 slotinfo.firmwareVersion.major,
361 362 slotinfo.firmwareVersion.minor);
362 363
363 364 (void) printf(gettext("Token Present: %s\n"),
364 365 (slotinfo.flags & CKF_TOKEN_PRESENT ?
365 366 gettext("True") : gettext("False")));
366 367
367 368 display_slot_flags(slotinfo.flags);
368 369
369 370 rv = prov_funcs->C_GetTokenInfo(prov_slots[i],
370 371 &tokeninfo);
371 372 if (rv != CKR_OK) {
372 373 cryptodebug("Failed to get "
373 374 "token info from %s", libname);
374 375 rc = FAILURE;
375 376 break;
376 377 }
377 378
378 379 (void) printf(gettext("Token Label: %.32s\n"
379 380 "Manufacturer ID: %.32s\n"
380 381 "Model: %.16s\n"
381 382 "Serial Number: %.16s\n"
382 383 "Hardware Version: %d.%d\n"
383 384 "Firmware Version: %d.%d\n"
384 385 "UTC Time: %.16s\n"
385 386 "PIN Min Length: %d\n"
386 387 "PIN Max Length: %d\n"),
387 388 tokeninfo.label,
388 389 tokeninfo.manufacturerID,
389 390 tokeninfo.model,
390 391 tokeninfo.serialNumber,
391 392 tokeninfo.hardwareVersion.major,
392 393 tokeninfo.hardwareVersion.minor,
393 394 tokeninfo.firmwareVersion.major,
394 395 tokeninfo.firmwareVersion.minor,
395 396 tokeninfo.utcTime,
396 397 tokeninfo.ulMinPinLen,
397 398 tokeninfo.ulMaxPinLen);
398 399
399 400 display_token_flags(tokeninfo.flags);
400 401 }
401 402
402 403 if (mlist == NULL) {
403 404 rv = prov_funcs->C_GetMechanismList(prov_slots[i],
404 405 NULL_PTR, &mech_count);
405 406 if (rv != CKR_OK) {
406 407 cryptodebug(
407 408 "failed to call C_GetMechanismList() "
408 409 "from %s.", libname);
409 410 rc = FAILURE;
410 411 break;
411 412 }
412 413
413 414 if (mech_count == 0) {
414 415 /* no mechanisms in this slot */
415 416 continue;
416 417 }
417 418
418 419 pmech_list = malloc(mech_count *
419 420 sizeof (CK_MECHANISM_TYPE));
420 421 if (pmech_list == NULL) {
421 422 cryptodebug("out of memory");
422 423 rc = FAILURE;
423 424 break;
424 425 }
425 426
426 427 /* Get the actual mechanism list */
427 428 rv = prov_funcs->C_GetMechanismList(prov_slots[i],
428 429 pmech_list, &mech_count);
429 430 if (rv != CKR_OK) {
430 431 cryptodebug(
431 432 "failed to call C_GetMechanismList() "
432 433 "from %s.", libname);
433 434 free(pmech_list);
434 435 rc = FAILURE;
435 436 break;
436 437 }
437 438 } else {
438 439 /* use the mechanism list passed in */
439 440 rc = convert_mechlist(&pmech_list, &mech_count, mlist);
440 441 if (rc != SUCCESS) {
441 442 goto clean_exit;
442 443 }
443 444 }
444 445 if (show_mechs)
445 446 (void) printf(gettext("Mechanisms:\n"));
446 447
447 448 if (verbose && show_mechs) {
448 449 display_verbose_mech_header();
449 450 }
450 451 /*
451 452 * Merge the current mechanism list into the returning
452 453 * mechanism list.
453 454 */
454 455 for (j = 0; show_mechs && j < mech_count; j++) {
455 456 CK_MECHANISM_TYPE mech = pmech_list[j];
456 457 CK_MECHANISM_INFO mech_info;
457 458
458 459 rv = prov_funcs->C_GetMechanismInfo(
459 460 prov_slots[i], mech, &mech_info);
460 461 if (rv != CKR_OK) {
461 462 cryptodebug(
462 463 "failed to call "
463 464 "C_GetMechanismInfo() from %s.",
464 465 libname);
465 466 free(pmech_list);
466 467 pmech_list = NULL;
467 468 rc = FAILURE;
468 469 break;
469 470 }
470 471 if (mech >= CKM_VENDOR_DEFINED) {
471 472 (void) printf("%#lx", mech);
472 473 } else {
473 474 mech_name = pkcs11_mech2str(mech);
474 475 (void) printf("%-29s", mech_name);
475 476 }
476 477
477 478 if (verbose) {
478 479 display_mech_info(&mech_info);
479 480 }
480 481 (void) printf("\n");
481 482 }
482 483 if (pmech_list)
483 484 free(pmech_list);
484 485 if (rc == FAILURE) {
485 486 break;
486 487 }
487 488 }
488 489
489 490 if (rng_flag != NULL || rc == FAILURE) {
490 491 goto clean_exit;
491 492 }
492 493
493 494 clean_exit:
494 495
495 496 if (rc == FAILURE) {
496 497 (void) printf(gettext(
497 498 "%s: failed to retrieve the mechanism list.\n"), libname);
498 499 }
499 500
500 501 if (lib_initialized) {
501 502 (void) prov_funcs->C_Finalize(NULL_PTR);
502 503 }
503 504
504 505 if (dldesc != NULL) {
505 506 (void) dlclose(dldesc);
506 507 }
507 508
508 509 if (prov_slots != NULL) {
509 510 free(prov_slots);
510 511 }
511 512
512 513 return (rc);
513 514 }
514 515
515 516
516 517 /*
517 518 * Display the mechanism policy for a user-level library
518 519 */
519 520 int
520 521 list_policy_for_lib(char *libname)
521 522 {
522 523 uentry_t *puent = NULL;
523 524 int rc;
524 525
525 526 if (libname == NULL) {
526 527 /* should not happen */
527 528 cryptoerror(LOG_STDERR, gettext("internal error."));
528 529 cryptodebug("list_policy_for_lib() - libname is NULL.");
529 530 return (FAILURE);
530 531 }
531 532
532 533 /* Get the library entry from the pkcs11.conf file */
533 534 if ((puent = getent_uef(libname)) == NULL) {
534 535 cryptoerror(LOG_STDERR,
535 536 gettext("%s does not exist."), libname);
536 537 return (FAILURE);
537 538 }
538 539
539 540 /* Print the policy for this library */
540 541 rc = print_uef_policy(puent);
541 542 free_uentry(puent);
542 543
543 544 return (rc);
544 545 }
545 546
546 547
547 548 /*
548 549 * Disable mechanisms for a user-level library
549 550 */
550 551 int
551 552 disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
552 553 mechlist_t *marglist)
553 554 {
554 555 uentry_t *puent;
555 556 int rc;
556 557
557 558 if (libname == NULL) {
558 559 /* should not happen */
559 560 cryptoerror(LOG_STDERR, gettext("internal error."));
560 561 cryptodebug("disable_uef_lib() - libname is NULL.");
561 562 return (FAILURE);
562 563 }
563 564
564 565 /* Get the provider entry from the pkcs11.conf file */
565 566 if ((puent = getent_uef(libname)) == NULL) {
566 567 cryptoerror(LOG_STDERR,
567 568 gettext("%s does not exist."), libname);
568 569 return (FAILURE);
569 570 }
570 571
571 572 /*
572 573 * Update the mechanism policy of this library entry, based on
573 574 * the current policy mode of the library and the mechanisms specified
574 575 * in CLI.
575 576 */
576 577 if (allflag) {
577 578 /*
578 579 * If disabling all, just need to clean up the policylist and
579 580 * set the flag_enabledlist flag to be B_TRUE.
580 581 */
581 582 free_umechlist(puent->policylist);
582 583 puent->policylist = NULL;
583 584 puent->count = 0;
584 585 puent->flag_enabledlist = B_TRUE;
585 586 rc = SUCCESS;
586 587 } else if (marglist != NULL) {
587 588 if (puent->flag_enabledlist == B_TRUE) {
588 589 /*
589 590 * The current default policy mode of this library
590 591 * is "all are disabled, except ...", so if a
591 592 * specified mechanism is in the exception list
592 593 * (the policylist), delete it from the policylist.
593 594 */
594 595 rc = update_policylist(puent, marglist, DELETE_MODE);
595 596 } else {
596 597 /*
597 598 * The current default policy mode of this library
598 599 * is "all are enabled", so if a specified mechanism
599 600 * is not in the exception list (policylist), add
600 601 * it into the policylist.
601 602 */
602 603 rc = update_policylist(puent, marglist, ADD_MODE);
603 604 }
604 605 } else if (!rndflag) {
605 606 /* should not happen */
606 607 cryptoerror(LOG_STDERR, gettext("internal error."));
607 608 cryptodebug("disable_uef_lib() - wrong arguments.");
608 609 return (FAILURE);
609 610 }
610 611
611 612 if (rndflag)
612 613 puent->flag_norandom = B_TRUE;
613 614
614 615 if (rc == FAILURE) {
615 616 free_uentry(puent);
616 617 return (FAILURE);
617 618 }
618 619
619 620 /* Update the pkcs11.conf file with the updated entry */
620 621 rc = update_pkcs11conf(puent);
621 622 free_uentry(puent);
622 623 return (rc);
623 624 }
624 625
625 626
626 627 /*
627 628 * Enable disabled mechanisms for a user-level library.
628 629 */
629 630 int
630 631 enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
631 632 mechlist_t *marglist)
632 633 {
633 634 uentry_t *puent;
634 635 int rc = SUCCESS;
635 636
636 637 if (libname == NULL) {
637 638 /* should not happen */
638 639 cryptoerror(LOG_STDERR, gettext("internal error."));
639 640 cryptodebug("enable_uef_lib() - libname is NULL.");
640 641 return (FAILURE);
641 642 }
642 643
643 644 /* Get the provider entry from the pkcs11.conf file */
644 645 if ((puent = getent_uef(libname)) == NULL) {
645 646 cryptoerror(LOG_STDERR,
646 647 gettext("%s does not exist."), libname);
647 648 return (FAILURE);
648 649 }
649 650
650 651 /*
651 652 * Update the mechanism policy of this library entry, based on
652 653 * the current policy mode of the library and the mechanisms
653 654 * specified in CLI.
654 655 */
655 656 if (allflag) {
656 657 /*
657 658 * If enabling all, what needs to be done are cleaning up the
658 659 * policylist and setting the "flag_enabledlist" flag to
659 660 * B_FALSE.
660 661 */
661 662 free_umechlist(puent->policylist);
662 663 puent->policylist = NULL;
663 664 puent->count = 0;
664 665 puent->flag_enabledlist = B_FALSE;
665 666 rc = SUCCESS;
666 667 } else if (marglist != NULL) {
667 668 if (puent->flag_enabledlist == B_TRUE) {
668 669 /*
669 670 * The current default policy mode of this library
670 671 * is "all are disabled, except ...", so if a
671 672 * specified mechanism is not in the exception list
672 673 * (policylist), add it.
673 674 */
674 675 rc = update_policylist(puent, marglist, ADD_MODE);
675 676 } else {
676 677 /*
677 678 * The current default policy mode of this library
678 679 * is "all are enabled, except", so if a specified
679 680 * mechanism is in the exception list (policylist),
680 681 * delete it.
681 682 */
682 683 rc = update_policylist(puent, marglist, DELETE_MODE);
683 684 }
684 685 } else if (!rndflag) {
685 686 /* should not come here */
686 687 cryptoerror(LOG_STDERR, gettext("internal error."));
687 688 cryptodebug("enable_uef_lib() - wrong arguments.");
688 689 return (FAILURE);
689 690 }
690 691
691 692 if (rndflag)
692 693 puent->flag_norandom = B_FALSE;
693 694
694 695 if (rc == FAILURE) {
695 696 free_uentry(puent);
696 697 return (FAILURE);
697 698 }
698 699
699 700 /* Update the pkcs11.conf file with the updated entry */
700 701 rc = update_pkcs11conf(puent);
701 702 free_uentry(puent);
702 703 return (rc);
703 704 }
704 705
705 706
706 707 /*
707 708 * Install a user-level library.
708 709 */
709 710 int
710 711 install_uef_lib(char *libname)
711 712 {
712 713 uentry_t *puent;
713 714 struct stat statbuf;
714 715 char libpath[MAXPATHLEN];
715 716 char libbuf[MAXPATHLEN];
716 717 char *isa;
717 718
718 719 if (libname == NULL) {
719 720 /* should not happen */
720 721 cryptoerror(LOG_STDERR, gettext("internal error."));
721 722 cryptodebug("install_uef_lib() - libname is NULL.");
722 723 return (FAILURE);
723 724 }
724 725
725 726 /* Check if the provider already exists in the framework */
726 727 if ((puent = getent_uef(libname)) != NULL) {
727 728 cryptoerror(LOG_STDERR, gettext("%s exists already."),
728 729 libname);
729 730 free_uentry(puent);
730 731 return (FAILURE);
731 732 }
732 733
733 734 /*
734 735 * Check if the library exists in the system. if $ISA is in the
735 736 * path, only check the 32bit version.
736 737 */
737 738 if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) {
738 739 cryptoerror(LOG_STDERR,
739 740 gettext("the provider name is too long - %s"), libname);
740 741 return (FAILURE);
741 742 }
742 743
743 744 if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) {
744 745 *isa = '\000';
745 746 isa += strlen(PKCS11_ISA);
746 747 (void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf,
747 748 "/", isa);
748 749 } else {
749 750 (void) strlcpy(libpath, libname, sizeof (libpath));
750 751 }
751 752
752 753 /* Check if it is same as the framework library */
753 754 if (strcmp(libpath, UEF_FRAME_LIB) == 0) {
754 755 cryptoerror(LOG_STDERR, gettext(
755 756 "The framework library %s can not be installed."),
756 757 libname);
757 758 return (FAILURE);
758 759 }
759 760
760 761 if (stat(libpath, &statbuf) != 0) {
761 762 cryptoerror(LOG_STDERR, gettext("%s not found"), libname);
762 763 return (FAILURE);
763 764 }
764 765
765 766 /* Need to add "\n" to libname for adding into the config file */
766 767 if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) {
767 768 cryptoerror(LOG_STDERR, gettext(
768 769 "can not install %s; the name is too long."), libname);
769 770 return (FAILURE);
770 771 }
771 772
772 773 return (update_conf(_PATH_PKCS11_CONF, libname));
773 774
774 775 }
775 776
776 777
777 778 /*
778 779 * Uninstall a user-level library.
779 780 */
780 781 int
781 782 uninstall_uef_lib(char *libname)
782 783 {
783 784 uentry_t *puent;
784 785 FILE *pfile;
785 786 FILE *pfile_tmp;
786 787 char buffer[BUFSIZ];
787 788 char buffer2[BUFSIZ];
788 789 char tmpfile_name[MAXPATHLEN];
789 790 char *name;
790 791 boolean_t found;
791 792 boolean_t in_package;
792 793 int len;
793 794 int rc = SUCCESS;
794 795
795 796 if (libname == NULL) {
796 797 /* should not happen */
797 798 cryptoerror(LOG_STDERR, gettext("internal error."));
798 799 cryptodebug("uninstall_uef_lib() - libname is NULL.");
799 800 return (FAILURE);
800 801 }
801 802
802 803 /* Check if the provider exists */
803 804 if ((puent = getent_uef(libname)) == NULL) {
804 805 cryptoerror(LOG_STDERR,
805 806 gettext("%s does not exist."), libname);
806 807 return (FAILURE);
807 808 }
808 809 free_uentry(puent);
809 810
810 811 /* Open the pkcs11.conf file and lock it */
811 812 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
812 813 err = errno;
813 814 cryptoerror(LOG_STDERR,
814 815 gettext("failed to update the configuration - %s"),
815 816 strerror(err));
816 817 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
817 818 return (FAILURE);
818 819 }
819 820
820 821 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
821 822 err = errno;
822 823 cryptoerror(LOG_STDERR,
823 824 gettext("failed to lock the configuration - %s"),
824 825 strerror(err));
825 826 (void) fclose(pfile);
826 827 return (FAILURE);
827 828 }
828 829
829 830 /*
830 831 * Create a temporary file in the /etc/crypto directory to save
831 832 * the new configuration file first.
832 833 */
833 834 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
834 835 if (mkstemp(tmpfile_name) == -1) {
835 836 err = errno;
836 837 cryptoerror(LOG_STDERR,
837 838 gettext("failed to create a temporary file - %s"),
838 839 strerror(err));
839 840 (void) fclose(pfile);
840 841 return (FAILURE);
841 842 }
842 843
843 844 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
844 845 err = errno;
845 846 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
846 847 tmpfile_name, strerror(err));
847 848 if (unlink(tmpfile_name) != 0) {
848 849 err = errno;
849 850 cryptoerror(LOG_STDERR, gettext(
850 851 "(Warning) failed to remove %s: %s"),
851 852 tmpfile_name, strerror(err));
852 853 }
853 854 (void) fclose(pfile);
854 855 return (FAILURE);
855 856 }
856 857
857 858
858 859 /*
859 860 * Loop thru the config file. If the library to be uninstalled
860 861 * is in a package, just comment it off.
861 862 */
862 863 in_package = B_FALSE;
863 864 while (fgets(buffer, BUFSIZ, pfile) != NULL) {
864 865 found = B_FALSE;
865 866 if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
866 867 buffer[0] == '\t')) {
867 868 if (strstr(buffer, " Start ") != NULL) {
868 869 in_package = B_TRUE;
869 870 } else if (strstr(buffer, " End ") != NULL) {
870 871 in_package = B_FALSE;
871 872 } else if (buffer[0] != '#') {
872 873 (void) strlcpy(buffer2, buffer, BUFSIZ);
873 874
874 875 /* get rid of trailing '\n' */
875 876 len = strlen(buffer2);
876 877 if (buffer2[len-1] == '\n') {
877 878 len--;
878 879 }
879 880 buffer2[len] = '\0';
880 881
881 882 if ((name = strtok(buffer2, SEP_COLON))
882 883 == NULL) {
883 884 rc = FAILURE;
884 885 break;
885 886 } else if (strcmp(libname, name) == 0) {
886 887 found = B_TRUE;
887 888 }
888 889 }
889 890 }
890 891
891 892 if (found) {
892 893 if (in_package) {
893 894 (void) snprintf(buffer2, sizeof (buffer2),
894 895 "%s%s%s", "#", libname, "\n");
895 896 if (fputs(buffer2, pfile_tmp) == EOF) {
896 897 rc = FAILURE;
897 898 }
898 899 }
899 900 } else {
900 901 if (fputs(buffer, pfile_tmp) == EOF) {
901 902 rc = FAILURE;
902 903 }
903 904 }
904 905
905 906 if (rc == FAILURE) {
906 907 break;
907 908 }
908 909 }
909 910
910 911 if (rc == FAILURE) {
911 912 cryptoerror(LOG_STDERR, gettext("write error."));
912 913 (void) fclose(pfile);
913 914 (void) fclose(pfile_tmp);
914 915 if (unlink(tmpfile_name) != 0) {
915 916 err = errno;
916 917 cryptoerror(LOG_STDERR, gettext(
917 918 "(Warning) failed to remove %s: %s"),
918 919 tmpfile_name, strerror(err));
919 920 }
920 921 return (FAILURE);
921 922 }
922 923
923 924 (void) fclose(pfile);
924 925 if (fclose(pfile_tmp) != 0) {
925 926 err = errno;
926 927 cryptoerror(LOG_STDERR,
927 928 gettext("failed to close a temporary file - %s"),
928 929 strerror(err));
929 930 return (FAILURE);
930 931 }
931 932
932 933 /* Now update the real config file */
933 934 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
934 935 err = errno;
935 936 cryptoerror(LOG_STDERR,
936 937 gettext("failed to update the configuration - %s"),
937 938 strerror(err));
938 939 cryptodebug("failed to rename %s to %s: %s", tmpfile,
939 940 _PATH_PKCS11_CONF, strerror(err));
940 941 rc = FAILURE;
941 942 } else if (chmod(_PATH_PKCS11_CONF,
942 943 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
943 944 err = errno;
944 945 cryptoerror(LOG_STDERR,
945 946 gettext("failed to update the configuration - %s"),
946 947 strerror(err));
947 948 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
948 949 strerror(err));
949 950 rc = FAILURE;
950 951 } else {
951 952 rc = SUCCESS;
952 953 }
953 954
954 955 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
955 956 err = errno;
956 957 cryptoerror(LOG_STDERR, gettext(
957 958 "(Warning) failed to remove %s: %s"),
958 959 tmpfile_name, strerror(err));
959 960 }
960 961
961 962 return (rc);
962 963 }
963 964
964 965
965 966 int
966 967 display_policy(uentry_t *puent)
967 968 {
968 969 CK_MECHANISM_TYPE mech_id;
969 970 const char *mech_name;
970 971 umechlist_t *ptr;
971 972
972 973 if (puent == NULL) {
973 974 return (SUCCESS);
974 975 }
975 976
976 977 if (puent->flag_enabledlist == B_FALSE) {
977 978 (void) printf(gettext("%s: all mechanisms are enabled"),
978 979 puent->name);
979 980 ptr = puent->policylist;
980 981 if (ptr == NULL) {
981 982 (void) printf(".");
982 983 } else {
983 984 (void) printf(gettext(", except "));
984 985 while (ptr != NULL) {
985 986 mech_id = strtoul(ptr->name, NULL, 0);
986 987 if (mech_id & CKO_VENDOR_DEFINED) {
987 988 /* vendor defined mechanism */
988 989 (void) printf("%s", ptr->name);
989 990 } else {
990 991 if (mech_id >= CKM_VENDOR_DEFINED) {
991 992 (void) printf("%#lx", mech_id);
992 993 } else {
993 994 mech_name = pkcs11_mech2str(
994 995 mech_id);
995 996 if (mech_name == NULL) {
996 997 return (FAILURE);
997 998 }
998 999 (void) printf("%s", mech_name);
999 1000 }
1000 1001 }
1001 1002
1002 1003 ptr = ptr->next;
1003 1004 if (ptr == NULL) {
1004 1005 (void) printf(".");
1005 1006 } else {
1006 1007 (void) printf(",");
1007 1008 }
1008 1009 }
1009 1010 }
1010 1011 } else { /* puent->flag_enabledlist == B_TRUE */
1011 1012 (void) printf(gettext("%s: all mechanisms are disabled"),
1012 1013 puent->name);
1013 1014 ptr = puent->policylist;
1014 1015 if (ptr == NULL) {
1015 1016 (void) printf(".");
1016 1017 } else {
1017 1018 (void) printf(gettext(", except "));
1018 1019 while (ptr != NULL) {
1019 1020 mech_id = strtoul(ptr->name, NULL, 0);
1020 1021 if (mech_id & CKO_VENDOR_DEFINED) {
1021 1022 /* vendor defined mechanism */
1022 1023 (void) printf("%s", ptr->name);
1023 1024 } else {
1024 1025 mech_name = pkcs11_mech2str(mech_id);
1025 1026 if (mech_name == NULL) {
1026 1027 return (FAILURE);
1027 1028 }
1028 1029 (void) printf("%s", mech_name);
1029 1030 }
1030 1031 ptr = ptr->next;
1031 1032 if (ptr == NULL) {
1032 1033 (void) printf(".");
1033 1034 } else {
1034 1035 (void) printf(",");
1035 1036 }
1036 1037 }
1037 1038 }
1038 1039 }
1039 1040 return (SUCCESS);
1040 1041 }
1041 1042
1042 1043
1043 1044
1044 1045 /*
1045 1046 * Print out the mechanism policy for a user-level provider pointed by puent.
1046 1047 */
1047 1048 int
1048 1049 print_uef_policy(uentry_t *puent)
1049 1050 {
1050 1051 flag_val_t rng_flag;
1051 1052
1052 1053 if (puent == NULL) {
1053 1054 return (FAILURE);
1054 1055 }
1055 1056
1056 1057 rng_flag = NO_RNG;
1057 1058 if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE,
1058 1059 B_FALSE, B_FALSE) != SUCCESS) {
1059 1060 cryptoerror(LOG_STDERR,
1060 1061 gettext("%s internal error."), puent->name);
1061 1062 return (FAILURE);
1062 1063 }
1063 1064
1064 1065 if (display_policy(puent) != SUCCESS) {
1065 1066 goto failed_exit;
1066 1067 }
1067 1068
1068 1069
1069 1070 if (puent->flag_norandom == B_TRUE)
1070 1071 /*
1071 1072 * TRANSLATION_NOTE
1072 1073 * "random" is a keyword and not to be translated.
1073 1074 */
1074 1075 (void) printf(gettext(" %s is disabled."), "random");
1075 1076 else {
1076 1077 if (rng_flag == HAS_RNG)
1077 1078 /*
1078 1079 * TRANSLATION_NOTE
1079 1080 * "random" is a keyword and not to be translated.
1080 1081 */
1081 1082 (void) printf(gettext(" %s is enabled."), "random");
1082 1083 }
1083 1084 (void) printf("\n");
1084 1085
1085 1086 return (SUCCESS);
1086 1087
1087 1088 failed_exit:
1088 1089
1089 1090 (void) printf(gettext("\nout of memory.\n"));
1090 1091 return (FAILURE);
1091 1092 }
1092 1093
1093 1094
1094 1095 /*
1095 1096 * Check if the mechanism is in the mechanism list.
1096 1097 */
1097 1098 static boolean_t
1098 1099 is_in_policylist(midstr_t mechname, umechlist_t *plist)
1099 1100 {
1100 1101 boolean_t found = B_FALSE;
1101 1102
1102 1103 if (mechname == NULL) {
1103 1104 return (B_FALSE);
1104 1105 }
1105 1106
1106 1107 while (plist != NULL) {
1107 1108 if (strcmp(plist->name, mechname) == 0) {
1108 1109 found = B_TRUE;
1109 1110 break;
1110 1111 }
1111 1112 plist = plist->next;
1112 1113 }
1113 1114
1114 1115 return (found);
1115 1116 }
1116 1117
1117 1118
1118 1119 /*
1119 1120 * Update the pkcs11.conf file with the updated entry.
1120 1121 */
1121 1122 int
1122 1123 update_pkcs11conf(uentry_t *puent)
1123 1124 {
1124 1125 FILE *pfile;
1125 1126 FILE *pfile_tmp;
1126 1127 char buffer[BUFSIZ];
1127 1128 char buffer2[BUFSIZ];
1128 1129 char tmpfile_name[MAXPATHLEN];
1129 1130 char *name;
1130 1131 char *str;
1131 1132 int len;
1132 1133 int rc = SUCCESS;
1133 1134 boolean_t found;
1134 1135
1135 1136 if (puent == NULL) {
1136 1137 cryptoerror(LOG_STDERR, gettext("internal error."));
1137 1138 return (FAILURE);
1138 1139 }
1139 1140
1140 1141 /* Open the pkcs11.conf file */
1141 1142 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
1142 1143 err = errno;
1143 1144 cryptoerror(LOG_STDERR,
1144 1145 gettext("failed to update the configuration - %s"),
1145 1146 strerror(err));
1146 1147 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
1147 1148 return (FAILURE);
1148 1149 }
1149 1150
1150 1151 /* Lock the pkcs11.conf file */
1151 1152 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
1152 1153 err = errno;
1153 1154 cryptoerror(LOG_STDERR,
1154 1155 gettext("failed to update the configuration - %s"),
1155 1156 strerror(err));
1156 1157 (void) fclose(pfile);
1157 1158 return (FAILURE);
1158 1159 }
1159 1160
1160 1161 /*
1161 1162 * Create a temporary file in the /etc/crypto directory to save
1162 1163 * updated configuration file first.
1163 1164 */
1164 1165 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
1165 1166 if (mkstemp(tmpfile_name) == -1) {
1166 1167 err = errno;
1167 1168 cryptoerror(LOG_STDERR,
1168 1169 gettext("failed to create a temporary file - %s"),
1169 1170 strerror(err));
1170 1171 (void) fclose(pfile);
1171 1172 return (FAILURE);
1172 1173 }
1173 1174
1174 1175 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
1175 1176 err = errno;
1176 1177 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
1177 1178 tmpfile_name, strerror(err));
1178 1179 if (unlink(tmpfile_name) != 0) {
1179 1180 err = errno;
1180 1181 cryptoerror(LOG_STDERR, gettext(
1181 1182 "(Warning) failed to remove %s: %s"),
1182 1183 tmpfile_name, strerror(err));
1183 1184 }
1184 1185 (void) fclose(pfile);
1185 1186 return (FAILURE);
1186 1187 }
1187 1188
1188 1189
1189 1190 /*
1190 1191 * Loop thru entire pkcs11.conf file, update the entry to be
1191 1192 * updated and save the updated file to the temporary file first.
1192 1193 */
1193 1194 while (fgets(buffer, BUFSIZ, pfile) != NULL) {
1194 1195 found = B_FALSE;
1195 1196 if (!(buffer[0] == '#' || buffer[0] == ' ' ||
1196 1197 buffer[0] == '\n'|| buffer[0] == '\t')) {
1197 1198 /*
1198 1199 * Get the provider name from this line and check if
1199 1200 * this is the entry to be updated. Note: can not use
1200 1201 * "buffer" directly because strtok will change its
1201 1202 * value.
1202 1203 */
1203 1204 (void) strlcpy(buffer2, buffer, BUFSIZ);
1204 1205
1205 1206 /* get rid of trailing '\n' */
1206 1207 len = strlen(buffer2);
1207 1208 if (buffer2[len-1] == '\n') {
1208 1209 len--;
1209 1210 }
1210 1211 buffer2[len] = '\0';
1211 1212
1212 1213 if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
1213 1214 rc = FAILURE;
1214 1215 break;
1215 1216 } else if (strcmp(puent->name, name) == 0) {
1216 1217 found = B_TRUE;
1217 1218 }
1218 1219 }
1219 1220
1220 1221 if (found) {
1221 1222 /*
1222 1223 * This is the entry to be modified, get the updated
1223 1224 * string.
1224 1225 */
1225 1226 if ((str = uent2str(puent)) == NULL) {
1226 1227 rc = FAILURE;
1227 1228 break;
1228 1229 } else {
1229 1230 (void) strlcpy(buffer, str, BUFSIZ);
1230 1231 free(str);
1231 1232 }
1232 1233 }
1233 1234
1234 1235 if (fputs(buffer, pfile_tmp) == EOF) {
1235 1236 err = errno;
1236 1237 cryptoerror(LOG_STDERR, gettext(
1237 1238 "failed to write to a temp file: %s."),
1238 1239 strerror(err));
1239 1240 rc = FAILURE;
1240 1241 break;
1241 1242 }
1242 1243 }
1243 1244
1244 1245 if (rc == FAILURE) {
1245 1246 (void) fclose(pfile);
1246 1247 (void) fclose(pfile_tmp);
1247 1248 if (unlink(tmpfile_name) != 0) {
1248 1249 err = errno;
1249 1250 cryptoerror(LOG_STDERR, gettext(
1250 1251 "(Warning) failed to remove %s: %s"),
1251 1252 tmpfile_name, strerror(err));
1252 1253 }
1253 1254 return (FAILURE);
1254 1255 }
1255 1256
1256 1257 (void) fclose(pfile);
1257 1258 if (fclose(pfile_tmp) != 0) {
1258 1259 err = errno;
1259 1260 cryptoerror(LOG_STDERR,
1260 1261 gettext("failed to close %s: %s"), tmpfile_name,
1261 1262 strerror(err));
1262 1263 return (FAILURE);
1263 1264 }
1264 1265
1265 1266 /* Copy the temporary file to the pkcs11.conf file */
1266 1267 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
1267 1268 err = errno;
1268 1269 cryptoerror(LOG_STDERR,
1269 1270 gettext("failed to update the configuration - %s"),
1270 1271 strerror(err));
1271 1272 cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
1272 1273 _PATH_PKCS11_CONF, strerror(err));
1273 1274 rc = FAILURE;
1274 1275 } else if (chmod(_PATH_PKCS11_CONF,
1275 1276 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1276 1277 err = errno;
1277 1278 cryptoerror(LOG_STDERR,
1278 1279 gettext("failed to update the configuration - %s"),
1279 1280 strerror(err));
1280 1281 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
1281 1282 strerror(err));
1282 1283 rc = FAILURE;
1283 1284 } else {
1284 1285 rc = SUCCESS;
1285 1286 }
1286 1287
1287 1288 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
1288 1289 err = errno;
1289 1290 cryptoerror(LOG_STDERR, gettext(
1290 1291 "(Warning) failed to remove %s: %s"),
1291 1292 tmpfile_name, strerror(err));
1292 1293 }
1293 1294
1294 1295 return (rc);
1295 1296 }
1296 1297
1297 1298
1298 1299 /*
1299 1300 * Convert an uentry to a character string
1300 1301 */
1301 1302 static char *
1302 1303 uent2str(uentry_t *puent)
1303 1304 {
1304 1305 umechlist_t *phead;
1305 1306 boolean_t tok1_present = B_FALSE;
1306 1307 char *buf;
1307 1308 char blank_buf[128];
1308 1309
1309 1310 if (puent == NULL) {
1310 1311 cryptoerror(LOG_STDERR, gettext("internal error."));
1311 1312 return (NULL);
1312 1313 }
1313 1314
1314 1315 buf = malloc(BUFSIZ);
1315 1316 if (buf == NULL) {
1316 1317 cryptoerror(LOG_STDERR, gettext("out of memory."));
1317 1318 return (NULL);
1318 1319 }
1319 1320
1320 1321 /* convert the library name */
1321 1322 if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) {
1322 1323 free(buf);
1323 1324 return (NULL);
1324 1325 }
1325 1326
1326 1327
1327 1328 /* convert the enabledlist or the disabledlist */
1328 1329 if (puent->flag_enabledlist == B_TRUE) {
1329 1330 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
1330 1331 free(buf);
1331 1332 return (NULL);
1332 1333 }
1333 1334
1334 1335 if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) {
1335 1336 free(buf);
1336 1337 return (NULL);
1337 1338 }
1338 1339
1339 1340 phead = puent->policylist;
1340 1341 while (phead != NULL) {
1341 1342 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
1342 1343 free(buf);
1343 1344 return (NULL);
1344 1345 }
1345 1346
1346 1347 phead = phead->next;
1347 1348 if (phead != NULL) {
1348 1349 if (strlcat(buf, SEP_COMMA, BUFSIZ)
1349 1350 >= BUFSIZ) {
1350 1351 free(buf);
1351 1352 return (NULL);
1352 1353 }
1353 1354 }
1354 1355 }
1355 1356 tok1_present = B_TRUE;
1356 1357 } else if (puent->policylist != NULL) {
1357 1358 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
1358 1359 free(buf);
1359 1360 return (NULL);
1360 1361 }
1361 1362
1362 1363 if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) {
1363 1364 free(buf);
1364 1365 return (NULL);
1365 1366 }
1366 1367 phead = puent->policylist;
1367 1368 while (phead != NULL) {
1368 1369 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
1369 1370 free(buf);
1370 1371 return (NULL);
1371 1372 }
1372 1373
1373 1374 phead = phead->next;
1374 1375 if (phead != NULL) {
1375 1376 if (strlcat(buf, SEP_COMMA, BUFSIZ)
1376 1377 >= BUFSIZ) {
1377 1378 free(buf);
1378 1379 return (NULL);
1379 1380 }
1380 1381 }
1381 1382 }
1382 1383 tok1_present = B_TRUE;
1383 1384 }
1384 1385
1385 1386 if (puent->flag_norandom == B_TRUE) {
1386 1387 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
1387 1388 BUFSIZ) >= BUFSIZ) {
1388 1389 free(buf);
1389 1390 return (NULL);
1390 1391 }
1391 1392
1392 1393 if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) {
1393 1394 free(buf);
1394 1395 return (NULL);
1395 1396 }
1396 1397 }
1397 1398
1398 1399 if (strcmp(puent->name, METASLOT_KEYWORD) == 0) {
1399 1400
1400 1401 /* write the metaslot_status= value */
1401 1402 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
1402 1403 BUFSIZ) >= BUFSIZ) {
1403 1404 free(buf);
1404 1405 return (NULL);
1405 1406 }
1406 1407
1407 1408 if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) {
1408 1409 free(buf);
1409 1410 return (NULL);
1410 1411 }
1411 1412
1412 1413 if (puent->flag_metaslot_enabled) {
1413 1414 if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
1414 1415 free(buf);
1415 1416 return (NULL);
1416 1417 }
1417 1418 } else {
1418 1419 if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ)
1419 1420 >= BUFSIZ) {
1420 1421 free(buf);
1421 1422 return (NULL);
1422 1423 }
1423 1424 }
1424 1425
1425 1426 if (!tok1_present) {
1426 1427 tok1_present = B_TRUE;
1427 1428 }
1428 1429
1429 1430 if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) {
1430 1431 free(buf);
1431 1432 return (NULL);
1432 1433 }
1433 1434
1434 1435 if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) {
1435 1436 free(buf);
1436 1437 return (NULL);
1437 1438 }
1438 1439
1439 1440 if (puent->flag_metaslot_auto_key_migrate) {
1440 1441 if (strlcat(buf, ENABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
1441 1442 free(buf);
1442 1443 return (NULL);
1443 1444 }
1444 1445 } else {
1445 1446 if (strlcat(buf, DISABLED_KEYWORD, BUFSIZ) >= BUFSIZ) {
1446 1447 free(buf);
1447 1448 return (NULL);
1448 1449 }
1449 1450 }
1450 1451
1451 1452 bzero(blank_buf, sizeof (blank_buf));
1452 1453
1453 1454 /* write metaslot_token= if specified */
1454 1455 if (memcmp(puent->metaslot_ks_token, blank_buf,
1455 1456 TOKEN_LABEL_SIZE) != 0) {
1456 1457 /* write the metaslot_status= value */
1457 1458 if (strlcat(buf, (tok1_present ?
1458 1459 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
1459 1460 free(buf);
1460 1461 return (NULL);
1461 1462 }
1462 1463
1463 1464 if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) {
1464 1465 free(buf);
1465 1466 return (NULL);
1466 1467 }
1467 1468
1468 1469 if (strlcat(buf,
1469 1470 (const char *)puent->metaslot_ks_token, BUFSIZ)
1470 1471 >= BUFSIZ) {
1471 1472 free(buf);
1472 1473 return (NULL);
1473 1474 }
1474 1475 }
1475 1476
1476 1477 /* write metaslot_slot= if specified */
1477 1478 if (memcmp(puent->metaslot_ks_slot, blank_buf,
1478 1479 SLOT_DESCRIPTION_SIZE) != 0) {
1479 1480 /* write the metaslot_status= value */
1480 1481 if (strlcat(buf, (tok1_present ?
1481 1482 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
1482 1483 free(buf);
1483 1484 return (NULL);
1484 1485 }
1485 1486
1486 1487 if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) {
1487 1488 free(buf);
1488 1489 return (NULL);
1489 1490 }
1490 1491
1491 1492 if (strlcat(buf,
1492 1493 (const char *)puent->metaslot_ks_slot, BUFSIZ)
1493 1494 >= BUFSIZ) {
1494 1495 free(buf);
1495 1496 return (NULL);
1496 1497 }
1497 1498 }
1498 1499 }
1499 1500
1500 1501 if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
1501 1502 free(buf);
1502 1503 return (NULL);
1503 1504 }
1504 1505
1505 1506 return (buf);
1506 1507 }
1507 1508
1508 1509
1509 1510 /*
1510 1511 * This function updates the default policy mode and the policy exception list
1511 1512 * for a user-level provider based on the mechanism specified in the disable
1512 1513 * or enable subcommand and the update mode. This function is called by the
1513 1514 * enable_uef_lib() or disable_uef_lib().
1514 1515 */
1515 1516 int
1516 1517 update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode)
1517 1518 {
1518 1519 CK_MECHANISM_TYPE mech_type;
1519 1520 midstr_t midname;
1520 1521 umechlist_t *phead;
1521 1522 umechlist_t *pcur;
1522 1523 umechlist_t *pumech;
1523 1524 boolean_t found;
1524 1525 int rc = SUCCESS;
1525 1526
1526 1527 if ((puent == NULL) || (marglist == NULL)) {
1527 1528 /* should not happen */
1528 1529 cryptoerror(LOG_STDERR, gettext("internal error."));
1529 1530 cryptodebug("update_policylist()- puent or marglist is NULL.");
1530 1531 return (FAILURE);
1531 1532 }
1532 1533
1533 1534 if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) {
1534 1535 /* should not happen */
1535 1536 cryptoerror(LOG_STDERR, gettext("internal error."));
1536 1537 cryptodebug("update_policylist() - update_mode is incorrect.");
1537 1538 return (FAILURE);
1538 1539 }
1539 1540
1540 1541 /*
1541 1542 * For each mechanism operand, get its mechanism type first.
1542 1543 * If fails to get the mechanism type, the mechanism operand must be
1543 1544 * invalid, gives an warning and ignore it. Otherwise,
1544 1545 * - convert the mechanism type to the internal representation (hex)
1545 1546 * in the pkcs11.conf file
1546 1547 * - If update_mode == DELETE_MODE,
1547 1548 * If the mechanism is in the policy list, delete it.
1548 1549 * If the mechanism is not in the policy list, do nothing.
1549 1550 * - If update_mode == ADD_MODE,
1550 1551 * If the mechanism is not in the policy list, add it.
1551 1552 * If the mechanism is in the policy list already, do nothing.
1552 1553 */
1553 1554 while (marglist) {
1554 1555 if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) {
1555 1556 /*
1556 1557 * This mechanism is not a valid PKCS11 mechanism,
1557 1558 * give warning and ignore it.
1558 1559 */
1559 1560 cryptoerror(LOG_STDERR, gettext(
1560 1561 "(Warning) %s is not a valid PKCS#11 mechanism."),
1561 1562 marglist->name);
1562 1563 rc = FAILURE;
1563 1564 } else {
1564 1565 (void) snprintf(midname, sizeof (midname), "%#010x",
1565 1566 (int)mech_type);
1566 1567 if (update_mode == DELETE_MODE) {
1567 1568 found = B_FALSE;
1568 1569 phead = pcur = puent->policylist;
1569 1570 while (!found && pcur) {
1570 1571 if (strcmp(pcur->name, midname) == 0) {
1571 1572 found = B_TRUE;
1572 1573 } else {
1573 1574 phead = pcur;
1574 1575 pcur = pcur->next;
1575 1576 }
1576 1577 }
1577 1578
1578 1579 if (found) {
1579 1580 if (phead == pcur) {
1580 1581 puent->policylist =
1581 1582 puent->policylist->next;
1582 1583 free(pcur);
1583 1584 } else {
1584 1585 phead->next = pcur->next;
1585 1586 free(pcur);
1586 1587 }
1587 1588 puent->count--;
1588 1589 if (puent->count == 0) {
1589 1590 puent->policylist = NULL;
1590 1591 }
1591 1592 }
1592 1593 } else if (update_mode == ADD_MODE) {
1593 1594 if (!is_in_policylist(midname,
1594 1595 puent->policylist)) {
1595 1596 pumech = create_umech(midname);
1596 1597 if (pumech == NULL) {
1597 1598 rc = FAILURE;
1598 1599 break;
1599 1600 }
1600 1601 phead = puent->policylist;
1601 1602 puent->policylist = pumech;
1602 1603 pumech->next = phead;
1603 1604 puent->count++;
1604 1605 }
1605 1606 }
1606 1607 }
1607 1608 marglist = marglist->next;
1608 1609 }
1609 1610
1610 1611 return (rc);
1611 1612 }
1612 1613
1613 1614 /*
1614 1615 * Open a session to the given slot and check if we can do
1615 1616 * random numbers by asking for one byte.
1616 1617 */
1617 1618 static boolean_t
1618 1619 check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs)
1619 1620 {
1620 1621 CK_RV rv;
1621 1622 CK_SESSION_HANDLE hSession;
1622 1623 CK_BYTE test_byte;
1623 1624 CK_BYTE_PTR test_byte_ptr = &test_byte;
1624 1625
1625 1626 rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION,
1626 1627 NULL_PTR, NULL, &hSession);
1627 1628 if (rv != CKR_OK)
1628 1629 return (B_FALSE);
1629 1630
1630 1631 /* We care only about the return value */
1631 1632 rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr,
1632 1633 sizeof (test_byte));
1633 1634 (void) prov_funcs->C_CloseSession(hSession);
1634 1635
1635 1636 /*
1636 1637 * These checks are purely to determine whether the slot can do
1637 1638 * random numbers. So, we don't check whether the routine
1638 1639 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that
1639 1640 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED.
1640 1641 */
1641 1642 if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG)
1642 1643 return (B_TRUE);
1643 1644 else
1644 1645 return (B_FALSE);
1645 1646 }
1646 1647
1647 1648 void
1648 1649 display_verbose_mech_header()
1649 1650 {
1650 1651 (void) printf("%28s %s", " ", HDR1);
1651 1652 (void) printf("%28s %s", " ", HDR2);
1652 1653 (void) printf("%28s %s", " ", HDR3);
1653 1654 (void) printf("%28s %s", " ", HDR4);
1654 1655 (void) printf("%28s %s", " ", HDR5);
1655 1656 (void) printf("%28s %s", " ", HDR6);
1656 1657 (void) printf("%-28.28s %s", gettext("mechanism name"), HDR7);
1657 1658 /*
1658 1659 * TRANSLATION_NOTE
1659 1660 * Strictly for appearance's sake, the first header line should be
1660 1661 * as long as the length of the translated text above. The format
1661 1662 * lengths should all match too.
1662 1663 */
1663 1664 (void) printf("%28s ---- ---- "
1664 1665 "- - - - - - - - - - - - - -\n",
1665 1666 gettext("----------------------------"));
1666 1667 }
↓ open down ↓ |
1492 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX