Print this page
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15555 SMB2 async redesign
NEX-15061 smtorture smb2.lock.cancel.cancel is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Also follow-up change to:
 NEX-1643 dtrace provider for smbsrv (remove "done2" probes,
 which don't make sense with the new async design)
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15555 SMB2 async redesign
NEX-15061 smtorture smb2.lock.cancel.cancel is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Also follow-up change to:
 NEX-1643 dtrace provider for smbsrv (remove "done2" probes,
 which don't make sense with the new async design)
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@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-3553 SMB2/3 durable handles
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3776 SMB should handle PreviousSessionID
Reviewed by: Gordon Ross <gwr@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-3610 CLONE NEX-3591 SMB3 signing
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-2781 SMB2 credit handling needs work
SMB-55 SMB2 signing
SMB-96 Codenomicon: SMB2 TC: 141500 - Panic in smb2_decode_create_ctx
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)

@@ -8,11 +8,11 @@
  * source.  A copy of the CDDL is also available via the Internet at
  * http://www.illumos.org/license/CDDL.
  */
 
 /*
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
  * Dispatch function for SMB2_SESSION_SETUP
  *

@@ -28,18 +28,19 @@
 
 smb_sdrc_t
 smb2_session_setup(smb_request_t *sr)
 {
         smb_arg_sessionsetup_t  *sinfo;
+        smb_user_t *prev_user;
         uint16_t StructureSize;
         uint8_t  Flags;
         uint8_t  SecurityMode;
         uint32_t Capabilities;  /* ignored - see above */
         uint32_t Channel;
         uint16_t SecBufOffset;
         uint16_t SecBufLength;
-        uint64_t PrevSessionId;
+        uint64_t PrevSsnId;
         uint16_t SessionFlags;
         uint32_t status;
         int skip;
         int rc = 0;
 

@@ -53,11 +54,11 @@
             &SecurityMode,      /* b */
             &Capabilities,      /* l */
             &Channel,           /* l */
             &SecBufOffset,      /* w */
             &SecBufLength,      /* w */
-            &PrevSessionId);    /* q */
+            &PrevSsnId);        /* q */
         if (rc)
                 return (SDRC_ERROR);
 
         /*
          * We're normally positioned at the security buffer now,

@@ -79,10 +80,47 @@
             sinfo->ssi_iseclen, sinfo->ssi_isecblob);
         if (rc)
                 return (SDRC_ERROR);
 
         /*
+         * Decoded everything.  Dtrace probe,
+         * then no more early returns.
+         */
+        DTRACE_SMB2_START(op__SessionSetup, smb_request_t *, sr);
+
+        /*
+         * [MS-SMB2] 3.3.5.5 Receiving an SMB2 SESSION_SETUP Request
+         *
+         * If we support 3.x, RejectUnencryptedAccess is TRUE,
+         * global EncryptData is TRUE, but we're not talking
+         * 3.x or the client doesn't support encryption,
+         * return ACCESS_DENIED.
+         *
+         * If RejectUnencryptedAccess is TRUE, we force max_protocol
+         * to at least 3.0.
+         */
+        if (sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED &&
+            (sr->session->dialect < SMB_VERS_3_0 ||
+            !SMB3_CLIENT_ENCRYPTS(sr))) {
+                status = NT_STATUS_ACCESS_DENIED;
+                goto errout;
+        }
+
+        /*
+         * SMB3 multi-channel features are not supported.
+         * Once they are, this will check the dialect and
+         * whether multi-channel was negotiated, i.e.
+         *      if (sr->session->dialect < SMB_VERS_3_0 ||
+         *          s->IsMultiChannelCapable == False)
+         *              return (error...)
+         */
+        if (Flags & SMB2_SESSION_FLAG_BINDING) {
+                status = NT_STATUS_REQUEST_NOT_ACCEPTED;
+                goto errout;
+        }
+
+        /*
          * The real auth. work happens in here.
          */
         status = smb_authenticate_ext(sr);
 
         SecBufOffset = SMB2_HDR_SIZE + 8;

@@ -90,16 +128,40 @@
         SessionFlags = 0;
 
         switch (status) {
 
         case NT_STATUS_SUCCESS: /* Authenticated */
-                if (sr->uid_user->u_flags & SMB_USER_FLAG_GUEST)
+                if ((sr->uid_user->u_flags & SMB_USER_FLAG_GUEST) != 0)
                         SessionFlags |= SMB2_SESSION_FLAG_IS_GUEST;
-                if (sr->uid_user->u_flags & SMB_USER_FLAG_ANON)
+                if ((sr->uid_user->u_flags & SMB_USER_FLAG_ANON) != 0)
                         SessionFlags |= SMB2_SESSION_FLAG_IS_NULL;
+                if (sr->uid_user->u_encrypt != SMB_CONFIG_DISABLED)
+                        SessionFlags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
                 smb2_ss_adjust_credits(sr);
+
+                /*
+                 * PrevSsnId is a session that the client is reporting as
+                 * having gone away, and for which we might not yet have seen
+                 * a disconnect. Find the session and log it off as if we had
+                 * received a disconnect.  Note that the client is allowed to
+                 * set PrevSsnID to the _current_ SessionID, so skip the lookup
+                 * in that case. Only allow this session logoff if we owned it.
+                 */
+                if (PrevSsnId == 0 ||
+                    PrevSsnId == sr->smb2_ssnid)
                 break;
+                prev_user = smb_server_lookup_ssnid(sr->sr_server, PrevSsnId);
+                if (prev_user != NULL) {
+                        if (smb_is_same_user(prev_user->u_cred, sr->user_cr)) {
+                                /* Treat this as if we lost the connection */
+                                prev_user->preserve_opens =
+                                    SMB2_DH_PRESERVE_SOME;
+                                smb_user_logoff(prev_user);
+                        }
+                        smb_user_release(prev_user); /* from lookup */
+                }
+                break;
 
         /*
          * This is not really an error, but tells the client
          * it should send another session setup request.
          * Not smb2_put_error because we send a payload.

@@ -107,15 +169,19 @@
         case NT_STATUS_MORE_PROCESSING_REQUIRED:
                 sr->smb2_status = status;
                 break;
 
         default:
+errout:
                 SecBufLength = 0;
                 sr->smb2_status = status;
                 break;
         }
 
+        /* sr->smb2_status set above */
+        DTRACE_SMB2_DONE(op__SessionSetup, smb_request_t *, sr);
+
         /*
          * SMB2 Session Setup reply
          */
 
         rc = smb_mbc_encodef(

@@ -126,11 +192,11 @@
             SecBufOffset,               /* w */
             SecBufLength,               /* w */
             SecBufLength,               /* # */
             sinfo->ssi_osecblob);       /* c */
         if (rc)
-                return (SDRC_ERROR);
+                sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
 
         return (SDRC_SUCCESS);
 }
 
 /*