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 }