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