Print this page
NEX-16502 libshare needs to support SMB in a zone
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-9497 SMB should bypass ACL traverse checking
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-10019 SMB server min_protocol setting
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-4598 SMB2 credit shortage with Mac client
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3863 Would like an SMB share property to enable/disable quotas
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3629 CLONE NEX-3624 SMB server max_workers cannot be increased above 1024
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
4295 libshare sa_get_proto_status sometimes returns unallocated strings
Reviewed by: Marcel Telka <marcel@telka.sk>
Approved by: Garrett D'Amore <garrett@damore.org>
NEX-1050 enable_smb2 should be smb2_enable
NEX-1022 SMB2 should be enabled by default
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
re #13470 rb4432 Sync some SMB differences from illumos
re #7930 rb3848 failover error: cannot share pool/folder - smb add share failed

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libshare/smb/libshare_smb.c
          +++ new/usr/src/lib/libshare/smb/libshare_smb.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  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   23   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
       24 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  25   25   */
  26   26  
  27   27  /*
  28   28   * SMB specific functions
  29   29   */
  30   30  #include <stdio.h>
  31   31  #include <string.h>
  32   32  #include <ctype.h>
  33   33  #include <stdlib.h>
  34   34  #include <unistd.h>
↓ open down ↓ 42 lines elided ↑ open up ↑
  77   77  static int range_check_validator(int, char *);
  78   78  static int range_check_validator_zero_ok(int, char *);
  79   79  static int string_length_check_validator(int, char *);
  80   80  static int print_enable_validator(int, char *);
  81   81  static int true_false_validator(int, char *);
  82   82  static int ipv4_validator(int, char *);
  83   83  static int hostname_validator(int, char *);
  84   84  static int path_validator(int, char *);
  85   85  static int cmd_validator(int, char *);
  86   86  static int disposition_validator(int, char *);
  87      -static int max_protocol_validator(int, char *);
       87 +static int protocol_validator(int, char *);
       88 +static int require_validator(int, char *);
  88   89  
  89   90  static int smb_enable_resource(sa_resource_t);
  90   91  static int smb_disable_resource(sa_resource_t);
  91   92  static uint64_t smb_share_features(void);
  92   93  static int smb_list_transient(sa_handle_t);
  93   94  
  94   95  static int smb_build_shareinfo(sa_share_t, sa_resource_t, smb_share_t *);
  95   96  static void smb_csc_option(const char *, smb_share_t *);
  96   97  static char *smb_csc_name(const smb_share_t *);
  97   98  static sa_group_t smb_get_defaultgrp(sa_handle_t);
  98   99  static int interface_validator(int, char *);
  99  100  static int smb_update_optionset_props(sa_handle_t, sa_resource_t, nvlist_t *);
 100  101  
 101      -static boolean_t smb_saprop_getbool(sa_optionset_t, char *);
      102 +static boolean_t smb_saprop_getbool(sa_optionset_t, char *, boolean_t);
 102  103  static boolean_t smb_saprop_getstr(sa_optionset_t, char *, char *, size_t);
 103  104  
 104  105  static struct {
 105  106          char *value;
 106  107          uint32_t flag;
 107  108  } cscopt[] = {
 108  109          { "disabled",   SMB_SHRF_CSC_DISABLED },
 109  110          { "manual",     SMB_SHRF_CSC_MANUAL },
 110  111          { "auto",       SMB_SHRF_CSC_AUTO },
 111  112          { "vdo",        SMB_SHRF_CSC_VDO }
↓ open down ↓ 59 lines elided ↑ open up ↑
 171  172          { SHOPT_ABE,            OPT_TYPE_BOOLEAN },
 172  173          { SHOPT_NAME,           OPT_TYPE_NAME },
 173  174          { SHOPT_RO,             OPT_TYPE_ACCLIST },
 174  175          { SHOPT_RW,             OPT_TYPE_ACCLIST },
 175  176          { SHOPT_NONE,           OPT_TYPE_ACCLIST },
 176  177          { SHOPT_CATIA,          OPT_TYPE_BOOLEAN },
 177  178          { SHOPT_CSC,            OPT_TYPE_CSC },
 178  179          { SHOPT_GUEST,          OPT_TYPE_BOOLEAN },
 179  180          { SHOPT_DFSROOT,        OPT_TYPE_BOOLEAN },
 180  181          { SHOPT_DESCRIPTION,    OPT_TYPE_STRING },
      182 +        { SHOPT_CA,             OPT_TYPE_BOOLEAN },
      183 +        { SHOPT_FSO,            OPT_TYPE_BOOLEAN },
      184 +        { SHOPT_QUOTAS,         OPT_TYPE_BOOLEAN },
      185 +        { SHOPT_ENCRYPT,        OPT_TYPE_STRING },
 181  186          { NULL, NULL }
 182  187  };
 183  188  
 184  189  /*
 185  190   * findopt(name)
 186  191   *
 187  192   * Lookup option "name" in the option table and return the table
 188  193   * index.
 189  194   */
 190  195  static int
↓ open down ↓ 188 lines elided ↑ open up ↑
 379  384   * calls. It is assumed that all error checking of paths, etc. were
 380  385   * done earlier.
 381  386   */
 382  387  static int
 383  388  smb_enable_share(sa_share_t share)
 384  389  {
 385  390          char *path;
 386  391          smb_share_t si;
 387  392          sa_resource_t resource;
 388  393          boolean_t iszfs;
 389      -        boolean_t privileged;
 390  394          int err = SA_OK;
 391      -        priv_set_t *priv_effective;
 392  395          boolean_t online;
 393  396  
 394  397          /*
 395  398           * Don't support Trusted Extensions.
 396  399           */
 397  400          if (is_system_labeled()) {
 398  401                  (void) printf(dgettext(TEXT_DOMAIN,
 399  402                      "SMB: service not supported with Trusted Extensions\n"));
 400  403                  return (SA_NOT_SUPPORTED);
 401  404          }
 402  405  
 403      -        priv_effective = priv_allocset();
 404      -        (void) getppriv(PRIV_EFFECTIVE, priv_effective);
 405      -        privileged = (priv_isfullset(priv_effective) == B_TRUE);
 406      -        priv_freeset(priv_effective);
 407      -
 408  406          /* get the path since it is important in several places */
 409  407          path = sa_get_share_attr(share, "path");
 410  408          if (path == NULL)
 411  409                  return (SA_NO_SUCH_PATH);
 412  410  
 413  411          /*
 414  412           * If administratively disabled, don't try to start anything.
 415  413           */
 416  414          online = smb_isonline();
 417  415          if (!online && !smb_isautoenable() && smb_isdisabled())
 418  416                  goto done;
 419  417  
 420  418          iszfs = sa_path_is_zfs(path);
 421  419  
 422      -        if (iszfs) {
 423      -
 424      -                if (privileged == B_FALSE && !online) {
 425      -
 426      -                        if (!online) {
 427      -                                (void) printf(dgettext(TEXT_DOMAIN,
 428      -                                    "SMB: Cannot share remove "
 429      -                                    "file system: %s\n"), path);
 430      -                                (void) printf(dgettext(TEXT_DOMAIN,
 431      -                                    "SMB: Service needs to be enabled "
 432      -                                    "by a privileged user\n"));
 433      -                                err = SA_NO_PERMISSION;
 434      -                                errno = EPERM;
 435      -                        }
 436      -                        if (err) {
 437      -                                sa_free_attr_string(path);
 438      -                                return (err);
 439      -                        }
 440      -
 441      -                }
 442      -        }
 443      -
 444      -        if (privileged == B_TRUE && !online) {
      420 +        if (!online) {
 445  421                  err = smb_enable_service();
 446  422                  if (err != SA_OK) {
 447  423                          (void) printf(dgettext(TEXT_DOMAIN,
 448  424                              "SMB: Unable to enable service\n"));
 449  425                  } else {
 450  426                          online = B_TRUE;
 451  427                  }
 452  428          }
 453  429  
 454  430          /*
↓ open down ↓ 452 lines elided ↑ open up ↑
 907  883              SMB_REFRESH_REFRESH },
 908  884          { SMB_CI_PRINT_ENABLE, 0, 0, print_enable_validator,
 909  885              SMB_REFRESH_REFRESH },
 910  886          { SMB_CI_TRAVERSE_MOUNTS, 0, 0, true_false_validator,
 911  887              SMB_REFRESH_REFRESH },
 912  888          { SMB_CI_MAP, 0, MAX_VALUE_BUFLEN, cmd_validator, SMB_REFRESH_REFRESH },
 913  889          { SMB_CI_UNMAP, 0, MAX_VALUE_BUFLEN, cmd_validator,
 914  890              SMB_REFRESH_REFRESH },
 915  891          { SMB_CI_DISPOSITION, 0, MAX_VALUE_BUFLEN,
 916  892              disposition_validator, SMB_REFRESH_REFRESH },
 917      -        { SMB_CI_MAX_PROTOCOL, 0, MAX_VALUE_BUFLEN, max_protocol_validator,
      893 +        { SMB_CI_MAX_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator,
 918  894              SMB_REFRESH_REFRESH },
      895 +        { SMB_CI_ENCRYPT, 0, MAX_VALUE_BUFLEN, require_validator,
      896 +            SMB_REFRESH_REFRESH },
      897 +        { SMB_CI_MIN_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator,
      898 +            SMB_REFRESH_REFRESH },
      899 +        { SMB_CI_BYPASS_TRAVERSE_CHECKING, 0, 0, true_false_validator,
      900 +            SMB_REFRESH_REFRESH },
      901 +        { SMB_CI_OPLOCK_ENABLE, 0, 0, true_false_validator,
      902 +            SMB_REFRESH_REFRESH },
 919  903  };
 920  904  
 921  905  #define SMB_OPT_NUM \
 922  906          (sizeof (smb_proto_options) / sizeof (smb_proto_options[0]))
 923  907  
      908 +static int
      909 +require_validator(int index, char *value)
      910 +{
      911 +        if (string_length_check_validator(index, value) != SA_OK)
      912 +                return (SA_BAD_VALUE);
      913 +
      914 +        if (strcmp(value, "required") == 0)
      915 +                return (SA_OK);
      916 +
      917 +        if (strcmp(value, "disabled") == 0)
      918 +                return (SA_OK);
      919 +
      920 +        if (strcmp(value, "enabled") == 0)
      921 +                return (SA_OK);
      922 +
      923 +        return (SA_BAD_VALUE);
      924 +}
      925 +
 924  926  /*
 925  927   * Check the range of value as int range.
 926  928   */
 927  929  static int
 928  930  range_check_validator(int index, char *value)
 929  931  {
 930  932          int ret = SA_OK;
 931  933  
 932  934          if (!is_a_number(value)) {
 933  935                  ret = SA_BAD_VALUE;
↓ open down ↓ 593 lines elided ↑ open up ↑
1527 1529          value = sa_get_property_attr(prop, "value");
1528 1530          if (name != NULL && value != NULL) {
1529 1531                  index = findprotoopt(name);
1530 1532                  if (index >= 0) {
1531 1533                          /* should test for valid value */
1532 1534                          ret = smb_validate_proto_prop(index, name, value);
1533 1535                          if (ret == SA_OK) {
1534 1536                                  opt = &smb_proto_options[index];
1535 1537  
1536 1538                                  /* Save to SMF */
1537      -                                (void) smb_config_set(opt->smb_index, value);
     1539 +                                if (smb_config_set(opt->smb_index,
     1540 +                                    value) != 0) {
     1541 +                                        ret = SA_BAD_VALUE;
     1542 +                                        goto out;
     1543 +                                }
1538 1544                                  /*
1539 1545                                   * Specialized refresh mechanisms can
1540 1546                                   * be flagged in the proto_options and
1541 1547                                   * processed here.
1542 1548                                   */
1543 1549                                  if (opt->refresh & SMB_REFRESH_REFRESH)
1544 1550                                          (void) smf_refresh_instance(
1545 1551                                              SMBD_DEFAULT_INSTANCE_FMRI);
1546 1552                                  else if (opt->refresh & SMB_REFRESH_RESTART)
1547 1553                                          (void) smf_restart_instance(
1548 1554                                              SMBD_DEFAULT_INSTANCE_FMRI);
1549 1555                          }
1550 1556                  }
1551 1557          }
1552 1558  
     1559 +out:
1553 1560          if (name != NULL)
1554 1561                  sa_free_attr_string(name);
1555 1562          if (value != NULL)
1556 1563                  sa_free_attr_string(value);
1557 1564  
1558 1565          return (ret);
1559 1566  }
1560 1567  
1561 1568  /*
1562 1569   * smb_get_status()
↓ open down ↓ 367 lines elided ↑ open up ↑
1930 1937   *
1931 1938   * provides a mechanism to format SMB properties into legacy output
1932 1939   * format. If the buffer would overflow, it is reallocated and grown
1933 1940   * as appropriate. Special cases of converting internal form of values
1934 1941   * to those used by "share" are done. this function does one property
1935 1942   * at a time.
1936 1943   */
1937 1944  
1938 1945  static void
1939 1946  smb_sprint_option(char **rbuff, size_t *rbuffsize, size_t incr,
1940      -                        sa_property_t prop, int sep)
     1947 +    sa_property_t prop, int sep)
1941 1948  {
1942 1949          char *name;
1943 1950          char *value;
1944 1951          int curlen;
1945 1952          char *buff = *rbuff;
1946 1953          size_t buffsize = *rbuffsize;
1947 1954  
1948 1955          name = sa_get_property_attr(prop, "type");
1949 1956          value = sa_get_property_attr(prop, "value");
1950 1957          if (buff != NULL)
↓ open down ↓ 157 lines elided ↑ open up ↑
2108 2115  }
2109 2116  
2110 2117  static int
2111 2118  smb_build_shareinfo(sa_share_t share, sa_resource_t resource, smb_share_t *si)
2112 2119  {
2113 2120          sa_optionset_t opts;
2114 2121          char *path;
2115 2122          char *rname;
2116 2123          char *val = NULL;
2117 2124          char csc_value[SMB_CSC_BUFSZ];
     2125 +        char strbuf[sizeof ("required")];
2118 2126  
2119 2127          bzero(si, sizeof (smb_share_t));
2120 2128  
2121 2129          if ((path = sa_get_share_attr(share, "path")) == NULL)
2122 2130                  return (SA_NO_SUCH_PATH);
2123 2131  
2124 2132          if ((rname = sa_get_resource_attr(resource, "name")) == NULL) {
2125 2133                  sa_free_attr_string(path);
2126 2134                  return (SA_NO_SUCH_RESOURCE);
2127 2135          }
↓ open down ↓ 12 lines elided ↑ open up ↑
2140 2148                  sa_free_share_description(val);
2141 2149          }
2142 2150  
2143 2151          si->shr_flags = (sa_is_persistent(share))
2144 2152              ? SMB_SHRF_PERM : SMB_SHRF_TRANS;
2145 2153  
2146 2154          opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
2147 2155          if (opts == NULL)
2148 2156                  return (SA_OK);
2149 2157  
2150      -        if (smb_saprop_getbool(opts, SHOPT_CATIA))
     2158 +        if (smb_saprop_getbool(opts, SHOPT_CATIA, B_FALSE))
2151 2159                  si->shr_flags |= SMB_SHRF_CATIA;
2152 2160  
2153      -        if (smb_saprop_getbool(opts, SHOPT_ABE))
     2161 +        if (smb_saprop_getbool(opts, SHOPT_ABE, B_FALSE))
2154 2162                  si->shr_flags |= SMB_SHRF_ABE;
2155 2163  
2156      -        if (smb_saprop_getbool(opts, SHOPT_GUEST))
     2164 +        if (smb_saprop_getbool(opts, SHOPT_GUEST, B_FALSE))
2157 2165                  si->shr_flags |= SMB_SHRF_GUEST_OK;
2158 2166  
2159      -        if (smb_saprop_getbool(opts, SHOPT_DFSROOT))
     2167 +        if (smb_saprop_getbool(opts, SHOPT_DFSROOT, B_FALSE))
2160 2168                  si->shr_flags |= SMB_SHRF_DFSROOT;
2161 2169  
     2170 +        if (smb_saprop_getbool(opts, SHOPT_CA, B_FALSE))
     2171 +                si->shr_flags |= SMB_SHRF_CA;
     2172 +
     2173 +        if (smb_saprop_getbool(opts, SHOPT_FSO, B_FALSE))
     2174 +                si->shr_flags |= SMB_SHRF_FSO;
     2175 +
     2176 +        /* Quotas are enabled by default. */
     2177 +        if (smb_saprop_getbool(opts, SHOPT_QUOTAS, B_TRUE))
     2178 +                si->shr_flags |= SMB_SHRF_QUOTAS;
     2179 +
     2180 +        if (smb_saprop_getstr(opts, SHOPT_ENCRYPT, strbuf, sizeof (strbuf)))
     2181 +                smb_cfg_set_require(strbuf, &si->shr_encrypt);
     2182 +
2162 2183          (void) smb_saprop_getstr(opts, SHOPT_AD_CONTAINER, si->shr_container,
2163 2184              sizeof (si->shr_container));
2164 2185  
2165 2186          if (smb_saprop_getstr(opts, SHOPT_CSC, csc_value, sizeof (csc_value)))
2166 2187                  smb_csc_option(csc_value, si);
2167 2188  
2168 2189          if (smb_saprop_getstr(opts, SHOPT_RO, si->shr_access_ro,
2169 2190              sizeof (si->shr_access_ro)))
2170 2191                  si->shr_flags |= SMB_SHRF_ACC_RO;
2171 2192  
↓ open down ↓ 168 lines elided ↑ open up ↑
2340 2361  
2341 2362          if ((strcasecmp(value, SMB_EXEC_DISP_CONTINUE) == 0) ||
2342 2363              (strcasecmp(value, SMB_EXEC_DISP_TERMINATE) == 0))
2343 2364                  return (SA_OK);
2344 2365  
2345 2366          return (SA_BAD_VALUE);
2346 2367  }
2347 2368  
2348 2369  /*ARGSUSED*/
2349 2370  static int
2350      -max_protocol_validator(int index, char *value)
     2371 +protocol_validator(int index, char *value)
2351 2372  {
2352 2373          if (value == NULL)
2353 2374                  return (SA_BAD_VALUE);
2354 2375  
2355 2376          if (*value == '\0')
2356 2377                  return (SA_OK);
2357 2378  
2358 2379          if (smb_config_check_protocol(value) == 0)
2359 2380                  return (SA_OK);
2360 2381  
↓ open down ↓ 55 lines elided ↑ open up ↑
2416 2437                                  break;
2417 2438                  }
2418 2439  
2419 2440                  cur = nvlist_next_nvpair(nvl, cur);
2420 2441          }
2421 2442  
2422 2443          return (err);
2423 2444  }
2424 2445  
2425 2446  static boolean_t
2426      -smb_saprop_getbool(sa_optionset_t opts, char *propname)
     2447 +smb_saprop_getbool(sa_optionset_t opts, char *propname, boolean_t def)
