diff --git a/SMBLibrary/Client/Authentication/NTLMAuthenticationClient.cs b/SMBLibrary/Client/Authentication/NTLMAuthenticationClient.cs index 0c31127c..079b723a 100644 --- a/SMBLibrary/Client/Authentication/NTLMAuthenticationClient.cs +++ b/SMBLibrary/Client/Authentication/NTLMAuthenticationClient.cs @@ -109,6 +109,10 @@ protected virtual byte[] GetAuthenticateMessage(byte[] securityBlob) challengeMessageBytes = securityBlob; } + // When NegState is AcceptCompleted or Reject, the SPNEGO token may not contain a Response Token + if (challengeMessageBytes == null) + return null; + byte[] authenticateMessageBytes = NTLMAuthenticationHelper.GetAuthenticateMessage(m_negotiateMessageBytes, challengeMessageBytes, m_domainName, m_userName, m_password, m_spn, m_authenticationMethod, out m_sessionKey); if (useGSSAPI && authenticateMessageBytes != null) { diff --git a/SMBLibrary/Client/SMB2Client.cs b/SMBLibrary/Client/SMB2Client.cs index 05cd549d..f35f925b 100644 --- a/SMBLibrary/Client/SMB2Client.cs +++ b/SMBLibrary/Client/SMB2Client.cs @@ -299,6 +299,16 @@ public NTStatus Login(IAuthenticationClient authenticationClient) if (m_isLoggedIn) { m_sessionID = response.Header.SessionID; + if (finalSessionSetupResponse.SecurityBuffer != null && finalSessionSetupResponse.SecurityBuffer.Length > 0) + { + // Some authentication mechanisms (e.g. Kerberos) embed acceptor-provider + // context data (such as an AP-REP subkey) in the final, successful + // SESSION_SETUP response. Give the authentication client a chance to + // process it before deriving the session key, since it may override + // the key negotiated so far. + authenticationClient.InitializeSecurityContext(finalSessionSetupResponse.SecurityBuffer); + } + m_sessionKey = authenticationClient.GetSessionKey(); m_authenticationClient = authenticationClient; SessionFlags sessionFlags = finalSessionSetupResponse.SessionFlags;