-
Notifications
You must be signed in to change notification settings - Fork 74
/
Copy pathntlmv2_test.go
189 lines (163 loc) · 7.4 KB
/
ntlmv2_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//Copyright 2013 Thomson Reuters Global Resources. BSD License please see License file for more information
package ntlm
import (
"bytes"
"encoding/base64"
"encoding/hex"
"strings"
"testing"
"time"
)
func checkV2Value(t *testing.T, name string, value []byte, expected string, err error) {
if err != nil {
t.Errorf("NTLMv2 %s received error: %s", name, err)
} else {
expectedBytes, _ := hex.DecodeString(expected)
if !bytes.Equal(expectedBytes, value) {
t.Errorf("NTLMv2 %s is not correct got %s expected %s", name, hex.EncodeToString(value), expected)
}
}
}
func TestNTOWFv2(t *testing.T) {
result := ntowfv2("User", "Password", "Domain")
// Sample value from 4.2.4.1.1 in MS-NLMP
expected, _ := hex.DecodeString("0c868a403bfd7a93a3001ef22ef02e3f")
if !bytes.Equal(result, expected) {
t.Errorf("NTOWFv2 is not correct got %s expected %s", hex.EncodeToString(result), "0c868a403bfd7a93a3001ef22ef02e3f")
}
}
func TestNTLMv2(t *testing.T) {
flags := uint32(0)
flags = NTLMSSP_NEGOTIATE_KEY_EXCH.Set(flags)
flags = NTLMSSP_NEGOTIATE_56.Set(flags)
flags = NTLMSSP_NEGOTIATE_128.Set(flags)
flags = NTLMSSP_NEGOTIATE_VERSION.Set(flags)
flags = NTLMSSP_NEGOTIATE_TARGET_INFO.Set(flags)
flags = NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.Set(flags)
flags = NTLMSSP_TARGET_TYPE_SERVER.Set(flags)
flags = NTLMSSP_NEGOTIATE_ALWAYS_SIGN.Set(flags)
flags = NTLMSSP_NEGOTIATE_NTLM.Set(flags)
flags = NTLMSSP_NEGOTIATE_SEAL.Set(flags)
flags = NTLMSSP_NEGOTIATE_SIGN.Set(flags)
flags = NTLM_NEGOTIATE_OEM.Set(flags)
flags = NTLMSSP_NEGOTIATE_UNICODE.Set(flags)
// n := new(V2Session)
// n.SetUserInfo("User","Password","Domain")
// n.NegotiateFlags = flags
// n.responseKeyNT, _ = hex.DecodeString("0c868a403bfd7a93a3001ef22ef02e3f")
// n.responseKeyLM = n.responseKeyNT
// n.clientChallenge, _ = hex.DecodeString("aaaaaaaaaaaaaaaa")
// n.serverChallenge, _ = hex.DecodeString("0123456789abcdef")
// Encrypted Random Session key
//c5 da d2 54 4f c9 79 90 94 ce 1c e9 0b c9 d0 3e
// Challenge message
client := new(V2ClientSession)
client.SetUserInfo("User", "Password", "Domain")
challengeMessageBytes, _ := hex.DecodeString("4e544c4d53535000020000000c000c003800000033828ae20123456789abcdef00000000000000002400240044000000060070170000000f53006500720076006500720002000c0044006f006d00610069006e0001000c0053006500720076006500720000000000")
challengeMessage, err := ParseChallengeMessage(challengeMessageBytes)
if err == nil {
challengeMessage.String()
} else {
t.Errorf("Could not parse challenge message: %s", err)
}
err = client.ProcessChallengeMessage(challengeMessage)
if err != nil {
t.Errorf("Could not process challenge message: %s", err)
}
server := new(V2ServerSession)
server.SetUserInfo("User", "Password", "Domain")
server.serverChallenge = challengeMessage.ServerChallenge
// Authenticate message
r := strings.NewReplacer("\n", "", "\t", "", " ", "")
authenticateMessageBytes, _ := hex.DecodeString(r.Replace(`
4e544c4d535350000300000018001800
6c00000054005400840000000c000c00
48000000080008005400000010001000
5c00000010001000d8000000358288e2
0501280a0000000f44006f006d006100
69006e00550073006500720043004f00
4d005000550054004500520086c35097
ac9cec102554764a57cccc19aaaaaaaa
aaaaaaaa68cd0ab851e51c96aabc927b
ebef6a1c010100000000000000000000
00000000aaaaaaaaaaaaaaaa00000000
02000c0044006f006d00610069006e00
01000c00530065007200760065007200
0000000000000000c5dad2544fc97990
94ce1ce90bc9d03e`))
authenticateMessage, err := ParseAuthenticateMessage(authenticateMessageBytes, 2)
if err == nil {
authenticateMessage.String()
} else {
t.Errorf("Could not parse authenticate message: %s", err)
}
err = server.ProcessAuthenticateMessage(authenticateMessage)
if err != nil {
t.Errorf("Could not process authenticate message: %s", err)
}
checkV2Value(t, "SessionBaseKey", server.sessionBaseKey, "8de40ccadbc14a82f15cb0ad0de95ca3", nil)
checkV2Value(t, "NTChallengeResponse", server.ntChallengeResponse[0:16], "68cd0ab851e51c96aabc927bebef6a1c", nil)
checkV2Value(t, "LMChallengeResponse", server.lmChallengeResponse, "86c35097ac9cec102554764a57cccc19aaaaaaaaaaaaaaaa", nil)
checkV2Value(t, "client seal key", server.ClientSealingKey, "59f600973cc4960a25480a7c196e4c58", nil)
checkV2Value(t, "client signing key", server.ClientSigningKey, "4788dc861b4782f35d43fd98fe1a2d39", nil)
// Have the server generate an initial challenge message
challenge, err := server.GenerateChallengeMessage()
challenge.String()
// Have the client process this server challenge message
client = new(V2ClientSession)
client.SetUserInfo("User", "Password", "Domain")
err = client.ProcessChallengeMessage(challenge)
if err != nil {
t.Errorf("Could not process server generated challenge message: %s", err)
}
// TODO: we should be able to use the ntlm library end to end to make sure
// that Mac, VerifyMac
// // the client should be able to verify the server's mac
// sig := "<NTLM><foo><bar>"
// mac, err := server.Mac([]byte(sig), 100)
// if err != nil {
// t.Errorf("Could not generate a mac for %s", sig)
// }
// matches, err := client.VerifyMac([]byte(sig), mac, 100)
// if err != nil {
// t.Errorf("Could not verify mac for %s (mac = %v)", sig, mac)
// }
// if !matches {
// t.Errorf("Server's Mac couldn't be verified by client")
// }
// mac, err = client.Mac([]byte(sig), 100)
// if err != nil {
// t.Errorf("Could not generate a mac for %s", sig)
// }
// matches, err = server.VerifyMac([]byte(sig), mac, 100)
// if err != nil {
// t.Errorf("Could not verify mac for %s (mac = %v)", sig, mac)
// }
// if !matches {
// t.Errorf("Client's Mac couldn't be verified by server")
// }
}
func TestNTLMv2WithDomain(t *testing.T) {
authenticateMessage := "TlRMTVNTUAADAAAAGAAYALYAAADSANIAzgAAADQANABIAAAAIAAgAHwAAAAaABoAnAAAABAAEACgAQAAVYKQQgUCzg4AAAAPYQByAHIAYQB5ADEAMgAuAG0AcwBnAHQAcwB0AC4AcgBlAHUAdABlAHIAcwAuAGMAbwBtAHUAcwBlAHIAcwB0AHIAZQBzAHMAMQAwADAAMAAwADgATgBZAEMAVgBBADEAMgBTADIAQwBNAFMAQQBPYrLjU4h0YlWZeEoNvTJtBQMnnJuAeUwsP+vGmAHNRBpgZ+4ChQLqAQEAAAAAAACPFEIFjx7OAQUDJ5ybgHlMAAAAAAIADgBSAEUAVQBUAEUAUgBTAAEAHABVAEsAQgBQAC0AQwBCAFQAUgBNAEYARQAwADYABAAWAFIAZQB1AHQAZQByAHMALgBuAGUAdAADADQAdQBrAGIAcAAtAGMAYgB0AHIAbQBmAGUAMAA2AC4AUgBlAHUAdABlAHIAcwAuAG4AZQB0AAUAFgBSAGUAdQB0AGUAcgBzAC4AbgBlAHQAAAAAAAAAAAANuvnqD3K88ZpjkLleL0NW"
server := new(V2ServerSession)
server.SetUserInfo("blahblah", "Welcome1", "blahblah")
authenticateData, _ := base64.StdEncoding.DecodeString(authenticateMessage)
a, _ := ParseAuthenticateMessage(authenticateData, 2)
serverChallenge, _ := hex.DecodeString("3d74b2d04ebe1eb3")
server.SetServerChallenge(serverChallenge)
err := server.ProcessAuthenticateMessage(a)
if err != nil {
t.Error("Could not process authenticate message: %s\n", err)
}
}
func TestWindowsTimeConversion(t *testing.T) {
// 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,
// 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)
// will give us tenths of a microsecond (127003176000000000). As a little-endian 64-bit value, this is
// "0x0090d336b734c301" (in hexadecimal).
unix := time.Unix(1055844000, 0)
result := timeToWindowsFileTime(unix)
checkV2Value(t, "Timestamp", result, "0090d336b734c301", nil)
}