Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16824 SMB client connection setup rework
NEX-17232 SMB client reconnect failures
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (improve debug)
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)
NEX-16805 Add smbutil discon command
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
re #12739 rb4173 AD join with lmauth_level=2 fails
re #12394 rb3934 Even NULL sessions should use SPNEGO

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libsmbfs/smb/ctx.c
          +++ new/usr/src/lib/libsmbfs/smb/ctx.c
↓ open down ↓ 26 lines elided ↑ open up ↑
  27   27   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28   28   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29   29   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30   30   * SUCH DAMAGE.
  31   31   *
  32   32   * $Id: ctx.c,v 1.32.70.2 2005/06/02 00:55:40 lindak Exp $
  33   33   */
  34   34  
  35   35  /*
  36   36   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  37      - * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       37 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  38   38   */
  39   39  
  40   40  #include <sys/param.h>
  41   41  #include <sys/ioctl.h>
  42   42  #include <sys/time.h>
  43   43  #include <sys/mount.h>
  44   44  #include <sys/types.h>
  45   45  #include <sys/byteorder.h>
  46   46  
  47   47  #include <fcntl.h>
↓ open down ↓ 93 lines elided ↑ open up ↑
 141  141          if (flags & SMBCF_KCBAD)
 142  142                  printf("KCBAD ");
 143  143          if (flags & SMBCF_KCFOUND)
 144  144                  printf("KCFOUND ");
 145  145          if (flags & SMBCF_BROWSEOK)
 146  146                  printf("BROWSEOK ");
 147  147          if (flags & SMBCF_AUTHREQ)
 148  148                  printf("AUTHREQ ");
 149  149          if (flags & SMBCF_KCSAVE)
 150  150                  printf("KCSAVE  ");
 151      -        if (flags & SMBCF_XXX)
 152      -                printf("XXX ");
 153      -        if (flags & SMBCF_SSNACTIVE)
 154      -                printf("SSNACTIVE ");
 155  151          if (flags & SMBCF_KCDOMAIN)
 156  152                  printf("KCDOMAIN ");
 157  153          printf("\n");
 158  154  }
 159  155  
 160  156  void
 161  157  dump_iod_ssn(smb_iod_ssn_t *is)
 162  158  {
 163  159          static const char zeros[NTLM_HASH_SZ] = {0};
 164  160          struct smbioc_ossn *ssn = &is->iod_ossn;
 165  161  
 166  162          printf(" ct_srvname=\"%s\", ", ssn->ssn_srvname);
 167  163          dump_sockaddr(&ssn->ssn_srvaddr.sa);
 168  164          printf(" dom=\"%s\", user=\"%s\"\n",
 169  165              ssn->ssn_domain, ssn->ssn_user);
 170  166          printf(" ct_vopt=0x%x, ct_owner=%d\n",
 171  167              ssn->ssn_vopt, ssn->ssn_owner);
      168 +        printf(" ct_minver=0x%x, ct_maxver=0x%x\n",
      169 +            ssn->ssn_minver, ssn->ssn_maxver);
 172  170          printf(" ct_authflags=0x%x\n", is->iod_authflags);
 173  171  
 174  172          printf(" ct_nthash:");
 175  173          if (bcmp(zeros, &is->iod_nthash, NTLM_HASH_SZ))
 176  174                  smb_hexdump(&is->iod_nthash, NTLM_HASH_SZ);
 177  175          else
 178  176                  printf(" {0}\n");
 179  177  
 180  178          printf(" ct_lmhash:");
 181  179          if (bcmp(zeros, &is->iod_lmhash, NTLM_HASH_SZ))
↓ open down ↓ 65 lines elided ↑ open up ↑
 247  245          int error;
 248  246  
 249  247          bzero(ctx, sizeof (*ctx));
 250  248  
 251  249          error = nb_ctx_create(&ctx->ct_nb);
 252  250          if (error)
 253  251                  return (error);
 254  252  
 255  253          ctx->ct_dev_fd = -1;
 256  254          ctx->ct_door_fd = -1;
 257      -        ctx->ct_tran_fd = -1;
 258  255          ctx->ct_parsedlevel = SMBL_NONE;
 259  256          ctx->ct_minlevel = SMBL_NONE;
 260  257          ctx->ct_maxlevel = SMBL_PATH;
 261  258  
 262  259          /* Fill in defaults */
 263      -        ctx->ct_vopt = SMBVOPT_EXT_SEC;
      260 +        ctx->ct_vopt = SMBVOPT_SIGNING_ENABLED;
 264  261          ctx->ct_owner = SMBM_ANY_OWNER;
 265  262          ctx->ct_authflags = SMB_AT_DEFAULT;
 266  263          ctx->ct_minauth = SMB_AT_MINAUTH;
      264 +        ctx->ct_maxver = SMB2_DIALECT_MAX;
 267  265  
 268  266          /*
 269  267           * Default domain, user, ...
 270  268           */
 271  269          strlcpy(ctx->ct_domain, default_domain,
 272  270              sizeof (ctx->ct_domain));
 273  271          strlcpy(ctx->ct_user, default_user,
 274  272              sizeof (ctx->ct_user));
 275  273  
 276  274          return (0);
↓ open down ↓ 49 lines elided ↑ open up ↑
 326  324          if (argv == NULL)
 327  325                  return (0);
 328  326  
 329  327          ctx->ct_minlevel = minlevel;
 330  328          ctx->ct_maxlevel = maxlevel;
 331  329          ctx->ct_shtype_req = sharetype;
 332  330  
 333  331          cf_opt_lock();
 334  332          /* Careful: no return/goto before cf_opt_unlock! */
 335  333          while (error == 0) {
 336      -                opt = cf_getopt(argc, argv, STDPARAM_OPT);
      334 +                /*
      335 +                 * Leading ':' tells this to skip unknown opts.
      336 +                 * Just get -A and -U here so we know the user
      337 +                 * for config file parsing.
      338 +                 */
      339 +                opt = cf_getopt(argc, argv, ":AU:");
 337  340                  if (opt == -1)
 338  341                          break;
 339  342                  arg = cf_optarg;
 340  343                  /* NB: handle most in smb_ctx_opt */
 341  344                  switch (opt) {
 342  345                  case 'A':
 343  346                          aflg = 1;
 344  347                          error = smb_ctx_setuser(ctx, "", TRUE);
 345  348                          ctx->ct_flags |= SMBCF_NOPWD;
 346  349                          break;
↓ open down ↓ 44 lines elided ↑ open up ↑
 391  394          free(ctx);
 392  395  }
 393  396  
 394  397  void
 395  398  smb_ctx_done(struct smb_ctx *ctx)
 396  399  {
 397  400  
 398  401          rpc_cleanup_smbctx(ctx);
 399  402  
 400  403          if (ctx->ct_dev_fd != -1) {
 401      -                close(ctx->ct_dev_fd);
      404 +                nsmb_close(ctx->ct_dev_fd);
 402  405                  ctx->ct_dev_fd = -1;
 403  406          }
 404  407          if (ctx->ct_door_fd != -1) {
 405  408                  close(ctx->ct_door_fd);
 406  409                  ctx->ct_door_fd = -1;
 407  410          }
 408      -        if (ctx->ct_tran_fd != -1) {
 409      -                close(ctx->ct_tran_fd);
 410      -                ctx->ct_tran_fd = -1;
 411      -        }
 412  411          if (ctx->ct_srvaddr_s) {
 413  412                  free(ctx->ct_srvaddr_s);
 414  413                  ctx->ct_srvaddr_s = NULL;
 415  414          }
 416  415          if (ctx->ct_nb) {
 417  416                  nb_ctx_done(ctx->ct_nb);
 418  417                  ctx->ct_nb = NULL;
 419  418          }
 420  419          if (ctx->ct_locname) {
 421  420                  free(ctx->ct_locname);
↓ open down ↓ 12 lines elided ↑ open up ↑
 434  433                  ctx->ct_addrinfo = NULL;
 435  434          }
 436  435          if (ctx->ct_home) {
 437  436                  free(ctx->ct_home);
 438  437                  ctx->ct_home = NULL;
 439  438          }
 440  439          if (ctx->ct_rpath) {
 441  440                  free(ctx->ct_rpath);
 442  441                  ctx->ct_rpath = NULL;
 443  442          }
 444      -        if (ctx->ct_srv_OS) {
 445      -                free(ctx->ct_srv_OS);
 446      -                ctx->ct_srv_OS = NULL;
      443 +        if (ctx->ct_ssnkey_buf) {
      444 +                free(ctx->ct_ssnkey_buf);
      445 +                ctx->ct_ssnkey_buf = NULL;
 447  446          }
 448      -        if (ctx->ct_srv_LM) {
 449      -                free(ctx->ct_srv_LM);
 450      -                ctx->ct_srv_LM = NULL;
 451      -        }
 452      -        if (ctx->ct_mackey) {
 453      -                free(ctx->ct_mackey);
 454      -                ctx->ct_mackey = NULL;
 455      -        }
 456  447  }
 457  448  
 458  449  /*
 459  450   * Parse the UNC path.  Here we expect something like
 460  451   *   "//[[domain;]user[:password]@]host[/share[/path]]"
 461  452   * See http://ietf.org/internet-drafts/draft-crhertel-smb-url-07.txt
 462  453   * Values found here are marked as "from CMD".
 463  454   */
 464  455  int
 465  456  smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc,
↓ open down ↓ 395 lines elided ↑ open up ↑
 861  852  {
 862  853          ctx->ct_vopt &= ~SMBVOPT_SIGNING_MASK;
 863  854          if (enable) {
 864  855                  ctx->ct_vopt |= SMBVOPT_SIGNING_ENABLED;
 865  856                  if (require)
 866  857                          ctx->ct_vopt |= SMBVOPT_SIGNING_REQUIRED;
 867  858          }
 868  859          return (0);
 869  860  }
 870  861  
      862 +/*
      863 + * Handle .nsmbrc "minver" option.
      864 + * Must be <= maxver
      865 + */
      866 +int
      867 +smb_ctx_setminver(struct smb_ctx *ctx, int ver)
      868 +{
      869 +        if (ver < 0 || ver > ctx->ct_maxver)
      870 +                return (EINVAL);
      871 +        ctx->ct_minver = (uint16_t)ver;
      872 +        return (0);
      873 +}
      874 +
      875 +/*
      876 + * Handle .nsmbrc "maxver" option.
      877 + * Must be >= minver
      878 + *
      879 + * Any "too high" value is just clamped, so the caller
      880 + * doesn't need to know what's the highest we support.
      881 + */
      882 +int
      883 +smb_ctx_setmaxver(struct smb_ctx *ctx, int ver)
      884 +{
      885 +        if (ver < 1 || ver < ctx->ct_minver)
      886 +                return (EINVAL);
      887 +        if (ver > SMB2_DIALECT_MAX)
      888 +                ver = SMB2_DIALECT_MAX;
      889 +        ctx->ct_maxver = (uint16_t)ver;
      890 +        return (0);
      891 +}
      892 +
 871  893  static int
 872  894  smb_parse_owner(char *pair, uid_t *uid, gid_t *gid)
 873  895  {
 874  896          struct group gr;
 875  897          struct passwd pw;
 876  898          char buf[NSS_BUFLEN_PASSWD];
 877  899          char *cp;
 878  900  
 879  901          cp = strchr(pair, ':');
 880  902          if (cp) {
↓ open down ↓ 11 lines elided ↑ open up ↑
 892  914                          *uid = pw.pw_uid;
 893  915                  } else
 894  916                          smb_error(dgettext(TEXT_DOMAIN,
 895  917                              "Invalid user name %s, ignored"), 0, pair);
 896  918          }
 897  919  
 898  920          return (0);
 899  921  }
 900  922  
 901  923  /*
 902      - * Suport a securty options arg, i.e. -S noext,lm,ntlm
      924 + * Suport a securty options arg, i.e. -S lm,ntlm
 903  925   * for testing various type of authenticators.
 904  926   */
 905  927  static struct nv
 906  928  sectype_table[] = {
 907      -        /* noext - handled below */
 908  929          { "anon",       SMB_AT_ANON },
 909  930          { "lm",         SMB_AT_LM1 },
 910  931          { "ntlm",       SMB_AT_NTLM1 },
 911  932          { "ntlm2",      SMB_AT_NTLM2 },
 912  933          { "krb5",       SMB_AT_KRB5 },
 913  934          { NULL,         0 },
 914  935  };
 915  936  int
 916  937  smb_parse_secopts(struct smb_ctx *ctx, const char *arg)
 917  938  {
↓ open down ↓ 5 lines elided ↑ open up ↑
 923  944  
 924  945          for (;;) {
 925  946                  /* skip separators */
 926  947                  tlen = strspn(p, sep);
 927  948                  p += tlen;
 928  949  
 929  950                  nlen = strcspn(p, sep);
 930  951                  if (nlen == 0)
 931  952                          break;
 932  953  
 933      -                if (nlen == 5 && 0 == strncmp(p, "noext", nlen)) {
 934      -                        /* Don't offer extended security. */
 935      -                        ctx->ct_vopt &= ~SMBVOPT_EXT_SEC;
 936      -                        p += nlen;
 937      -                        continue;
 938      -                }
 939      -
 940  954                  /* This is rarely called, so not optimized. */
 941  955                  for (nv = sectype_table; nv->name; nv++) {
 942  956                          tlen = strlen(nv->name);
 943  957                          if (tlen == nlen && 0 == strncmp(p, nv->name, tlen))
 944  958                                  break;
 945  959                  }
 946  960                  if (nv->name == NULL) {
 947  961                          smb_error(dgettext(TEXT_DOMAIN,
 948  962                              "%s: invalid security options"), 0, p);
 949  963                          return (EINVAL);
↓ open down ↓ 160 lines elided ↑ open up ↑
1110 1124          if (error) {
1111 1125                  const char *ais = gai_strerror(error);
1112 1126                  smb_error(dgettext(TEXT_DOMAIN,
1113 1127                      "can't resolve name\"%s\", %s"),
1114 1128                      0, ctx->ct_fullserver, ais);
1115 1129                  return (ENODATA);
1116 1130          }
1117 1131          assert(ctx->ct_addrinfo != NULL);
1118 1132  
1119 1133          /*
     1134 +         * Empty user name means an explicit request for
     1135 +         * NULL session setup, which is a special case.
     1136 +         * (No SMB signing, per [MS-SMB] 3.3.5.3)
     1137 +         */
     1138 +        if (ctx->ct_user[0] == '\0') {
     1139 +                /* Null user should have null domain too. */
     1140 +                ctx->ct_domain[0] = '\0';
     1141 +                ctx->ct_authflags = SMB_AT_ANON;
     1142 +                ctx->ct_vopt |= SMBVOPT_ANONYMOUS;
     1143 +                ctx->ct_vopt &= ~SMBVOPT_SIGNING_REQUIRED;
     1144 +        }
     1145 +
     1146 +        /*
1120 1147           * If we have a user name but no password,
1121 1148           * check for a keychain entry.
1122 1149           * XXX: Only for auth NTLM?
1123 1150           */
1124 1151          if (ctx->ct_user[0] != '\0') {
1125 1152                  /*
1126 1153                   * Have a user name.
1127 1154                   * If we don't have a p/w yet,
1128 1155                   * try the keychain.
1129 1156                   */
1130      -                if (ctx->ct_password[0] == '\0')
1131      -                        (void) smb_get_keychain(ctx);
     1157 +                if (ctx->ct_password[0] == '\0' &&
     1158 +                    smb_get_keychain(ctx) == 0) {
     1159 +                        strlcpy(ctx->ct_password, "$HASH",
     1160 +                            sizeof (ctx->ct_password));
     1161 +                }
     1162 +
1132 1163                  /*
1133 1164                   * Mask out disallowed auth types.
1134 1165                   */
1135 1166                  ctx->ct_authflags &= ctx->ct_minauth;
1136 1167          }
     1168 +
1137 1169          if (ctx->ct_authflags == 0) {
1138 1170                  smb_error(dgettext(TEXT_DOMAIN,
1139 1171                      "no valid auth. types"), 0);
1140 1172                  return (ENOTSUP);
1141 1173          }
1142 1174  
1143 1175          ctx->ct_flags |= SMBCF_RESOLVED;
1144 1176          if (smb_debug)
1145 1177                  dump_ctx("after smb_ctx_resolve", ctx);
1146 1178  
1147 1179          return (0);
1148 1180  }
1149 1181  
     1182 +/*
     1183 + * Note: The next three have NODIRECT binding so the
     1184 + * "fksmbcl" development tool can provide its own.
     1185 + */
1150 1186  int
1151 1187  smb_open_driver()
1152 1188  {
1153 1189          int fd;
1154 1190  
1155 1191          fd = open("/dev/"NSMB_NAME, O_RDWR);
1156 1192          if (fd < 0) {
1157 1193                  return (-1);
1158 1194          }
1159 1195  
1160 1196          /* This handle controls per-process resources. */
1161 1197          (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
1162 1198  
1163 1199          return (fd);
1164 1200  }
1165 1201  
1166 1202  int
     1203 +nsmb_close(int fd)
     1204 +{
     1205 +        return (close(fd));
     1206 +}
     1207 +
     1208 +int
     1209 +nsmb_ioctl(int fd, int cmd, void *arg)
     1210 +{
     1211 +        return (ioctl(fd, cmd, arg));
     1212 +}
     1213 +
     1214 +
     1215 +int
1167 1216  smb_ctx_gethandle(struct smb_ctx *ctx)
1168 1217  {
1169 1218          int fd, err;
1170 1219          uint32_t version;
1171 1220  
1172 1221          if (ctx->ct_dev_fd != -1) {
1173 1222                  rpc_cleanup_smbctx(ctx);
1174      -                close(ctx->ct_dev_fd);
     1223 +                nsmb_close(ctx->ct_dev_fd);
1175 1224                  ctx->ct_dev_fd = -1;
1176      -                ctx->ct_flags &= ~SMBCF_SSNACTIVE;
1177 1225          }
1178 1226  
1179 1227          fd = smb_open_driver();
1180 1228          if (fd < 0) {
1181 1229                  err = errno;
1182 1230                  smb_error(dgettext(TEXT_DOMAIN,
1183 1231                      "failed to open driver"), err);
1184 1232                  return (err);
1185 1233          }
1186 1234  
1187 1235          /*
1188 1236           * Check the driver version (paranoia)
1189 1237           */
1190      -        if (ioctl(fd, SMBIOC_GETVERS, &version) < 0)
     1238 +        if (nsmb_ioctl(fd, SMBIOC_GETVERS, &version) < 0)
1191 1239                  version = 0;
1192 1240          if (version != NSMB_VERSION) {
1193 1241                  smb_error(dgettext(TEXT_DOMAIN,
1194 1242                      "incorrect driver version"), 0);
1195      -                close(fd);
     1243 +                nsmb_close(fd);
1196 1244                  return (ENODEV);
1197 1245          }
1198 1246  
1199 1247          ctx->ct_dev_fd = fd;
1200 1248          return (0);
1201 1249  }
1202 1250  
1203 1251  
1204 1252  /*
1205 1253   * Find or create a connection + logon session
1206 1254   */
1207 1255  int
1208 1256  smb_ctx_get_ssn(struct smb_ctx *ctx)
1209 1257  {
1210 1258          int err = 0;
1211 1259  
1212 1260          if ((ctx->ct_flags & SMBCF_RESOLVED) == 0)
1213 1261                  return (EINVAL);
1214 1262  
1215      -        if (ctx->ct_dev_fd < 0) {
1216      -                if ((err = smb_ctx_gethandle(ctx)))
1217      -                        return (err);
1218      -        }
1219      -
1220 1263          /*
1221 1264           * Check whether the driver already has a VC
1222 1265           * we can use.  If so, we're done!
1223 1266           */
1224 1267          err = smb_ctx_findvc(ctx);
1225 1268          if (err == 0) {
1226 1269                  DPRINT("found an existing VC");
1227 1270          } else {
1228 1271                  /*
     1272 +                 * If we're authenticating (real user, not NULL session)
     1273 +                 * and we don't yet have a password, return EAUTH and
     1274 +                 * the caller will prompt for it and call again.
     1275 +                 */
     1276 +                if (ctx->ct_user[0] != '\0' &&
     1277 +                    ctx->ct_password[0] == '\0')
     1278 +                        return (EAUTH);
     1279 +
     1280 +                /*
1229 1281                   * This calls the IOD to create a new session.
1230 1282                   */
1231 1283                  DPRINT("setup a new VC");
1232 1284                  err = smb_ctx_newvc(ctx);
1233 1285                  if (err != 0)
1234 1286                          return (err);
1235 1287  
1236 1288                  /*
1237 1289                   * Call findvc again.  The new VC sould be
1238 1290                   * found in the driver this time.
↓ open down ↓ 31 lines elided ↑ open up ↑
1270 1322              sizeof (tcon->tc_sh.sh_name));
1271 1323  
1272 1324          /* The share "use" type. */
1273 1325          tcon->tc_sh.sh_use = ctx->ct_shtype_req;
1274 1326  
1275 1327          /*
1276 1328           * Todo: share passwords for share-level security.
1277 1329           *
1278 1330           * The driver does the actual TCON call.
1279 1331           */
1280      -        if (ioctl(ctx->ct_dev_fd, cmd, tcon) == -1) {
     1332 +        if (nsmb_ioctl(ctx->ct_dev_fd, cmd, tcon) == -1) {
1281 1333                  err = errno;
1282 1334                  goto out;
1283 1335          }
1284 1336  
1285 1337          /*
1286 1338           * Check the returned share type
1287 1339           */
1288 1340          DPRINT("ret. sh_type: \"%d\"", tcon->tc_sh.sh_type);
1289 1341          if (ctx->ct_shtype_req != USE_WILDCARD &&
1290 1342              ctx->ct_shtype_req != tcon->tc_sh.sh_type) {
↓ open down ↓ 10 lines elided ↑ open up ↑
1301 1353  }
1302 1354  
1303 1355  /*
1304 1356   * Return the hflags2 word for an smb_ctx.
1305 1357   */
1306 1358  int
1307 1359  smb_ctx_flags2(struct smb_ctx *ctx)
1308 1360  {
1309 1361          uint16_t flags2;
1310 1362  
1311      -        if (ioctl(ctx->ct_dev_fd, SMBIOC_FLAGS2, &flags2) == -1) {
     1363 +        if (nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_FLAGS2, &flags2) == -1) {
1312 1364                  smb_error(dgettext(TEXT_DOMAIN,
1313 1365                      "can't get flags2 for a session"), errno);
1314 1366                  return (-1);
1315 1367          }
1316 1368          return (flags2);
1317 1369  }
1318 1370  
1319 1371  /*
1320 1372   * Get the transport level session key.
1321 1373   * Must already have an active SMB session.
1322 1374   */
1323 1375  int
1324 1376  smb_fh_getssnkey(int dev_fd, uchar_t *key, size_t len)
1325 1377  {
1326 1378          if (len < SMBIOC_HASH_SZ)
1327 1379                  return (EINVAL);
1328 1380  
1329      -        if (ioctl(dev_fd, SMBIOC_GETSSNKEY, key) == -1)
     1381 +        if (nsmb_ioctl(dev_fd, SMBIOC_GETSSNKEY, key) == -1)
1330 1382                  return (errno);
1331 1383  
1332 1384          return (0);
1333 1385  }
1334 1386  
1335 1387  /*
1336 1388   * RC file parsing stuff
1337 1389   */
1338 1390  
1339 1391  static struct nv
↓ open down ↓ 1 lines elided ↑ open up ↑
1341 1393          /* Allowed auth. types */
1342 1394          { "kerberos",   SMB_AT_KRB5 },
1343 1395          { "ntlmv2",     SMB_AT_KRB5|SMB_AT_NTLM2 },
1344 1396          { "ntlm",       SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1 },
1345 1397          { "lm",         SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1|SMB_AT_LM1 },
1346 1398          { "none",       SMB_AT_KRB5|SMB_AT_NTLM2|SMB_AT_NTLM1|SMB_AT_LM1|
1347 1399                          SMB_AT_ANON },
1348 1400          { NULL }
1349 1401  };
1350 1402  
     1403 +int
     1404 +smb_cf_minauth_from_str(char *str)
     1405 +{
     1406 +        struct nv *nvp;
1351 1407  
     1408 +        for (nvp = minauth_table; nvp->name; nvp++)
     1409 +                if (strcmp(nvp->name, str) == 0)
     1410 +                        return (nvp->value);
     1411 +        return (-1);
     1412 +}
     1413 +
     1414 +
     1415 +static struct nv
     1416 +smbver_table[] = {
     1417 +        { "2.1",        SMB2_DIALECT_0210 },
     1418 +        { "1",          1 },
     1419 +        { NULL,         0 }
     1420 +};
     1421 +
     1422 +int
     1423 +smb_cf_version_from_str(char *str)
     1424 +{
     1425 +        struct nv *nvp;
     1426 +
     1427 +        for (nvp = smbver_table; nvp->name; nvp++)
     1428 +                if (strcmp(nvp->name, str) == 0)
     1429 +                        return (nvp->value);
     1430 +        return (-1);
     1431 +}
     1432 +
1352 1433  /*
1353 1434   * level values:
1354 1435   * 0 - default
1355 1436   * 1 - server
1356 1437   * 2 - server:user
1357 1438   * 3 - server:user:share
1358 1439   */
1359 1440  static int
1360 1441  smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
1361 1442  {
1362 1443          char *p;
     1444 +        int ival;
1363 1445          int error;
     1446 +        int minver, maxver;
1364 1447  
1365 1448  #ifdef  KICONV_SUPPORT
1366 1449          if (level > 0) {
1367 1450                  rc_getstringptr(smb_rc, sname, "charsets", &p);
1368 1451                  if (p) {
1369 1452                          error = smb_ctx_setcharset(ctx, p);
1370 1453                          if (error)
1371 1454                                  smb_error(dgettext(TEXT_DOMAIN,
1372 1455          "charset specification in the section '%s' ignored"),
1373 1456                                      error, sname);
1374 1457                  }
1375 1458          }
1376 1459  #endif
1377 1460  
1378 1461          if (level <= 1) {
1379 1462                  /* Section is: [default] or [server] */
1380 1463  
     1464 +                /*
     1465 +                 * Handle min_protocol, max_protocol
     1466 +                 * (SMB protocol versions)
     1467 +                 */
     1468 +                minver = -1;
     1469 +                rc_getstringptr(smb_rc, sname, "min_protocol", &p);
     1470 +                if (p != NULL) {
     1471 +                        minver = smb_cf_version_from_str(p);
     1472 +                        if (minver == -1) {
     1473 +                                smb_error(dgettext(TEXT_DOMAIN,
     1474 +"invalid min_protocol value \"%s\" specified in the section %s"),
     1475 +                                    0, p, sname);
     1476 +                        }
     1477 +                }
     1478 +                maxver = -1;
     1479 +                rc_getstringptr(smb_rc, sname, "max_protocol", &p);
     1480 +                if (p != NULL) {
     1481 +                        maxver = smb_cf_version_from_str(p);
     1482 +                        if (maxver == -1) {
     1483 +                                smb_error(dgettext(TEXT_DOMAIN,
     1484 +"invalid max_protocol value \"%s\" specified in the section %s"),
     1485 +                                    0, p, sname);
     1486 +                        }
     1487 +                }
     1488 +
     1489 +                /*
     1490 +                 * If setting both min/max protocol,
     1491 +                 * validate against each other
     1492 +                 */
     1493 +                if (minver != -1 && maxver != -1) {
     1494 +                        if (minver > maxver) {
     1495 +                                smb_error(dgettext(TEXT_DOMAIN,
     1496 +"invalid min/max protocol combination in the section %s"),
     1497 +                                    0, sname);
     1498 +                        } else {
     1499 +                                ctx->ct_minver = minver;
     1500 +                                ctx->ct_maxver = maxver;
     1501 +                        }
     1502 +                }
     1503 +
     1504 +                /*
     1505 +                 * Setting just min or max, validate against
     1506 +                 * current settings
     1507 +                 */
     1508 +                if (minver != -1) {
     1509 +                        if (minver > ctx->ct_maxver) {
     1510 +                                smb_error(dgettext(TEXT_DOMAIN,
     1511 +"invalid min/max protocol combination in the section %s"),
     1512 +                                    0, sname);
     1513 +                        } else {
     1514 +                                ctx->ct_minver = minver;
     1515 +                        }
     1516 +                }
     1517 +                if (maxver != -1) {
     1518 +                        if (maxver < ctx->ct_minver) {
     1519 +                                smb_error(dgettext(TEXT_DOMAIN,
     1520 +"invalid min/max protocol combination in the section %s"),
     1521 +                                    0, sname);
     1522 +                        } else {
     1523 +                                ctx->ct_maxver = maxver;
     1524 +                        }
     1525 +                }
     1526 +
1381 1527                  rc_getstringptr(smb_rc, sname, "minauth", &p);
1382 1528                  if (p) {
1383 1529                          /*
1384 1530                           * "minauth" was set in this section; override
1385 1531                           * the current minimum authentication setting.
1386 1532                           */
1387      -                        struct nv *nvp;
1388      -                        for (nvp = minauth_table; nvp->name; nvp++)
1389      -                                if (strcmp(p, nvp->name) == 0)
1390      -                                        break;
1391      -                        if (nvp->name)
1392      -                                ctx->ct_minauth = nvp->value;
1393      -                        else {
     1533 +                        ival = smb_cf_minauth_from_str(p);
     1534 +                        if (ival != -1) {
     1535 +                                ctx->ct_minauth = ival;
     1536 +                        } else {
1394 1537                                  /*
1395 1538                                   * Unknown minimum authentication level.
1396 1539                                   */
1397 1540                                  smb_error(dgettext(TEXT_DOMAIN,
1398 1541  "invalid minimum authentication level \"%s\" specified in the section %s"),
1399 1542                                      0, p, sname);
1400 1543                                  return (EINVAL);
1401 1544                          }
1402 1545                  }
1403 1546  
↓ open down ↓ 198 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX