Print this page
6414175 kcf.conf's supportedlist not providing much usefulness

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c
          +++ new/usr/src/cmd/cmd-crypto/cryptoadm/adm_kef.c
↓ open down ↓ 29 lines elided ↑ open up ↑
  30   30  #include <unistd.h>
  31   31  #include <locale.h>
  32   32  #include <libgen.h>
  33   33  #include <sys/types.h>
  34   34  #include <sys/stat.h>
  35   35  #include <sys/crypto/ioctladmin.h>
  36   36  #include <signal.h>
  37   37  #include <sys/crypto/elfsign.h>
  38   38  #include "cryptoadm.h"
  39   39  
  40      -static int err; /* to store the value of errno in case being overwritten */
  41   40  static int check_hardware_provider(char *, char *, int *, int *);
  42   41  
  43   42  /*
  44   43   * Display the mechanism list for a kernel software provider.
       44 + * This implements part of the "cryptoadm list -m" command.
       45 + *
       46 + * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
       47 + * If NULL, this function obtains it by calling get_kcfconf_info() internally.
  45   48   */
  46   49  int
  47      -list_mechlist_for_soft(char *provname)
       50 +list_mechlist_for_soft(char *provname,
       51 +    entrylist_t *phardlist, entrylist_t *psoftlist)
  48   52  {
  49      -        mechlist_t *pmechlist;
  50      -        int rc;
       53 +        mechlist_t      *pmechlist = NULL;
       54 +        int             rc;
  51   55  
  52   56          if (provname == NULL) {
  53   57                  return (FAILURE);
  54   58          }
  55   59  
  56      -        rc = get_soft_info(provname, &pmechlist);
       60 +        rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
  57   61          if (rc == SUCCESS) {
  58   62                  (void) filter_mechlist(&pmechlist, RANDOM);
  59   63                  print_mechlist(provname, pmechlist);
  60   64                  free_mechlist(pmechlist);
  61   65          } else {
  62   66                  cryptoerror(LOG_STDERR, gettext(
  63   67                      "failed to retrieve the mechanism list for %s."),
  64   68                      provname);
  65   69          }
  66   70  
  67   71          return (rc);
  68      -
  69   72  }
  70   73  
  71   74  /*
  72   75   * Display the mechanism list for a kernel hardware provider.
       76 + * This implements part of the "cryptoadm list -m" command.
  73   77   */
  74   78  int
  75   79  list_mechlist_for_hard(char *provname)
  76   80  {
  77      -        mechlist_t *pmechlist;
  78      -        char    devname[MAXNAMELEN];
  79      -        int     inst_num;
  80      -        int     count;
  81      -        int rc = SUCCESS;
       81 +        mechlist_t      *pmechlist = NULL;
       82 +        char            devname[MAXNAMELEN];
       83 +        int             inst_num;
       84 +        int             count;
       85 +        int             rc = SUCCESS;
  82   86  
  83   87          if (provname == NULL) {
  84   88                  return (FAILURE);
  85   89          }
  86   90  
  87   91          /*
  88   92           * Check if the provider is valid. If it is valid, get the number of
  89   93           * mechanisms also.
  90   94           */
  91   95          if (check_hardware_provider(provname, devname, &inst_num, &count) ==
↓ open down ↓ 8 lines elided ↑ open up ↑
 100  104                  print_mechlist(provname, pmechlist);
 101  105                  free_mechlist(pmechlist);
 102  106          }
 103  107  
 104  108          return (rc);
 105  109  }
 106  110  
 107  111  
 108  112  /*
 109  113   * Display the policy information for a kernel software provider.
      114 + * This implements part of the "cryptoadm list -p" command.
      115 + *
      116 + * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
      117 + * If NULL, this function obtains it by calling get_kcfconf_info() internally.
 110  118   */
 111  119  int
 112      -list_policy_for_soft(char *provname)
      120 +list_policy_for_soft(char *provname,
      121 +    entrylist_t *phardlist, entrylist_t *psoftlist)
 113  122  {
 114      -        int rc;
 115      -        entry_t *pent = NULL;
 116      -        mechlist_t *pmechlist;
 117      -        boolean_t has_random = B_FALSE;
 118      -        boolean_t has_mechs = B_FALSE;
      123 +        int             rc;
      124 +        entry_t         *pent = NULL;
      125 +        mechlist_t      *pmechlist = NULL;
      126 +        boolean_t       has_random = B_FALSE;
      127 +        boolean_t       has_mechs = B_FALSE;
      128 +        boolean_t       in_kernel = B_FALSE;
 119  129  
 120  130          if (provname == NULL) {
 121  131                  return (FAILURE);
 122  132          }
 123  133  
 124      -        if ((pent = getent_kef(provname)) == NULL) {
      134 +        if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
      135 +                return (FAILURE);
      136 +        } else if (in_kernel == B_FALSE) {
 125  137                  cryptoerror(LOG_STDERR, gettext("%s does not exist."),
 126  138                      provname);
 127  139                  return (FAILURE);
 128  140          }
      141 +        pent = getent_kef(provname, phardlist, psoftlist);
 129  142  
 130      -        rc = get_soft_info(provname, &pmechlist);
      143 +        rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist);
 131  144          if (rc == SUCCESS) {
 132  145                  has_random = filter_mechlist(&pmechlist, RANDOM);
 133  146                  if (pmechlist != NULL) {
 134  147                          has_mechs = B_TRUE;
 135  148                          free_mechlist(pmechlist);
 136  149                  }
 137  150          } else {
 138  151                  cryptoerror(LOG_STDERR, gettext(
 139  152                      "failed to retrieve the mechanism list for %s."),
 140  153                      provname);
 141  154                  return (rc);
 142  155          }
 143  156  
 144      -        print_kef_policy(pent, has_random, has_mechs);
      157 +        print_kef_policy(provname, pent, has_random, has_mechs);
 145  158          free_entry(pent);
 146  159          return (SUCCESS);
 147  160  }
 148  161  
 149  162  
 150  163  
 151  164  /*
 152  165   * Display the policy information for a kernel hardware provider.
      166 + * This implements part of the "cryptoadm list -p" command.
      167 + *
      168 + * Parameters phardlist and psoftlist are supplied by get_kcfconf_info().
      169 + * If NULL, this function obtains it by calling get_kcfconf_info() internally.
      170 + * Parameter pdevlist is supplied by get_dev_list().
      171 + * If NULL, this function obtains it by calling get_dev_list() internally.
 153  172   */
 154  173  int
 155      -list_policy_for_hard(char *provname)
      174 +list_policy_for_hard(char *provname,
      175 +        entrylist_t *phardlist, entrylist_t *psoftlist,
      176 +        crypto_get_dev_list_t *pdevlist)
 156  177  {
 157      -        entry_t *pent;
 158      -        boolean_t is_active;
 159      -        mechlist_t *pmechlist;
 160      -        char    devname[MAXNAMELEN];
 161      -        int     inst_num;
 162      -        int     count;
 163      -        int rc = SUCCESS;
 164      -        boolean_t has_random = B_FALSE;
 165      -        boolean_t has_mechs = B_FALSE;
      178 +        entry_t         *pent = NULL;
      179 +        boolean_t       in_kernel;
      180 +        mechlist_t      *pmechlist = NULL;
      181 +        char            devname[MAXNAMELEN];
      182 +        int             inst_num;
      183 +        int             count;
      184 +        int             rc = SUCCESS;
      185 +        boolean_t       has_random = B_FALSE;
      186 +        boolean_t       has_mechs = B_FALSE;
 166  187  
 167  188          if (provname == NULL) {
 168  189                  return (FAILURE);
 169  190          }
 170  191  
 171  192          /*
 172  193           * Check if the provider is valid. If it is valid, get the number of
 173  194           * mechanisms also.
 174  195           */
 175  196          if (check_hardware_provider(provname, devname, &inst_num, &count) ==
↓ open down ↓ 16 lines elided ↑ open up ↑
 192  213                      devname);
 193  214                  return (rc);
 194  215          }
 195  216  
 196  217          /*
 197  218           * If the hardware provider has an entry in the kcf.conf file,
 198  219           * some of its mechanisms must have been disabled.  Print out
 199  220           * the disabled list from the config file entry.  Otherwise,
 200  221           * if it is active, then all the mechanisms for it are enabled.
 201  222           */
 202      -        if ((pent = getent_kef(provname)) != NULL) {
 203      -                print_kef_policy(pent, has_random, has_mechs);
      223 +        if ((pent = getent_kef(provname, phardlist, psoftlist)) != NULL) {
      224 +                print_kef_policy(provname, pent, has_random, has_mechs);
 204  225                  free_entry(pent);
 205  226                  return (SUCCESS);
 206  227          } else {
 207      -                if (check_active_for_hard(provname, &is_active) ==
 208      -                    FAILURE) {
      228 +                if (check_kernel_for_hard(provname, pdevlist,
      229 +                    &in_kernel) == FAILURE) {
 209  230                          return (FAILURE);
 210      -                } else if (is_active == B_TRUE) {
      231 +                } else if (in_kernel == B_TRUE) {
 211  232                          (void) printf(gettext(
 212  233                              "%s: all mechanisms are enabled."), provname);
 213  234                          if (has_random)
 214  235                                  /*
 215  236                                   * TRANSLATION_NOTE
 216  237                                   * "random" is a keyword and not to be
 217  238                                   * translated.
 218  239                                   */
 219  240                                  (void) printf(gettext(" %s is enabled.\n"),
 220  241                                      "random");
↓ open down ↓ 2 lines elided ↑ open up ↑
 223  244                          return (SUCCESS);
 224  245                  } else {
 225  246                          cryptoerror(LOG_STDERR,
 226  247                              gettext("%s does not exist."), provname);
 227  248                          return (FAILURE);
 228  249                  }
 229  250          }
 230  251  }
 231  252  
 232  253  
 233      -
      254 +/*
      255 + * Disable a kernel hardware provider.
      256 + * This implements the "cryptoadm disable" command for
      257 + * kernel hardware providers.
      258 + */
 234  259  int
 235  260  disable_kef_hardware(char *provname, boolean_t rndflag, boolean_t allflag,
 236  261      mechlist_t *dislist)
 237  262  {
 238      -        crypto_load_dev_disabled_t      *pload_dev_dis;
 239      -        mechlist_t      *infolist;
 240      -        entry_t         *pent;
 241      -        boolean_t       new_dev_entry = B_FALSE;
 242      -        char    devname[MAXNAMELEN];
 243      -        int     inst_num;
 244      -        int     count;
 245      -        int     fd;
 246      -        int     rc = SUCCESS;
      263 +        crypto_load_dev_disabled_t      *pload_dev_dis = NULL;
      264 +        mechlist_t                      *infolist = NULL;
      265 +        entry_t                         *pent = NULL;
      266 +        boolean_t                       new_dev_entry = B_FALSE;
      267 +        char                            devname[MAXNAMELEN];
      268 +        int                             inst_num;
      269 +        int                             count;
      270 +        int                             fd = -1;
      271 +        int                             rc = SUCCESS;
 247  272  
 248  273          if (provname == NULL) {
 249  274                  return (FAILURE);
 250  275          }
 251  276  
 252  277          /*
 253  278           * Check if the provider is valid. If it is valid, get the number of
 254  279           * mechanisms also.
 255  280           */
 256  281          if (check_hardware_provider(provname, devname, &inst_num, &count)
↓ open down ↓ 3 lines elided ↑ open up ↑
 260  285  
 261  286          /* Get the mechanism list for the kernel hardware provider */
 262  287          if (get_dev_info(devname, inst_num, count, &infolist) == FAILURE) {
 263  288                  return (FAILURE);
 264  289          }
 265  290  
 266  291          /*
 267  292           * Get the entry of this hardware provider from the config file.
 268  293           * If there is no entry yet, create one for it.
 269  294           */
 270      -        if ((pent = getent_kef(provname)) == NULL) {
 271      -                if ((pent = malloc(sizeof (entry_t))) == NULL) {
      295 +        if ((pent = getent_kef(provname, NULL, NULL)) == NULL) {
      296 +                if ((pent = create_entry(provname)) == NULL) {
 272  297                          cryptoerror(LOG_STDERR, gettext("out of memory."));
 273  298                          free_mechlist(infolist);
 274  299                          return (FAILURE);
 275  300                  }
 276  301                  new_dev_entry = B_TRUE;
 277      -                (void) strlcpy(pent->name, provname, MAXNAMELEN);
 278      -                pent->suplist = NULL;
 279      -                pent->sup_count = 0;
 280      -                pent->dislist = NULL;
 281      -                pent->dis_count = 0;
 282  302          }
 283  303  
 284  304          /*
 285  305           * kCF treats random as an internal mechanism. So, we need to
 286  306           * filter it from the mechanism list here, if we are NOT disabling
 287  307           * or enabling the random feature. Note that we map random feature at
 288  308           * cryptoadm(1M) level to the "random" mechanism in kCF.
 289  309           */
 290  310          if (!rndflag) {
 291  311                  (void) filter_mechlist(&dislist, RANDOM);
↓ open down ↓ 54 lines elided ↑ open up ↑
 346  366                  (void) close(fd);
 347  367                  return (FAILURE);
 348  368          }
 349  369  
 350  370          free(pload_dev_dis);
 351  371          (void) close(fd);
 352  372          return (SUCCESS);
 353  373  }
 354  374  
 355  375  
 356      -
      376 +/*
      377 + * Disable a kernel software provider.
      378 + * This implements the "cryptoadm disable" command for
      379 + * kernel software providers.
      380 + */
 357  381  int
 358  382  disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag,
 359  383      mechlist_t *dislist)
 360  384  {
 361  385          crypto_load_soft_disabled_t     *pload_soft_dis = NULL;
 362      -        mechlist_t      *infolist;
 363      -        entry_t         *pent;
 364      -        boolean_t       is_active;
 365      -        int     fd;
      386 +        mechlist_t                      *infolist = NULL;
      387 +        entry_t                         *pent = NULL;
      388 +        entrylist_t                     *phardlist = NULL;
      389 +        entrylist_t                     *psoftlist = NULL;
      390 +        boolean_t                       in_kernel = B_FALSE;
      391 +        int                             fd = -1;
      392 +        int                             rc = SUCCESS;
 366  393  
 367  394          if (provname == NULL) {
 368  395                  return (FAILURE);
 369  396          }
 370  397  
 371      -        /* Get the entry of this provider from the config file. */
 372      -        if ((pent = getent_kef(provname)) == NULL) {
 373      -                cryptoerror(LOG_STDERR,
 374      -                    gettext("%s does not exist."), provname);
 375      -                return (FAILURE);
 376      -        }
 377      -
 378  398          /*
 379  399           * Check if the kernel software provider is currently unloaded.
 380  400           * If it is unloaded, return FAILURE, because the disable subcommand
 381  401           * can not perform on inactive (unloaded) providers.
 382  402           */
 383      -        if (check_active_for_soft(provname, &is_active) == FAILURE) {
 384      -                free_entry(pent);
      403 +        if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
 385  404                  return (FAILURE);
 386      -        } else if (is_active == B_FALSE) {
 387      -                /*
 388      -                 * TRANSLATION_NOTE
 389      -                 * "disable" is a keyword and not to be translated.
 390      -                 */
      405 +        } else if (in_kernel == B_FALSE) {
 391  406                  cryptoerror(LOG_STDERR,
 392      -                    gettext("can not do %1$s on an unloaded "
 393      -                    "kernel software provider -- %2$s."), "disable", provname);
 394      -                free_entry(pent);
      407 +                    gettext("%s is not loaded or does not exist."),
      408 +                    provname);
 395  409                  return (FAILURE);
 396  410          }
 397  411  
 398      -        /* Get the mechanism list for the software provider */
 399      -        if (get_soft_info(provname, &infolist) == FAILURE) {
 400      -                free(pent);
      412 +        if (get_kcfconf_info(&phardlist, &psoftlist) == FAILURE) {
      413 +                cryptoerror(LOG_ERR,
      414 +                    "failed to retrieve the providers' "
      415 +                    "information from the configuration file - %s.",
      416 +                    _PATH_KCF_CONF);
 401  417                  return (FAILURE);
 402  418          }
 403  419  
 404      -        /* See comments in disable_kef_hardware() */
      420 +        /*
      421 +         * Get the entry of this provider from the kcf.conf file, if any.
      422 +         * Otherwise, create a new kcf.conf entry for writing back to the file.
      423 +         */
      424 +        pent = getent_kef(provname, phardlist, psoftlist);
      425 +        if (pent == NULL) { /* create a new entry */
      426 +                pent = create_entry(provname);
      427 +                if (pent == NULL) {
      428 +                        cryptodebug("out of memory.");
      429 +                        rc = FAILURE;
      430 +                        goto out;
      431 +                }
      432 +        }
      433 +
      434 +        /* Get the mechanism list for the software provider from the kernel */
      435 +        if (get_soft_info(provname, &infolist, phardlist, psoftlist) ==
      436 +            FAILURE) {
      437 +                rc = FAILURE;
      438 +                goto out;
      439 +        }
      440 +
      441 +        if ((infolist != NULL) && (infolist->name[0] != '\0')) {
      442 +                /*
      443 +                 * Replace the supportedlist from kcf.conf with possibly
      444 +                 * more-up-to-date list from the kernel.  This is the case
      445 +                 * for default software providers that had more mechanisms
      446 +                 * added in the current version of the kernel.
      447 +                 */
      448 +                free_mechlist(pent->suplist);
      449 +                pent->suplist = infolist;
      450 +        }
      451 +
      452 +        /*
      453 +         * kCF treats random as an internal mechanism. So, we need to
      454 +         * filter it from the mechanism list here, if we are NOT disabling
      455 +         * or enabling the random feature. Note that we map random feature at
      456 +         * cryptoadm(1M) level to the "random" mechanism in kCF.
      457 +         */
 405  458          if (!rndflag) {
 406  459                  (void) filter_mechlist(&infolist, RANDOM);
 407  460          }
 408  461  
 409  462          /* Calculate the new disabled list */
 410  463          if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) {
 411      -                free_entry(pent);
 412      -                free_mechlist(infolist);
 413      -                return (FAILURE);
      464 +                rc = FAILURE;
      465 +                goto out;
 414  466          }
 415  467  
 416      -        /* infolist is no longer needed; free it */
 417      -        free_mechlist(infolist);
 418      -
 419  468          /* Update the kcf.conf file with the updated entry */
 420  469          if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) {
 421      -                free_entry(pent);
 422      -                return (FAILURE);
      470 +                rc = FAILURE;
      471 +                goto out;
 423  472          }
 424  473  
 425      -        /* Inform kernel about the new disabled list. */
      474 +        /* Setup argument to inform kernel about the new disabled list. */
 426  475          if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
 427      -                free_entry(pent);
 428      -                return (FAILURE);
      476 +                rc = FAILURE;
      477 +                goto out;
 429  478          }
 430  479  
 431      -        /* pent is no longer needed; free it. */
 432      -        free_entry(pent);
 433      -
 434  480          if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
 435  481                  cryptoerror(LOG_STDERR,
 436  482                      gettext("failed to open %s for RW: %s"),
 437  483                      ADMIN_IOCTL_DEVICE, strerror(errno));
 438      -                free(pload_soft_dis);
 439      -                return (FAILURE);
      484 +                rc = FAILURE;
      485 +                goto out;
 440  486          }
 441  487  
      488 +        /* Inform kernel about the new disabled list. */
 442  489          if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) {
 443  490                  cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s",
 444  491                      strerror(errno));
 445      -                free(pload_soft_dis);
 446      -                (void) close(fd);
 447      -                return (FAILURE);
      492 +                rc = FAILURE;
      493 +                goto out;
 448  494          }
 449  495  
 450  496          if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
 451  497                  cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = "
 452  498                      "%d", pload_soft_dis->sd_return_value);
 453      -                free(pload_soft_dis);
 454      -                (void) close(fd);
 455      -                return (FAILURE);
      499 +                rc = FAILURE;
      500 +                goto out;
 456  501          }
 457  502  
      503 +out:
      504 +        free_entrylist(phardlist);
      505 +        free_entrylist(psoftlist);
      506 +        free_mechlist(infolist);
      507 +        free_entry(pent);
 458  508          free(pload_soft_dis);
 459      -        (void) close(fd);
 460      -        return (SUCCESS);
      509 +        if (fd != -1)
      510 +                (void) close(fd);
      511 +        return (rc);
 461  512  }
 462  513  
 463  514  
      515 +/*
      516 + * Enable a kernel software or hardware provider.
      517 + * This implements the "cryptoadm enable" command for kernel providers.
      518 + */
 464  519  int
 465  520  enable_kef(char *provname, boolean_t rndflag, boolean_t allflag,
 466  521      mechlist_t *mlist)
 467  522  {
 468  523          crypto_load_soft_disabled_t     *pload_soft_dis = NULL;
 469  524          crypto_load_dev_disabled_t      *pload_dev_dis = NULL;
 470      -        entry_t         *pent;
 471      -        boolean_t redo_flag = B_FALSE;
 472      -        int     fd;
 473      -        int     rc = SUCCESS;
      525 +        entry_t                         *pent = NULL;
      526 +        boolean_t                       redo_flag = B_FALSE;
      527 +        boolean_t                       in_kernel = B_FALSE;
      528 +        int                             fd = -1;
      529 +        int                             rc = SUCCESS;
 474  530  
 475  531  
 476      -        /* Get the entry with the provider name from the kcf.conf file */
 477      -        pent = getent_kef(provname);
      532 +        /* Get the entry of this provider from the kcf.conf file, if any. */
      533 +        pent = getent_kef(provname, NULL, NULL);
 478  534  
 479  535          if (is_device(provname)) {
 480  536                  if (pent == NULL) {
 481  537                          /*
 482  538                           * This device doesn't have an entry in the config
 483  539                           * file, therefore nothing is disabled.
 484  540                           */
 485  541                          cryptoerror(LOG_STDERR, gettext(
 486  542                              "all mechanisms are enabled already for %s."),
 487  543                              provname);
      544 +                        free_entry(pent);
 488  545                          return (SUCCESS);
 489  546                  }
 490  547          } else { /* a software module */
 491      -                if (pent == NULL) {
 492      -                        cryptoerror(LOG_STDERR,
 493      -                            gettext("%s does not exist."), provname);
      548 +                if (check_kernel_for_soft(provname, NULL, &in_kernel) ==
      549 +                    FAILURE) {
      550 +                        free_entry(pent);
 494  551                          return (FAILURE);
 495      -                } else if (pent->dis_count == 0) {
      552 +                } else if (in_kernel == B_FALSE) {
      553 +                        cryptoerror(LOG_STDERR, gettext("%s does not exist."),
      554 +                            provname);
      555 +                        free_entry(pent);
      556 +                        return (FAILURE);
      557 +                } else if ((pent == NULL) || (pent->dis_count == 0)) {
 496  558                          /* nothing to be enabled. */
 497  559                          cryptoerror(LOG_STDERR, gettext(
 498  560                              "all mechanisms are enabled already for %s."),
 499  561                              provname);
 500  562                          free_entry(pent);
 501  563                          return (SUCCESS);
 502  564                  }
 503  565          }
 504  566  
      567 +        /*
      568 +         * kCF treats random as an internal mechanism. So, we need to
      569 +         * filter it from the mechanism list here, if we are NOT disabling
      570 +         * or enabling the random feature. Note that we map random feature at
      571 +         * cryptoadm(1M) level to the "random" mechanism in kCF.
      572 +         */
 505  573          if (!rndflag) {
 506      -                /* See comments in disable_kef_hardware() */
 507  574                  redo_flag = filter_mechlist(&pent->dislist, RANDOM);
 508  575                  if (redo_flag)
 509  576                          pent->dis_count--;
 510  577          }
 511  578  
 512  579          /* Update the entry by enabling mechanisms for this provider */
 513  580          if ((rc = enable_mechs(&pent, allflag, mlist)) != SUCCESS) {
 514  581                  free_entry(pent);
 515  582                  return (rc);
 516  583          }
↓ open down ↓ 4 lines elided ↑ open up ↑
 521  588                  if ((tmp = create_mech(RANDOM)) == NULL) {
 522  589                          free_entry(pent);
 523  590                          return (FAILURE);
 524  591                  }
 525  592                  tmp->next = pent->dislist;
 526  593                  pent->dislist = tmp;
 527  594                  pent->dis_count++;
 528  595          }
 529  596  
 530  597          /*
 531      -         * Update the kcf.conf file  with the updated entry.
      598 +         * Update the kcf.conf file with the updated entry.
 532  599           * For a hardware provider, if there is no more disabled mechanism,
 533      -         * the entire entry in the config file should be removed.
      600 +         * remove the entire kcf.conf entry.
 534  601           */
 535  602          if (is_device(pent->name) && (pent->dis_count == 0)) {
 536  603                  rc = update_kcfconf(pent, DELETE_MODE);
 537  604          } else {
 538  605                  rc = update_kcfconf(pent, MODIFY_MODE);
 539  606          }
 540  607  
 541  608          if (rc == FAILURE) {
 542  609                  free_entry(pent);
 543  610                  return (FAILURE);
 544  611          }
 545  612  
 546  613  
 547  614          /* Inform Kernel about the policy change */
 548  615  
 549  616          if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
 550  617                  cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
 551  618                      ADMIN_IOCTL_DEVICE, strerror(errno));
      619 +                free_entry(pent);
 552  620                  return (FAILURE);
 553  621          }
 554  622  
 555  623          if (is_device(provname)) {
 556  624                  /*  LOAD_DEV_DISABLED */
 557  625                  if ((pload_dev_dis = setup_dev_dis(pent)) == NULL) {
      626 +                        free_entry(pent);
 558  627                          return (FAILURE);
 559  628                  }
 560  629  
 561  630                  if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis) == -1) {
 562  631                          cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl failed: "
 563  632                              "%s", strerror(errno));
      633 +                        free_entry(pent);
 564  634                          free(pload_dev_dis);
 565  635                          (void) close(fd);
 566  636                          return (FAILURE);
 567  637                  }
 568  638  
 569  639                  if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
 570  640                          cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
 571  641                              "return_value = %d",
 572  642                              pload_dev_dis->dd_return_value);
      643 +                        free_entry(pent);
 573  644                          free(pload_dev_dis);
 574  645                          (void) close(fd);
 575  646                          return (FAILURE);
 576  647                  }
 577  648  
 578      -        } else {
      649 +        } else { /* a software module */
 579  650                  /* LOAD_SOFT_DISABLED */
 580  651                  if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) {
      652 +                        free_entry(pent);
 581  653                          return (FAILURE);
 582  654                  }
 583  655  
 584  656                  if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis)
 585  657                      == -1) {
 586  658                          cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: "
 587  659                              "%s", strerror(errno));
      660 +                        free_entry(pent);
 588  661                          free(pload_soft_dis);
 589  662                          (void) close(fd);
 590  663                          return (FAILURE);
 591  664                  }
 592  665  
 593  666                  if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) {
 594  667                          cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
 595  668                              "return_value = %d",
 596  669                              pload_soft_dis->sd_return_value);
      670 +                        free_entry(pent);
 597  671                          free(pload_soft_dis);
 598  672                          (void) close(fd);
 599  673                          return (FAILURE);
 600  674                  }
 601  675          }
 602  676  
      677 +        free_entry(pent);
      678 +        free(pload_soft_dis);
 603  679          (void) close(fd);
 604  680          return (SUCCESS);
 605  681  }
 606  682  
 607  683  
 608  684  /*
 609  685   * Install a software module with the specified mechanism list into the system.
 610  686   * This routine adds an entry into the config file for this software module
 611  687   * first, then makes a CRYPTO_LOAD_SOFT_CONFIG ioctl call to inform kernel
 612  688   * about the new addition.
 613  689   */
 614  690  int
 615  691  install_kef(char *provname, mechlist_t *mlist)
 616  692  {
 617  693          crypto_load_soft_config_t       *pload_soft_conf = NULL;
 618      -        boolean_t       found;
 619      -        entry_t *pent;
 620      -        FILE    *pfile;
 621      -        FILE    *pfile_tmp;
 622      -        char    tmpfile_name[MAXPATHLEN];
 623      -        char    *ptr;
 624      -        char    *str;
 625      -        char    *name;
 626      -        char    buffer[BUFSIZ];
 627      -        char    buffer2[BUFSIZ];
 628      -        int     found_count;
 629      -        int     fd;
 630      -        int     rc = SUCCESS;
      694 +        boolean_t                       found;
      695 +        entry_t                         *pent = NULL;
      696 +        FILE                            *pfile = NULL;
      697 +        FILE                            *pfile_tmp = NULL;
      698 +        char                            tmpfile_name[MAXPATHLEN];
      699 +        char                            *ptr;
      700 +        char                            *str;
      701 +        char                            *name;
      702 +        char                            buffer[BUFSIZ];
      703 +        char                            buffer2[BUFSIZ];
      704 +        int                             found_count;
      705 +        int                             fd = -1;
      706 +        int                             rc = SUCCESS;
      707 +        int                             err;
 631  708  
 632  709          if ((provname == NULL) || (mlist == NULL)) {
 633  710                  return (FAILURE);
 634  711          }
 635  712  
 636  713          /* Check if the provider already exists */
 637      -        if ((pent = getent_kef(provname)) != NULL) {
      714 +        if ((pent = getent_kef(provname, NULL, NULL)) != NULL) {
 638  715                  cryptoerror(LOG_STDERR, gettext("%s exists already."),
 639  716                      provname);
 640  717                  free_entry(pent);
 641  718                  return (FAILURE);
 642  719          }
 643  720  
 644  721          /* Create an entry with provname and mlist. */
 645      -        if ((pent = malloc(sizeof (entry_t))) == NULL) {
      722 +        if ((pent = create_entry(provname)) == NULL) {
 646  723                  cryptoerror(LOG_STDERR, gettext("out of memory."));
 647  724                  return (FAILURE);
 648  725          }
 649      -
 650      -        (void) strlcpy(pent->name, provname, MAXNAMELEN);
 651  726          pent->sup_count = get_mech_count(mlist);
 652  727          pent->suplist = mlist;
 653      -        pent->dis_count = 0;
 654      -        pent->dislist = NULL;
 655  728  
 656  729          /* Append an entry for this software module to the kcf.conf file. */
 657  730          if ((str = ent2str(pent)) == NULL) {
 658  731                  free_entry(pent);
 659  732                  return (FAILURE);
 660  733          }
 661  734  
 662  735          if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
 663  736                  err = errno;
 664  737                  cryptoerror(LOG_STDERR,
↓ open down ↓ 65 lines elided ↑ open up ↑
 730  803                                  rc = FAILURE;
 731  804                          }
 732  805                  } else {
 733  806                          if (found_count == 1) {
 734  807                                  if (fputs(str, pfile_tmp) == EOF) {
 735  808                                          rc = FAILURE;
 736  809                                  }
 737  810                          } else {
 738  811                                  /*
 739  812                                   * Found a second entry with #libname.
 740      -                                 * Should not happen. The kcf.conf ffile
      813 +                                 * Should not happen. The kcf.conf file
 741  814                                   * is corrupted. Give a warning and skip
 742  815                                   * this entry.
 743  816                                   */
 744  817                                  cryptoerror(LOG_STDERR, gettext(
 745  818                                      "(Warning) Found an additional reserved "
 746  819                                      "entry for %s."), provname);
 747  820                          }
 748  821                  }
 749  822  
 750  823                  if (rc == FAILURE) {
↓ open down ↓ 34 lines elided ↑ open up ↑
 785  858                          free_entry(pent);
 786  859                          return (FAILURE);
 787  860                  }
 788  861          }
 789  862  
 790  863          if (fclose(pfile_tmp) != 0) {
 791  864                  err = errno;
 792  865                  cryptoerror(LOG_STDERR,
 793  866                      gettext("failed to close %s: %s"), tmpfile_name,
 794  867                      strerror(err));
      868 +                free_entry(pent);
 795  869                  return (FAILURE);
 796  870          }
 797  871  
 798  872          if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
 799  873                  err = errno;
 800  874                  cryptoerror(LOG_STDERR,
 801  875                      gettext("failed to update the configuration - %s"),
 802      -                        strerror(err));
      876 +                    strerror(err));
 803  877                  cryptodebug("failed to rename %s to %s: %s", tmpfile_name,
 804  878                      _PATH_KCF_CONF, strerror(err));
 805  879                  rc = FAILURE;
 806  880          } else if (chmod(_PATH_KCF_CONF,
 807  881              S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
 808  882                  err = errno;
 809  883                  cryptoerror(LOG_STDERR,
 810  884                      gettext("failed to update the configuration - %s"),
 811  885                      strerror(err));
 812  886                  cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
↓ open down ↓ 3 lines elided ↑ open up ↑
 816  890                  rc = SUCCESS;
 817  891          }
 818  892  
 819  893          if (rc == FAILURE) {
 820  894                  if (unlink(tmpfile_name) != 0) {
 821  895                          err = errno;
 822  896                          cryptoerror(LOG_STDERR, gettext(
 823  897                              "(Warning) failed to remove %s: %s"),
 824  898                              tmpfile_name, strerror(err));
 825  899                  }
      900 +                free_entry(pent);
 826  901                  return (FAILURE);
 827  902          }
 828  903  
 829  904  
 830  905          /* Inform kernel of this new software module. */
 831  906  
 832  907          if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
 833  908                  free_entry(pent);
 834  909                  return (FAILURE);
 835  910          }
