Print this page
    
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libsmbfs/smb/keychain.c
          +++ new/usr/src/lib/libsmbfs/smb/keychain.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23      - * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  24   24   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  25   25   * Use is subject to license terms.
  26   26   */
  27   27  
  28   28  /*
  29   29   * External interface to the libsmbfs/netsmb keychain
  30   30   * storage mechanism.  This interface is consumed by
  31   31   * the "smbutil" commands: login, logout, ...
  32   32   * and by the SMBFS PAM module.
  33   33   */
  34   34  
  35   35  #include <sys/types.h>
  36   36  
  37   37  #include <errno.h>
  38   38  #include <stdio.h>
  39   39  #include <stdlib.h>
  40   40  #include <string.h>
  41   41  #include <unistd.h>
  42   42  #include <libintl.h>
  43   43  
  44   44  #include <cflib.h>
  45   45  #include <netsmb/smb_dev.h>
  46   46  #include <netsmb/smb_lib.h>
  47   47  #include <netsmb/smb_keychain.h>
  48   48  
  49   49  #include "charsets.h"
  50   50  #include "private.h"
  51   51  #include "ntlm.h"
  52   52  
  53   53  /* common func. for add/del/chk */
  54   54  static int
  55   55  smbfs_keychain_cmn(
  56   56          int cmd,
  57   57          uid_t uid,
  58   58          const char *dom,
  59   59          const char *usr,
  60   60          uchar_t *lmhash,
  61   61          uchar_t *nthash)
  62   62  {
  63   63          smbioc_pk_t pk;
  64   64          int err, fd, sz;
  65   65  
  66   66          memset(&pk, 0, sizeof (pk));
  67   67          pk.pk_uid = uid;
  68   68          err = 0;
  69   69          fd = -1;
  70   70  
  71   71          switch (cmd) {
  72   72  
  73   73          case SMBIOC_PK_ADD:
  74   74                  /*
  75   75                   * Add password hashes to the keychain.
  76   76                   */
  77   77                  if (lmhash == NULL || nthash == NULL) {
  78   78                          err = SMB_KEYCHAIN_BADPASSWD;
  79   79                          goto out;
  80   80                  }
  81   81                  memcpy(pk.pk_lmhash, lmhash, SMBIOC_HASH_SZ);
  82   82                  memcpy(pk.pk_nthash, nthash, SMBIOC_HASH_SZ);
  83   83                  /* FALLTHROUGH */
  84   84  
  85   85          case SMBIOC_PK_CHK:
  86   86          case SMBIOC_PK_DEL:
  87   87                  /*
  88   88                   * Copy domain and user.
  89   89                   */
  90   90                  if (dom == NULL) {
  91   91                          err = SMB_KEYCHAIN_BADDOMAIN;
  92   92                          goto out;
  93   93                  }
  94   94                  sz = sizeof (pk.pk_dom);
  95   95                  if (strlcpy(pk.pk_dom, dom, sz) >= sz) {
  96   96                          err = SMB_KEYCHAIN_BADDOMAIN;
  97   97                          goto out;
  98   98                  }
  99   99                  if (usr == NULL) {
 100  100                          err = SMB_KEYCHAIN_BADUSER;
 101  101                          goto out;
 102  102                  }
 103  103                  sz = sizeof (pk.pk_usr);
 104  104                  if (strlcpy(pk.pk_usr, usr, sz) >= sz) {
 105  105                          err = SMB_KEYCHAIN_BADUSER;
 106  106                          goto out;
 107  107                  }
 108  108                  break;
 109  109  
 110  110          case SMBIOC_PK_DEL_OWNER:       /* all owned by the caller */
 111  111          case SMBIOC_PK_DEL_EVERYONE:    /* all owned by everyone */
 112  112                  /*
 113  113                   * These two do not copyin any args, but we'll
 114  114                   * pass pk here anyway just so we can use the
 115  115                   * common code path below.
 116  116                   */
 117  117                  break;
 118  118  
 119  119          default:
 120  120                  err = SMB_KEYCHAIN_UNKNOWN;
  
    | 
      ↓ open down ↓ | 
    87 lines elided | 
    
      ↑ open up ↑ | 
  
 121  121                  goto out;
 122  122          }
 123  123  
 124  124          fd = smb_open_driver();
 125  125          if (fd < 0) {
 126  126                  err = SMB_KEYCHAIN_NODRIVER;
 127  127                  goto out;
 128  128          }
 129  129  
 130  130          err = 0;
 131      -        if (ioctl(fd, cmd, &pk) < 0) {
      131 +        if (nsmb_ioctl(fd, cmd, &pk) < 0) {
 132  132                  err = errno;
 133  133                  goto out;
 134  134          }
 135  135  
 136  136          if (cmd == SMBIOC_PK_CHK) {
 137  137                  if (lmhash != NULL)
 138  138                          memcpy(lmhash, pk.pk_lmhash, SMBIOC_HASH_SZ);
 139  139                  if (nthash != NULL)
 140  140                          memcpy(nthash, pk.pk_nthash, SMBIOC_HASH_SZ);
 141  141          }
 142  142  
 143  143  out:
 144  144          if (fd != -1)
 145      -                close(fd);
      145 +                nsmb_close(fd);
 146  146  
 147  147          return (err);
 148  148  }
 149  149  
 150  150  /*
 151  151   * Add a password to the keychain.
 152  152   *
 153  153   * Note: pass is a cleartext password.
 154  154   * We use it here to compute the LM hash and NT hash,
 155  155   * and then store ONLY the hashes.
 156  156   */
 157  157  int
 158  158  smbfs_keychain_add(uid_t uid, const char *dom, const char *usr,
 159  159          const char *pass)
 160  160  {
 161  161          uchar_t lmhash[SMBIOC_HASH_SZ];
 162  162          uchar_t nthash[SMBIOC_HASH_SZ];
 163  163          int err, cmd = SMBIOC_PK_ADD;
 164  164  
 165  165          if (pass == NULL)
 166  166                  return (SMB_KEYCHAIN_BADPASSWD);
 167  167  
 168  168          if ((err = ntlm_compute_lm_hash(lmhash, pass)) != 0)
 169  169                  return (err);
 170  170          if ((err = ntlm_compute_nt_hash(nthash, pass)) != 0)
 171  171                  return (err);
 172  172  
 173  173          err = smbfs_keychain_cmn(cmd, uid, dom, usr, lmhash, nthash);
 174  174          return (err);
 175  175  }
 176  176  
 177  177  /* Variant of the above that takes an NT hash. */
 178  178  int
 179  179  smbfs_keychain_addhash(uid_t uid, const char *dom, const char *usr,
 180  180          const uchar_t *nthash)
 181  181  {
 182  182          static const uchar_t lmhash[SMBIOC_HASH_SZ] = { 0 };
 183  183          int err, cmd = SMBIOC_PK_ADD;
 184  184          err = smbfs_keychain_cmn(cmd, uid, dom, usr,
 185  185              (uchar_t *)lmhash, (uchar_t *)nthash);
 186  186          return (err);
 187  187  }
 188  188  
 189  189  /* Delete a password from the keychain. */
 190  190  int
 191  191  smbfs_keychain_del(uid_t uid, const char *dom, const char *usr)
 192  192  {
 193  193          return (smbfs_keychain_cmn(SMBIOC_PK_DEL, uid, dom, usr, NULL, NULL));
 194  194  }
 195  195  
 196  196  /*
 197  197   * Check for existence of a keychain entry.
 198  198   * Returns 0 if it exists, else ENOENT.
 199  199   */
 200  200  int
 201  201  smbfs_keychain_chk(const char *dom, const char *usr)
 202  202  {
 203  203          uid_t uid = (uid_t)-1;
 204  204          return (smbfs_keychain_cmn(SMBIOC_PK_CHK, uid, dom, usr, NULL, NULL));
 205  205  }
 206  206  
 207  207  /*
 208  208   * Get the stored hashes
 209  209   */
 210  210  int
 211  211  smbfs_keychain_get(const char *dom, const char *usr,
 212  212                  uchar_t *lmhash, uchar_t *nthash)
 213  213  {
 214  214          uid_t uid = (uid_t)-1;
 215  215          int err, cmd = SMBIOC_PK_CHK;
 216  216  
 217  217          err = smbfs_keychain_cmn(cmd, uid, dom, usr, lmhash, nthash);
 218  218          return (err);
 219  219  }
 220  220  
 221  221  /*
 222  222   * Delete all keychain entries owned by the caller.
 223  223   */
 224  224  int
 225  225  smbfs_keychain_del_owner()
 226  226  {
 227  227          int cmd = SMBIOC_PK_DEL_OWNER;
 228  228          uid_t uid = getuid();
 229  229          return (smbfs_keychain_cmn(cmd, uid, NULL, NULL, NULL, NULL));
 230  230  }
 231  231  
 232  232  /*
 233  233   * Delete all keychain entries (regardless of onwer).
 234  234   * Requires super-user privliege.
 235  235   */
 236  236  int
 237  237  smbfs_keychain_del_everyone()
 238  238  {
 239  239          int cmd = SMBIOC_PK_DEL_EVERYONE;
 240  240          uid_t uid = getuid();
 241  241          return (smbfs_keychain_cmn(cmd, uid, NULL, NULL, NULL, NULL));
 242  242  }
 243  243  
 244  244  /*
 245  245   * Private function to get keychain p/w hashes.
 246  246   */
 247  247  int
 248  248  smb_get_keychain(struct smb_ctx *ctx)
 249  249  {
 250  250          int err;
 251  251  
 252  252          if (ctx->ct_fullserver == NULL) {
 253  253                  DPRINT("ct_fullserver == NULL");
 254  254                  return (EINVAL);
 255  255          }
 256  256  
 257  257          /*
 258  258           * 1st: try lookup using system name
 259  259           */
 260  260          err = smbfs_keychain_get(ctx->ct_fullserver, ctx->ct_user,
 261  261              ctx->ct_lmhash, ctx->ct_nthash);
 262  262          if (!err) {
 263  263                  ctx->ct_flags |= SMBCF_KCFOUND;
 264  264                  DPRINT("found keychain entry for"
 265  265                      " server/user: %s/%s\n",
 266  266                      ctx->ct_fullserver, ctx->ct_user);
 267  267                  return (0);
 268  268          }
 269  269  
 270  270          /*
 271  271           * 2nd: try lookup using domain name
 272  272           */
 273  273          err = smbfs_keychain_get(ctx->ct_domain, ctx->ct_user,
 274  274              ctx->ct_lmhash, ctx->ct_nthash);
 275  275          if (!err) {
 276  276                  ctx->ct_flags |= (SMBCF_KCFOUND | SMBCF_KCDOMAIN);
 277  277                  DPRINT("found keychain entry for"
 278  278                      " domain/user: %s/%s\n",
 279  279                      ctx->ct_domain, ctx->ct_user);
 280  280                  return (0);
 281  281          }
 282  282  
 283  283          return (err);
 284  284  }
 285  285  
 286  286  
 287  287  /*
 288  288   * This is not really part of the keychain library,
 289  289   * but is typically needed in code that wants to
 290  290   * provide (editable) defaults for domain/user
 291  291   *
 292  292   * Get default domain and user names
 293  293   * Server name is optional.
 294  294   */
 295  295  int
 296  296  smbfs_default_dom_usr(const char *home, const char *server,
 297  297          char *dom, int maxdom, char *usr, int maxusr)
 298  298  {
 299  299          struct smb_ctx  *ctx;
 300  300          int err;
 301  301  
 302  302          err = smb_ctx_alloc(&ctx);
 303  303          if (err)
 304  304                  return (err);
 305  305  
 306  306          if (server) {
 307  307                  err = smb_ctx_setfullserver(ctx, server);
 308  308                  if (err != 0)
 309  309                          goto out;
 310  310          }
 311  311  
 312  312          if (home && *home) {
 313  313                  if (ctx->ct_home)
 314  314                          free(ctx->ct_home);
 315  315                  ctx->ct_home = strdup(home);
 316  316          }
 317  317  
 318  318          err = smb_ctx_readrc(ctx);
 319  319          if (err)
 320  320                  goto out;
 321  321  
 322  322          if (dom)
 323  323                  strlcpy(dom, ctx->ct_domain, maxdom);
 324  324  
 325  325          if (usr)
 326  326                  strlcpy(usr, ctx->ct_user, maxusr);
 327  327  
 328  328  out:
 329  329          smb_ctx_free(ctx);
 330  330          return (err);
 331  331  }
  
    | 
      ↓ open down ↓ | 
    176 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX