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