↓ open down ↓ 32 lines elided ↑ open up ↑
 868  943  
 869  944  /*
 870  945   * Uninstall the software module. This routine first unloads the software
 871  946   * module with 3 ioctl calls, then deletes its entry from the config file.
 872  947   * Removing an entry from the config file needs to be done last to ensure
 873  948   * that there is still an entry if the earlier unload failed for any reason.
 874  949   */
 875  950  int
 876  951  uninstall_kef(char *provname)
 877  952  {
 878      -        entry_t         *pent;
 879      -        boolean_t       is_active;
 880      -        boolean_t       in_package;
 881      -        boolean_t       found;
 882      -        FILE    *pfile;
 883      -        FILE    *pfile_tmp;
 884      -        char    tmpfile_name[MAXPATHLEN];
 885      -        char    *name;
 886      -        char    strbuf[BUFSIZ];
 887      -        char    buffer[BUFSIZ];
 888      -        char    buffer2[BUFSIZ];
 889      -        char    *str;
 890      -        int     len;
 891      -        int     rc = SUCCESS;
      953 +        entry_t         *pent = NULL;
      954 +        int             rc = SUCCESS;
      955 +        boolean_t       in_kernel = B_FALSE;
      956 +        boolean_t       in_kcfconf = B_FALSE;
      957 +        int             fd = -1;
      958 +        crypto_load_soft_config_t *pload_soft_conf = NULL;
 892  959  
 893      -
 894      -        /* Check if it is in the kcf.conf file first. */
 895      -        if ((pent = getent_kef(provname)) == NULL) {
 896      -                cryptoerror(LOG_STDERR,
 897      -                    gettext("%s does not exist."), provname);
      960 +        /* Check to see if the provider exists first. */
      961 +        if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
 898  962                  return (FAILURE);
      963 +        } else if (in_kernel == B_FALSE) {
      964 +                cryptoerror(LOG_STDERR, gettext("%s does not exist."),
      965 +                    provname);
      966 +                return (FAILURE);
 899  967          }
 900  968  
 901      -
 902  969          /*
 903      -         * Get rid of the disabled list for the provider and get the converted
 904      -         * string for the entry.  This is to prepare the string for a provider
 905      -         * that is in a package.
      970 +         * If it is loaded, unload it first.  This does 2 ioctl calls:
      971 +         * CRYPTO_UNLOAD_SOFT_MODULE and CRYPTO_LOAD_SOFT_DISABLED.
 906  972           */
 907      -        free_mechlist(pent->dislist);
 908      -        pent->dis_count = 0;
 909      -        pent->dislist = NULL;
 910      -        str = ent2str(pent);
 911      -        free_entry(pent);
 912      -        if (str == NULL) {
 913      -                cryptoerror(LOG_STDERR, gettext("internal error."));
 914      -                return (FAILURE);
 915      -        }
 916      -        (void) snprintf(strbuf, sizeof (strbuf), "%s%s", "#", str);
 917      -        free(str);
 918      -
 919      -        /* If it is not loaded, unload it first  */
 920      -        if (check_active_for_soft(provname, &is_active) == FAILURE) {
 921      -                return (FAILURE);
 922      -        } else if ((is_active == B_TRUE) &&
 923      -            (unload_kef_soft(provname, B_TRUE) == FAILURE)) {
      973 +        if (unload_kef_soft(provname) == FAILURE) {
 924  974                  cryptoerror(LOG_STDERR,
 925      -                    gettext("failed to uninstall %s.\n"), provname);
      975 +                    gettext("failed to unload %s during uninstall.\n"),
      976 +                    provname);
 926  977                  return (FAILURE);
 927  978          }
 928  979  
 929  980          /*
 930      -         * Remove the entry from the config file.  If the provider to be
 931      -         * uninstalled is in a package, just comment it off.
      981 +         * Inform kernel to remove the configuration of this software module.
 932  982           */
 933      -        if ((pfile = fopen(_PATH_KCF_CONF, "r+")) == NULL) {
 934      -                err = errno;
 935      -                cryptoerror(LOG_STDERR,
 936      -                    gettext("failed to update the configuration - %s"),
 937      -                    strerror(err));
 938      -                cryptodebug("failed to open %s for write.", _PATH_KCF_CONF);
 939      -                return (FAILURE);
 940      -        }
 941  983  
 942      -        if (lockf(fileno(pfile), F_TLOCK, 0) == -1) {
 943      -                err = errno;
 944      -                cryptoerror(LOG_STDERR,
 945      -                    gettext("failed to lock the configuration - %s"),
 946      -                    strerror(err));
 947      -                (void) fclose(pfile);
      984 +        /* Setup ioctl() parameter */
      985 +        pent = getent_kef(provname, NULL, NULL);
      986 +        if (pent != NULL) { /* in kcf.conf */
      987 +                in_kcfconf = B_TRUE;
      988 +                free_mechlist(pent->suplist);
      989 +                pent->suplist = NULL;
      990 +                pent->sup_count = 0;
      991 +        } else if ((pent = create_entry(provname)) == NULL) {
      992 +                cryptoerror(LOG_STDERR, gettext("out of memory."));
 948  993                  return (FAILURE);
 949  994          }
 950      -
 951      -        /*
 952      -         * Create a temporary file in the /etc/crypto directory to save
 953      -         * the new configuration file first.
 954      -         */
 955      -        (void) strlcpy(tmpfile_name, TMPFILE_TEMPLATE, sizeof (tmpfile_name));
 956      -        if (mkstemp(tmpfile_name) == -1) {
 957      -                err = errno;
 958      -                cryptoerror(LOG_STDERR,
 959      -                    gettext("failed to create a temporary file - %s"),
 960      -                    strerror(err));
 961      -                (void) fclose(pfile);
      995 +        if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
      996 +                free_entry(pent);
 962  997                  return (FAILURE);
 963  998          }
 964  999  
 965      -        if ((pfile_tmp = fopen(tmpfile_name, "w")) == NULL) {
 966      -                err = errno;
 967      -                cryptoerror(LOG_STDERR, gettext("failed to open %s - %s"),
 968      -                    tmpfile_name, strerror(err));
 969      -                if (unlink(tmpfile_name) != 0) {
 970      -                        err = errno;
 971      -                        cryptoerror(LOG_STDERR, gettext(
 972      -                            "(Warning) failed to remove %s: %s"), tmpfile_name,
 973      -                            strerror(err));
 974      -                }
 975      -                (void) fclose(pfile);
     1000 +        /* Open the /dev/cryptoadm device */
     1001 +        if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
     1002 +                int     err = errno;
     1003 +                cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
     1004 +                    ADMIN_IOCTL_DEVICE, strerror(err));
     1005 +                free_entry(pent);
     1006 +                free(pload_soft_conf);
 976 1007                  return (FAILURE);
 977 1008          }
 978 1009  
 979      -        /*
 980      -         * Loop thru the config file.  If the kernel software provider
 981      -         * to be uninstalled is in a package, just comment it off.
 982      -         */
 983      -        in_package = B_FALSE;
 984      -        while (fgets(buffer, BUFSIZ, pfile) != NULL) {
 985      -                found = B_FALSE;
 986      -                if (!(buffer[0] == ' ' || buffer[0] == '\n' ||
 987      -                    buffer[0] == '\t')) {
 988      -                        if (strstr(buffer, " Start ") != NULL) {
 989      -                                in_package = B_TRUE;
 990      -                        } else if (strstr(buffer, " End ") != NULL) {
 991      -                                in_package = B_FALSE;
 992      -                        } else if (buffer[0] != '#') {
 993      -                                (void) strlcpy(buffer2, buffer, BUFSIZ);
 994      -
 995      -                                /* get rid of trailing '\n' */
 996      -                                len = strlen(buffer2);
 997      -                                if (buffer2[len-1] == '\n') {
 998      -                                        len--;
 999      -                                }
1000      -                                buffer2[len] = '\0';
1001      -
1002      -                                if ((name = strtok(buffer2, SEP_COLON))
1003      -                                    == NULL) {
1004      -                                        rc = FAILURE;
1005      -                                        break;
1006      -                                } else if (strcmp(provname, name) == 0) {
1007      -                                        found = B_TRUE;
1008      -                                }
1009      -                        }
1010      -                }
1011      -
1012      -                if (found) {
1013      -                        if (in_package) {
1014      -                                if (fputs(strbuf, pfile_tmp) == EOF) {
1015      -                                        rc = FAILURE;
1016      -                                }
1017      -                        }
1018      -                } else {
1019      -                        if (fputs(buffer, pfile_tmp) == EOF) {
1020      -                                rc = FAILURE;
1021      -                        }
1022      -                }
1023      -
1024      -                if (rc == FAILURE) {
1025      -                        break;
1026      -                }
1027      -        }
1028      -
1029      -        if (rc == FAILURE) {
1030      -                cryptoerror(LOG_STDERR, gettext("write error."));
1031      -                (void) fclose(pfile);
1032      -                (void) fclose(pfile_tmp);
1033      -                if (unlink(tmpfile_name) != 0) {
1034      -                        err = errno;
1035      -                        cryptoerror(LOG_STDERR, gettext(
1036      -                            "(Warning) failed to remove %s: %s"), tmpfile_name,
1037      -                            strerror(err));
1038      -                }
     1010 +        if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG,
     1011 +            pload_soft_conf) == -1) {
     1012 +                cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
     1013 +                    strerror(errno));
     1014 +                free_entry(pent);
     1015 +                free(pload_soft_conf);
     1016 +                (void) close(fd);
