1 //
2 // NTLMCredentialsTest.cpp
3 //
4 // Copyright (c) 2014, Applied Informatics Software Engineering GmbH.
5 // and Contributors.
6 //
7 // SPDX-License-Identifier: BSL-1.0
8 //
9
10
11 #include "NTLMCredentialsTest.h"
12 #include "CppUnit/TestCaller.h"
13 #include "CppUnit/TestSuite.h"
14 #include "Poco/Net/NTLMCredentials.h"
15 #include "Poco/DigestEngine.h"
16
17
18 using Poco::Net::NTLMCredentials;
19
20
NTLMCredentialsTest(const std::string & name)21 NTLMCredentialsTest::NTLMCredentialsTest(const std::string& name): CppUnit::TestCase(name)
22 {
23 }
24
25
~NTLMCredentialsTest()26 NTLMCredentialsTest::~NTLMCredentialsTest()
27 {
28 }
29
30
testNonce()31 void NTLMCredentialsTest::testNonce()
32 {
33 std::vector<unsigned char> nonce1 = NTLMCredentials::createNonce();
34 assertTrue (nonce1.size() == 8);
35
36 std::vector<unsigned char> nonce2 = NTLMCredentials::createNonce();
37 assertTrue (nonce2.size() == 8);
38
39 assertTrue (nonce1 != nonce2);
40 }
41
42
testPasswordHash()43 void NTLMCredentialsTest::testPasswordHash()
44 {
45 std::vector<unsigned char> passHash = NTLMCredentials::createPasswordHash("SecREt01");
46 std::string passHashHex = Poco::DigestEngine::digestToHex(passHash);
47 assertTrue (passHashHex == "cd06ca7c7e10c99b1d33b7485a2ed808");
48 }
49
50
testNTLMv2Hash()51 void NTLMCredentialsTest::testNTLMv2Hash()
52 {
53 std::vector<unsigned char> ntlm2Hash = NTLMCredentials::createNTLMv2Hash("user", "DOMAIN", "SecREt01");
54 std::string ntlm2HashHex = Poco::DigestEngine::digestToHex(ntlm2Hash);
55 assertTrue (ntlm2HashHex == "04b8e0ba74289cc540826bab1dee63ae");
56 }
57
58
testLMv2Response()59 void NTLMCredentialsTest::testLMv2Response()
60 {
61 static const unsigned char CHALLENGE[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
62 static const unsigned char NONCE[] = {0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44};
63
64 std::vector<unsigned char> challenge(CHALLENGE, CHALLENGE + 8);
65 std::vector<unsigned char> nonce(NONCE, NONCE + 8);
66
67 std::vector<unsigned char> ntlm2Hash = NTLMCredentials::createNTLMv2Hash("user", "DOMAIN", "SecREt01");
68 std::vector<unsigned char> lm2Response = NTLMCredentials::createLMv2Response(ntlm2Hash, challenge, nonce);
69
70 std::string lm2ResponseHex = Poco::DigestEngine::digestToHex(lm2Response);
71 assertTrue (lm2ResponseHex == "d6e6152ea25d03b7c6ba6629c2d6aaf0ffffff0011223344");
72 }
73
74
testNTLMv2Response()75 void NTLMCredentialsTest::testNTLMv2Response()
76 {
77 static const unsigned char CHALLENGE[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
78 static const unsigned char NONCE[] = {0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44};
79 static const unsigned char TARGET_INFO[] = {
80 0x02, 0x00, 0x0c, 0x00, 0x44, 0x00, 0x4f, 0x00,
81 0x4d, 0x00, 0x41, 0x00, 0x49, 0x00, 0x4e, 0x00,
82 0x01, 0x00, 0x0c, 0x00, 0x53, 0x00, 0x45, 0x00,
83 0x52, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00,
84 0x04, 0x00, 0x14, 0x00, 0x64, 0x00, 0x6f, 0x00,
85 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00,
86 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00,
87 0x03, 0x00, 0x22, 0x00, 0x73, 0x00, 0x65, 0x00,
88 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00,
89 0x2e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00,
90 0x61, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00,
91 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x00, 0x00,
92 0x00, 0x00
93 };
94
95 std::vector<unsigned char> challenge(CHALLENGE, CHALLENGE + 8);
96 std::vector<unsigned char> nonce(NONCE, NONCE + 8);
97 std::vector<unsigned char> targetInfo(TARGET_INFO, TARGET_INFO + sizeof(TARGET_INFO));
98
99 std::vector<unsigned char> ntlm2Hash = NTLMCredentials::createNTLMv2Hash("user", "DOMAIN", "SecREt01");
100 Poco::UInt64 timestamp = Poco::UInt64(12700317600)*10000000;
101
102 std::vector<unsigned char> ntlm2Response = NTLMCredentials::createNTLMv2Response(
103 ntlm2Hash,
104 challenge,
105 nonce,
106 targetInfo,
107 timestamp);
108
109 std::string ntlm2ResponseHex = Poco::DigestEngine::digestToHex(ntlm2Response);
110
111 assertTrue (ntlm2ResponseHex ==
112 "cbabbca713eb795d04c97abc01ee4983"
113 "01010000000000000090d336b734c301"
114 "ffffff00112233440000000002000c00"
115 "44004f004d00410049004e0001000c00"
116 "53004500520056004500520004001400"
117 "64006f006d00610069006e002e006300"
118 "6f006d00030022007300650072007600"
119 "650072002e0064006f006d0061006900"
120 "6e002e0063006f006d00000000000000"
121 "0000"
122 );
123 }
124
125
testFormatNegotiateMessage()126 void NTLMCredentialsTest::testFormatNegotiateMessage()
127 {
128 NTLMCredentials::NegotiateMessage msg1;
129 msg1.flags = 0;
130
131 std::vector<unsigned char> msg1Buffer = NTLMCredentials::formatNegotiateMessage(msg1);
132 std::string msg1BufferHex = Poco::DigestEngine::digestToHex(msg1Buffer);
133
134 assertTrue (msg1BufferHex == "4e544c4d53535000010000000582080000000000180000000000000018000000");
135
136 msg1.domain = "DOMAIN";
137 msg1Buffer = NTLMCredentials::formatNegotiateMessage(msg1);
138 msg1BufferHex = Poco::DigestEngine::digestToHex(msg1Buffer);
139
140 assertTrue (msg1BufferHex == "4e544c4d5353500001000000059208000c000c0018000000000000002400000044004f004d00410049004e00");
141
142 msg1.workstation = "WORKST";
143 msg1Buffer = NTLMCredentials::formatNegotiateMessage(msg1);
144 msg1BufferHex = Poco::DigestEngine::digestToHex(msg1Buffer);
145
146 assertTrue (msg1BufferHex == "4e544c4d535350000100000005b208000c000c00180000000c000c002400000044004f004d00410049004e0057004f0052004b0053005400");
147 }
148
149
testParseChallengeMessage()150 void NTLMCredentialsTest::testParseChallengeMessage()
151 {
152 const unsigned char BUFFER[] = {
153 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00,
154 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00,
156 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
157 };
158
159 NTLMCredentials::ChallengeMessage msg2;
160 bool ok = NTLMCredentials::parseChallengeMessage(BUFFER, sizeof(BUFFER), msg2);
161
162 assertTrue (ok);
163 assertTrue (msg2.flags == (NTLMCredentials::NTLM_FLAG_NEGOTIATE_OEM | NTLMCredentials::NTLM_FLAG_NEGOTIATE_NTLM));
164 assertTrue (msg2.challenge.size() == 8);
165 assertTrue (msg2.targetInfo.empty());
166
167 assertTrue (msg2.challenge[0] == 0x01);
168 assertTrue (msg2.challenge[1] == 0x23);
169 assertTrue (msg2.challenge[7] == 0xef);
170 }
171
172
testParseChallengeMessageWithTargetInfo()173 void NTLMCredentialsTest::testParseChallengeMessageWithTargetInfo()
174 {
175 const unsigned char BUFFER[] = {
176 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00,
177 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
178 0x30, 0x00, 0x00, 0x00, 0x01, 0x02, 0x81, 0x00,
179 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x62, 0x00, 0x62, 0x00, 0x3c, 0x00, 0x00, 0x00,
182 0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00,
183 0x49, 0x00, 0x4e, 0x00, 0x02, 0x00, 0x0c, 0x00,
184 0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00,
185 0x49, 0x00, 0x4e, 0x00, 0x01, 0x00, 0x0c, 0x00,
186 0x53, 0x00, 0x45, 0x00, 0x52, 0x00, 0x56, 0x00,
187 0x45, 0x00, 0x52, 0x00, 0x04, 0x00, 0x14, 0x00,
188 0x64, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00,
189 0x69, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00,
190 0x6f, 0x00, 0x6d, 0x00, 0x03, 0x00, 0x22, 0x00,
191 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00,
192 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x64, 0x00,
193 0x6f, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00,
194 0x6e, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00,
195 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00
196 };
197
198 NTLMCredentials::ChallengeMessage msg2;
199 bool ok = NTLMCredentials::parseChallengeMessage(BUFFER, sizeof(BUFFER), msg2);
200
201 assertTrue (ok);
202 assertTrue (msg2.flags == (NTLMCredentials::NTLM_FLAG_NEGOTIATE_UNICODE | NTLMCredentials::NTLM_FLAG_NEGOTIATE_NTLM | NTLMCredentials::NTLM_FLAG_NEGOTIATE_TARGET | NTLMCredentials::NTLM_FLAG_TARGET_DOMAIN));
203 assertTrue (msg2.challenge.size() == 8);
204 assertTrue (msg2.target == "DOMAIN");
205
206 assertTrue (msg2.targetInfo.size() == 98);
207
208 assertTrue (msg2.challenge[0] == 0x01);
209 assertTrue (msg2.challenge[1] == 0x23);
210 assertTrue (msg2.challenge[7] == 0xef);
211
212 assertTrue (msg2.targetInfo[0] == 0x02);
213 assertTrue (msg2.targetInfo[1] == 0x00);
214 assertTrue (msg2.targetInfo[97] == 0x00);
215 }
216
217
testFormatAuthenticateMessage()218 void NTLMCredentialsTest::testFormatAuthenticateMessage()
219 {
220 const unsigned char LM[] = {
221 0xc3, 0x37, 0xcd, 0x5c, 0xbd, 0x44, 0xfc, 0x97,
222 0x82, 0xa6, 0x67, 0xaf, 0x6d, 0x42, 0x7c, 0x6d,
223 0xe6, 0x7c, 0x20, 0xc2, 0xd3, 0xe7, 0x7c, 0x56
224 };
225 const unsigned char NTLM[] = {
226 0x25, 0xa9, 0x8c, 0x1c, 0x31, 0xe8, 0x18, 0x47,
227 0x46, 0x6b, 0x29, 0xb2, 0xdf, 0x46, 0x80, 0xf3,
228 0x99, 0x58, 0xfb, 0x8c, 0x21, 0x3a, 0x9c, 0xc6
229 };
230
231 NTLMCredentials::AuthenticateMessage msg3;
232 msg3.flags = NTLMCredentials::NTLM_FLAG_NEGOTIATE_UNICODE | NTLMCredentials::NTLM_FLAG_NEGOTIATE_NTLM;
233 msg3.target = "DOMAIN";
234 msg3.username = "user";
235 msg3.workstation = "WORKSTATION";
236 msg3.lmResponse.assign(LM, LM + sizeof(LM));
237 msg3.ntlmResponse.assign(NTLM, NTLM + sizeof(NTLM));
238
239 std::vector<unsigned char> msg3Buffer = NTLMCredentials::formatAuthenticateMessage(msg3);
240 std::string msg3BufferHex = Poco::DigestEngine::digestToHex(msg3Buffer);
241
242 assertTrue (msg3BufferHex ==
243 "4e544c4d5353500003000000180018004000000018001800"
244 "580000000c000c0070000000080008007c00000016001600"
245 "84000000000000009a00000001020000c337cd5cbd44fc97"
246 "82a667af6d427c6de67c20c2d3e77c5625a98c1c31e81847"
247 "466b29b2df4680f39958fb8c213a9cc644004f004d004100"
248 "49004e00750073006500720057004f0052004b0053005400"
249 "4100540049004f004e00"
250 );
251 }
252
253
setUp()254 void NTLMCredentialsTest::setUp()
255 {
256 }
257
258
tearDown()259 void NTLMCredentialsTest::tearDown()
260 {
261 }
262
263
suite()264 CppUnit::Test* NTLMCredentialsTest::suite()
265 {
266 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NTLMCredentialsTest");
267
268 CppUnit_addTest(pSuite, NTLMCredentialsTest, testNonce);
269 CppUnit_addTest(pSuite, NTLMCredentialsTest, testPasswordHash);
270 CppUnit_addTest(pSuite, NTLMCredentialsTest, testNTLMv2Hash);
271 CppUnit_addTest(pSuite, NTLMCredentialsTest, testLMv2Response);
272 CppUnit_addTest(pSuite, NTLMCredentialsTest, testNTLMv2Response);
273 CppUnit_addTest(pSuite, NTLMCredentialsTest, testFormatNegotiateMessage);
274 CppUnit_addTest(pSuite, NTLMCredentialsTest, testParseChallengeMessage);
275 CppUnit_addTest(pSuite, NTLMCredentialsTest, testParseChallengeMessageWithTargetInfo);
276 CppUnit_addTest(pSuite, NTLMCredentialsTest, testFormatAuthenticateMessage);
277
278 return pSuite;
279 }
280