smbd: fix initial large PAC sess setup response
authorDavid Disseldorp <ddiss@samba.org>
Tue, 12 Feb 2013 10:58:06 +0000 (11:58 +0100)
committerKarolin Seeger <kseeger@samba.org>
Thu, 14 Mar 2013 09:51:41 +0000 (10:51 +0100)
An oversize Kerberos security token may be split across multiple Session
Setup AndX requests when authenticating as a user who is a member of
many (~2000) groups.
In such a case the NativeOS, NativeLanMan & PrimaryDomain fields must be
sent with the NT_STATUS_MORE_PROCESSING_REQUIRED response. Otherwise
Windows clients may resend the same security token data in subsequent
session setup andX requests, as observed with Windows 7 and Server 2012.

This change fixes the SMB1 server only.

Fix bug #9658 - Session Setup AndX exchange fails with an oversize security
token.
(cherry picked from commit e28ec902a207655acab665c4cfabb1f2031fb24f)

source3/smbd/sesssetup.c

index 4f09db929ac9834dd38d69646c6ba5f087a5cede..75c2a1551d157f2b721081107155e2c58c8d997f 100644 (file)
@@ -905,6 +905,13 @@ static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
                        (unsigned int)copy_len,
                        (unsigned int)pblob->length ));
 
+               if (pblob->length > pad->needed_len) {
+                       DEBUG(2, ("subsequent security token data length %u "
+                                 "exceeds expected length %u\n",
+                                 (unsigned int)pblob->length,
+                                 (unsigned int)pad->needed_len));
+               }
+
                tmp_blob = data_blob(NULL,
                                pad->partial_data.length + copy_len);
 
@@ -1165,13 +1172,18 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 
        status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
        if (!NT_STATUS_IS_OK(status)) {
+               /*
+                * Pack error response, ensuring to fill NativeOS, NativeLanMan
+                * & PrimaryDomain fields on NT_STATUS_MORE_PROCESSING_REQUIRED
+                */
+               reply_outbuf(req, 4, 0);
+               reply_sesssetup_blob(req, data_blob_null, status);
                if (!NT_STATUS_EQUAL(status,
                                NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                        /* Real error - kill the intermediate vuid */
                        invalidate_vuid(sconn, vuid);
                }
                data_blob_free(&blob1);
-               reply_nterror(req, nt_status_squash(status));
                return;
        }