1039 1017                  return (FAILURE);
1040 1018          }
1041 1019  
1042      -        (void) fclose(pfile);
1043      -        if (fclose(pfile_tmp) != 0) {
1044      -                err = errno;
1045      -                cryptoerror(LOG_STDERR,
1046      -                    gettext("failed to close %s: %s"), tmpfile_name,
1047      -                    strerror(err));
     1020 +        if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
     1021 +                cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl = return_value = %d",
     1022 +                    pload_soft_conf->sc_return_value);
     1023 +                free_entry(pent);
     1024 +                free(pload_soft_conf);
     1025 +                (void) close(fd);
1048 1026                  return (FAILURE);
1049 1027          }
1050 1028  
1051      -        /* Now update the real config file */
1052      -        if (rename(tmpfile_name, _PATH_KCF_CONF) == -1) {
1053      -                err = errno;
1054      -                cryptoerror(LOG_STDERR,
1055      -                    gettext("failed to update the configuration - %s"),
1056      -                    strerror(err));
1057      -                cryptodebug("failed to rename %1$s to %2$s: %3$s", tmpfile,
1058      -                    _PATH_KCF_CONF, strerror(err));
1059      -                rc = FAILURE;
1060      -        } else if (chmod(_PATH_KCF_CONF,
1061      -            S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
1062      -                err = errno;
1063      -                cryptoerror(LOG_STDERR,
1064      -                    gettext("failed to update the configuration - %s"),
1065      -                    strerror(err));
1066      -                cryptodebug("failed to chmod to %s: %s", _PATH_KCF_CONF,
1067      -                    strerror(err));
1068      -                rc = FAILURE;
1069      -        } else {
1070      -                rc = SUCCESS;
1071      -        }
     1029 +        /* ioctl cleanup */
     1030 +        free(pload_soft_conf);
     1031 +        (void) close(fd);
1072 1032  
1073      -        if ((rc == FAILURE) && (unlink(tmpfile_name) != 0)) {
1074      -                err = errno;
1075      -                cryptoerror(LOG_STDERR, gettext(
1076      -                    "(Warning) failed to remove %s: %s"), tmpfile_name,
1077      -                    strerror(err));
     1033 +
     1034 +        /* Finally, remove entry from kcf.conf, if present */
     1035 +        if (in_kcfconf && (pent != NULL)) {
     1036 +                rc = update_kcfconf(pent, DELETE_MODE);
1078 1037          }
1079 1038  
     1039 +        free_entry(pent);
1080 1040          return (rc);
1081      -
1082 1041  }
1083 1042  
1084 1043  
     1044 +/*
     1045 + * Implement the "cryptoadm refresh" command for global zones.
     1046 + * That is, send the current contents of kcf.conf to the kernel via ioctl().
     1047 + */
1085 1048  int
1086 1049  refresh(void)
1087 1050  {
1088      -        crypto_get_soft_list_t          *psoftlist_kernel = NULL;
1089 1051          crypto_load_soft_config_t       *pload_soft_conf = NULL;
1090 1052          crypto_load_soft_disabled_t     *pload_soft_dis = NULL;
1091 1053          crypto_load_dev_disabled_t      *pload_dev_dis = NULL;
1092      -        entrylist_t     *pdevlist = NULL;
1093      -        entrylist_t     *psoftlist = NULL;
1094      -        entrylist_t     *ptr;
1095      -        boolean_t       found;
1096      -        char    *psoftname;
1097      -        int     fd;
1098      -        int     rc = SUCCESS;
1099      -        int     i;
     1054 +        entrylist_t                     *pdevlist = NULL;
     1055 +        entrylist_t                     *psoftlist = NULL;
     1056 +        entrylist_t                     *ptr;
     1057 +        int                             fd = -1;
     1058 +        int                             rc = SUCCESS;
     1059 +        int                             err;
1100 1060  
1101      -        if (get_soft_list(&psoftlist_kernel) == FAILURE) {
1102      -                cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
1103      -                    "software provider list from kernel."));
1104      -                return (FAILURE);
1105      -        }
1106      -
1107 1061          if (get_kcfconf_info(&pdevlist, &psoftlist) == FAILURE) {
1108 1062                  cryptoerror(LOG_ERR, "failed to retrieve the providers' "
1109 1063                      "information from the configuration file - %s.",
1110 1064                      _PATH_KCF_CONF);
1111 1065                  return (FAILURE);
1112 1066          }
1113 1067  
1114      -        /*
1115      -         * If a kernel software provider is in kernel, but it is not in the
1116      -         * kcf.conf file, it must have been pkgrm'ed and needs to be unloaded
1117      -         * now.
1118      -         */
1119      -        if (psoftlist_kernel->sl_soft_count > 0) {
1120      -                psoftname = psoftlist_kernel->sl_soft_names;
1121      -                for (i = 0; i < psoftlist_kernel->sl_soft_count; i++) {
1122      -                        ptr = psoftlist;
1123      -                        found = B_FALSE;
1124      -                        while (ptr != NULL) {
1125      -                                if (strcmp(psoftname, ptr->pent->name) == 0) {
1126      -                                        found = B_TRUE;
1127      -                                        break;
1128      -                                }
1129      -                                ptr = ptr->next;
1130      -                        }
1131      -
1132      -                        if (!found) {
1133      -                                rc = unload_kef_soft(psoftname, B_FALSE);
1134      -                                if (rc == FAILURE) {
1135      -                                        cryptoerror(LOG_ERR, gettext(
1136      -                                            "WARNING - the provider %s is "
1137      -                                            "still in kernel."), psoftname);
1138      -                                }
1139      -                        }
1140      -                        psoftname = psoftname + strlen(psoftname) + 1;
1141      -                }
1142      -        }
1143      -        free(psoftlist_kernel);
1144      -
1145 1068          if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
1146 1069                  err = errno;
1147 1070                  cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
1148 1071                      ADMIN_IOCTL_DEVICE, strerror(err));
1149 1072                  free(psoftlist);
1150 1073                  free(pdevlist);
1151 1074                  return (FAILURE);
1152 1075          }
1153 1076  
1154 1077          /*
1155      -         * For each software module, pass two sets of information to kernel
1156      -         * - the supported list and the disabled list
     1078 +         * For each software provider module, pass two sets of information to
     1079 +         * the kernel: the supported list and the disabled list.
1157 1080           */
1158      -        ptr = psoftlist;
1159      -        while (ptr != NULL) {
     1081 +        for (ptr = psoftlist; ptr != NULL; ptr = ptr->next) {
     1082 +                entry_t         *pent = ptr->pent;
     1083 +
1160 1084                  /* load the supported list */
1161      -                if ((pload_soft_conf = setup_soft_conf(ptr->pent)) == NULL) {
     1085 +                if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
     1086 +                        cryptodebug("setup_soft_conf() failed");
1162 1087                          rc = FAILURE;
1163 1088                          break;
1164 1089                  }
1165 1090  
     1091 +                if (!pent->load) { /* unloaded--mark as loaded */
     1092 +                        pent->load = B_TRUE;
     1093 +                        rc = update_kcfconf(pent, MODIFY_MODE);
     1094 +                        if (rc != SUCCESS) {
     1095 +                                free(pload_soft_conf);
     1096 +                                break;
     1097 +                        }
     1098 +                }
     1099 +
1166 1100                  if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf)
1167 1101                      == -1) {
1168 1102                          cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
1169 1103                              strerror(errno));
1170 1104                          free(pload_soft_conf);
1171 1105                          rc = FAILURE;
1172 1106                          break;
1173 1107                  }
1174 1108  
1175 1109                  if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
1176 1110                          cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl "
1177 1111                              "return_value = %d",
1178 1112                              pload_soft_conf->sc_return_value);
1179 1113                          free(pload_soft_conf);
1180 1114                          rc = FAILURE;
1181 1115                          break;
1182 1116                  }
1183 1117  
     1118 +                free(pload_soft_conf);
     1119 +
