3.2.5.2 Receiving an SMB2 NEGOTIATE Response
If the Status field in the SMB2 header of the response is not STATUS_SUCCESS, the client MUST return the error code to the calling application.
The client MUST store the received MaxTransactSize in Connection.MaxTransactSize, the received MaxReadSize in Connection.MaxReadSize, the received MaxWriteSize in Connection.MaxWriteSize, and the received ServerGuid in Connection.ServerGuid.<185> The client MUST store the received security buffer described by SecurityBufferOffset and SecurityBufferLength into Connection.GSSNegotiateToken.
The client SHOULD<186> disconnect the connection if the size, in bytes, received in MaxTransactSize, MaxReadSize, or MaxWriteSize is less than 65536.
If the SecurityMode field in the Negotiate Response has the SMB2_NEGOTIATE_SIGNING_REQUIRED bit set, the client MUST set Connection.RequireSigning to TRUE.
If the client implements SMB 3.1.1, the DialectRevision in the SMB2 NEGOTIATE Response is 0x02FF, and the Connection is NetBIOS over TCP, the client MUST close the connection. The client MUST establish a new connection to the server, as specified in section 3.2.4.2.1, by providing the ServerName and TransportIdentifier indicating Direct TCP transport.
If the DialectRevision field in the SMB2 NEGOTIATE Response is 0x02FF, the client MUST issue a new SMB2 NEGOTIATE request as described in section 3.2.4.2.2.2 with the only exception that the client MUST allocate sequence number 1 from Connection.SequenceWindow, and MUST set MessageId field of the SMB2 header to 1. Otherwise, the client MUST proceed as follows.
If the DialectRevision field in the SMB2 NEGOTIATE Response is equal to one of the values in the Dialects field of the SMB2 NEGOTIATE request, the client MUST set Connection.Dialect to DialectRevision. Otherwise, the client MUST close the connection and SHOULD fail the application request.
If the client implements SMB 2.1 or SMB 3.x dialect family, the client MUST perform the following:
If SMB2_GLOBAL_CAP_LEASING is set in the Capabilities field of the SMB2 NEGOTIATE Response, the client MUST set Connection.SupportsFileLeasing to TRUE. Otherwise, it MUST be set to FALSE.
If SMB2_GLOBAL_CAP_LARGE_MTU is set in the Capabilities field of the SMB2 NEGOTIATE Response, the client MUST set Connection.SupportsMultiCredit to TRUE. Otherwise, it MUST be set to FALSE.
If Connection.Dialect belongs to the SMB 3.x dialect family, the client MUST perform the following:
If SMB2_GLOBAL_CAP_DIRECTORY_LEASING is set in the Capabilities field of the SMB2 NEGOTIATE Response, the client MUST set Connection.SupportsDirectoryLeasing to TRUE. Otherwise, it MUST be set to FALSE.
If SMB2_GLOBAL_CAP_MULTI_CHANNEL is set in the Capabilities field of the SMB2 NEGOTIATE Response, the client MUST set Connection.SupportsMultiChannel to TRUE. Otherwise, it MUST be set to FALSE.
If SMB2_GLOBAL_CAP_PERSISTENT_HANDLES is set in the Capabilities field of the SMB2 NEGOTIATE Response, the client MUST set Connection.SupportsPersistentHandles to TRUE. Otherwise, it MUST be set to FALSE.
If SMB2_GLOBAL_CAP_ENCRYPTION is set in the Capabilities field of the SMB2 NEGOTIATE Response and Connection.Dialect is "3.0" or "3.0.2", the client MUST set Connection.SupportsEncryption to TRUE. Otherwise, it MUST be set to FALSE.
If SMB2_GLOBAL_CAP_NOTIFICATIONS is set in the Capabilities field of the SMB2 NEGOTIATE Response and Connection Dialect is at least "3.0", then the client MUST set the Connection.SupportsNotifications to TRUE. Otherwise, it MUST be set to FALSE.
Connection.ServerCapabilities MUST be set to the Capabilities field of the SMB2 NEGOTIATE Response.
Connection.ServerSecurityMode MUST be set to the SecurityMode field of the SMB2 NEGOTIATE Response.
If the client implements the SMB 3.x dialect family, the client MUST look up the server entry in ServerList where Server.ServerName matches the Connection.ServerName. If an entry is found, the client MUST set Connection.Server to the server entry found. Otherwise, the client MUST initialize a server object and MUST set Server.ServerName to Connection.ServerName and Connection.Server to NULL. The client MUST add the Server entry to ServerList.
If the client implements the SMB 3.x dialect family and Connection.Server is not NULL, the client MUST disconnect the connection if any of the following conditions is satisfied:
Connection.Server.ServerGUID does not match ServerGUID in the response.
Connection.Server.DialectRevision does not match DialectRevision in the response.
Connection.Server.SecurityMode does not match SecurityMode in the response.
Connection.Server.Capabilities does not match Capabilities in the response.
If the client implements the SMB 3.x dialect family and Connection.Server is NULL, the client MUST set the following values:
Connection.Server to the server entry in ServerList where Server.ServerName matches the Connection.ServerName.
Connection.Server.ServerGUID to ServerGUID in the response
Connection.Server.DialectRevision to DialectRevision in the response
Connection.Server.SecurityMode to SecurityMode in the response
Connection.Server.Capabilities to Capabilities in the response
Connection.Server.AddressList to empty
If Connection.Dialect is "3.1.1", the client MUST process the NegotiateContextList that is specified by the response's NegotiateContextOffset and NegotiateContextCount fields as follows:
If the NegotiateContextList does not contain exactly one SMB2_PREAUTH_INTEGRITY_CAPABILITIES negotiate context, the client MUST return an error to the calling application.
If the NegotiateContextList contains more than one SMB2_ENCRYPTION_CAPABILITIES negotiate context, the client MUST return an error to the calling application.
If the NegotiateContextList contains more than one SMB2_COMPRESSION_CAPABILITIES negotiate context, the client MUST return an error to the calling application.
If the NegotiateContextList contains more than one SMB2_RDMA_TRANSFORM_CAPABILITIES negotiate context, the client MUST return an error to the calling application.
If the NegotiateContextList contains more than one SMB2_SIGNING_CAPABILITIES negotiate context, the client MUST return an error to the calling application.
If the NegotiateContextList contains more than one SMB2_TRANSPORT_CAPABILITIES negotiate context, the client MUST return an error to the calling application.
For each context in the received NegotiateContextList, if the context is any negotiate context other than SMB2_PREAUTH_INTEGRITY_CAPABILITIES, SMB2_COMPRESSION_CAPABILITIES, SMB2_RDMA_TRANSFORM_CAPABILITIES, SMB2_SIGNING_CAPABILITIES, SMB2_TRANSPORT_CAPABILITIES, and SMB2_ENCRYPTION_CAPABILITIES negotiate context, the client MUST ignore the negotiate context.
Processing the SMB2_PREAUTH_INTEGRITY_CAPABILITIES negotiate context:
The client MUST return an error to the calling application in the following cases:
If the DataLength of the negotiate context is less than the size of SMB2_PREAUTH_INTEGRITY_CAPABILITIES structure.
If HashAlgorithmCount is not 1.
If HashAlgorithms[0] is not one of the hash algorithms from the set of hash algorithms that the client specified in its negotiate request.
The client MUST set Connection.PreauthIntegrityHashId to HashAlgorithms[0].
Processing the SMB2_ENCRYPTION_CAPABILITIES negotiate context
The client MUST return an error to the calling application in the following cases:
The DataLength of the negotiate context is less than the size of SMB2_ENCRYPTION_CAPABILITIES structure.
CipherCount is not 1.
Ciphers[0] is not 0 and not one of the ciphers that the client specified in its negotiate request.
The client MUST set Connection.CipherId to Ciphers[0] and if Server.CipherId is empty, set Server.CipherId to Ciphers[0].
If Connection.CipherId is nonzero, the client MUST set Connection.SupportsEncryption to TRUE. Otherwise, it MUST be set to FALSE.
Processing the SMB2_COMPRESSION_CAPABILITIES negotiate context
If the DataLength of the negotiate context is less than the size of SMB2_COMPRESSION_CAPABILITIES structure, the client MUST return an error to the calling application.
If CompressionAlgorithmCount is zero, the client MUST return an error to the calling application.
If the length of the negotiate context is greater than DataLength of the negotiate context, the client MUST return an error to the calling application.
For each algorithm in CompressionAlgorithms, if the value of algorithm is greater than or equal to 32, the client MUST return an error to the calling application.
If there is a duplicate value in CompressionAlgorithms, the client MUST return an error to the calling application.
If CompressionAlgorithmCount is 1 and CompressionAlgorithms contains “NONE”, the client SHOULD<187> set Connection.CompressionIds to an empty list.
Otherwise, for each algorithm in CompressionAlgorithms, if the value of algorithm does not match any of the algorithms sent in SMB2 NEGOTIATE request, the client MUST return an error to the calling application.
Otherwise, the client MUST set Connection.CompressionIds to all the algorithms received in CompressionAlgorithms.
If SMB2_COMPRESSION_CAPABILITIES_FLAG_CHAINED bit is set in Flags field and IsChainedCompressionSupported is TRUE, Connection.SupportsChainedCompression MUST be set to TRUE.
Processing the SMB2_RDMA_TRANSFORM_CAPABILITIES negotiate context
If the DataLength of the negotiate context is less than the size of SMB2_RDMA_TRANSFORM_CAPABILITIES structure, the client MUST return an error to the calling application.
If the received TransformCount is greater than TransformCount sent in the request, the client MUST return an error to the calling application.
If any of the values in the received RDMATransformIds do not match the transform identifiers sent in the request, the client MUST return an error to the calling application.
The client MUST set Connection.RDMATransformIds to all the transforms received in RDMATransformIds. If Server.RDMATransformIds is empty, the client MUST set Server.RDMATransformIds to Connection.RDMATransformIds.
Processing the SMB2_SIGNING_CAPABILITIES negotiate context
If the DataLength of the negotiate context is less than the size of SMB2_SIGNING_CAPABILITIES structure, the client MUST return an error to the calling application.
If the received SigningAlgorithmCount is not equal to 1, the client MUST return an error to the calling application.
If any of the values in the received SigningAlgorithms do not match the identifiers sent in the request, the client MUST return an error to the calling application.
The client MUST set Connection.SigningAlgorithmId to SigningAlgorithms received in the response. If Server.SigningAlgorithmId is empty, the client MUST set Server.SigningAlgorithmId to Connection.SigningAlgorithmId.
Processing the SMB2_TRANSPORT_CAPABILITIES negotiate context
If the DataLength of the negotiate context is less than the size of SMB2_TRANSPORT_CAPABILITIES structure, the client MUST return an error to the calling application.
If the underlying connection is over QUIC and SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY is set in Flags field, the client MUST set Connection.AcceptTransportSecurity to TRUE
If Connection.Dialect is "3.1.1", the client MUST update its preauthentication integrity hash value as follows:
The client MUST initialize Connection.PreauthIntegrityHashValue with zero.
The client MUST generate a hash using the Connection.PreauthIntegrityHashId algorithm on the string constructed by concatenating Connection.PreauthIntegrityHashValue and the negotiate request message retrieved from the first entry of Connection.OutstandingRequests. The client MUST set Connection.PreauthIntegrityHashValue to the hash value generated above.
The client MUST generate a hash using Connection.PreauthIntegrityHashId algorithm on the string constructed by concatenating Connection.PreauthIntegrityHashValue and the negotiate response message, including all bytes from the response's SMB2 header to the last byte received from the network. The client MUST set Connection.PreauthIntegrityHashValue to the hash value generated above.
The client MUST continue processing, as specified in section 3.2.4.2.3.