exposing more functions

This commit is contained in:
Matthew Kanwisher 2013-05-11 18:09:05 -04:00
parent d960dfe90e
commit 1da4ab53b9
5 changed files with 68 additions and 53 deletions

View File

@ -97,7 +97,7 @@ type SessionData struct {
password string password string
userDomain string userDomain string
negotiateFlags uint32 NegotiateFlags uint32
negotiateMessage *messages.Negotiate negotiateMessage *messages.Negotiate
challengeMessage *messages.Challenge challengeMessage *messages.Challenge

View File

@ -46,7 +46,7 @@ func (n *V1Session) fetchResponseKeys() (err error) {
} }
func (n *V1Session) computeExpectedResponses() (err error) { func (n *V1Session) computeExpectedResponses() (err error) {
if messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(n.negotiateFlags) { if messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(n.NegotiateFlags) {
n.ntChallengeResponse, err = desL(n.responseKeyNT, md5(concat(n.serverChallenge, n.clientChallenge))[0:8]) n.ntChallengeResponse, err = desL(n.responseKeyNT, md5(concat(n.serverChallenge, n.clientChallenge))[0:8])
if err != nil { if err != nil {
return err return err
@ -81,10 +81,10 @@ func (n *V1Session) computeSessionBaseKey() (err error) {
} }
func (n *V1Session) computeKeyExchangeKey() (err error) { func (n *V1Session) computeKeyExchangeKey() (err error) {
if messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(n.negotiateFlags) { if messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(n.NegotiateFlags) {
n.keyExchangeKey = hmacMd5(n.sessionBaseKey, concat(n.serverChallenge, n.lmChallengeResponse[0:8])) n.keyExchangeKey = hmacMd5(n.sessionBaseKey, concat(n.serverChallenge, n.lmChallengeResponse[0:8]))
} else { } else {
n.keyExchangeKey, err = kxKey(n.negotiateFlags, n.sessionBaseKey, n.lmChallengeResponse, n.serverChallenge, n.responseKeyLM) n.keyExchangeKey, err = kxKey(n.NegotiateFlags, n.sessionBaseKey, n.lmChallengeResponse, n.serverChallenge, n.responseKeyLM)
} }
return return
} }
@ -95,13 +95,13 @@ func (n *V1Session) calculateKeys(ntlmRevisionCurrent uint8) (err error) {
// We must treat the flags as if NTLMSSP_NEGOTIATE_LM_KEY is set. // We must treat the flags as if NTLMSSP_NEGOTIATE_LM_KEY is set.
// This information is not contained (at least currently, until they correct it) in the MS-NLMP document // This information is not contained (at least currently, until they correct it) in the MS-NLMP document
if ntlmRevisionCurrent == 15 { if ntlmRevisionCurrent == 15 {
n.negotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Set(n.negotiateFlags) n.NegotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Set(n.NegotiateFlags)
} }
n.ClientSigningKey = signKey(n.negotiateFlags, n.exportedSessionKey, "Client") n.ClientSigningKey = signKey(n.NegotiateFlags, n.exportedSessionKey, "Client")
n.ServerSigningKey = signKey(n.negotiateFlags, n.exportedSessionKey, "Server") n.ServerSigningKey = signKey(n.NegotiateFlags, n.exportedSessionKey, "Server")
n.ClientSealingKey = sealKey(n.negotiateFlags, n.exportedSessionKey, "Client") n.ClientSealingKey = sealKey(n.NegotiateFlags, n.exportedSessionKey, "Client")
n.ServerSealingKey = sealKey(n.negotiateFlags, n.exportedSessionKey, "Server") n.ServerSealingKey = sealKey(n.NegotiateFlags, n.exportedSessionKey, "Server")
return return
} }
@ -113,36 +113,36 @@ func (n *V1Session) Sign(message []byte) ([]byte, error) {
return nil, nil return nil, nil
} }
func ntlmV1Mac(message []byte, sequenceNumber int, handle *rc4P.Cipher, sealingKey, signingKey []byte, negotiateFlags uint32) []byte { func ntlmV1Mac(message []byte, sequenceNumber int, handle *rc4P.Cipher, sealingKey, signingKey []byte, NegotiateFlags uint32) []byte {
// TODO: Need to keep track of the sequence number for connection oriented NTLM // TODO: Need to keep track of the sequence number for connection oriented NTLM
if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(negotiateFlags) && messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(negotiateFlags) { if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(NegotiateFlags) && messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(NegotiateFlags) {
handle, _ = reinitSealingKey(sealingKey, sequenceNumber) handle, _ = reinitSealingKey(sealingKey, sequenceNumber)
} else if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(negotiateFlags) { } else if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(NegotiateFlags) {
// CONOR: Reinitializing the rc4 cipher on every requst, but not using the // CONOR: Reinitializing the rc4 cipher on every requst, but not using the
// algorithm as described in the MS-NTLM document. Just reinitialize it directly. // algorithm as described in the MS-NTLM document. Just reinitialize it directly.
handle, _ = rc4Init(sealingKey) handle, _ = rc4Init(sealingKey)
} }
sig := mac(negotiateFlags, handle, signingKey, uint32(sequenceNumber), message) sig := mac(NegotiateFlags, handle, signingKey, uint32(sequenceNumber), message)
return sig.Bytes() return sig.Bytes()
} }
func (n *V1ServerSession) Mac(message []byte, sequenceNumber int) ([]byte, error) { func (n *V1ServerSession) Mac(message []byte, sequenceNumber int) ([]byte, error) {
mac := ntlmV1Mac(message, sequenceNumber, n.serverHandle, n.ServerSealingKey, n.ServerSigningKey, n.negotiateFlags) mac := ntlmV1Mac(message, sequenceNumber, n.serverHandle, n.ServerSealingKey, n.ServerSigningKey, n.NegotiateFlags)
return mac, nil return mac, nil
} }
func (n *V1ClientSession) Mac(message []byte, sequenceNumber int) ([]byte, error) { func (n *V1ClientSession) Mac(message []byte, sequenceNumber int) ([]byte, error) {
mac := ntlmV1Mac(message, sequenceNumber, n.clientHandle, n.ClientSealingKey, n.ClientSigningKey, n.negotiateFlags) mac := ntlmV1Mac(message, sequenceNumber, n.clientHandle, n.ClientSealingKey, n.ClientSigningKey, n.NegotiateFlags)
return mac, nil return mac, nil
} }
func (n *V1ServerSession) VerifyMac(message, expectedMac []byte, sequenceNumber int) (bool, error) { func (n *V1ServerSession) VerifyMac(message, expectedMac []byte, sequenceNumber int) (bool, error) {
mac := ntlmV1Mac(message, sequenceNumber, n.clientHandle, n.ClientSealingKey, n.ClientSigningKey, n.negotiateFlags) mac := ntlmV1Mac(message, sequenceNumber, n.clientHandle, n.ClientSealingKey, n.ClientSigningKey, n.NegotiateFlags)
return macsEqual(mac, expectedMac), nil return macsEqual(mac, expectedMac), nil
} }
func (n *V1ClientSession) VerifyMac(message, expectedMac []byte, sequenceNumber int) (bool, error) { func (n *V1ClientSession) VerifyMac(message, expectedMac []byte, sequenceNumber int) (bool, error) {
mac := ntlmV1Mac(message, sequenceNumber, n.serverHandle, n.ServerSealingKey, n.ServerSigningKey, n.negotiateFlags) mac := ntlmV1Mac(message, sequenceNumber, n.serverHandle, n.ServerSealingKey, n.ServerSigningKey, n.NegotiateFlags)
return macsEqual(mac, expectedMac), nil return macsEqual(mac, expectedMac), nil
} }
@ -174,7 +174,7 @@ func (n *V1ServerSession) GetSessionData() *SessionData {
func (n *V1ServerSession) ProcessAuthenticateMessage(am *messages.Authenticate) (err error) { func (n *V1ServerSession) ProcessAuthenticateMessage(am *messages.Authenticate) (err error) {
n.authenticateMessage = am n.authenticateMessage = am
n.negotiateFlags = am.NegotiateFlags n.NegotiateFlags = am.NegotiateFlags
n.clientChallenge = am.ClientChallenge() n.clientChallenge = am.ClientChallenge()
n.encryptedRandomSessionKey = am.EncryptedRandomSessionKey.Payload n.encryptedRandomSessionKey = am.EncryptedRandomSessionKey.Payload
// Ignore the values used in SetUserInfo and use these instead from the authenticate message // Ignore the values used in SetUserInfo and use these instead from the authenticate message
@ -235,7 +235,7 @@ func (n *V1ServerSession) ProcessAuthenticateMessage(am *messages.Authenticate)
} }
func (n *V1ServerSession) computeExportedSessionKey() (err error) { func (n *V1ServerSession) computeExportedSessionKey() (err error) {
if messages.NTLMSSP_NEGOTIATE_KEY_EXCH.IsSet(n.negotiateFlags) { if messages.NTLMSSP_NEGOTIATE_KEY_EXCH.IsSet(n.NegotiateFlags) {
n.exportedSessionKey, err = rc4K(n.keyExchangeKey, n.encryptedRandomSessionKey) n.exportedSessionKey, err = rc4K(n.keyExchangeKey, n.encryptedRandomSessionKey)
if err != nil { if err != nil {
return err return err
@ -283,7 +283,7 @@ func (n *V1ClientSession) ProcessChallengeMessage(cm *messages.Challenge) (err e
flags = messages.NTLMSSP_REQUEST_TARGET.Set(flags) flags = messages.NTLMSSP_REQUEST_TARGET.Set(flags)
flags = messages.NTLMSSP_NEGOTIATE_UNICODE.Set(flags) flags = messages.NTLMSSP_NEGOTIATE_UNICODE.Set(flags)
n.negotiateFlags = flags n.NegotiateFlags = flags
err = n.fetchResponseKeys() err = n.fetchResponseKeys()
if err != nil { if err != nil {
@ -337,13 +337,13 @@ func (n *V1ClientSession) GenerateAuthenticateMessage() (am *messages.Authentica
am.UserName, _ = messages.CreateStringPayload(n.user) am.UserName, _ = messages.CreateStringPayload(n.user)
am.Workstation, _ = messages.CreateStringPayload("SQUAREMILL") am.Workstation, _ = messages.CreateStringPayload("SQUAREMILL")
am.EncryptedRandomSessionKey, _ = messages.CreateBytePayload(n.encryptedRandomSessionKey) am.EncryptedRandomSessionKey, _ = messages.CreateBytePayload(n.encryptedRandomSessionKey)
am.NegotiateFlags = n.negotiateFlags am.NegotiateFlags = n.NegotiateFlags
am.Version = &messages.VersionStruct{ProductMajorVersion: uint8(5), ProductMinorVersion: uint8(1), ProductBuild: uint16(2600), NTLMRevisionCurrent: uint8(15)} am.Version = &messages.VersionStruct{ProductMajorVersion: uint8(5), ProductMinorVersion: uint8(1), ProductBuild: uint16(2600), NTLMRevisionCurrent: uint8(15)}
return am, nil return am, nil
} }
func (n *V1ClientSession) computeEncryptedSessionKey() (err error) { func (n *V1ClientSession) computeEncryptedSessionKey() (err error) {
if messages.NTLMSSP_NEGOTIATE_KEY_EXCH.IsSet(n.negotiateFlags) { if messages.NTLMSSP_NEGOTIATE_KEY_EXCH.IsSet(n.NegotiateFlags) {
n.exportedSessionKey = randomBytes(16) n.exportedSessionKey = randomBytes(16)
n.encryptedRandomSessionKey, err = rc4K(n.keyExchangeKey, n.exportedSessionKey) n.encryptedRandomSessionKey, err = rc4K(n.keyExchangeKey, n.exportedSessionKey)
if err != nil { if err != nil {

View File

@ -52,7 +52,7 @@ func TestNtlmV1(t *testing.T) {
n := new(V1ClientSession) n := new(V1ClientSession)
n.SetUserInfo("User", "Password", "Domain") n.SetUserInfo("User", "Password", "Domain")
n.negotiateFlags = flags n.NegotiateFlags = flags
n.responseKeyNT, _ = hex.DecodeString("a4f49c406510bdcab6824ee7c30fd852") n.responseKeyNT, _ = hex.DecodeString("a4f49c406510bdcab6824ee7c30fd852")
n.responseKeyLM, _ = hex.DecodeString("e52cac67419a9a224a3b108f3fa6cb6d") n.responseKeyLM, _ = hex.DecodeString("e52cac67419a9a224a3b108f3fa6cb6d")
n.clientChallenge, _ = hex.DecodeString("aaaaaaaaaaaaaaaa") n.clientChallenge, _ = hex.DecodeString("aaaaaaaaaaaaaaaa")
@ -75,10 +75,10 @@ func TestNtlmV1(t *testing.T) {
checkV1Value(t, "LMChallengeResponse", n.lmChallengeResponse, "98def7b87f88aa5dafe2df779688a172def11c7d5ccdef13", err) checkV1Value(t, "LMChallengeResponse", n.lmChallengeResponse, "98def7b87f88aa5dafe2df779688a172def11c7d5ccdef13", err)
// If the NTLMSSP_NEGOTIATE_LM_KEY flag is set then the KeyExchangeKey is: // If the NTLMSSP_NEGOTIATE_LM_KEY flag is set then the KeyExchangeKey is:
n.negotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Set(n.negotiateFlags) n.NegotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Set(n.NegotiateFlags)
err = n.computeKeyExchangeKey() err = n.computeKeyExchangeKey()
checkV1Value(t, "keyExchangeKey with NTLMSSP_NEGOTIATE_LM_KEY", n.keyExchangeKey, "b09e379f7fbecb1eaf0afdcb0383c8a0", err) checkV1Value(t, "keyExchangeKey with NTLMSSP_NEGOTIATE_LM_KEY", n.keyExchangeKey, "b09e379f7fbecb1eaf0afdcb0383c8a0", err)
n.negotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Unset(n.negotiateFlags) n.NegotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Unset(n.NegotiateFlags)
// 4.2.2.2.3 Encrypted Session Key // 4.2.2.2.3 Encrypted Session Key
//n.randomSessionKey, _ = hex.DecodeString("55555555555555555555555555555555") //n.randomSessionKey, _ = hex.DecodeString("55555555555555555555555555555555")
@ -90,20 +90,20 @@ func TestNtlmV1(t *testing.T) {
//checkV1Value(t, "ExportedSessionKey", n.exportedSessionKey, "55555555555555555555555555555555", err) //checkV1Value(t, "ExportedSessionKey", n.exportedSessionKey, "55555555555555555555555555555555", err)
// NTLMSSP_REQUEST_NON_NT_SESSION_KEY is set: // NTLMSSP_REQUEST_NON_NT_SESSION_KEY is set:
n.negotiateFlags = messages.NTLMSSP_REQUEST_NON_NT_SESSION_KEY.Set(n.negotiateFlags) n.NegotiateFlags = messages.NTLMSSP_REQUEST_NON_NT_SESSION_KEY.Set(n.NegotiateFlags)
err = n.computeKeyExchangeKey() err = n.computeKeyExchangeKey()
// n.encryptedRandomSessionKey, err = hex.DecodeString("7452ca55c225a1ca04b48fae32cf56fc") // n.encryptedRandomSessionKey, err = hex.DecodeString("7452ca55c225a1ca04b48fae32cf56fc")
// err = n.computeExportedSessionKey() // err = n.computeExportedSessionKey()
// checkV1Value(t, "ExportedSessionKey - NTLMSSP_REQUEST_NON_NT_SESSION_KEY", n.exportedSessionKey, "55555555555555555555555555555555", err) // checkV1Value(t, "ExportedSessionKey - NTLMSSP_REQUEST_NON_NT_SESSION_KEY", n.exportedSessionKey, "55555555555555555555555555555555", err)
n.negotiateFlags = messages.NTLMSSP_REQUEST_NON_NT_SESSION_KEY.Unset(n.negotiateFlags) n.NegotiateFlags = messages.NTLMSSP_REQUEST_NON_NT_SESSION_KEY.Unset(n.NegotiateFlags)
// NTLMSSP_NEGOTIATE_LM_KEY is set: // NTLMSSP_NEGOTIATE_LM_KEY is set:
n.negotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Set(n.negotiateFlags) n.NegotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Set(n.NegotiateFlags)
err = n.computeKeyExchangeKey() err = n.computeKeyExchangeKey()
// n.encryptedRandomSessionKey, err = hex.DecodeString("4cd7bb57d697ef9b549f02b8f9b37864") // n.encryptedRandomSessionKey, err = hex.DecodeString("4cd7bb57d697ef9b549f02b8f9b37864")
// err = n.computeExportedSessionKey() // err = n.computeExportedSessionKey()
// checkV1Value(t, "ExportedSessionKey - NTLMSSP_NEGOTIATE_LM_KEY", n.exportedSessionKey, "55555555555555555555555555555555", err) // checkV1Value(t, "ExportedSessionKey - NTLMSSP_NEGOTIATE_LM_KEY", n.exportedSessionKey, "55555555555555555555555555555555", err)
n.negotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Unset(n.negotiateFlags) n.NegotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Unset(n.NegotiateFlags)
// 4.2.2.3 Messages // 4.2.2.3 Messages
challengeMessageBytes, _ := hex.DecodeString("4e544c4d53535000020000000c000c003800000033820a820123456789abcdef00000000000000000000000000000000060070170000000f530065007200760065007200") challengeMessageBytes, _ := hex.DecodeString("4e544c4d53535000020000000c000c003800000033820a820123456789abcdef00000000000000000000000000000000060070170000000f530065007200760065007200")
@ -155,7 +155,7 @@ func TestNTLMv1WithClientChallenge(t *testing.T) {
flags = messages.NTLMSSP_NEGOTIATE_UNICODE.Set(flags) flags = messages.NTLMSSP_NEGOTIATE_UNICODE.Set(flags)
n := new(V1Session) n := new(V1Session)
n.negotiateFlags = flags n.NegotiateFlags = flags
n.responseKeyNT, _ = hex.DecodeString("a4f49c406510bdcab6824ee7c30fd852") n.responseKeyNT, _ = hex.DecodeString("a4f49c406510bdcab6824ee7c30fd852")
n.responseKeyLM, _ = hex.DecodeString("e52cac67419a9a224a3b108f3fa6cb6d") n.responseKeyLM, _ = hex.DecodeString("e52cac67419a9a224a3b108f3fa6cb6d")
n.clientChallenge, _ = hex.DecodeString("aaaaaaaaaaaaaaaa") n.clientChallenge, _ = hex.DecodeString("aaaaaaaaaaaaaaaa")

View File

@ -72,13 +72,13 @@ func (n *V2Session) calculateKeys(ntlmRevisionCurrent uint8) (err error) {
// We must treat the flags as if NTLMSSP_NEGOTIATE_LM_KEY is set. // We must treat the flags as if NTLMSSP_NEGOTIATE_LM_KEY is set.
// This information is not contained (at least currently, until they correct it) in the MS-NLMP document // This information is not contained (at least currently, until they correct it) in the MS-NLMP document
if ntlmRevisionCurrent == 15 { if ntlmRevisionCurrent == 15 {
n.negotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Set(n.negotiateFlags) n.NegotiateFlags = messages.NTLMSSP_NEGOTIATE_LM_KEY.Set(n.NegotiateFlags)
} }
n.ClientSigningKey = signKey(n.negotiateFlags, n.exportedSessionKey, "Client") n.ClientSigningKey = signKey(n.NegotiateFlags, n.exportedSessionKey, "Client")
n.ServerSigningKey = signKey(n.negotiateFlags, n.exportedSessionKey, "Server") n.ServerSigningKey = signKey(n.NegotiateFlags, n.exportedSessionKey, "Server")
n.ClientSealingKey = sealKey(n.negotiateFlags, n.exportedSessionKey, "Client") n.ClientSealingKey = sealKey(n.NegotiateFlags, n.exportedSessionKey, "Client")
n.ServerSealingKey = sealKey(n.negotiateFlags, n.exportedSessionKey, "Server") n.ServerSealingKey = sealKey(n.NegotiateFlags, n.exportedSessionKey, "Server")
return return
} }
@ -89,36 +89,51 @@ func (n *V2Session) Sign(message []byte) ([]byte, error) {
return nil, nil return nil, nil
} }
func ntlmV2Mac(message []byte, sequenceNumber int, handle *rc4P.Cipher, sealingKey, signingKey []byte, negotiateFlags uint32) []byte { //Mildly ghetto that we expose this
func NtlmVCommonMac(message []byte, sequenceNumber int, sealingKey, signingKey []byte, NegotiateFlags uint32) []byte {
var handle *rc4P.Cipher
// TODO: Need to keep track of the sequence number for connection oriented NTLM // TODO: Need to keep track of the sequence number for connection oriented NTLM
if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(negotiateFlags) && messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(negotiateFlags) { if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(NegotiateFlags) && messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(NegotiateFlags) {
handle, _ = reinitSealingKey(sealingKey, sequenceNumber) handle, _ = reinitSealingKey(sealingKey, sequenceNumber)
} else if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(negotiateFlags) { } else if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(NegotiateFlags) {
// CONOR: Reinitializing the rc4 cipher on every requst, but not using the // CONOR: Reinitializing the rc4 cipher on every requst, but not using the
// algorithm as described in the MS-NTLM document. Just reinitialize it directly. // algorithm as described in the MS-NTLM document. Just reinitialize it directly.
handle, _ = rc4Init(sealingKey) handle, _ = rc4Init(sealingKey)
} }
sig := mac(negotiateFlags, handle, signingKey, uint32(sequenceNumber), message) sig := mac(NegotiateFlags, handle, signingKey, uint32(sequenceNumber), message)
return sig.Bytes()
}
func NtlmV2Mac(message []byte, sequenceNumber int, handle *rc4P.Cipher, sealingKey, signingKey []byte, NegotiateFlags uint32) []byte {
// TODO: Need to keep track of the sequence number for connection oriented NTLM
if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(NegotiateFlags) && messages.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.IsSet(NegotiateFlags) {
handle, _ = reinitSealingKey(sealingKey, sequenceNumber)
} else if messages.NTLMSSP_NEGOTIATE_DATAGRAM.IsSet(NegotiateFlags) {
// CONOR: Reinitializing the rc4 cipher on every requst, but not using the
// algorithm as described in the MS-NTLM document. Just reinitialize it directly.
handle, _ = rc4Init(sealingKey)
}
sig := mac(NegotiateFlags, handle, signingKey, uint32(sequenceNumber), message)
return sig.Bytes() return sig.Bytes()
} }
func (n *V2ServerSession) Mac(message []byte, sequenceNumber int) ([]byte, error) { func (n *V2ServerSession) Mac(message []byte, sequenceNumber int) ([]byte, error) {
mac := ntlmV2Mac(message, sequenceNumber, n.serverHandle, n.ServerSealingKey, n.ServerSigningKey, n.negotiateFlags) mac := NtlmV2Mac(message, sequenceNumber, n.serverHandle, n.ServerSealingKey, n.ServerSigningKey, n.NegotiateFlags)
return mac, nil return mac, nil
} }
func (n *V2ServerSession) VerifyMac(message, expectedMac []byte, sequenceNumber int) (bool, error) { func (n *V2ServerSession) VerifyMac(message, expectedMac []byte, sequenceNumber int) (bool, error) {
mac := ntlmV2Mac(message, sequenceNumber, n.clientHandle, n.ClientSealingKey, n.ClientSigningKey, n.negotiateFlags) mac := NtlmV2Mac(message, sequenceNumber, n.clientHandle, n.ClientSealingKey, n.ClientSigningKey, n.NegotiateFlags)
return macsEqual(mac, expectedMac), nil return macsEqual(mac, expectedMac), nil
} }
func (n *V2ClientSession) Mac(message []byte, sequenceNumber int) ([]byte, error) { func (n *V2ClientSession) Mac(message []byte, sequenceNumber int) ([]byte, error) {
mac := ntlmV2Mac(message, sequenceNumber, n.clientHandle, n.ClientSealingKey, n.ClientSigningKey, n.negotiateFlags) mac := NtlmV2Mac(message, sequenceNumber, n.clientHandle, n.ClientSealingKey, n.ClientSigningKey, n.NegotiateFlags)
return mac, nil return mac, nil
} }
func (n *V2ClientSession) VerifyMac(message, expectedMac []byte, sequenceNumber int) (bool, error) { func (n *V2ClientSession) VerifyMac(message, expectedMac []byte, sequenceNumber int) (bool, error) {
mac := ntlmV2Mac(message, sequenceNumber, n.serverHandle, n.ServerSealingKey, n.ServerSigningKey, n.negotiateFlags) mac := NtlmV2Mac(message, sequenceNumber, n.serverHandle, n.ServerSealingKey, n.ServerSigningKey, n.NegotiateFlags)
return macsEqual(mac, expectedMac), nil return macsEqual(mac, expectedMac), nil
} }
@ -182,7 +197,7 @@ func (n *V2ServerSession) GenerateChallengeMessage() (cm *messages.Challenge, er
func (n *V2ServerSession) ProcessAuthenticateMessage(am *messages.Authenticate) (err error) { func (n *V2ServerSession) ProcessAuthenticateMessage(am *messages.Authenticate) (err error) {
n.authenticateMessage = am n.authenticateMessage = am
n.negotiateFlags = am.NegotiateFlags n.NegotiateFlags = am.NegotiateFlags
n.clientChallenge = am.ClientChallenge() n.clientChallenge = am.ClientChallenge()
n.encryptedRandomSessionKey = am.EncryptedRandomSessionKey.Payload n.encryptedRandomSessionKey = am.EncryptedRandomSessionKey.Payload
// Ignore the values used in SetUserInfo and use these instead from the authenticate message // Ignore the values used in SetUserInfo and use these instead from the authenticate message
@ -241,7 +256,7 @@ func (n *V2ServerSession) ProcessAuthenticateMessage(am *messages.Authenticate)
} }
func (n *V2ServerSession) computeExportedSessionKey() (err error) { func (n *V2ServerSession) computeExportedSessionKey() (err error) {
if messages.NTLMSSP_NEGOTIATE_KEY_EXCH.IsSet(n.negotiateFlags) { if messages.NTLMSSP_NEGOTIATE_KEY_EXCH.IsSet(n.NegotiateFlags) {
n.exportedSessionKey, err = rc4K(n.keyExchangeKey, n.encryptedRandomSessionKey) n.exportedSessionKey, err = rc4K(n.keyExchangeKey, n.encryptedRandomSessionKey)
if err != nil { if err != nil {
return err return err
@ -289,7 +304,7 @@ func (n *V2ClientSession) ProcessChallengeMessage(cm *messages.Challenge) (err e
flags = messages.NTLMSSP_NEGOTIATE_UNICODE.Set(flags) flags = messages.NTLMSSP_NEGOTIATE_UNICODE.Set(flags)
flags = messages.NTLMSSP_NEGOTIATE_128.Set(flags) flags = messages.NTLMSSP_NEGOTIATE_128.Set(flags)
n.negotiateFlags = flags n.NegotiateFlags = flags
err = n.fetchResponseKeys() err = n.fetchResponseKeys()
if err != nil { if err != nil {
@ -338,14 +353,14 @@ func (n *V2ClientSession) GenerateAuthenticateMessage() (am *messages.Authentica
am.UserName, _ = messages.CreateStringPayload(n.user) am.UserName, _ = messages.CreateStringPayload(n.user)
am.Workstation, _ = messages.CreateStringPayload("SQUAREMILL") am.Workstation, _ = messages.CreateStringPayload("SQUAREMILL")
am.EncryptedRandomSessionKey, _ = messages.CreateBytePayload(n.encryptedRandomSessionKey) am.EncryptedRandomSessionKey, _ = messages.CreateBytePayload(n.encryptedRandomSessionKey)
am.NegotiateFlags = n.negotiateFlags am.NegotiateFlags = n.NegotiateFlags
am.Mic = make([]byte, 16) am.Mic = make([]byte, 16)
am.Version = &messages.VersionStruct{ProductMajorVersion: uint8(5), ProductMinorVersion: uint8(1), ProductBuild: uint16(2600), NTLMRevisionCurrent: 0x0F} am.Version = &messages.VersionStruct{ProductMajorVersion: uint8(5), ProductMinorVersion: uint8(1), ProductBuild: uint16(2600), NTLMRevisionCurrent: 0x0F}
return am, nil return am, nil
} }
func (n *V2ClientSession) computeEncryptedSessionKey() (err error) { func (n *V2ClientSession) computeEncryptedSessionKey() (err error) {
if messages.NTLMSSP_NEGOTIATE_KEY_EXCH.IsSet(n.negotiateFlags) { if messages.NTLMSSP_NEGOTIATE_KEY_EXCH.IsSet(n.NegotiateFlags) {
n.exportedSessionKey = randomBytes(16) n.exportedSessionKey = randomBytes(16)
n.encryptedRandomSessionKey, err = rc4K(n.keyExchangeKey, n.exportedSessionKey) n.encryptedRandomSessionKey, err = rc4K(n.keyExchangeKey, n.exportedSessionKey)
if err != nil { if err != nil {

View File

@ -48,7 +48,7 @@ func TestNTLMv2(t *testing.T) {
// n := new(V2Session) // n := new(V2Session)
// n.SetUserInfo("User","Password","Domain") // n.SetUserInfo("User","Password","Domain")
// n.negotiateFlags = flags // n.NegotiateFlags = flags
// n.responseKeyNT, _ = hex.DecodeString("0c868a403bfd7a93a3001ef22ef02e3f") // n.responseKeyNT, _ = hex.DecodeString("0c868a403bfd7a93a3001ef22ef02e3f")
// n.responseKeyLM = n.responseKeyNT // n.responseKeyLM = n.responseKeyNT
// n.clientChallenge, _ = hex.DecodeString("aaaaaaaaaaaaaaaa") // n.clientChallenge, _ = hex.DecodeString("aaaaaaaaaaaaaaaa")
@ -177,10 +177,10 @@ func TestNTLMv2WithDomain(t *testing.T) {
func TestWindowsTimeConversion(t *testing.T) { func TestWindowsTimeConversion(t *testing.T) {
// From http://davenport.sourceforge.net/ntlm.html#theType3Message // From http://davenport.sourceforge.net/ntlm.html#theType3Message
// Next, the blob is constructed. The timestamp is the most tedious part of this; looking at the clock on my desk, // Next, the blob is constructed. The timestamp is the most tedious part of this; looking at the clock on my desk,
// it's about 6:00 AM EDT on June 17th, 2003. In Unix time, that would be 1055844000 seconds after the Epoch. // it's about 6:00 AM EDT on June 17th, 2003. In Unix time, that would be 1055844000 seconds after the Epoch.
// Adding 11644473600 will give us seconds after January 1, 1601 (12700317600). Multiplying by 107 (10000000) // Adding 11644473600 will give us seconds after January 1, 1601 (12700317600). Multiplying by 107 (10000000)
// will give us tenths of a microsecond (127003176000000000). As a little-endian 64-bit value, this is // will give us tenths of a microsecond (127003176000000000). As a little-endian 64-bit value, this is
// "0x0090d336b734c301" (in hexadecimal). // "0x0090d336b734c301" (in hexadecimal).
unix := time.Unix(1055844000, 0) unix := time.Unix(1055844000, 0)
result := timeToWindowsFileTime(unix) result := timeToWindowsFileTime(unix)