1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "@(#)adm_uef.c 1.12 06/11/02 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 corrsponding 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 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 mech_name = pkcs11_mech2str(pmech_list[j]);
450 (void) printf("%-29s", mech_name);
451 if (verbose) {
452 CK_MECHANISM_INFO mech_info;
453 rv = prov_funcs->C_GetMechanismInfo(
454 prov_slots[i], pmech_list[j], &mech_info);
455 if (rv != CKR_OK) {
456 cryptodebug(
457 "failed to call "
458 "C_GetMechanismInfo() from %s.",
459 libname);
460 (void) free(pmech_list);
461 rc = FAILURE;
462 break;
463 }
464 display_mech_info(&mech_info);
465 }
466 (void) printf("\n");
467 }
468 (void) free(pmech_list);
469 if (rc == FAILURE) {
470 break;
471 }
472 }
473
474 if (rng_flag != NULL || rc == FAILURE) {
475 goto clean_exit;
476 }
477
478 clean_exit:
479
480 if (rc == FAILURE) {
481 (void) printf(gettext(
482 "%s: failed to retrieve the mechanism list.\n"), libname);
483 }
484
485 if (lib_initialized) {
486 (void) prov_funcs->C_Finalize(NULL_PTR);
487 }
488
489 if (dldesc != NULL) {
490 (void) dlclose(dldesc);
491 }
492
493 if (prov_slots != NULL) {
494 (void) free(prov_slots);
495 }
496
497 return (rc);
498 }
499
500
501 /*
502 * Display the mechanism policy for a user-level library
503 */
504 int
505 list_policy_for_lib(char *libname)
506 {
507 uentry_t *puent = NULL;
508 int rc;
509
510 if (libname == NULL) {
511 /* should not happen */
512 cryptoerror(LOG_STDERR, gettext("internal error."));
513 cryptodebug("list_policy_for_lib() - libname is NULL.");
514 return (FAILURE);
515 }
516
517 /* Get the library entry from the pkcs11.conf file */
518 if ((puent = getent_uef(libname)) == NULL) {
519 cryptoerror(LOG_STDERR,
520 gettext("%s does not exist."), libname);
521 return (FAILURE);
522 }
523
524 /* Print the policy for this library */
525 rc = print_uef_policy(puent);
526 free_uentry(puent);
527
528 return (rc);
529 }
530
531
532 /*
533 * Disable mechanisms for a user-level library
534 */
535 int
536 disable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
537 mechlist_t *marglist)
538 {
539 uentry_t *puent;
540 int rc;
541
542 if (libname == NULL) {
543 /* should not happen */
544 cryptoerror(LOG_STDERR, gettext("internal error."));
545 cryptodebug("disable_uef_lib() - libname is NULL.");
546 return (FAILURE);
547 }
548
549 /* Get the provider entry from the pkcs11.conf file */
550 if ((puent = getent_uef(libname)) == NULL) {
551 cryptoerror(LOG_STDERR,
552 gettext("%s does not exist."), libname);
553 return (FAILURE);
554 }
555
556 /*
557 * Update the mechanism policy of this library entry, based on
558 * the current policy mode of the library and the mechanisms specified
559 * in CLI.
560 */
561 if (allflag) {
562 /*
563 * If disabling all, just need to clean up the policylist and
564 * set the flag_enabledlist flag to be B_TRUE.
565 */
566 free_umechlist(puent->policylist);
567 puent->policylist = NULL;
568 puent->count = 0;
569 puent->flag_enabledlist = B_TRUE;
570 rc = SUCCESS;
571 } else if (marglist != NULL) {
572 if (puent->flag_enabledlist == B_TRUE) {
573 /*
574 * The current default policy mode of this library
575 * is "all are disabled, except ...", so if a
576 * specified mechanism is in the exception list
577 * (the policylist), delete it from the policylist.
578 */
579 rc = update_policylist(puent, marglist, DELETE_MODE);
580 } else {
581 /*
582 * The current default policy mode of this library
583 * is "all are enabled", so if a specified mechanism
584 * is not in the exception list (policylist), add
585 * it into the policylist.
586 */
587 rc = update_policylist(puent, marglist, ADD_MODE);
588 }
589 } else if (!rndflag) {
590 /* should not happen */
591 cryptoerror(LOG_STDERR, gettext("internal error."));
592 cryptodebug("disable_uef_lib() - wrong arguments.");
593 return (FAILURE);
594 }
595
596 if (rndflag)
597 puent->flag_norandom = B_TRUE;
598
599 if (rc == FAILURE) {
600 free_uentry(puent);
601 return (FAILURE);
602 }
603
604 /* Update the pkcs11.conf file with the updated entry */
605 rc = update_pkcs11conf(puent);
606 free_uentry(puent);
607 return (rc);
608 }
609
610
611 /*
612 * Enable disabled mechanisms for a user-level library.
613 */
614 int
615 enable_uef_lib(char *libname, boolean_t rndflag, boolean_t allflag,
616 mechlist_t *marglist)
617 {
618 uentry_t *puent;
619 int rc = SUCCESS;
620
621 if (libname == NULL) {
622 /* should not happen */
623 cryptoerror(LOG_STDERR, gettext("internal error."));
624 cryptodebug("enable_uef_lib() - libname is NULL.");
625 return (FAILURE);
626 }
627
628 /* Get the provider entry from the pkcs11.conf file */
629 if ((puent = getent_uef(libname)) == NULL) {
630 cryptoerror(LOG_STDERR,
631 gettext("%s does not exist."), libname);
632 return (FAILURE);
633 }
634
635 /*
636 * Update the mechanism policy of this library entry, based on
637 * the current policy mode of the library and the mechanisms
638 * specified in CLI.
639 */
640 if (allflag) {
641 /*
642 * If enabling all, what needs to be done are cleaning up the
643 * policylist and setting the "flag_enabledlist" flag to
644 * B_FALSE.
645 */
646 free_umechlist(puent->policylist);
647 puent->policylist = NULL;
648 puent->count = 0;
649 puent->flag_enabledlist = B_FALSE;
650 rc = SUCCESS;
651 } else if (marglist != NULL) {
652 if (puent->flag_enabledlist == B_TRUE) {
653 /*
654 * The current default policy mode of this library
655 * is "all are disabled, except ...", so if a
656 * specified mechanism is not in the exception list
657 * (policylist), add it.
658 */
659 rc = update_policylist(puent, marglist, ADD_MODE);
660 } else {
661 /*
662 * The current default policy mode of this library
663 * is "all are enabled, except", so if a specified
664 * mechanism is in the exception list (policylist),
665 * delete it.
666 */
667 rc = update_policylist(puent, marglist, DELETE_MODE);
668 }
669 } else if (!rndflag) {
670 /* should not come here */
671 cryptoerror(LOG_STDERR, gettext("internal error."));
672 cryptodebug("enable_uef_lib() - wrong arguments.");
673 return (FAILURE);
674 }
675
676 if (rndflag)
677 puent->flag_norandom = B_FALSE;
678
679 if (rc == FAILURE) {
680 free_uentry(puent);
681 return (FAILURE);
682 }
683
684 /* Update the pkcs11.conf file with the updated entry */
685 rc = update_pkcs11conf(puent);
686 free_uentry(puent);
687 return (rc);
688 }
689
690
691 /*
692 * Install a user-level library.
693 */
694 int
695 install_uef_lib(char *libname)
696 {
697 uentry_t *puent;
698 struct stat statbuf;
699 boolean_t found;
700 FILE *pfile;
701 FILE *pfile_tmp;
702 char tmpfile_name[MAXPATHLEN];
703 char libpath[MAXPATHLEN];
704 char libbuf[MAXPATHLEN];
705 char *isa;
706 char buffer[BUFSIZ];
707 char *ptr;
708 int found_count;
709 int rc = SUCCESS;
710
711
712 if (libname == NULL) {
713 /* should not happen */
714 cryptoerror(LOG_STDERR, gettext("internal error."));
715 cryptodebug("install_uef_lib() - libname is NULL.");
716 return (FAILURE);
717 }
718
719 /* Check if the provider already exists in the framework */
720 if ((puent = getent_uef(libname)) != NULL) {
721 cryptoerror(LOG_STDERR, gettext("%s exists already."),
722 libname);
723 free_uentry(puent);
724 return (FAILURE);
725 }
726
727 /*
728 * Check if the library exists in the system. if $ISA is in the
729 * path, only check the 32bit version.
730 */
731 if (strlcpy(libbuf, libname, MAXPATHLEN) >= MAXPATHLEN) {
732 cryptoerror(LOG_STDERR,
733 gettext("the provider name is too long - %s"), libname);
734 return (FAILURE);
735 }
736
737 if ((isa = strstr(libbuf, PKCS11_ISA)) != NULL) {
738 *isa = '\000';
739 isa += strlen(PKCS11_ISA);
740 (void) snprintf(libpath, sizeof (libpath), "%s%s%s", libbuf,
741 "/", isa);
742 } else {
743 (void) strlcpy(libpath, libname, sizeof (libpath));
744 }
745
746 /* Check if it is same as the framework library */
747 if (strcmp(libpath, UEF_FRAME_LIB) == 0) {
748 cryptoerror(LOG_STDERR, gettext(
749 "The framework library %s can not be installed."),
750 libname);
751 return (FAILURE);
752 }
753
754 if (stat(libpath, &statbuf) != 0) {
755 cryptoerror(LOG_STDERR, gettext("%s not found"), libname);
756 return (FAILURE);
757 }
758
759 /* Need to add "\n" to libname for adding into the config file */
760 if (strlcat(libname, "\n", MAXPATHLEN) >= MAXPATHLEN) {
761 cryptoerror(LOG_STDERR, gettext(
762 "can not install %s; the name is too long."), libname);
763 return (FAILURE);
764 }
765
766 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
767 err = errno;
768 cryptoerror(LOG_STDERR,
769 gettext("failed to update the configuration - %s"),
770 strerror(err));
771 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
772 return (FAILURE);
773 }
774
775 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
776 err = errno;
777 cryptoerror(LOG_STDERR,
778 gettext("failed to lock the configuration - %s"),
779 strerror(err));
780 (void) fclose(pfile);
781 return (FAILURE);
782 }
783
784 /*
785 * Create a temporary file in the /etc/crypto directory.
786 */
787 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
788 if (mkstemp(tmpfile_name) == -1) {
789 err = errno;
790 cryptoerror(LOG_STDERR,
791 gettext("failed to create a temporary file - %s"),
792 strerror(err));
793 (void) fclose(pfile);
794 return (FAILURE);
795 }
796
797 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
798 err = errno;
799 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
800 tmpfile_name, strerror(err));
801 (void) fclose(pfile);
802 return (FAILURE);
803 }
804
805 /*
806 * Loop thru the config file. If the file was reserved within a
807 * package bracket, just uncomment it. Other wise, append it at
808 * the end. The resulting file will be saved in the temp file first.
809 */
810 found_count = 0;
811 rc = SUCCESS;
812 while (fgets(buffer, BUFSIZ, pfile) != NULL) {
813 found = B_FALSE;
814 if (buffer[0] == '#') {
815 ptr = buffer;
816 ptr++;
817 if (strcmp(libname, ptr) == 0) {
818 found = B_TRUE;
819 found_count++;
820 }
821 }
822
823 if (found == B_FALSE) {
824 if (fputs(buffer, pfile_tmp) == EOF) {
825 rc = FAILURE;
826 }
827 } else {
828 if (found_count == 1) {
829 if (fputs(ptr, pfile_tmp) == EOF) {
830 rc = FAILURE;
831 }
832 } else {
833 /*
834 * Found a second entry with #libname.
835 * Should not happen. The pkcs11.conf file
836 * is corrupted. Give a warning and skip
837 * this entry.
838 */
839 cryptoerror(LOG_STDERR, gettext(
840 "(Warning) Found an additional reserved "
841 "entry for %s."), libname);
842 }
843 }
844
845 if (rc == FAILURE) {
846 break;
847 }
848 }
849
850 if (rc == FAILURE) {
851 cryptoerror(LOG_STDERR, gettext("write error."));
852 (void) fclose(pfile);
853 (void) fclose(pfile_tmp);
854 if (unlink(tmpfile_name) != 0) {
855 err = errno;
856 cryptoerror(LOG_STDERR, gettext(
857 "(Warning) failed to remove %s: %s"), tmpfile_name,
858 strerror(err));
859 }
860 return (FAILURE);
861 }
862
863 if (found_count == 0) {
864 /*
865 * This libname was not in package before, append it to the
866 * end of the temp file.
867 */
868 if (fputs(libname, pfile_tmp) == EOF) {
869 err = errno;
870 cryptoerror(LOG_STDERR, gettext(
871 "failed to write to %s: %s"), tmpfile_name,
872 strerror(err));
873 (void) fclose(pfile);
874 (void) fclose(pfile_tmp);
875 if (unlink(tmpfile_name) != 0) {
876 err = errno;
877 cryptoerror(LOG_STDERR, gettext(
878 "(Warning) failed to remove %s: %s"),
879 tmpfile_name, strerror(err));
880 }
881 return (FAILURE);
882 }
883 }
884
885 (void) fclose(pfile);
886 if (fclose(pfile_tmp) != 0) {
887 err = errno;
888 cryptoerror(LOG_STDERR,
889 gettext("failed to close %s: %s"), tmpfile_name,
890 strerror(err));
891 return (FAILURE);
892 }
893
894 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
895 err = errno;
896 cryptoerror(LOG_STDERR,
897 gettext("failed to update the configuration - %s"),
898 strerror(err));
899 cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
900 _PATH_PKCS11_CONF, strerror(err));
901 rc = FAILURE;
902 } else if (chmod(_PATH_PKCS11_CONF,
903 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
904 err = errno;
905 cryptoerror(LOG_STDERR,
906 gettext("failed to update the configuration - %s"),
907 strerror(err));
908 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
909 strerror(err));
910 rc = FAILURE;
911 } else {
912 rc = SUCCESS;
913 }
914
915 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
916 err = errno;
917 cryptoerror(LOG_STDERR, gettext(
918 "(Warning) failed to remove %s: %s"), tmpfile_name,
919 strerror(err));
920 }
921
922 return (rc);
923 }
924
925
926 /*
927 * Uninstall a user-level library.
928 */
929 int
930 uninstall_uef_lib(char *libname)
931 {
932 uentry_t *puent;
933 FILE *pfile;
934 FILE *pfile_tmp;
935 char buffer[BUFSIZ];
936 char buffer2[BUFSIZ];
937 char tmpfile_name[MAXPATHLEN];
938 char *name;
939 boolean_t found;
940 boolean_t in_package;
941 int len;
942 int rc = SUCCESS;
943
944 if (libname == NULL) {
945 /* should not happen */
946 cryptoerror(LOG_STDERR, gettext("internal error."));
947 cryptodebug("uninstall_uef_lib() - libname is NULL.");
948 return (FAILURE);
949 }
950
951 /* Check if the provider exists */
952 if ((puent = getent_uef(libname)) == NULL) {
953 cryptoerror(LOG_STDERR,
954 gettext("%s does not exist."), libname);
955 return (FAILURE);
956 }
957 free_uentry(puent);
958
959 /* Open the pkcs11.conf file and lock it */
960 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
961 err = errno;
962 cryptoerror(LOG_STDERR,
963 gettext("failed to update the configuration - %s"),
964 strerror(err));
965 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
966 return (FAILURE);
967 }
968
969 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
970 err = errno;
971 cryptoerror(LOG_STDERR,
972 gettext("failed to lock the configuration - %s"),
973 strerror(err));
974 (void) fclose(pfile);
975 return (FAILURE);
976 }
977
978 /*
979 * Create a temporary file in the /etc/crypto directory to save
980 * the new configuration file first.
981 */
982 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
983 if (mkstemp(tmpfile_name) == -1) {
984 err = errno;
985 cryptoerror(LOG_STDERR,
986 gettext("failed to create a temporary file - %s"),
987 strerror(err));
988 (void) fclose(pfile);
989 return (FAILURE);
990 }
991
992 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
993 err = errno;
994 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
995 tmpfile_name, strerror(err));
996 if (unlink(tmpfile_name) != 0) {
997 err = errno;
998 cryptoerror(LOG_STDERR, gettext(
999 "(Warning) failed to remove %s: %s"),
1000 tmpfile_name, strerror(err));
1001 }
1002 (void) fclose(pfile);
1003 return (FAILURE);
1004 }
1005
1006
1007 /*
1008 * Loop thru the config file. If the library to be uninstalled
1009 * is in a package, just comment it off.
1010 */
1011 in_package = B_FALSE;
1012 while (fgets(buffer, BUFSIZ, pfile) != NULL) {
1013 found = B_FALSE;
1014 if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
1015 buffer[0] == '\t')) {
1016 if (strstr(buffer, " Start ") != NULL) {
1017 in_package = B_TRUE;
1018 } else if (strstr(buffer, " End ") != NULL) {
1019 in_package = B_FALSE;
1020 } else if (buffer[0] != '#') {
1021 (void) strlcpy(buffer2, buffer, BUFSIZ);
1022
1023 /* get rid of trailing '\n' */
1024 len = strlen(buffer2);
1025 if (buffer2[len-1] == '\n') {
1026 len--;
1027 }
1028 buffer2[len] = '\0';
1029
1030 if ((name = strtok(buffer2, SEP_COLON))
1031 == NULL) {
1032 rc = FAILURE;
1033 break;
1034 } else if (strcmp(libname, name) == 0) {
1035 found = B_TRUE;
1036 }
1037 }
1038 }
1039
1040 if (found) {
1041 if (in_package) {
1042 (void) snprintf(buffer2, sizeof (buffer2),
1043 "%s%s%s", "#", libname, "\n");
1044 if (fputs(buffer2, pfile_tmp) == EOF) {
1045 rc = FAILURE;
1046 }
1047 }
1048 } else {
1049 if (fputs(buffer, pfile_tmp) == EOF) {
1050 rc = FAILURE;
1051 }
1052 }
1053
1054 if (rc == FAILURE) {
1055 break;
1056 }
1057 }
1058
1059 if (rc == FAILURE) {
1060 cryptoerror(LOG_STDERR, gettext("write error."));
1061 (void) fclose(pfile);
1062 (void) fclose(pfile_tmp);
1063 if (unlink(tmpfile_name) != 0) {
1064 err = errno;
1065 cryptoerror(LOG_STDERR, gettext(
1066 "(Warning) failed to remove %s: %s"),
1067 tmpfile_name, strerror(err));
1068 }
1069 return (FAILURE);
1070 }
1071
1072 (void) fclose(pfile);
1073 if (fclose(pfile_tmp) != 0) {
1074 err = errno;
1075 cryptoerror(LOG_STDERR,
1076 gettext("failed to close a temporary file - %s"),
1077 strerror(err));
1078 return (FAILURE);
1079 }
1080
1081 /* Now update the real config file */
1082 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
1083 err = errno;
1084 cryptoerror(LOG_STDERR,
1085 gettext("failed to update the configuration - %s"),
1086 strerror(err));
1087 cryptodebug("failed to rename %s to %s: %s", tmpfile,
1088 _PATH_PKCS11_CONF, strerror(err));
1089 rc = FAILURE;
1090 } else if (chmod(_PATH_PKCS11_CONF,
1091 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1092 err = errno;
1093 cryptoerror(LOG_STDERR,
1094 gettext("failed to update the configuration - %s"),
1095 strerror(err));
1096 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
1097 strerror(err));
1098 rc = FAILURE;
1099 } else {
1100 rc = SUCCESS;
1101 }
1102
1103 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
1104 err = errno;
1105 cryptoerror(LOG_STDERR, gettext(
1106 "(Warning) failed to remove %s: %s"),
1107 tmpfile_name, strerror(err));
1108 }
1109
1110 return (rc);
1111 }
1112
1113
1114 int
1115 display_policy(uentry_t *puent)
1116 {
1117 CK_MECHANISM_TYPE mech_id;
1118 char *mech_name;
1119 umechlist_t *ptr;
1120
1121 if (puent == NULL) {
1122 return (SUCCESS);
1123 }
1124
1125 if (puent->flag_enabledlist == B_FALSE) {
1126 (void) printf(gettext("%s: all mechanisms are enabled"),
1127 puent->name);
1128 ptr = puent->policylist;
1129 if (ptr == NULL) {
1130 (void) printf(".");
1131 } else {
1132 (void) printf(gettext(", except "));
1133 while (ptr != NULL) {
1134 mech_id = strtoul(ptr->name, NULL, 0);
1135 if (mech_id & CKO_VENDOR_DEFINED) {
1136 /* vendor defined mechanism */
1137 (void) printf("%s", ptr->name);
1138 } else {
1139 mech_name = pkcs11_mech2str(mech_id);
1140 if (mech_name == NULL) {
1141 return (FAILURE);
1142 }
1143 (void) printf("%s", mech_name);
1144 free(mech_name);
1145 }
1146
1147 ptr = ptr->next;
1148 if (ptr == NULL) {
1149 (void) printf(".");
1150 } else {
1151 (void) printf(",");
1152 }
1153 }
1154 }
1155 } else { /* puent->flag_enabledlist == B_TRUE */
1156 (void) printf(gettext("%s: all mechanisms are disabled"),
1157 puent->name);
1158 ptr = puent->policylist;
1159 if (ptr == NULL) {
1160 (void) printf(".");
1161 } else {
1162 (void) printf(gettext(", except "));
1163 while (ptr != NULL) {
1164 mech_id = strtoul(ptr->name, NULL, 0);
1165 if (mech_id & CKO_VENDOR_DEFINED) {
1166 /* vendor defined mechanism */
1167 (void) printf("%s", ptr->name);
1168 } else {
1169 mech_name = pkcs11_mech2str(mech_id);
1170 if (mech_name == NULL) {
1171 return (FAILURE);
1172 }
1173 (void) printf("%s", mech_name);
1174 free(mech_name);
1175 }
1176 ptr = ptr->next;
1177 if (ptr == NULL) {
1178 (void) printf(".");
1179 } else {
1180 (void) printf(",");
1181 }
1182 }
1183 }
1184 }
1185 return (SUCCESS);
1186 }
1187
1188
1189
1190 /*
1191 * Print out the mechanism policy for a user-level provider pointed by puent.
1192 */
1193 int
1194 print_uef_policy(uentry_t *puent)
1195 {
1196 flag_val_t rng_flag;
1197
1198 if (puent == NULL) {
1199 return (FAILURE);
1200 }
1201
1202 rng_flag = NO_RNG;
1203 if (list_mechlist_for_lib(puent->name, NULL, &rng_flag, B_TRUE,
1204 B_FALSE, B_FALSE) != SUCCESS) {
1205 cryptoerror(LOG_STDERR,
1206 gettext("%s internal error."), puent->name);
1207 return (FAILURE);
1208 }
1209
1210 if (display_policy(puent) != SUCCESS) {
1211 goto failed_exit;
1212 }
1213
1214
1215 if (puent->flag_norandom == B_TRUE)
1216 /*
1217 * TRANSLATION_NOTE:
1218 * "random" is a keyword and not to be translated.
1219 */
1220 (void) printf(gettext(" %s is disabled."), "random");
1221 else {
1222 if (rng_flag == HAS_RNG)
1223 /*
1224 * TRANSLATION_NOTE:
1225 * "random" is a keyword and not to be translated.
1226 */
1227 (void) printf(gettext(" %s is enabled."), "random");
1228 }
1229 (void) printf("\n");
1230
1231 return (SUCCESS);
1232
1233 failed_exit:
1234
1235 (void) printf(gettext("\nout of memory.\n"));
1236 return (FAILURE);
1237 }
1238
1239
1240 /*
1241 * Check if the mechanism is in the mechanism list.
1242 */
1243 static boolean_t
1244 is_in_policylist(midstr_t mechname, umechlist_t *plist)
1245 {
1246 boolean_t found = B_FALSE;
1247
1248 if (mechname == NULL) {
1249 return (B_FALSE);
1250 }
1251
1252 while (plist != NULL) {
1253 if (strcmp(plist->name, mechname) == 0) {
1254 found = B_TRUE;
1255 break;
1256 }
1257 plist = plist->next;
1258 }
1259
1260 return (found);
1261 }
1262
1263
1264 /*
1265 * Update the pkcs11.conf file with the updated entry.
1266 */
1267 int
1268 update_pkcs11conf(uentry_t *puent)
1269 {
1270 FILE *pfile;
1271 FILE *pfile_tmp;
1272 char buffer[BUFSIZ];
1273 char buffer2[BUFSIZ];
1274 char tmpfile_name[MAXPATHLEN];
1275 char *name;
1276 char *str;
1277 int len;
1278 int rc = SUCCESS;
1279 boolean_t found;
1280
1281 if (puent == NULL) {
1282 cryptoerror(LOG_STDERR, gettext("internal error."));
1283 return (FAILURE);
1284 }
1285
1286 /* Open the pkcs11.conf file */
1287 if ((pfile = fopen(_PATH_PKCS11_CONF, "r+")) == NULL) {
1288 err = errno;
1289 cryptoerror(LOG_STDERR,
1290 gettext("failed to update the configuration - %s"),
1291 strerror(err));
1292 cryptodebug("failed to open %s for write.", _PATH_PKCS11_CONF);
1293 return (FAILURE);
1294 }
1295
1296 /* Lock the pkcs11.conf file */
1297 if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
1298 err = errno;
1299 cryptoerror(LOG_STDERR,
1300 gettext("failed to update the configuration - %s"),
1301 strerror(err));
1302 (void) fclose(pfile);
1303 return (FAILURE);
1304 }
1305
1306 /*
1307 * Create a temporary file in the /etc/crypto directory to save
1308 * updated configuration file first.
1309 */
1310 (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
1311 if (mkstemp(tmpfile_name) == -1) {
1312 err = errno;
1313 cryptoerror(LOG_STDERR,
1314 gettext("failed to create a temporary file - %s"),
1315 strerror(err));
1316 (void) fclose(pfile);
1317 return (FAILURE);
1318 }
1319
1320 if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
1321 err = errno;
1322 cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
1323 tmpfile_name, strerror(err));
1324 if (unlink(tmpfile_name) != 0) {
1325 err = errno;
1326 cryptoerror(LOG_STDERR, gettext(
1327 "(Warning) failed to remove %s: %s"),
1328 tmpfile_name, strerror(err));
1329 }
1330 (void) fclose(pfile);
1331 return (FAILURE);
1332 }
1333
1334
1335 /*
1336 * Loop thru entire pkcs11.conf file, update the entry to be
1337 * updated and save the updated file to the temporary file first.
1338 */
1339 while (fgets(buffer, BUFSIZ, pfile) != NULL) {
1340 found = B_FALSE;
1341 if (!(buffer[0] == '#' || buffer[0] == ' ' ||
1342 buffer[0] == '\n'|| buffer[0] == '\t')) {
1343 /*
1344 * Get the provider name from this line and check if
1345 * this is the entry to be updated. Note: can not use
1346 * "buffer" directly because strtok will change its
1347 * value.
1348 */
1349 (void) strlcpy(buffer2, buffer, BUFSIZ);
1350
1351 /* get rid of trailing '\n' */
1352 len = strlen(buffer2);
1353 if (buffer2[len-1] == '\n') {
1354 len--;
1355 }
1356 buffer2[len] = '\0';
1357
1358 if ((name = strtok(buffer2, SEP_COLON)) == NULL) {
1359 rc = FAILURE;
1360 break;
1361 } else if (strcmp(puent->name, name) == 0) {
1362 found = B_TRUE;
1363 }
1364 }
1365
1366 if (found) {
1367 /*
1368 * This is the entry to be modified, get the updated
1369 * string.
1370 */
1371 if ((str = uent2str(puent)) == NULL) {
1372 rc = FAILURE;
1373 break;
1374 } else {
1375 (void) strlcpy(buffer, str, BUFSIZ);
1376 free(str);
1377 }
1378 }
1379
1380 if (fputs(buffer, pfile_tmp) == EOF) {
1381 err = errno;
1382 cryptoerror(LOG_STDERR, gettext(
1383 "failed to write to a temp file: %s."),
1384 strerror(err));
1385 rc = FAILURE;
1386 break;
1387 }
1388 }
1389
1390 if (rc == FAILURE) {
1391 (void) fclose(pfile);
1392 (void) fclose(pfile_tmp);
1393 if (unlink(tmpfile_name) != 0) {
1394 err = errno;
1395 cryptoerror(LOG_STDERR, gettext(
1396 "(Warning) failed to remove %s: %s"),
1397 tmpfile_name, strerror(err));
1398 }
1399 return (FAILURE);
1400 }
1401
1402 (void) fclose(pfile);
1403 if (fclose(pfile_tmp) != 0) {
1404 err = errno;
1405 cryptoerror(LOG_STDERR,
1406 gettext("failed to close %s: %s"), tmpfile_name,
1407 strerror(err));
1408 return (FAILURE);
1409 }
1410
1411 /* Copy the temporary file to the pkcs11.conf file */
1412 if (rename(tmpfile_name, _PATH_PKCS11_CONF) == -1) {
1413 err = errno;
1414 cryptoerror(LOG_STDERR,
1415 gettext("failed to update the configuration - %s"),
1416 strerror(err));
1417 cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
1418 _PATH_PKCS11_CONF, strerror(err));
1419 rc = FAILURE;
1420 } else if (chmod(_PATH_PKCS11_CONF,
1421 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1422 err = errno;
1423 cryptoerror(LOG_STDERR,
1424 gettext("failed to update the configuration - %s"),
1425 strerror(err));
1426 cryptodebug("failed to chmod to %s: %s", _PATH_PKCS11_CONF,
1427 strerror(err));
1428 rc = FAILURE;
1429 } else {
1430 rc = SUCCESS;
1431 }
1432
1433 if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
1434 err = errno;
1435 cryptoerror(LOG_STDERR, gettext(
1436 "(Warning) failed to remove %s: %s"),
1437 tmpfile_name, strerror(err));
1438 }
1439
1440 return (rc);
1441 }
1442
1443
1444 /*
1445 * Convert an uentry to a character string
1446 */
1447 static char *
1448 uent2str(uentry_t *puent)
1449 {
1450 umechlist_t *phead;
1451 boolean_t tok1_present = B_FALSE;
1452 char *buf;
1453 char blank_buf[128];
1454
1455 if (puent == NULL) {
1456 cryptoerror(LOG_STDERR, gettext("internal error."));
1457 return (NULL);
1458 }
1459
1460 buf = malloc(BUFSIZ);
1461 if (buf == NULL) {
1462 cryptoerror(LOG_STDERR, gettext("out of memory."));
1463 return (NULL);
1464 }
1465
1466 /* convert the library name */
1467 if (strlcpy(buf, puent->name, BUFSIZ) >= BUFSIZ) {
1468 free(buf);
1469 return (NULL);
1470 }
1471
1472
1473 /* convert the enabledlist or the disabledlist */
1474 if (puent->flag_enabledlist == B_TRUE) {
1475 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
1476 free(buf);
1477 return (NULL);
1478 }
1479
1480 if (strlcat(buf, EF_ENABLED, BUFSIZ) >= BUFSIZ) {
1481 free(buf);
1482 return (NULL);
1483 }
1484
1485 phead = puent->policylist;
1486 while (phead != NULL) {
1487 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
1488 free(buf);
1489 return (NULL);
1490 }
1491
1492 phead = phead->next;
1493 if (phead != NULL) {
1494 if (strlcat(buf, SEP_COMMA, BUFSIZ)
1495 >= BUFSIZ) {
1496 free(buf);
1497 return (NULL);
1498 }
1499 }
1500 }
1501 tok1_present = B_TRUE;
1502 } else if (puent->policylist != NULL) {
1503 if (strlcat(buf, SEP_COLON, BUFSIZ) >= BUFSIZ) {
1504 free(buf);
1505 return (NULL);
1506 }
1507
1508 if (strlcat(buf, EF_DISABLED, BUFSIZ) >= BUFSIZ) {
1509 free(buf);
1510 return (NULL);
1511 }
1512 phead = puent->policylist;
1513 while (phead != NULL) {
1514 if (strlcat(buf, phead->name, BUFSIZ) >= BUFSIZ) {
1515 free(buf);
1516 return (NULL);
1517 }
1518
1519 phead = phead->next;
1520 if (phead != NULL) {
1521 if (strlcat(buf, SEP_COMMA, BUFSIZ)
1522 >= BUFSIZ) {
1523 free(buf);
1524 return (NULL);
1525 }
1526 }
1527 }
1528 tok1_present = B_TRUE;
1529 }
1530
1531 if (puent->flag_norandom == B_TRUE) {
1532 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
1533 BUFSIZ) >= BUFSIZ) {
1534 free(buf);
1535 return (NULL);
1536 }
1537
1538 if (strlcat(buf, EF_NORANDOM, BUFSIZ) >= BUFSIZ) {
1539 free(buf);
1540 return (NULL);
1541 }
1542 }
1543
1544 if (strcmp(puent->name, METASLOT_KEYWORD) == 0) {
1545
1546 /* write the metaslot_status= value */
1547 if (strlcat(buf, (tok1_present ? SEP_SEMICOLON : SEP_COLON),
1548 BUFSIZ) >= BUFSIZ) {
1549 free(buf);
1550 return (NULL);
1551 }
1552
1553 if (strlcat(buf, METASLOT_STATUS, BUFSIZ) >= BUFSIZ) {
1554 free(buf);
1555 return (NULL);
1556 }
1557
1558 if (puent->flag_metaslot_enabled) {
1559 if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) {
1560 free(buf);
1561 return (NULL);
1562 }
1563 } else {
1564 if (strlcat(buf, METASLOT_DISABLED, BUFSIZ)
1565 >= BUFSIZ) {
1566 free(buf);
1567 return (NULL);
1568 }
1569 }
1570
1571 if (!tok1_present) {
1572 tok1_present = B_TRUE;
1573 }
1574
1575 if (strlcat(buf, SEP_SEMICOLON, BUFSIZ) >= BUFSIZ) {
1576 free(buf);
1577 return (NULL);
1578 }
1579
1580 if (strlcat(buf, METASLOT_AUTO_KEY_MIGRATE, BUFSIZ) >= BUFSIZ) {
1581 free(buf);
1582 return (NULL);
1583 }
1584
1585 if (puent->flag_metaslot_auto_key_migrate) {
1586 if (strlcat(buf, METASLOT_ENABLED, BUFSIZ) >= BUFSIZ) {
1587 free(buf);
1588 return (NULL);
1589 }
1590 } else {
1591 if (strlcat(buf, METASLOT_DISABLED, BUFSIZ) >= BUFSIZ) {
1592 free(buf);
1593 return (NULL);
1594 }
1595 }
1596
1597 bzero(blank_buf, sizeof (blank_buf));
1598
1599 /* write metaslot_token= if specified */
1600 if (memcmp(puent->metaslot_ks_token, blank_buf,
1601 TOKEN_LABEL_SIZE) != 0) {
1602 /* write the metaslot_status= value */
1603 if (strlcat(buf, (tok1_present ?
1604 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
1605 free(buf);
1606 return (NULL);
1607 }
1608
1609 if (strlcat(buf, METASLOT_TOKEN, BUFSIZ) >= BUFSIZ) {
1610 free(buf);
1611 return (NULL);
1612 }
1613
1614 if (strlcat(buf,
1615 (const char *)puent->metaslot_ks_token, BUFSIZ)
1616 >= BUFSIZ) {
1617 free(buf);
1618 return (NULL);
1619 }
1620 }
1621
1622 /* write metaslot_slot= if specified */
1623 if (memcmp(puent->metaslot_ks_slot, blank_buf,
1624 SLOT_DESCRIPTION_SIZE) != 0) {
1625 /* write the metaslot_status= value */
1626 if (strlcat(buf, (tok1_present ?
1627 SEP_SEMICOLON : SEP_COLON), BUFSIZ) >= BUFSIZ) {
1628 free(buf);
1629 return (NULL);
1630 }
1631
1632 if (strlcat(buf, METASLOT_SLOT, BUFSIZ) >= BUFSIZ) {
1633 free(buf);
1634 return (NULL);
1635 }
1636
1637 if (strlcat(buf,
1638 (const char *)puent->metaslot_ks_slot, BUFSIZ)
1639 >= BUFSIZ) {
1640 free(buf);
1641 return (NULL);
1642 }
1643 }
1644 }
1645
1646 if (strlcat(buf, "\n", BUFSIZ) >= BUFSIZ) {
1647 free(buf);
1648 return (NULL);
1649 }
1650
1651 return (buf);
1652 }
1653
1654
1655 /*
1656 * This function updates the default policy mode and the policy exception list
1657 * for a user-level provider based on the mechanism specified in the disable
1658 * or enable subcommand and the update mode. This function is called by the
1659 * enable_uef_lib() or disable_uef_lib().
1660 */
1661 int
1662 update_policylist(uentry_t *puent, mechlist_t *marglist, int update_mode)
1663 {
1664 CK_MECHANISM_TYPE mech_type;
1665 midstr_t midname;
1666 umechlist_t *phead;
1667 umechlist_t *pcur;
1668 umechlist_t *pumech;
1669 boolean_t found;
1670 int rc = SUCCESS;
1671
1672 if ((puent == NULL) || (marglist == NULL)) {
1673 /* should not happen */
1674 cryptoerror(LOG_STDERR, gettext("internal error."));
1675 cryptodebug("update_policylist()- puent or marglist is NULL.");
1676 return (FAILURE);
1677 }
1678
1679 if ((update_mode != ADD_MODE) && (update_mode != DELETE_MODE)) {
1680 /* should not happen */
1681 cryptoerror(LOG_STDERR, gettext("internal error."));
1682 cryptodebug("update_policylist() - update_mode is incorrect.");
1683 return (FAILURE);
1684 }
1685
1686 /*
1687 * For each mechanism operand, get its mechanism type first.
1688 * If fails to get the mechanism type, the mechanism operand must be
1689 * invalid, gives an warning and ignore it. Otherwise,
1690 * - convert the mechanism type to the internal representation (hex)
1691 * in the pkcs11.conf file
1692 * - If update_mode == DELETE_MODE,
1693 * If the mechanism is in the policy list, delete it.
1694 * If the mechanism is not in the policy list, do nothing.
1695 * - If update_mode == ADD_MODE,
1696 * If the mechanism is not in the policy list, add it.
1697 * If the mechanism is in the policy list already, do nothing.
1698 */
1699 while (marglist) {
1700 if (pkcs11_str2mech(marglist->name, &mech_type) != CKR_OK) {
1701 /*
1702 * This mechanism is not a valid PKCS11 mechanism,
1703 * give warning and ignore it.
1704 */
1705 cryptoerror(LOG_STDERR, gettext(
1706 "(Warning) %s is not a valid PKCS#11 mechanism."),
1707 marglist->name);
1708 rc = FAILURE;
1709 } else {
1710 (void) snprintf(midname, sizeof (midname), "%#010x",
1711 (int)mech_type);
1712 if (update_mode == DELETE_MODE) {
1713 found = B_FALSE;
1714 phead = pcur = puent->policylist;
1715 while (!found && pcur) {
1716 if (strcmp(pcur->name, midname) == 0) {
1717 found = B_TRUE;
1718 } else {
1719 phead = pcur;
1720 pcur = pcur->next;
1721 }
1722 }
1723
1724 if (found) {
1725 if (phead == pcur) {
1726 puent->policylist =
1727 puent->policylist->next;
1728 free(pcur);
1729 } else {
1730 phead->next = pcur->next;
1731 free(pcur);
1732 }
1733 puent->count--;
1734 if (puent->count == 0) {
1735 puent->policylist = NULL;
1736 }
1737 }
1738 } else if (update_mode == ADD_MODE) {
1739 if (!is_in_policylist(midname,
1740 puent->policylist)) {
1741 pumech = create_umech(midname);
1742 if (pumech == NULL) {
1743 rc = FAILURE;
1744 break;
1745 }
1746 phead = puent->policylist;
1747 puent->policylist = pumech;
1748 pumech->next = phead;
1749 puent->count++;
1750 }
1751 }
1752 }
1753 marglist = marglist->next;
1754 }
1755
1756 return (rc);
1757 }
1758
1759 /*
1760 * Open a session to the given slot and check if we can do
1761 * random numbers by asking for one byte.
1762 */
1763 static boolean_t
1764 check_random(CK_SLOT_ID slot_id, CK_FUNCTION_LIST_PTR prov_funcs)
1765 {
1766 CK_RV rv;
1767 CK_SESSION_HANDLE hSession;
1768 CK_BYTE test_byte;
1769 CK_BYTE_PTR test_byte_ptr = &test_byte;
1770
1771 rv = prov_funcs->C_OpenSession(slot_id, CKF_SERIAL_SESSION,
1772 NULL_PTR, NULL, &hSession);
1773 if (rv != CKR_OK)
1774 return (B_FALSE);
1775
1776 /* We care only about the return value */
1777 rv = prov_funcs->C_GenerateRandom(hSession, test_byte_ptr,
1778 sizeof (test_byte));
1779 (void) prov_funcs->C_CloseSession(hSession);
1780
1781 /*
1782 * These checks are purely to determine whether the slot can do
1783 * random numbers. So, we don't check whether the routine
1784 * succeeds. The reason we check for CKR_RANDOM_NO_RNG also is that
1785 * this error effectively means CKR_FUNCTION_NOT_SUPPORTED.
1786 */
1787 if (rv != CKR_FUNCTION_NOT_SUPPORTED && rv != CKR_RANDOM_NO_RNG)
1788 return (B_TRUE);
1789 else
1790 return (B_FALSE);
1791 }
1792
1793 void
1794 display_verbose_mech_header()
1795 {
1796 (void) printf("%28s %s", " ", HDR1);
1797 (void) printf("%28s %s", " ", HDR2);
1798 (void) printf("%28s %s", " ", HDR3);
1799 (void) printf("%28s %s", " ", HDR4);
1800 (void) printf("%28s %s", " ", HDR5);
1801 (void) printf("%28s %s", " ", HDR6);
1802 (void) printf("%-28.28s %s", gettext("mechanism name"), HDR7);
1803 /*
1804 * TRANSLATION_NOTE:
1805 * Strictly for appearance's sake, the first header line should be
1806 * as long as the length of the translated text above. The format
1807 * lengths should all match too.
1808 */
1809 (void) printf("%28s ---- ---- "
1810 "- - - - - - - - - - - - - -\n",
1811 gettext("----------------------------"));
1812 }