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
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <strings.h>
31 #include <unistd.h>
32 #include <locale.h>
33 #include <libgen.h>
34 #include <sys/types.h>
35 #include <zone.h>
36 #include <sys/crypto/ioctladmin.h>
37 #include <cryptoutil.h>
38 #include "cryptoadm.h"
39
40 #define REQ_ARG_CNT 2
41
42 /* subcommand index */
43 enum subcommand_index {
44 CRYPTO_LIST,
45 CRYPTO_DISABLE,
46 CRYPTO_ENABLE,
47 CRYPTO_INSTALL,
48 CRYPTO_UNINSTALL,
49 CRYPTO_UNLOAD,
50 CRYPTO_REFRESH,
51 CRYPTO_START,
52 CRYPTO_STOP,
53 CRYPTO_HELP };
54
55 /*
56 * TRANSLATION_NOTE
57 * Command keywords are not to be translated.
58 */
59 static char *cmd_table[] = {
60 "list",
61 "disable",
62 "enable",
63 "install",
64 "uninstall",
65 "unload",
66 "refresh",
67 "start",
68 "stop",
69 "--help" };
70
71 /* provider type */
72 enum provider_type_index {
73 PROV_UEF_LIB,
74 PROV_KEF_SOFT,
75 PROV_KEF_HARD,
76 METASLOT,
77 PROV_BADNAME };
78
79 typedef struct {
80 char cp_name[MAXPATHLEN];
81 enum provider_type_index cp_type;
82 } cryptoadm_provider_t;
83
84 /*
85 * TRANSLATION_NOTE
86 * Operand keywords are not to be translated.
87 */
88 static const char *KN_PROVIDER = "provider=";
89 static const char *KN_MECH = "mechanism=";
90 static const char *KN_ALL = "all";
91 static const char *KN_TOKEN = "token=";
92 static const char *KN_SLOT = "slot=";
93 static const char *KN_DEFAULT_KS = "default-keystore";
94 static const char *KN_AUTO_KEY_MIGRATE = "auto-key-migrate";
95
96 /* static variables */
97 static boolean_t allflag = B_FALSE;
98 static boolean_t rndflag = B_FALSE;
99 static mechlist_t *mecharglist = NULL;
100
101 /* static functions */
102 static void usage(void);
103 static int get_provider_type(char *);
104 static int process_mech_operands(int, char **, boolean_t);
105 static int do_list(int, char **);
106 static int do_disable(int, char **);
107 static int do_enable(int, char **);
108 static int do_install(int, char **);
109 static int do_uninstall(int, char **);
110 static int do_unload(int, char **);
111 static int do_refresh(int);
112 static int do_start(int);
113 static int do_stop(int);
114 static int list_simple_for_all(boolean_t);
115 static int list_mechlist_for_all(boolean_t);
116 static int list_policy_for_all(void);
117
118 int
119 main(int argc, char *argv[])
120 {
121 char *subcmd;
122 int cmdnum;
123 int cmd_index = 0;
124 int rc = SUCCESS;
125
126 (void) setlocale(LC_ALL, "");
127
128 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
129 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
130 #endif
131 (void) textdomain(TEXT_DOMAIN);
132
133 cryptodebug_init(basename(argv[0]));
134
135 if (argc < REQ_ARG_CNT) {
136 usage();
137 return (ERROR_USAGE);
138 }
139
140 /* get the subcommand index */
141 cmd_index = 0;
142 subcmd = argv[1];
143 cmdnum = sizeof (cmd_table)/sizeof (cmd_table[0]);
144
145 while ((cmd_index < cmdnum) &&
146 (strcmp(subcmd, cmd_table[cmd_index]) != 0)) {
147 cmd_index++;
148 }
149 if (cmd_index >= cmdnum) {
150 usage();
151 return (ERROR_USAGE);
152 }
153
154 /* do the subcommand */
155 switch (cmd_index) {
156 case CRYPTO_LIST:
157 rc = do_list(argc, argv);
158 break;
159 case CRYPTO_DISABLE:
160 rc = do_disable(argc, argv);
161 break;
162 case CRYPTO_ENABLE:
163 rc = do_enable(argc, argv);
164 break;
165 case CRYPTO_INSTALL:
166 rc = do_install(argc, argv);
167 break;
168 case CRYPTO_UNINSTALL:
169 rc = do_uninstall(argc, argv);
170 break;
171 case CRYPTO_UNLOAD:
172 rc = do_unload(argc, argv);
173 break;
174 case CRYPTO_REFRESH:
175 rc = do_refresh(argc);
176 break;
177 case CRYPTO_START:
178 rc = do_start(argc);
179 break;
180 case CRYPTO_STOP:
181 rc = do_stop(argc);
182 break;
183 case CRYPTO_HELP:
184 usage();
185 rc = SUCCESS;
186 break;
187 default: /* should not come here */
188 usage();
189 rc = ERROR_USAGE;
190 break;
191 }
192 return (rc);
193 }
194
195
196 static void
197 usage(void)
198 {
199 /*
200 * TRANSLATION_NOTE
201 * Command usage is not to be translated. Only the word "Usage:"
202 * along with localized expressions indicating what kind of value
203 * is expected for arguments.
204 */
205 (void) fprintf(stderr, gettext("Usage:\n"));
206 (void) fprintf(stderr,
207 " cryptoadm list [-mpv] [provider=<%s> | metaslot]"
208 " [mechanism=<%s>]\n",
209 gettext("provider-name"), gettext("mechanism-list"));
210 (void) fprintf(stderr,
211 " cryptoadm disable provider=<%s>"
212 " mechanism=<%s> | random | all\n",
213 gettext("provider-name"), gettext("mechanism-list"));
214 (void) fprintf(stderr,
215 " cryptoadm disable metaslot"
216 " [auto-key-migrate] [mechanism=<%s>]\n",
217 gettext("mechanism-list"));
218 (void) fprintf(stderr,
219 " cryptoadm enable provider=<%s>"
220 " mechanism=<%s> | random | all\n",
221 gettext("provider-name"), gettext("mechanism-list"));
222 (void) fprintf(stderr,
223 " cryptoadm enable metaslot [mechanism=<%s>]"
224 " [[token=<%s>] [slot=<%s>]"
225 " | [default-keystore]] | [auto-key-migrate]\n",
226 gettext("mechanism-list"), gettext("token-label"),
227 gettext("slot-description"));
228 (void) fprintf(stderr,
229 " cryptoadm install provider=<%s>\n",
230 gettext("provider-name"));
231 (void) fprintf(stderr,
232 " cryptoadm install provider=<%s> [mechanism=<%s>]\n",
233 gettext("provider-name"), gettext("mechanism-list"));
234 (void) fprintf(stderr,
235 " cryptoadm uninstall provider=<%s>\n",
236 gettext("provider-name"));
237 (void) fprintf(stderr,
238 " cryptoadm unload provider=<%s>\n",
239 gettext("provider-name"));
240 (void) fprintf(stderr,
241 " cryptoadm refresh\n"
242 " cryptoadm start\n"
243 " cryptoadm stop\n"
244 " cryptoadm --help\n");
245 }
246
247
248 /*
249 * Get the provider type. This function returns
250 * - PROV_UEF_LIB if provname contains an absolute path name
251 * - PROV_KEF_SOFT if provname is a base name only
252 * - PROV_KEF_HARD if provname contains one slash only and the slash is not
253 * the 1st character.
254 * - PROV_BADNAME otherwise.
255 */
256 static int
257 get_provider_type(char *provname)
258 {
259 char *pslash1;
260 char *pslash2;
261
262 if (provname == NULL) {
263 return (FAILURE);
264 }
265
266 if (provname[0] == '/') {
267 return (PROV_UEF_LIB);
268 } else if ((pslash1 = strchr(provname, SEP_SLASH)) == NULL) {
269 /* no slash */
270 return (PROV_KEF_SOFT);
271 } else {
272 pslash2 = strrchr(provname, SEP_SLASH);
273 if (pslash1 == pslash2) {
274 return (PROV_KEF_HARD);
275 } else {
276 return (PROV_BADNAME);
277 }
278 }
279 }
280
281 /*
282 * Get the provider structure. This function returns NULL if no valid
283 * provider= is found in argv[], otherwise a cryptoadm_provider_t is returned.
284 * If provider= is found but has no argument, then a cryptoadm_provider_t
285 * with cp_type = PROV_BADNAME is returned.
286 */
287 static cryptoadm_provider_t *
288 get_provider(int argc, char **argv)
289 {
290 int c = 0;
291 boolean_t found = B_FALSE;
292 cryptoadm_provider_t *provider = NULL;
293 char *provstr = NULL, *savstr;
294 boolean_t is_metaslot = B_FALSE;
295
296 while (!found && ++c < argc) {
297 if (strncmp(argv[c], METASLOT_KEYWORD,
298 strlen(METASLOT_KEYWORD)) == 0) {
299 is_metaslot = B_TRUE;
300 found = B_TRUE;
301 } else if (strncmp(argv[c], KN_PROVIDER,
302 strlen(KN_PROVIDER)) == 0 &&
303 strlen(argv[c]) > strlen(KN_PROVIDER)) {
304 if ((provstr = strdup(argv[c])) == NULL) {
305 int err = errno;
306 /*
307 * TRANSLATION_NOTE
308 * "get_provider" is a function name and should
309 * not be translated.
310 */
311 cryptoerror(LOG_STDERR, "get_provider: %s.",
312 strerror(err));
313 return (NULL);
314 }
315 found = B_TRUE;
316 }
317 }
318 if (!found)
319 return (NULL);
320
321 provider = malloc(sizeof (cryptoadm_provider_t));
322 if (provider == NULL) {
323 cryptoerror(LOG_STDERR, gettext("out of memory."));
324 if (provstr) {
325 free(provstr);
326 }
327 return (NULL);
328 }
329
330 if (is_metaslot) {
331 (void) strlcpy(provider->cp_name, METASLOT_KEYWORD,
332 strlen(METASLOT_KEYWORD));
333 provider->cp_type = METASLOT;
334 } else {
335
336 savstr = provstr;
337 (void) strtok(provstr, "=");
338 provstr = strtok(NULL, "=");
339 if (provstr == NULL) {
340 cryptoerror(LOG_STDERR, gettext("bad provider name."));
341 provider->cp_type = PROV_BADNAME;
342 free(savstr);
343 return (provider);
344 }
345
346 (void) strlcpy(provider->cp_name, provstr,
347 sizeof (provider->cp_name));
348 provider->cp_type = get_provider_type(provider->cp_name);
349
350 free(savstr);
351 }
352 return (provider);
353 }
354
355 /*
356 * Process the "feature" operands.
357 *
358 * "argc" and "argv" contain values specified on the command line.
359 * All other arguments are used for returning parsing results.
360 * If any of these arguments are NULL, that keyword is not expected,
361 * and FAILURE will be returned.
362 */
363 static int
364 process_metaslot_operands(int argc, char **argv, char **meta_ks_token,
365 char **meta_ks_slot, boolean_t *use_default,
366 boolean_t *auto_key_migrate_flag)
367 {
368 int c = 2;
369 int rc = SUCCESS;
370
371 while (++c < argc) {
372 if ((strncmp(argv[c], KN_MECH, strlen(KN_MECH)) == 0) &&
373 strlen(argv[c]) > strlen(KN_MECH)) {
374
375 /* process mechanism operands */
376 if ((rc = process_mech_operands(argc, argv, B_TRUE))
377 != SUCCESS) {
378 goto finish;
379 }
380
381 } else if ((strncmp(argv[c], KN_TOKEN,
382 strlen(KN_TOKEN)) == 0) &&
383 strlen(argv[c]) > strlen(KN_TOKEN)) {
384 if ((meta_ks_token) && (strtok(argv[c], "=") != NULL)) {
385 char *tmp;
386 if ((tmp = strtok(NULL, "=")) != NULL) {
387 *meta_ks_token = strdup(tmp);
388 } else {
389 return (FAILURE);
390 }
391 } else {
392 return (FAILURE);
393 }
394
395 } else if ((strncmp(argv[c], KN_SLOT,
396 strlen(KN_SLOT)) == 0) &&
397 strlen(argv[c]) > strlen(KN_SLOT)) {
398
399 if ((meta_ks_slot) && (strtok(argv[c], "=") != NULL)) {
400 char *tmp;
401 if ((tmp = strtok(NULL, "=")) != NULL) {
402 *meta_ks_slot = strdup(tmp);
403 } else {
404 return (FAILURE);
405 }
406 } else {
407 return (FAILURE);
408 }
409
410 } else if (strncmp(argv[c], KN_DEFAULT_KS,
411 strlen(KN_DEFAULT_KS)) == 0) {
412
413 if (use_default) {
414 *use_default = B_TRUE;
415 } else {
416 return (FAILURE);
417 }
418 } else if (strncmp(argv[c], KN_AUTO_KEY_MIGRATE,
419 strlen(KN_AUTO_KEY_MIGRATE)) == 0) {
420
421 if (auto_key_migrate_flag) {
422 *auto_key_migrate_flag = B_TRUE;
423 } else {
424 return (FAILURE);
425 }
426 } else {
427 return (FAILURE);
428 }
429 }
430 finish:
431 return (rc);
432 }
433
434 /*
435 * Process the "feature" operands.
436 */
437 static int
438 process_feature_operands(int argc, char **argv)
439 {
440 int c = 2;
441
442 while (++c < argc) {
443 if (strcmp(argv[c], KN_ALL) == 0) {
444 allflag = B_TRUE;
445 rndflag = B_TRUE; /* all includes random also. */
446 } else if (strcmp(argv[c], RANDOM) == 0) {
447 rndflag = B_TRUE;
448 }
449 }
450 return (SUCCESS);
451 }
452
453 /*
454 * Process the mechanism operands for the disable, enable and install
455 * subcommands. This function sets the static variable allflag to be B_TRUE
456 * if the keyword "all" is specified, otherwise builds a link list of the
457 * mechanism operands and save it in the static variable mecharglist.
458 *
459 * This function returns
460 * ERROR_USAGE: mechanism operand is missing.
461 * FAILURE: out of memory.
462 * SUCCESS: otherwise.
463 */
464 static int
465 process_mech_operands(int argc, char **argv, boolean_t quiet)
466 {
467 mechlist_t *pmech;
468 mechlist_t *pcur = NULL;
469 mechlist_t *phead = NULL;
470 boolean_t found = B_FALSE;
471 char *mechliststr = NULL;
472 char *curmech = NULL;
473 int c = -1;
474 int rc = SUCCESS;
475
476 while (!found && ++c < argc) {
477 if ((strncmp(argv[c], KN_MECH, strlen(KN_MECH)) == 0) &&
478 strlen(argv[c]) > strlen(KN_MECH)) {
479 found = B_TRUE;
480 }
481 }
482 if (!found) {
483 if (!quiet)
484 /*
485 * TRANSLATION_NOTE
486 * "mechanism" could be either a literal keyword
487 * and hence not to be translated, or a descriptive
488 * word and translatable. A choice was made to
489 * view it as a literal keyword.
490 */
491 cryptoerror(LOG_STDERR,
492 gettext("the %s operand is missing.\n"),
493 "mechanism");
494 return (ERROR_USAGE);
495 }
496 (void) strtok(argv[c], "=");
497 mechliststr = strtok(NULL, "=");
498
499 if (strcmp(mechliststr, "all") == 0) {
500 allflag = B_TRUE;
501 mecharglist = NULL;
502 return (SUCCESS);
503 }
504
505 curmech = strtok(mechliststr, ",");
506 do {
507 if ((pmech = create_mech(curmech)) == NULL) {
508 rc = FAILURE;
509 break;
510 } else {
511 if (phead == NULL) {
512 phead = pcur = pmech;
513 } else {
514 pcur->next = pmech;
515 pcur = pmech;
516 }
517 }
518 } while ((curmech = strtok(NULL, ",")) != NULL);
519
520 if (rc == FAILURE) {
521 cryptoerror(LOG_STDERR, gettext("out of memory."));
522 free_mechlist(phead);
523 } else {
524 mecharglist = phead;
525 rc = SUCCESS;
526 }
527 return (rc);
528 }
529
530
531
532 /*
533 * The top level function for the list subcommand and options.
534 */
535 static int
536 do_list(int argc, char **argv)
537 {
538 boolean_t mflag = B_FALSE;
539 boolean_t pflag = B_FALSE;
540 boolean_t vflag = B_FALSE;
541 char ch;
542 cryptoadm_provider_t *prov = NULL;
543 int rc = SUCCESS;
544
545 argc -= 1;
546 argv += 1;
547
548 if (argc == 1) {
549 rc = list_simple_for_all(B_FALSE);
550 goto out;
551 }
552
553 /*
554 * [-v] [-m] [-p] [provider=<>] [mechanism=<>]
555 */
556 if (argc > 5) {
557 usage();
558 return (rc);
559 }
560
561 while ((ch = getopt(argc, argv, "mpv")) != EOF) {
562 switch (ch) {
563 case 'm':
564 mflag = B_TRUE;
565 if (pflag) {
566 rc = ERROR_USAGE;
567 }
568 break;
569 case 'p':
570 pflag = B_TRUE;
571 if (mflag || vflag) {
572 rc = ERROR_USAGE;
573 }
574 break;
575 case 'v':
576 vflag = B_TRUE;
577 if (pflag)
578 rc = ERROR_USAGE;
579 break;
580 default:
581 rc = ERROR_USAGE;
582 break;
583 }
584 }
585
586 if (rc == ERROR_USAGE) {
587 usage();
588 return (rc);
589 }
590
591 if ((rc = process_feature_operands(argc, argv)) != SUCCESS) {
592 goto out;
593 }
594
595 prov = get_provider(argc, argv);
596
597 if (mflag || vflag) {
598 if (argc > 0) {
599 rc = process_mech_operands(argc, argv, B_TRUE);
600 if (rc == FAILURE)
601 goto out;
602 /* "-m" is implied when a mechanism list is given */
603 if (mecharglist != NULL || allflag)
604 mflag = B_TRUE;
605 }
606 }
607
608 if (prov == NULL) {
609 if (mflag) {
610 rc = list_mechlist_for_all(vflag);
611 } else if (pflag) {
612 rc = list_policy_for_all();
613 } else if (vflag) {
614 rc = list_simple_for_all(vflag);
615 }
616 } else if (prov->cp_type == METASLOT) {
617 if ((!mflag) && (!vflag) && (!pflag)) {
618 /* no flag is specified, just list metaslot status */
619 rc = list_metaslot_info(mflag, vflag, mecharglist);
620 } else if (mflag || vflag) {
621 rc = list_metaslot_info(mflag, vflag, mecharglist);
622 } else if (pflag) {
623 rc = list_metaslot_policy();
624 } else {
625 /* error message */
626 usage();
627 rc = ERROR_USAGE;
628 }
629 } else if (prov->cp_type == PROV_BADNAME) {
630 usage();
631 rc = ERROR_USAGE;
632 goto out;
633 } else { /* do the listing for a provider only */
634 if (mflag || vflag) {
635 if (vflag)
636 (void) printf(gettext("Provider: %s\n"),
637 prov->cp_name);
638 switch (prov->cp_type) {
639 case PROV_UEF_LIB:
640 rc = list_mechlist_for_lib(prov->cp_name,
641 mecharglist, NULL, B_FALSE,
642 vflag, mflag);
643 break;
644 case PROV_KEF_SOFT:
645 rc = list_mechlist_for_soft(prov->cp_name);
646 break;
647 case PROV_KEF_HARD:
648 rc = list_mechlist_for_hard(prov->cp_name);
649 break;
650 default: /* should not come here */
651 rc = FAILURE;
652 break;
653 }
654 } else if (pflag) {
655 switch (prov->cp_type) {
656 case PROV_UEF_LIB:
657 rc = list_policy_for_lib(prov->cp_name);
658 break;
659 case PROV_KEF_SOFT:
660 if (getzoneid() == GLOBAL_ZONEID) {
661 rc = list_policy_for_soft(
662 prov->cp_name);
663 } else {
664 /*
665 * TRANSLATION_NOTE
666 * "global" is keyword and not to
667 * be translated.
668 */
669 cryptoerror(LOG_STDERR, gettext(
670 "policy information for kernel "
671 "providers is available "
672 "in the %s zone only"), "global");
673 rc = FAILURE;
674 }
675 break;
676 case PROV_KEF_HARD:
677 if (getzoneid() == GLOBAL_ZONEID) {
678 rc = list_policy_for_hard(
679 prov->cp_name);
680 } else {
681 /*
682 * TRANSLATION_NOTE
683 * "global" is keyword and not to
684 * be translated.
685 */
686 cryptoerror(LOG_STDERR, gettext(
687 "policy information for kernel "
688 "providers is available "
689 "in the %s zone only"), "global");
690 rc = FAILURE;
691 }
692
693 break;
694 default: /* should not come here */
695 rc = FAILURE;
696 break;
697 }
698 } else {
699 /* error message */
700 usage();
701 rc = ERROR_USAGE;
702 }
703 }
704
705 out:
706 if (prov != NULL)
707 free(prov);
708
709 if (mecharglist != NULL)
710 free_mechlist(mecharglist);
711 return (rc);
712 }
713
714
715 /*
716 * The top level function for the disable subcommand.
717 */
718 static int
719 do_disable(int argc, char **argv)
720 {
721 cryptoadm_provider_t *prov = NULL;
722 int rc = SUCCESS;
723 boolean_t auto_key_migrate_flag = B_FALSE;
724
725 if ((argc < 3) || (argc > 5)) {
726 usage();
727 return (ERROR_USAGE);
728 }
729
730 prov = get_provider(argc, argv);
731 if (prov == NULL) {
732 usage();
733 return (ERROR_USAGE);
734 }
735 if (prov->cp_type == PROV_BADNAME) {
736 return (FAILURE);
737 }
738
739 if ((rc = process_feature_operands(argc, argv)) != SUCCESS) {
740 goto out;
741 }
742
743 /*
744 * If allflag or rndflag has already been set there is no reason to
745 * process mech=
746 */
747 if (prov->cp_type == METASLOT) {
748 if ((argc > 3) &&
749 (rc = process_metaslot_operands(argc, argv,
750 NULL, NULL, NULL, &auto_key_migrate_flag)) != SUCCESS) {
751 usage();
752 return (rc);
753 }
754 } else if (!allflag && !rndflag &&
755 (rc = process_mech_operands(argc, argv, B_FALSE)) != SUCCESS) {
756 return (rc);
757 }
758
759 switch (prov->cp_type) {
760 case METASLOT:
761 rc = disable_metaslot(mecharglist, allflag,
762 auto_key_migrate_flag);
763 break;
764 case PROV_UEF_LIB:
765 rc = disable_uef_lib(prov->cp_name, rndflag, allflag,
766 mecharglist);
767 break;
768 case PROV_KEF_SOFT:
769 if (rndflag && !allflag) {
770 if ((mecharglist = create_mech(RANDOM)) == NULL) {
771 rc = FAILURE;
772 break;
773 }
774 }
775 if (getzoneid() == GLOBAL_ZONEID) {
776 rc = disable_kef_software(prov->cp_name, rndflag,
777 allflag, mecharglist);
778 } else {
779 /*
780 * TRANSLATION_NOTE
781 * "disable" could be either a literal keyword
782 * and hence not to be translated, or a verb and
783 * translatable. A choice was made to view it as
784 * a literal keyword. "global" is keyword and not
785 * to be translated.
786 */
787 cryptoerror(LOG_STDERR, gettext("%1$s for kernel "
788 "providers is supported in the %2$s zone only"),
789 "disable", "global");
790 rc = FAILURE;
791 }
792 break;
793 case PROV_KEF_HARD:
794 if (rndflag && !allflag) {
795 if ((mecharglist = create_mech(RANDOM)) == NULL) {
796 rc = FAILURE;
797 break;
798 }
799 }
800 if (getzoneid() == GLOBAL_ZONEID) {
801 rc = disable_kef_hardware(prov->cp_name, rndflag,
802 allflag, mecharglist);
803 } else {
804 /*
805 * TRANSLATION_NOTE
806 * "disable" could be either a literal keyword
807 * and hence not to be translated, or a verb and
808 * translatable. A choice was made to view it as
809 * a literal keyword. "global" is keyword and not
810 * to be translated.
811 */
812 cryptoerror(LOG_STDERR, gettext("%1$s for kernel "
813 "providers is supported in the %2$s zone only"),
814 "disable", "global");
815 rc = FAILURE;
816 }
817 break;
818 default: /* should not come here */
819 rc = FAILURE;
820 break;
821 }
822
823 out:
824 free(prov);
825 if (mecharglist != NULL) {
826 free_mechlist(mecharglist);
827 }
828 return (rc);
829 }
830
831
832 /*
833 * The top level function fo the enable subcommand.
834 */
835 static int
836 do_enable(int argc, char **argv)
837 {
838 cryptoadm_provider_t *prov = NULL;
839 int rc = SUCCESS;
840 char *alt_token = NULL, *alt_slot = NULL;
841 boolean_t use_default = B_FALSE, auto_key_migrate_flag = B_FALSE;
842
843 if ((argc < 3) || (argc > 6)) {
844 usage();
845 return (ERROR_USAGE);
846 }
847
848 prov = get_provider(argc, argv);
849 if (prov == NULL) {
850 usage();
851 return (ERROR_USAGE);
852 }
853 if ((prov->cp_type != METASLOT) && (argc != 4)) {
854 usage();
855 return (ERROR_USAGE);
856 }
857 if (prov->cp_type == PROV_BADNAME) {
858 rc = FAILURE;
859 goto out;
860 }
861
862
863 if (prov->cp_type == METASLOT) {
864 if ((rc = process_metaslot_operands(argc, argv, &alt_token,
865 &alt_slot, &use_default, &auto_key_migrate_flag))
866 != SUCCESS) {
867 usage();
868 goto out;
869 }
870 if ((alt_slot || alt_token) && use_default) {
871 usage();
872 rc = FAILURE;
873 goto out;
874 }
875 } else {
876 if ((rc = process_feature_operands(argc, argv)) != SUCCESS) {
877 goto out;
878 }
879
880 /*
881 * If allflag or rndflag has already been set there is
882 * no reason to process mech=
883 */
884 if (!allflag && !rndflag &&
885 (rc = process_mech_operands(argc, argv, B_FALSE))
886 != SUCCESS) {
887 goto out;
888 }
889 }
890
891 switch (prov->cp_type) {
892 case METASLOT:
893 rc = enable_metaslot(alt_token, alt_slot, use_default,
894 mecharglist, allflag, auto_key_migrate_flag);
895 break;
896 case PROV_UEF_LIB:
897 rc = enable_uef_lib(prov->cp_name, rndflag, allflag,
898 mecharglist);
899 break;
900 case PROV_KEF_SOFT:
901 case PROV_KEF_HARD:
902 if (rndflag && !allflag) {
903 if ((mecharglist = create_mech(RANDOM)) == NULL) {
904 rc = FAILURE;
905 break;
906 }
907 }
908 if (getzoneid() == GLOBAL_ZONEID) {
909 rc = enable_kef(prov->cp_name, rndflag, allflag,
910 mecharglist);
911 } else {
912 /*
913 * TRANSLATION_NOTE
914 * "enable" could be either a literal keyword
915 * and hence not to be translated, or a verb and
916 * translatable. A choice was made to view it as
917 * a literal keyword. "global" is keyword and not
918 * to be translated.
919 */
920 cryptoerror(LOG_STDERR, gettext("%1$s for kernel "
921 "providers is supported in the %2$s zone only"),
922 "enable", "global");
923 rc = FAILURE;
924 }
925 break;
926 default: /* should not come here */
927 rc = FAILURE;
928 break;
929 }
930 out:
931 free(prov);
932 if (mecharglist != NULL) {
933 free_mechlist(mecharglist);
934 }
935 if (alt_token != NULL) {
936 free(alt_token);
937 }
938 if (alt_slot != NULL) {
939 free(alt_slot);
940 }
941 return (rc);
942 }
943
944
945
946 /*
947 * The top level function fo the install subcommand.
948 */
949 static int
950 do_install(int argc, char **argv)
951 {
952 cryptoadm_provider_t *prov = NULL;
953 int rc;
954
955 if (argc < 3) {
956 usage();
957 return (ERROR_USAGE);
958 }
959
960 prov = get_provider(argc, argv);
961 if (prov == NULL ||
962 prov->cp_type == PROV_BADNAME || prov->cp_type == PROV_KEF_HARD) {
963 /*
964 * TRANSLATION_NOTE
965 * "install" could be either a literal keyword and hence
966 * not to be translated, or a verb and translatable. A
967 * choice was made to view it as a literal keyword.
968 */
969 cryptoerror(LOG_STDERR,
970 gettext("bad provider name for %s."), "install");
971 rc = FAILURE;
972 goto out;
973 }
974
975 if (prov->cp_type == PROV_UEF_LIB) {
976 rc = install_uef_lib(prov->cp_name);
977 goto out;
978 }
979
980 /* It is the PROV_KEF_SOFT type now */
981
982 /* check if there are mechanism operands */
983 if (argc < 4) {
984 /*
985 * TRANSLATION_NOTE
986 * "mechanism" could be either a literal keyword and hence
987 * not to be translated, or a descriptive word and
988 * translatable. A choice was made to view it as a literal
989 * keyword.
990 */
991 cryptoerror(LOG_STDERR,
992 gettext("need %s operands for installing a"
993 " kernel software provider."), "mechanism");
994 rc = ERROR_USAGE;
995 goto out;
996 }
997
998 if ((rc = process_mech_operands(argc, argv, B_FALSE)) != SUCCESS) {
999 goto out;
1000 }
1001
1002 if (allflag == B_TRUE) {
1003 /*
1004 * TRANSLATION_NOTE
1005 * "all", "mechanism", and "install" are all keywords and
1006 * not to be translated.
1007 */
1008 cryptoerror(LOG_STDERR,
1009 gettext("can not use the %1$s keyword for %2$s "
1010 "in the %3$s subcommand."), "all", "mechanism", "install");
1011 rc = ERROR_USAGE;
1012 goto out;
1013 }
1014
1015 if (getzoneid() == GLOBAL_ZONEID) {
1016 rc = install_kef(prov->cp_name, mecharglist);
1017 } else {
1018 /*
1019 * TRANSLATION_NOTE
1020 * "install" could be either a literal keyword and hence
1021 * not to be translated, or a verb and translatable. A
1022 * choice was made to view it as a literal keyword.
1023 * "global" is keyword and not to be translated.
1024 */
1025 cryptoerror(LOG_STDERR, gettext("%1$s for kernel providers "
1026 "is supported in the %2$s zone only"), "install", "global");
1027 rc = FAILURE;
1028 }
1029 out:
1030 free(prov);
1031 return (rc);
1032 }
1033
1034
1035
1036 /*
1037 * The top level function for the uninstall subcommand.
1038 */
1039 static int
1040 do_uninstall(int argc, char **argv)
1041 {
1042 cryptoadm_provider_t *prov = NULL;
1043 int rc = SUCCESS;
1044
1045 if (argc != 3) {
1046 usage();
1047 return (ERROR_USAGE);
1048 }
1049
1050 prov = get_provider(argc, argv);
1051 if (prov == NULL ||
1052 prov->cp_type == PROV_BADNAME || prov->cp_type == PROV_KEF_HARD) {
1053 /*
1054 * TRANSLATION_NOTE
1055 * "uninstall" could be either a literal keyword and hence
1056 * not to be translated, or a verb and translatable. A
1057 * choice was made to view it as a literal keyword.
1058 */
1059 cryptoerror(LOG_STDERR,
1060 gettext("bad provider name for %s."), "uninstall");
1061 free(prov);
1062 return (FAILURE);
1063 }
1064
1065 if (prov->cp_type == PROV_UEF_LIB) {
1066 rc = uninstall_uef_lib(prov->cp_name);
1067 } else if (prov->cp_type == PROV_KEF_SOFT) {
1068 if (getzoneid() == GLOBAL_ZONEID) {
1069 rc = uninstall_kef(prov->cp_name);
1070 } else {
1071 /*
1072 * TRANSLATION_NOTE
1073 * "uninstall" could be either a literal keyword and
1074 * hence not to be translated, or a verb and
1075 * translatable. A choice was made to view it as a
1076 * literal keyword. "global" is keyword and not to
1077 * be translated.
1078 */
1079 cryptoerror(LOG_STDERR, gettext("%1$s for kernel "
1080 "providers is supported in the %2$s zone only"),
1081 "uninstall", "global");
1082 rc = FAILURE;
1083 }
1084 }
1085
1086 free(prov);
1087 return (rc);
1088 }
1089
1090
1091 /*
1092 * The top level function for the unload subcommand.
1093 */
1094 static int
1095 do_unload(int argc, char **argv)
1096 {
1097 cryptoadm_provider_t *prov = NULL;
1098 entry_t *pent;
1099 boolean_t is_active;
1100 int rc = SUCCESS;
1101
1102 if (argc != 3) {
1103 usage();
1104 return (ERROR_USAGE);
1105 }
1106
1107 /* check if it is a kernel software provider */
1108 prov = get_provider(argc, argv);
1109 if (prov == NULL) {
1110 cryptoerror(LOG_STDERR,
1111 gettext("unable to determine provider name."));
1112 goto out;
1113 }
1114 if (prov->cp_type != PROV_KEF_SOFT) {
1115 cryptoerror(LOG_STDERR,
1116 gettext("%s is not a valid kernel software provider."),
1117 prov->cp_name);
1118 rc = FAILURE;
1119 goto out;
1120 }
1121
1122 if (getzoneid() != GLOBAL_ZONEID) {
1123 /*
1124 * TRANSLATION_NOTE
1125 * "unload" could be either a literal keyword and hence
1126 * not to be translated, or a verb and translatable.
1127 * A choice was made to view it as a literal keyword.
1128 * "global" is keyword and not to be translated.
1129 */
1130 cryptoerror(LOG_STDERR, gettext("%1$s for kernel providers "
1131 "is supported in the %2$s zone only"), "unload", "global");
1132 rc = FAILURE;
1133 goto out;
1134 }
1135
1136 /* Check if it is in the kcf.conf file first */
1137 if ((pent = getent_kef(prov->cp_name)) == NULL) {
1138 cryptoerror(LOG_STDERR,
1139 gettext("provider %s does not exist."), prov->cp_name);
1140 rc = FAILURE;
1141 goto out;
1142 }
1143 free_entry(pent);
1144
1145 /* If it is unloaded already, return */
1146 if (check_active_for_soft(prov->cp_name, &is_active) == FAILURE) {
1147 cryptodebug("internal error");
1148 cryptoerror(LOG_STDERR,
1149 gettext("failed to unload %s."), prov->cp_name);
1150 rc = FAILURE;
1151 goto out;
1152 }
1153
1154 if (is_active == B_FALSE) { /* unloaded already */
1155 rc = SUCCESS;
1156 goto out;
1157 } else if (unload_kef_soft(prov->cp_name, B_TRUE) == FAILURE) {
1158 cryptoerror(LOG_STDERR,
1159 gettext("failed to unload %s."), prov->cp_name);
1160 rc = FAILURE;
1161 } else {
1162 rc = SUCCESS;
1163 }
1164 out:
1165 free(prov);
1166 return (rc);
1167 }
1168
1169
1170
1171 /*
1172 * The top level function for the refresh subcommand.
1173 */
1174 static int
1175 do_refresh(int argc)
1176 {
1177 if (argc != 2) {
1178 usage();
1179 return (ERROR_USAGE);
1180 }
1181
1182 /*
1183 * Note: in non-global zone, this must silently return SUCCESS
1184 * due to integration with SMF, for "svcadm refresh cryptosvc"
1185 */
1186 if (getzoneid() != GLOBAL_ZONEID)
1187 return (SUCCESS);
1188
1189 return (refresh());
1190 }
1191
1192
1193 /*
1194 * The top level function for the start subcommand.
1195 */
1196 static int
1197 do_start(int argc)
1198 {
1199 int ret;
1200
1201 if (argc != 2) {
1202 usage();
1203 return (ERROR_USAGE);
1204 }
1205
1206 ret = do_refresh(argc);
1207 if (ret != SUCCESS)
1208 return (ret);
1209
1210 return (start_daemon());
1211 }
1212
1213 /*
1214 * The top level function for the stop subcommand.
1215 */
1216 static int
1217 do_stop(int argc)
1218 {
1219 if (argc != 2) {
1220 usage();
1221 return (ERROR_USAGE);
1222 }
1223
1224 return (stop_daemon());
1225 }
1226
1227
1228
1229 /*
1230 * List all the providers.
1231 */
1232 static int
1233 list_simple_for_all(boolean_t verbose)
1234 {
1235 uentrylist_t *pliblist;
1236 uentrylist_t *plibptr;
1237 entrylist_t *pdevlist_conf;
1238 entrylist_t *psoftlist_conf;
1239 entrylist_t *pdevlist_zone;
1240 entrylist_t *psoftlist_zone;
1241 entrylist_t *ptr;
1242 crypto_get_dev_list_t *pdevlist_kernel = NULL;
1243 boolean_t is_active;
1244 int ru = SUCCESS;
1245 int rs = SUCCESS;
1246 int rd = SUCCESS;
1247 int i;
1248
1249 /* get user-level providers */
1250 (void) printf(gettext("\nUser-level providers:\n"));
1251 if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
1252 cryptoerror(LOG_STDERR, gettext(
1253 "failed to retrieve the list of user-level providers."));
1254 ru = FAILURE;
1255 }
1256 plibptr = pliblist;
1257 while (plibptr != NULL) {
1258 if (strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) {
1259 (void) printf(gettext("Provider: %s\n"),
1260 plibptr->puent->name);
1261 if (verbose) {
1262 (void) list_mechlist_for_lib(
1263 plibptr->puent->name, mecharglist, NULL,
1264 B_FALSE, verbose, B_FALSE);
1265 (void) printf("\n");
1266 }
1267 }
1268 plibptr = plibptr->next;
1269 }
1270 free_uentrylist(pliblist);
1271
1272 /* get kernel software providers */
1273 (void) printf(gettext("\nKernel software providers:\n"));
1274
1275 if (getzoneid() == GLOBAL_ZONEID) {
1276 /* use kcf.conf for kernel software providers in global zone */
1277 pdevlist_conf = NULL;
1278 psoftlist_conf = NULL;
1279
1280 if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) !=
1281 SUCCESS) {
1282 cryptoerror(LOG_STDERR,
1283 gettext("failed to retrieve the "
1284 "list of kernel software providers.\n"));
1285 rs = FAILURE;
1286 }
1287
1288 ptr = psoftlist_conf;
1289 while (ptr != NULL) {
1290 if (check_active_for_soft(ptr->pent->name, &is_active)
1291 == FAILURE) {
1292 rs = FAILURE;
1293 cryptoerror(LOG_STDERR, gettext("failed to "
1294 "get the state of a kernel software "
1295 "providers.\n"));
1296 break;
1297 }
1298
1299 (void) printf("\t%s", ptr->pent->name);
1300 if (is_active == B_FALSE) {
1301 (void) printf(gettext(" (inactive)\n"));
1302 } else {
1303 (void) printf("\n");
1304 }
1305 ptr = ptr->next;
1306 }
1307
1308 free_entrylist(pdevlist_conf);
1309 free_entrylist(psoftlist_conf);
1310 } else {
1311 /* kcf.conf not there in non-global zone, use /dev/cryptoadm */
1312 pdevlist_zone = NULL;
1313 psoftlist_zone = NULL;
1314
1315 if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
1316 SUCCESS) {
1317 cryptoerror(LOG_STDERR,
1318 gettext("failed to retrieve the "
1319 "list of kernel software providers.\n"));
1320 rs = FAILURE;
1321 }
1322
1323 ptr = psoftlist_zone;
1324 while (ptr != NULL) {
1325 (void) printf("\t%s\n", ptr->pent->name);
1326 ptr = ptr->next;
1327 }
1328
1329 free_entrylist(pdevlist_zone);
1330 free_entrylist(psoftlist_zone);
1331 }
1332
1333 /* get kernel hardware providers */
1334 (void) printf(gettext("\nKernel hardware providers:\n"));
1335 if (get_dev_list(&pdevlist_kernel) == FAILURE) {
1336 cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1337 "the list of kernel hardware providers.\n"));
1338 rd = FAILURE;
1339 } else {
1340 for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
1341 (void) printf("\t%s/%d\n",
1342 pdevlist_kernel->dl_devs[i].le_dev_name,
1343 pdevlist_kernel->dl_devs[i].le_dev_instance);
1344 }
1345 }
1346 free(pdevlist_kernel);
1347
1348 if (ru == FAILURE || rs == FAILURE || rd == FAILURE) {
1349 return (FAILURE);
1350 } else {
1351 return (SUCCESS);
1352 }
1353 }
1354
1355
1356
1357 /*
1358 * List all the providers. And for each provider, list the mechanism list.
1359 */
1360 static int
1361 list_mechlist_for_all(boolean_t verbose)
1362 {
1363 crypto_get_dev_list_t *pdevlist_kernel;
1364 uentrylist_t *pliblist;
1365 uentrylist_t *plibptr;
1366 entrylist_t *pdevlist_conf;
1367 entrylist_t *psoftlist_conf;
1368 entrylist_t *pdevlist_zone;
1369 entrylist_t *psoftlist_zone;
1370 entrylist_t *ptr;
1371 mechlist_t *pmechlist;
1372 boolean_t is_active;
1373 char provname[MAXNAMELEN];
1374 char devname[MAXNAMELEN];
1375 int inst_num;
1376 int count;
1377 int i;
1378 int rv;
1379 int rc = SUCCESS;
1380
1381 /* get user-level providers */
1382 (void) printf(gettext("\nUser-level providers:\n"));
1383 /*
1384 * TRANSLATION_NOTE
1385 * Strictly for appearance's sake, this line should be as long as
1386 * the length of the translated text above.
1387 */
1388 (void) printf(gettext("=====================\n"));
1389 if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
1390 cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1391 "the list of user-level providers.\n"));
1392 rc = FAILURE;
1393 }
1394
1395 plibptr = pliblist;
1396 while (plibptr != NULL) {
1397 /* skip metaslot entry */
1398 if (strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) {
1399 (void) printf(gettext("\nProvider: %s\n"),
1400 plibptr->puent->name);
1401 rv = list_mechlist_for_lib(plibptr->puent->name,
1402 mecharglist, NULL, B_FALSE, verbose, B_TRUE);
1403 if (rv == FAILURE) {
1404 rc = FAILURE;
1405 }
1406 }
1407 plibptr = plibptr->next;
1408 }
1409 free_uentrylist(pliblist);
1410
1411 /* get kernel software providers */
1412 (void) printf(gettext("\nKernel software providers:\n"));
1413 /*
1414 * TRANSLATION_NOTE
1415 * Strictly for appearance's sake, this line should be as long as
1416 * the length of the translated text above.
1417 */
1418 (void) printf(gettext("==========================\n"));
1419 if (getzoneid() == GLOBAL_ZONEID) {
1420 /* use kcf.conf for kernel software providers in global zone */
1421 pdevlist_conf = NULL;
1422 psoftlist_conf = NULL;
1423
1424 if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) !=
1425 SUCCESS) {
1426 cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1427 "the list of kernel software providers.\n"));
1428 rc = FAILURE;
1429 }
1430
1431 ptr = psoftlist_conf;
1432 while (ptr != NULL) {
1433 if (check_active_for_soft(ptr->pent->name, &is_active)
1434 == SUCCESS) {
1435 if (is_active) {
1436 rv = list_mechlist_for_soft(
1437 ptr->pent->name);
1438 if (rv == FAILURE) {
1439 rc = FAILURE;
1440 }
1441 } else {
1442 (void) printf(gettext(
1443 "%s: (inactive)\n"),
1444 ptr->pent->name);
1445 }
1446 } else {
1447 /* should not happen */
1448 (void) printf(gettext(
1449 "%s: failed to get the mechanism list.\n"),
1450 ptr->pent->name);
1451 rc = FAILURE;
1452 }
1453 ptr = ptr->next;
1454 }
1455
1456 free_entrylist(pdevlist_conf);
1457 free_entrylist(psoftlist_conf);
1458 } else {
1459 /* kcf.conf not there in non-global zone, use /dev/cryptoadm */
1460 pdevlist_zone = NULL;
1461 psoftlist_zone = NULL;
1462
1463 if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
1464 SUCCESS) {
1465 cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1466 "the list of kernel software providers.\n"));
1467 rc = FAILURE;
1468 }
1469
1470 ptr = psoftlist_zone;
1471 while (ptr != NULL) {
1472 rv = list_mechlist_for_soft(ptr->pent->name);
1473 if (rv == FAILURE) {
1474 (void) printf(gettext(
1475 "%s: failed to get the mechanism list.\n"),
1476 ptr->pent->name);
1477 rc = FAILURE;
1478 }
1479 ptr = ptr->next;
1480 }
1481
1482 free_entrylist(pdevlist_zone);
1483 free_entrylist(psoftlist_zone);
1484 }
1485
1486 /* Get kernel hardware providers and their mechanism lists */
1487 (void) printf(gettext("\nKernel hardware providers:\n"));
1488 /*
1489 * TRANSLATION_NOTE
1490 * Strictly for appearance's sake, this line should be as long as
1491 * the length of the translated text above.
1492 */
1493 (void) printf(gettext("==========================\n"));
1494 if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
1495 cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1496 "the list of hardware providers.\n"));
1497 return (FAILURE);
1498 }
1499
1500 for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
1501 (void) strlcpy(devname,
1502 pdevlist_kernel->dl_devs[i].le_dev_name, MAXNAMELEN);
1503 inst_num = pdevlist_kernel->dl_devs[i].le_dev_instance;
1504 count = pdevlist_kernel->dl_devs[i].le_mechanism_count;
1505 (void) snprintf(provname, sizeof (provname), "%s/%d", devname,
1506 inst_num);
1507 if (get_dev_info(devname, inst_num, count, &pmechlist) ==
1508 SUCCESS) {
1509 (void) filter_mechlist(&pmechlist, RANDOM);
1510 print_mechlist(provname, pmechlist);
1511 free_mechlist(pmechlist);
1512 } else {
1513 (void) printf(gettext("%s: failed to get the mechanism"
1514 " list.\n"), provname);
1515 rc = FAILURE;
1516 }
1517 }
1518 free(pdevlist_kernel);
1519 return (rc);
1520 }
1521
1522
1523 /*
1524 * List all the providers. And for each provider, list the policy information.
1525 */
1526 static int
1527 list_policy_for_all(void)
1528 {
1529 crypto_get_dev_list_t *pdevlist_kernel;
1530 uentrylist_t *pliblist;
1531 uentrylist_t *plibptr;
1532 entrylist_t *pdevlist_conf;
1533 entrylist_t *psoftlist_conf;
1534 entrylist_t *ptr;
1535 entrylist_t *phead;
1536 boolean_t found;
1537 char provname[MAXNAMELEN];
1538 int i;
1539 int rc = SUCCESS;
1540
1541 /* Get user-level providers */
1542 (void) printf(gettext("\nUser-level providers:\n"));
1543 /*
1544 * TRANSLATION_NOTE
1545 * Strictly for appearance's sake, this line should be as long as
1546 * the length of the translated text above.
1547 */
1548 (void) printf(gettext("=====================\n"));
1549 if (get_pkcs11conf_info(&pliblist) == FAILURE) {
1550 cryptoerror(LOG_STDERR, gettext("failed to retrieve "
1551 "the list of user-level providers.\n"));
1552 } else {
1553 plibptr = pliblist;
1554 while (plibptr != NULL) {
1555 /* skip metaslot entry */
1556 if (strcmp(plibptr->puent->name,
1557 METASLOT_KEYWORD) != 0) {
1558 if (print_uef_policy(plibptr->puent)
1559 == FAILURE) {
1560 rc = FAILURE;
1561 }
1562 }
1563 plibptr = plibptr->next;
1564 }
1565 free_uentrylist(pliblist);
1566 }
1567
1568 /* kernel software providers */
1569 (void) printf(gettext("\nKernel software providers:\n"));
1570 /*
1571 * TRANSLATION_NOTE
1572 * Strictly for appearance's sake, this line should be as long as
1573 * the length of the translated text above.
1574 */
1575 (void) printf(gettext("==========================\n"));
1576
1577 /* Get all entries from the kcf.conf file */
1578 pdevlist_conf = NULL;
1579 if (getzoneid() == GLOBAL_ZONEID) {
1580 /* use kcf.conf for kernel software providers in global zone */
1581 psoftlist_conf = NULL;
1582
1583 if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) ==
1584 FAILURE) {
1585 cryptoerror(LOG_STDERR, gettext(
1586 "failed to retrieve the list of kernel "
1587 "providers.\n"));
1588 return (FAILURE);
1589 }
1590
1591 ptr = psoftlist_conf;
1592 while (ptr != NULL) {
1593 (void) list_policy_for_soft(ptr->pent->name);
1594 ptr = ptr->next;
1595 }
1596
1597 free_entrylist(psoftlist_conf);
1598 } else {
1599 /* kcf.conf not there in non-global zone, no policy info */
1600
1601 /*
1602 * TRANSLATION_NOTE
1603 * "global" is keyword and not to be translated.
1604 */
1605 cryptoerror(LOG_STDERR, gettext(
1606 "policy information for kernel software providers is "
1607 "available in the %s zone only"), "global");
1608 }
1609
1610 /* Kernel hardware providers */
1611 (void) printf(gettext("\nKernel hardware providers:\n"));
1612 /*
1613 * TRANSLATION_NOTE
1614 * Strictly for appearance's sake, this line should be as long as
1615 * the length of the translated text above.
1616 */
1617 (void) printf(gettext("==========================\n"));
1618
1619 if (getzoneid() != GLOBAL_ZONEID) {
1620 /*
1621 * TRANSLATION_NOTE
1622 * "global" is keyword and not to be translated.
1623 */
1624 cryptoerror(LOG_STDERR, gettext(
1625 "policy information for kernel hardware providers is "
1626 "available in the %s zone only"), "global");
1627 return (FAILURE);
1628 }
1629
1630 /* Get the hardware provider list from kernel */
1631 if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
1632 cryptoerror(LOG_STDERR, gettext(
1633 "failed to retrieve the list of hardware providers.\n"));
1634 free_entrylist(pdevlist_conf);
1635 return (FAILURE);
1636 }
1637
1638 /*
1639 * For each hardware provider from kernel, check if it has an entry
1640 * in the config file. If it has an entry, print out the policy from
1641 * config file and remove the entry from the hardware provider list
1642 * of the config file. If it does not have an entry in the config
1643 * file, no mechanisms of it have been disabled. But, we still call
1644 * list_policy_for_hard() to account for the "random" feature.
1645 */
1646 for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
1647 (void) snprintf(provname, sizeof (provname), "%s/%d",
1648 pdevlist_kernel->dl_devs[i].le_dev_name,
1649 pdevlist_kernel->dl_devs[i].le_dev_instance);
1650 found = B_FALSE;
1651 phead = ptr = pdevlist_conf;
1652 while (!found && ptr) {
1653 if (strcmp(ptr->pent->name, provname) == 0) {
1654 found = B_TRUE;
1655 } else {
1656 phead = ptr;
1657 ptr = ptr->next;
1658 }
1659 }
1660
1661 if (found) {
1662 (void) list_policy_for_hard(ptr->pent->name);
1663 if (phead == ptr) {
1664 pdevlist_conf = pdevlist_conf->next;
1665 } else {
1666 phead->next = ptr->next;
1667 }
1668 free_entry(ptr->pent);
1669 free(ptr);
1670 } else {
1671 (void) list_policy_for_hard(provname);
1672 }
1673 }
1674
1675 /*
1676 * If there are still entries left in the pdevlist_conf list from
1677 * the config file, these providers must have been detached.
1678 * Should print out their policy information also.
1679 */
1680 ptr = pdevlist_conf;
1681 while (ptr != NULL) {
1682 print_kef_policy(ptr->pent, B_FALSE, B_TRUE);
1683 ptr = ptr->next;
1684 }
1685
1686 free_entrylist(pdevlist_conf);
1687 free(pdevlist_kernel);
1688
1689 return (rc);
1690 }