s3:smb2_server: allow logoff, close, unlock, cancel and echo on expired sessions
authorStefan Metzmacher <metze@samba.org>
Wed, 20 Dec 2017 13:05:54 +0000 (14:05 +0100)
committerJeremy Allison <jra@samba.org>
Thu, 21 Dec 2017 22:28:41 +0000 (23:28 +0100)
Windows client at least doesn't have code to replay
a SMB2 Close after getting NETWORK_SESSION_EXPIRED,
which locks out a the client and generates an endless
loop around NT_STATUS_SHARING_VIOLATION.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13197

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Thu Dec 21 23:28:42 CET 2017 on sn-devel-144

selftest/knownfail.d/session.expire2 [deleted file]
source3/smbd/smb2_lock.c
source3/smbd/smb2_server.c

diff --git a/selftest/knownfail.d/session.expire2 b/selftest/knownfail.d/session.expire2
deleted file mode 100644 (file)
index 998ccbd..0000000
+++ /dev/null
@@ -1 +0,0 @@
-^samba3.smb2.session.*krb5.expire2
index 2fcd35926246b405016d146f4995c581c6e8feea..45b833cbca6f2068ccf5928a2321504dc28b3133 100644 (file)
@@ -98,6 +98,23 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req)
        in_locks[l].flags       = IVAL(lock_buffer, 0x10);
        /* 0x14 - 4 reserved bytes */
 
+       status = req->session->status;
+       if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
+               /*
+                * We need to catch NT_STATUS_NETWORK_SESSION_EXPIRED
+                * for lock requests only.
+                *
+                * Unlock requests still need to be processed!
+                *
+                * This means smbd_smb2_request_check_session()
+                * can't handle the difference and always
+                * allows SMB2_OP_LOCK.
+                */
+               if (in_locks[0].flags != SMB2_LOCK_FLAG_UNLOCK) {
+                       return smbd_smb2_request_error(req, status);
+               }
+       }
+
        lock_buffer = SMBD_SMB2_IN_DYN_PTR(req);
 
        for (l=1; l < in_lock_count; l++) {
index 68a024f4ec8103eb3c4faa6fa1d9f0f59a9b171e..5290c05cb228b0f051f4efb587c7192c7253f4a1 100644 (file)
@@ -1902,6 +1902,25 @@ static NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
                case SMB2_OP_SESSSETUP:
                        status = NT_STATUS_OK;
                        break;
+               case SMB2_OP_LOGOFF:
+               case SMB2_OP_CLOSE:
+               case SMB2_OP_LOCK:
+               case SMB2_OP_CANCEL:
+               case SMB2_OP_KEEPALIVE:
+                       /*
+                        * [MS-SMB2] 3.3.5.2.9 Verifying the Session
+                        * specifies that LOGOFF, CLOSE and (UN)LOCK
+                        * should always be processed even on expired sessions.
+                        *
+                        * Also see the logic in
+                        * smbd_smb2_request_process_lock().
+                        *
+                        * The smb2.session.expire2 test shows that
+                        * CANCEL and KEEPALIVE/ECHO should also
+                        * be processed.
+                        */
+                       status = NT_STATUS_OK;
+                       break;
                default:
                        break;
                }