1184 1120                  /* load the disabled list */
1185 1121                  if (ptr->pent->dis_count != 0) {
1186 1122                          pload_soft_dis = setup_soft_dis(ptr->pent);
1187 1123                          if (pload_soft_dis == NULL) {
     1124 +                                cryptodebug("setup_soft_dis() failed");
     1125 +                                free(pload_soft_dis);
1188 1126                                  rc = FAILURE;
1189 1127                                  break;
1190 1128                          }
1191 1129  
1192 1130                          if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED,
1193 1131                              pload_soft_dis) == -1) {
1194 1132                                  cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
1195 1133                                      "failed: %s", strerror(errno));
1196 1134                                  free(pload_soft_dis);
1197 1135                                  rc = FAILURE;
↓ open down ↓ 4 lines elided ↑ open up ↑
1202 1140                              CRYPTO_SUCCESS) {
1203 1141                                  cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl "
1204 1142                                      "return_value = %d",
1205 1143                                      pload_soft_dis->sd_return_value);
1206 1144                                  free(pload_soft_dis);
1207 1145                                  rc = FAILURE;
1208 1146                                  break;
1209 1147                          }
1210 1148                          free(pload_soft_dis);
1211 1149                  }
1212      -
1213      -                free(pload_soft_conf);
1214      -                ptr = ptr->next;
1215 1150          }
1216 1151  
1217 1152          if (rc != SUCCESS) {
1218 1153                  (void) close(fd);
1219 1154                  return (rc);
1220 1155          }
1221 1156  
1222 1157  
1223      -        /* Pass the disabledlist information for Device to kernel */
1224      -        ptr = pdevlist;
1225      -        while (ptr != NULL) {
     1158 +        /*
     1159 +         * For each hardware provider module, pass the disabled list
     1160 +         * information to the kernel.
     1161 +         */
     1162 +        for (ptr = pdevlist; ptr != NULL; ptr = ptr->next) {
1226 1163                  /* load the disabled list */
1227 1164                  if (ptr->pent->dis_count != 0) {
1228 1165                          pload_dev_dis = setup_dev_dis(ptr->pent);
1229 1166                          if (pload_dev_dis == NULL) {
1230 1167                                  rc = FAILURE;
1231 1168                                  break;
1232 1169                          }
1233 1170  
1234 1171                          if (ioctl(fd, CRYPTO_LOAD_DEV_DISABLED, pload_dev_dis)
1235 1172                              == -1) {
↓ open down ↓ 7 lines elided ↑ open up ↑
1243 1180                          if (pload_dev_dis->dd_return_value != CRYPTO_SUCCESS) {
1244 1181                                  cryptodebug("CRYPTO_LOAD_DEV_DISABLED ioctl "
1245 1182                                      "return_value = %d",
1246 1183                                      pload_dev_dis->dd_return_value);
1247 1184                                  free(pload_dev_dis);
1248 1185                                  rc = FAILURE;
1249 1186                                  break;
1250 1187                          }
1251 1188                          free(pload_dev_dis);
1252 1189                  }
1253      -
1254      -                ptr = ptr->next;
1255 1190          }
1256 1191  
1257 1192          (void) close(fd);
1258 1193          return (rc);
1259 1194  }
1260 1195  
1261 1196  /*
1262 1197   * Unload the kernel software provider. Before calling this function, the
1263      - * caller should check if the provider is in the config file and if it
1264      - * is kernel. This routine makes 3 ioctl calls to remove it from kernel
1265      - * completely. The argument do_check set to B_FALSE means that the
1266      - * caller knows the provider is not the config file and hence the check
1267      - * is skipped.
     1198 + * caller should check to see if the provider is in the kernel.
     1199 + *
     1200 + * This routine makes 2 ioctl calls to remove it completely from the kernel:
     1201 + *      CRYPTO_UNLOAD_SOFT_MODULE - does a modunload of the KCF module
     1202 + *      CRYPTO_LOAD_SOFT_DISABLED - updates kernel disabled mechanism list
     1203 + *
     1204 + * This implements part of "cryptoadm unload" and "cryptoadm uninstall".
1268 1205   */
1269 1206  int
1270      -unload_kef_soft(char *provname, boolean_t do_check)
     1207 +unload_kef_soft(char *provname)
1271 1208  {
1272      -        crypto_unload_soft_module_t     *punload_soft = NULL;
1273      -        crypto_load_soft_config_t       *pload_soft_conf = NULL;
     1209 +        crypto_unload_soft_module_t     *punload_soft = NULL;
1274 1210          crypto_load_soft_disabled_t     *pload_soft_dis = NULL;
1275      -        entry_t *pent = NULL;
1276      -        int     fd;
     1211 +        entry_t                         *pent = NULL;
     1212 +        int                             fd = -1;
     1213 +        int                             err;
1277 1214  
1278 1215          if (provname == NULL) {
1279 1216                  cryptoerror(LOG_STDERR, gettext("internal error."));
1280 1217                  return (FAILURE);
1281 1218          }
1282 1219  
1283      -        if (!do_check) {
     1220 +        pent = getent_kef(provname, NULL, NULL);
     1221 +        if (pent == NULL) { /* not in kcf.conf */
1284 1222                  /* Construct an entry using the provname */
1285      -                pent = calloc(1, sizeof (entry_t));
     1223 +                pent = create_entry(provname);
1286 1224                  if (pent == NULL) {
1287 1225                          cryptoerror(LOG_STDERR, gettext("out of memory."));
1288 1226                          return (FAILURE);
1289 1227                  }
1290      -                (void) strlcpy(pent->name, provname, MAXNAMELEN);
1291      -        } else if ((pent = getent_kef(provname)) == NULL) {
1292      -                cryptoerror(LOG_STDERR, gettext("%s does not exist."),
1293      -                    provname);
1294      -                return (FAILURE);
1295 1228          }
1296 1229  
1297 1230          /* Open the admin_ioctl_device */
1298 1231          if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) {
1299 1232                  err = errno;
1300 1233                  cryptoerror(LOG_STDERR, gettext("failed to open %s: %s"),
1301 1234                      ADMIN_IOCTL_DEVICE, strerror(err));
     1235 +                free_entry(pent);
1302 1236                  return (FAILURE);
1303 1237          }
1304 1238  
1305 1239          /* Inform kernel to unload this software module */
1306 1240          if ((punload_soft = setup_unload_soft(pent)) == NULL) {
     1241 +                free_entry(pent);
1307 1242                  (void) close(fd);
1308 1243                  return (FAILURE);
1309 1244          }
1310 1245  
1311 1246          if (ioctl(fd, CRYPTO_UNLOAD_SOFT_MODULE, punload_soft) == -1) {
1312 1247                  cryptodebug("CRYPTO_UNLOAD_SOFT_MODULE ioctl failed: %s",
1313 1248                      strerror(errno));
1314 1249                  free_entry(pent);
1315 1250                  free(punload_soft);
1316 1251                  (void) close(fd);
↓ open down ↓ 11 lines elided ↑ open up ↑
1328 1263                  if (punload_soft->sm_return_value != CRYPTO_UNKNOWN_PROVIDER) {
1329 1264                          free_entry(pent);
1330 1265                          free(punload_soft);
1331 1266                          (void) close(fd);
1332 1267                          return (FAILURE);
1333 1268                  }
1334 1269          }
1335 1270  
1336 1271          free(punload_soft);
1337 1272  
1338      -        /*
1339      -         * Inform kernel to remove the configuration of this software
1340      -         * module.
1341      -         */
1342      -        free_mechlist(pent->suplist);
1343      -        pent->suplist = NULL;
1344      -        pent->sup_count = 0;
1345      -        if ((pload_soft_conf = setup_soft_conf(pent)) == NULL) {
1346      -                free_entry(pent);
1347      -                (void) close(fd);
1348      -                return (FAILURE);
1349      -        }
1350      -
1351      -        if (ioctl(fd, CRYPTO_LOAD_SOFT_CONFIG, pload_soft_conf) == -1) {
1352      -                cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl failed: %s",
1353      -                    strerror(errno));
1354      -                free_entry(pent);
1355      -                free(pload_soft_conf);
1356      -                (void) close(fd);
1357      -                return (FAILURE);
1358      -        }
1359      -
1360      -        if (pload_soft_conf->sc_return_value != CRYPTO_SUCCESS) {
1361      -                cryptodebug("CRYPTO_LOAD_SOFT_CONFIG ioctl return_value = "
1362      -                    "%d", pload_soft_conf->sc_return_value);
1363      -                free_entry(pent);
1364      -                free(pload_soft_conf);
1365      -                (void) close(fd);
1366      -                return (FAILURE);
1367      -        }
1368      -
1369      -        free(pload_soft_conf);
1370      -
1371 1273          /* Inform kernel to remove the disabled entries if any */
1372 1274          if (pent->dis_count == 0) {
1373 1275                  free_entry(pent);
1374 1276                  (void) close(fd);
1375 1277                  return (SUCCESS);
1376 1278          } else {
1377 1279                  free_mechlist(pent->dislist);
1378 1280                  pent->dislist = NULL;
1379 1281                  pent->dis_count = 0;
1380 1282          }
↓ open down ↓ 80 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX