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

@@ -19,11 +19,11 @@
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
  * SMB specific functions
  */

@@ -82,11 +82,12 @@
 static int ipv4_validator(int, char *);
 static int hostname_validator(int, char *);
 static int path_validator(int, char *);
 static int cmd_validator(int, char *);
 static int disposition_validator(int, char *);
-static int max_protocol_validator(int, char *);
+static int protocol_validator(int, char *);
+static int require_validator(int, char *);
 
 static int smb_enable_resource(sa_resource_t);
 static int smb_disable_resource(sa_resource_t);
 static uint64_t smb_share_features(void);
 static int smb_list_transient(sa_handle_t);

@@ -96,11 +97,11 @@
 static char *smb_csc_name(const smb_share_t *);
 static sa_group_t smb_get_defaultgrp(sa_handle_t);
 static int interface_validator(int, char *);
 static int smb_update_optionset_props(sa_handle_t, sa_resource_t, nvlist_t *);
 
-static boolean_t smb_saprop_getbool(sa_optionset_t, char *);
+static boolean_t smb_saprop_getbool(sa_optionset_t, char *, boolean_t);
 static boolean_t smb_saprop_getstr(sa_optionset_t, char *, char *, size_t);
 
 static struct {
         char *value;
         uint32_t flag;

@@ -176,10 +177,14 @@
         { SHOPT_CATIA,          OPT_TYPE_BOOLEAN },
         { SHOPT_CSC,            OPT_TYPE_CSC },
         { SHOPT_GUEST,          OPT_TYPE_BOOLEAN },
         { SHOPT_DFSROOT,        OPT_TYPE_BOOLEAN },
         { SHOPT_DESCRIPTION,    OPT_TYPE_STRING },
+        { SHOPT_CA,             OPT_TYPE_BOOLEAN },
+        { SHOPT_FSO,            OPT_TYPE_BOOLEAN },
+        { SHOPT_QUOTAS,         OPT_TYPE_BOOLEAN },
+        { SHOPT_ENCRYPT,        OPT_TYPE_STRING },
         { NULL, NULL }
 };
 
 /*
  * findopt(name)

@@ -384,13 +389,11 @@
 {
         char *path;
         smb_share_t si;
         sa_resource_t resource;
         boolean_t iszfs;
-        boolean_t privileged;
         int err = SA_OK;
-        priv_set_t *priv_effective;
         boolean_t online;
 
         /*
          * Don't support Trusted Extensions.
          */

@@ -398,15 +401,10 @@
                 (void) printf(dgettext(TEXT_DOMAIN,
                     "SMB: service not supported with Trusted Extensions\n"));
                 return (SA_NOT_SUPPORTED);
         }
 
-        priv_effective = priv_allocset();
-        (void) getppriv(PRIV_EFFECTIVE, priv_effective);
-        privileged = (priv_isfullset(priv_effective) == B_TRUE);
-        priv_freeset(priv_effective);
-
         /* get the path since it is important in several places */
         path = sa_get_share_attr(share, "path");
         if (path == NULL)
                 return (SA_NO_SUCH_PATH);
 

@@ -417,33 +415,11 @@
         if (!online && !smb_isautoenable() && smb_isdisabled())
                 goto done;
 
         iszfs = sa_path_is_zfs(path);
 
-        if (iszfs) {
-
-                if (privileged == B_FALSE && !online) {
-
                         if (!online) {
-                                (void) printf(dgettext(TEXT_DOMAIN,
-                                    "SMB: Cannot share remove "
-                                    "file system: %s\n"), path);
-                                (void) printf(dgettext(TEXT_DOMAIN,
-                                    "SMB: Service needs to be enabled "
-                                    "by a privileged user\n"));
-                                err = SA_NO_PERMISSION;
-                                errno = EPERM;
-                        }
-                        if (err) {
-                                sa_free_attr_string(path);
-                                return (err);
-                        }
-
-                }
-        }
-
-        if (privileged == B_TRUE && !online) {
                 err = smb_enable_service();
                 if (err != SA_OK) {
                         (void) printf(dgettext(TEXT_DOMAIN,
                             "SMB: Unable to enable service\n"));
                 } else {

@@ -912,17 +888,43 @@
         { SMB_CI_MAP, 0, MAX_VALUE_BUFLEN, cmd_validator, SMB_REFRESH_REFRESH },
         { SMB_CI_UNMAP, 0, MAX_VALUE_BUFLEN, cmd_validator,
             SMB_REFRESH_REFRESH },
         { SMB_CI_DISPOSITION, 0, MAX_VALUE_BUFLEN,
             disposition_validator, SMB_REFRESH_REFRESH },
-        { SMB_CI_MAX_PROTOCOL, 0, MAX_VALUE_BUFLEN, max_protocol_validator,
+        { SMB_CI_MAX_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator,
             SMB_REFRESH_REFRESH },
+        { SMB_CI_ENCRYPT, 0, MAX_VALUE_BUFLEN, require_validator,
+            SMB_REFRESH_REFRESH },
+        { SMB_CI_MIN_PROTOCOL, 0, MAX_VALUE_BUFLEN, protocol_validator,
+            SMB_REFRESH_REFRESH },
+        { SMB_CI_BYPASS_TRAVERSE_CHECKING, 0, 0, true_false_validator,
+            SMB_REFRESH_REFRESH },
+        { SMB_CI_OPLOCK_ENABLE, 0, 0, true_false_validator,
+            SMB_REFRESH_REFRESH },
 };
 
 #define SMB_OPT_NUM \
         (sizeof (smb_proto_options) / sizeof (smb_proto_options[0]))
 
+static int
+require_validator(int index, char *value)
+{
+        if (string_length_check_validator(index, value) != SA_OK)
+                return (SA_BAD_VALUE);
+
+        if (strcmp(value, "required") == 0)
+                return (SA_OK);
+
+        if (strcmp(value, "disabled") == 0)
+                return (SA_OK);
+
+        if (strcmp(value, "enabled") == 0)
+                return (SA_OK);
+
+        return (SA_BAD_VALUE);
+}
+
 /*
  * Check the range of value as int range.
  */
 static int
 range_check_validator(int index, char *value)

@@ -1532,11 +1534,15 @@
                         ret = smb_validate_proto_prop(index, name, value);
                         if (ret == SA_OK) {
                                 opt = &smb_proto_options[index];
 
                                 /* Save to SMF */
-                                (void) smb_config_set(opt->smb_index, value);
+                                if (smb_config_set(opt->smb_index,
+                                    value) != 0) {
+                                        ret = SA_BAD_VALUE;
+                                        goto out;
+                                }
                                 /*
                                  * Specialized refresh mechanisms can
                                  * be flagged in the proto_options and
                                  * processed here.
                                  */

@@ -1548,10 +1554,11 @@
                                             SMBD_DEFAULT_INSTANCE_FMRI);
                         }
                 }
         }
 
+out:
         if (name != NULL)
                 sa_free_attr_string(name);
         if (value != NULL)
                 sa_free_attr_string(value);
 

@@ -2113,10 +2120,11 @@
         sa_optionset_t opts;
         char *path;
         char *rname;
         char *val = NULL;
         char csc_value[SMB_CSC_BUFSZ];
+        char strbuf[sizeof ("required")];
 
         bzero(si, sizeof (smb_share_t));
 
         if ((path = sa_get_share_attr(share, "path")) == NULL)
                 return (SA_NO_SUCH_PATH);

@@ -2145,22 +2153,35 @@
 
         opts = sa_get_derived_optionset(resource, SMB_PROTOCOL_NAME, 1);
         if (opts == NULL)
                 return (SA_OK);
 
-        if (smb_saprop_getbool(opts, SHOPT_CATIA))
+        if (smb_saprop_getbool(opts, SHOPT_CATIA, B_FALSE))
                 si->shr_flags |= SMB_SHRF_CATIA;
 
-        if (smb_saprop_getbool(opts, SHOPT_ABE))
+        if (smb_saprop_getbool(opts, SHOPT_ABE, B_FALSE))
                 si->shr_flags |= SMB_SHRF_ABE;
 
-        if (smb_saprop_getbool(opts, SHOPT_GUEST))
+        if (smb_saprop_getbool(opts, SHOPT_GUEST, B_FALSE))
                 si->shr_flags |= SMB_SHRF_GUEST_OK;
 
-        if (smb_saprop_getbool(opts, SHOPT_DFSROOT))
+        if (smb_saprop_getbool(opts, SHOPT_DFSROOT, B_FALSE))
                 si->shr_flags |= SMB_SHRF_DFSROOT;
 
+        if (smb_saprop_getbool(opts, SHOPT_CA, B_FALSE))
+                si->shr_flags |= SMB_SHRF_CA;
+
+        if (smb_saprop_getbool(opts, SHOPT_FSO, B_FALSE))
+                si->shr_flags |= SMB_SHRF_FSO;
+
+        /* Quotas are enabled by default. */
+        if (smb_saprop_getbool(opts, SHOPT_QUOTAS, B_TRUE))
+                si->shr_flags |= SMB_SHRF_QUOTAS;
+
+        if (smb_saprop_getstr(opts, SHOPT_ENCRYPT, strbuf, sizeof (strbuf)))
+                smb_cfg_set_require(strbuf, &si->shr_encrypt);
+
         (void) smb_saprop_getstr(opts, SHOPT_AD_CONTAINER, si->shr_container,
             sizeof (si->shr_container));
 
         if (smb_saprop_getstr(opts, SHOPT_CSC, csc_value, sizeof (csc_value)))
                 smb_csc_option(csc_value, si);

@@ -2345,11 +2366,11 @@
         return (SA_BAD_VALUE);
 }
 
 /*ARGSUSED*/
 static int
-max_protocol_validator(int index, char *value)
+protocol_validator(int index, char *value)
 {
         if (value == NULL)
                 return (SA_BAD_VALUE);
 
         if (*value == '\0')

@@ -2421,24 +2442,33 @@
 
         return (err);
 }
 
 static boolean_t
-smb_saprop_getbool(sa_optionset_t opts, char *propname)
+smb_saprop_getbool(sa_optionset_t opts, char *propname, boolean_t def)
 {
         sa_property_t prop;
         char *val;
-        boolean_t propval = B_FALSE;
+        boolean_t ret = def;
 
         prop = sa_get_property(opts, propname);
         if ((val = sa_get_property_attr(prop, "value")) != NULL) {
-                if ((strcasecmp(val, "true") == 0) || (strcmp(val, "1") == 0))
-                        propval = B_TRUE;
+                if (def) {
+                        /* Default is true, ret false if... */
+                        if ((strcasecmp(val, "false") == 0) ||
+                            (strcmp(val, "0") == 0))
+                                ret = B_FALSE;
+                } else {
+                        /* Default is false, ret true if... */
+                        if ((strcasecmp(val, "true") == 0) ||
+                            (strcmp(val, "1") == 0))
+                                ret = B_TRUE;
+                }
                 free(val);
         }
 
-        return (propval);
+        return (ret);
 }
 
 static boolean_t
 smb_saprop_getstr(sa_optionset_t opts, char *propname, char *buf, size_t bufsz)
 {