2427 2448  {
2428 2449          sa_property_t prop;
2429 2450          char *val;
2430      -        boolean_t propval = B_FALSE;
     2451 +        boolean_t ret = def;
2431 2452  
2432 2453          prop = sa_get_property(opts, propname);
2433 2454          if ((val = sa_get_property_attr(prop, "value")) != NULL) {
2434      -                if ((strcasecmp(val, "true") == 0) || (strcmp(val, "1") == 0))
2435      -                        propval = B_TRUE;
     2455 +                if (def) {
     2456 +                        /* Default is true, ret false if... */
     2457 +                        if ((strcasecmp(val, "false") == 0) ||
     2458 +                            (strcmp(val, "0") == 0))
     2459 +                                ret = B_FALSE;
     2460 +                } else {
     2461 +                        /* Default is false, ret true if... */
     2462 +                        if ((strcasecmp(val, "true") == 0) ||
     2463 +                            (strcmp(val, "1") == 0))
     2464 +                                ret = B_TRUE;
     2465 +                }
2436 2466                  free(val);
2437 2467          }
2438 2468  
2439      -        return (propval);
     2469 +        return (ret);
2440 2470  }
2441 2471  
2442 2472  static boolean_t
2443 2473  smb_saprop_getstr(sa_optionset_t opts, char *propname, char *buf, size_t bufsz)
2444 2474  {
2445 2475          sa_property_t prop;
2446 2476          char *val;
2447 2477  
2448 2478          prop = sa_get_property(opts, propname);
2449 2479          if ((val = sa_get_property_attr(prop, "value")) != NULL) {
2450 2480                  (void) strlcpy(buf, val, bufsz);
2451 2481                  free(val);
2452 2482                  return (B_TRUE);
2453 2483          }
2454 2484  
2455 2485          return (B_FALSE);
2456 2486  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX