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,18 ****
   * 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.
   */
  
  /*
   * Dispatch function for SMB2_SESSION_SETUP
   *
--- 8,18 ----
   * source.  A copy of the CDDL is also available via the Internet at
   * http://www.illumos.org/license/CDDL.
   */
  
  /*
!  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
   */
  
  /*
   * Dispatch function for SMB2_SESSION_SETUP
   *
*** 28,45 ****
  
  smb_sdrc_t
  smb2_session_setup(smb_request_t *sr)
  {
          smb_arg_sessionsetup_t  *sinfo;
          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;
          uint16_t SessionFlags;
          uint32_t status;
          int skip;
          int rc = 0;
  
--- 28,46 ----
  
  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 PrevSsnId;
          uint16_t SessionFlags;
          uint32_t status;
          int skip;
          int rc = 0;
  
*** 53,63 ****
              &SecurityMode,      /* b */
              &Capabilities,      /* l */
              &Channel,           /* l */
              &SecBufOffset,      /* w */
              &SecBufLength,      /* w */
!             &PrevSessionId);    /* q */
          if (rc)
                  return (SDRC_ERROR);
  
          /*
           * We're normally positioned at the security buffer now,
--- 54,64 ----
              &SecurityMode,      /* b */
              &Capabilities,      /* l */
              &Channel,           /* l */
              &SecBufOffset,      /* w */
              &SecBufLength,      /* w */
!             &PrevSsnId);        /* q */
          if (rc)
                  return (SDRC_ERROR);
  
          /*
           * We're normally positioned at the security buffer now,
*** 79,88 ****
--- 80,126 ----
              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,105 ****
          SessionFlags = 0;
  
          switch (status) {
  
          case NT_STATUS_SUCCESS: /* Authenticated */
!                 if (sr->uid_user->u_flags & SMB_USER_FLAG_GUEST)
                          SessionFlags |= SMB2_SESSION_FLAG_IS_GUEST;
!                 if (sr->uid_user->u_flags & SMB_USER_FLAG_ANON)
                          SessionFlags |= SMB2_SESSION_FLAG_IS_NULL;
                  smb2_ss_adjust_credits(sr);
                  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.
--- 128,167 ----
          SessionFlags = 0;
  
          switch (status) {
  
          case NT_STATUS_SUCCESS: /* Authenticated */
!                 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) != 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,121 ****
--- 169,187 ----
          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,136 ****
              SecBufOffset,               /* w */
              SecBufLength,               /* w */
              SecBufLength,               /* # */
              sinfo->ssi_osecblob);       /* c */
          if (rc)
!                 return (SDRC_ERROR);
  
          return (SDRC_SUCCESS);
  }
  
  /*
--- 192,202 ----
              SecBufOffset,               /* w */
              SecBufLength,               /* w */
              SecBufLength,               /* # */
              sinfo->ssi_osecblob);       /* c */
          if (rc)
!                 sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
  
          return (SDRC_SUCCESS);
  }
  
  /*