diff --git a/ntlm/ntlmv1.go b/ntlm/ntlmv1.go index 84cbcd6..a01b1b3 100644 --- a/ntlm/ntlmv1.go +++ b/ntlm/ntlmv1.go @@ -205,7 +205,11 @@ func (n *V1ServerSession) ProcessAuthenticateMessage(am *messages.Authenticate) } if !bytes.Equal(am.NtChallengeResponseFields.Payload, n.ntChallengeResponse) { - if !bytes.Equal(am.LmChallengeResponse.Payload, n.lmChallengeResponse) { + // There is a bug with the steps in MS-NLMP. In section 3.2.5.1.2 it says you should fall through + // to compare the lmChallengeResponse if the ntChallengeRepsonse fails, but with extended session security + // this would *always* pass because the lmChallengeResponse and expectedLmChallengeRepsonse will always + // be the same + if !bytes.Equal(am.LmChallengeResponse.Payload, n.lmChallengeResponse) || messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(n.NegotiateFlags) { return errors.New("Could not authenticate") } } diff --git a/ntlm/ntlmv1_test.go b/ntlm/ntlmv1_test.go index ed852da..aec9348 100644 --- a/ntlm/ntlmv1_test.go +++ b/ntlm/ntlmv1_test.go @@ -4,6 +4,7 @@ package ntlm import ( "bytes" + "encoding/base64" "encoding/hex" "github.com/ThomsonReutersEikon/go-ntlm/ntlm/messages" "testing" @@ -38,6 +39,34 @@ func checkV1Value(t *testing.T, name string, value []byte, expected string, err } } +// There was an issue where all NTLMv1 authentications with extended session security +// would authenticate. This was due to a bug in the MS-NLMP docs. This tests for that issue +func TestNtlmV1ExtendedSessionSecurity(t *testing.T) { + // NTLMv1 with extended session security + challengeMessage := "TlRMTVNTUAACAAAAAAAAADgAAABVgphiRy3oSZvn1I4AAAAAAAAAAKIAogA4AAAABQEoCgAAAA8CAA4AUgBFAFUAVABFAFIAUwABABwAVQBLAEIAUAAtAEMAQgBUAFIATQBGAEUAMAA2AAQAFgBSAGUAdQB0AGUAcgBzAC4AbgBlAHQAAwA0AHUAawBiAHAALQBjAGIAdAByAG0AZgBlADAANgAuAFIAZQB1AHQAZQByAHMALgBuAGUAdAAFABYAUgBlAHUAdABlAHIAcwAuAG4AZQB0AAAAAAA=" + authenticateMessage := "TlRMTVNTUAADAAAAGAAYAJgAAAAYABgAsAAAAAAAAABIAAAAOgA6AEgAAAAWABYAggAAABAAEADIAAAAVYKYYgUCzg4AAAAPMQAwADAAMAAwADEALgB3AGMAcABAAHQAaABvAG0AcwBvAG4AcgBlAHUAdABlAHIAcwAuAGMAbwBtAE4AWQBDAFMATQBTAEcAOQA5ADAAOQBRWAK3h/TIywAAAAAAAAAAAAAAAAAAAAA3tp89kZU1hs1XZp7KTyGm3XsFAT9stEDW9YXDaeYVBmBcBb//2FOu" + + challengeData, _ := base64.StdEncoding.DecodeString(challengeMessage) + c, _ := messages.ParseChallengeMessage(challengeData) + + authenticateData, _ := base64.StdEncoding.DecodeString(authenticateMessage) + msg, err := messages.ParseAuthenticateMessage(authenticateData, 1) + if err != nil { + t.Errorf("Could not process authenticate message: %s", err) + } + + context, err := CreateServerSession(Version1, ConnectionlessMode) + if err != nil { + t.Errorf("Could not create NTLMv1 session") + } + context.SetUserInfo("100001.wcp.thomsonreuters.com", "notmypass", "") + context.SetServerChallenge(c.ServerChallenge) + err = context.ProcessAuthenticateMessage(msg) + if err == nil { + t.Errorf("This message should have failed to authenticate, but it passed", err) + } +} + func TestNtlmV1(t *testing.T) { flags := uint32(0) flags = messages.NTLMSSP_NEGOTIATE_KEY_EXCH.Set(flags)