Bug 1146304 - Touch slider bar or tap forward button, the video got stuck 1s then...
[gecko.git] / netwerk / test / ReadNTLM.cpp
blob20411e33697bec6b2ee9ec0f990f852398465e19
1 /* vim: set ts=2 sw=2 et cindent: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <ctype.h>
10 #include "plbase64.h"
11 #include "nsStringAPI.h"
12 #include "prmem.h"
15 * ReadNTLM : reads NTLM messages.
17 * based on http://davenport.sourceforge.net/ntlm.html
20 #define kNegotiateUnicode 0x00000001
21 #define kNegotiateOEM 0x00000002
22 #define kRequestTarget 0x00000004
23 #define kUnknown1 0x00000008
24 #define kNegotiateSign 0x00000010
25 #define kNegotiateSeal 0x00000020
26 #define kNegotiateDatagramStyle 0x00000040
27 #define kNegotiateLanManagerKey 0x00000080
28 #define kNegotiateNetware 0x00000100
29 #define kNegotiateNTLMKey 0x00000200
30 #define kUnknown2 0x00000400
31 #define kUnknown3 0x00000800
32 #define kNegotiateDomainSupplied 0x00001000
33 #define kNegotiateWorkstationSupplied 0x00002000
34 #define kNegotiateLocalCall 0x00004000
35 #define kNegotiateAlwaysSign 0x00008000
36 #define kTargetTypeDomain 0x00010000
37 #define kTargetTypeServer 0x00020000
38 #define kTargetTypeShare 0x00040000
39 #define kNegotiateNTLM2Key 0x00080000
40 #define kRequestInitResponse 0x00100000
41 #define kRequestAcceptResponse 0x00200000
42 #define kRequestNonNTSessionKey 0x00400000
43 #define kNegotiateTargetInfo 0x00800000
44 #define kUnknown4 0x01000000
45 #define kUnknown5 0x02000000
46 #define kUnknown6 0x04000000
47 #define kUnknown7 0x08000000
48 #define kUnknown8 0x10000000
49 #define kNegotiate128 0x20000000
50 #define kNegotiateKeyExchange 0x40000000
51 #define kNegotiate56 0x80000000
53 static const char NTLM_SIGNATURE[] = "NTLMSSP";
54 static const char NTLM_TYPE1_MARKER[] = { 0x01, 0x00, 0x00, 0x00 };
55 static const char NTLM_TYPE2_MARKER[] = { 0x02, 0x00, 0x00, 0x00 };
56 static const char NTLM_TYPE3_MARKER[] = { 0x03, 0x00, 0x00, 0x00 };
58 #define NTLM_MARKER_LEN 4
59 #define NTLM_TYPE1_HEADER_LEN 32
60 #define NTLM_TYPE2_HEADER_LEN 32
61 #define NTLM_TYPE3_HEADER_LEN 64
63 #define LM_HASH_LEN 16
64 #define LM_RESP_LEN 24
66 #define NTLM_HASH_LEN 16
67 #define NTLM_RESP_LEN 24
69 static void PrintFlags(uint32_t flags)
71 #define TEST(_flag) \
72 if (flags & k ## _flag) \
73 printf(" 0x%08x (" # _flag ")\n", k ## _flag)
75 TEST(NegotiateUnicode);
76 TEST(NegotiateOEM);
77 TEST(RequestTarget);
78 TEST(Unknown1);
79 TEST(NegotiateSign);
80 TEST(NegotiateSeal);
81 TEST(NegotiateDatagramStyle);
82 TEST(NegotiateLanManagerKey);
83 TEST(NegotiateNetware);
84 TEST(NegotiateNTLMKey);
85 TEST(Unknown2);
86 TEST(Unknown3);
87 TEST(NegotiateDomainSupplied);
88 TEST(NegotiateWorkstationSupplied);
89 TEST(NegotiateLocalCall);
90 TEST(NegotiateAlwaysSign);
91 TEST(TargetTypeDomain);
92 TEST(TargetTypeServer);
93 TEST(TargetTypeShare);
94 TEST(NegotiateNTLM2Key);
95 TEST(RequestInitResponse);
96 TEST(RequestAcceptResponse);
97 TEST(RequestNonNTSessionKey);
98 TEST(NegotiateTargetInfo);
99 TEST(Unknown4);
100 TEST(Unknown5);
101 TEST(Unknown6);
102 TEST(Unknown7);
103 TEST(Unknown8);
104 TEST(Negotiate128);
105 TEST(NegotiateKeyExchange);
106 TEST(Negotiate56);
108 #undef TEST
111 static void
112 PrintBuf(const char *tag, const uint8_t *buf, uint32_t bufLen)
114 int i;
116 printf("%s =\n", tag);
117 while (bufLen > 0)
119 int count = bufLen;
120 if (count > 8)
121 count = 8;
123 printf(" ");
124 for (i=0; i<count; ++i)
126 printf("0x%02x ", int(buf[i]));
128 for (; i<8; ++i)
130 printf(" ");
133 printf(" ");
134 for (i=0; i<count; ++i)
136 if (isprint(buf[i]))
137 printf("%c", buf[i]);
138 else
139 printf(".");
141 printf("\n");
143 bufLen -= count;
144 buf += count;
148 static uint16_t
149 ReadUint16(const uint8_t *&buf)
151 uint16_t x;
152 #ifdef IS_BIG_ENDIAN
153 x = ((uint16_t) buf[1]) | ((uint16_t) buf[0] << 8);
154 #else
155 x = ((uint16_t) buf[0]) | ((uint16_t) buf[1] << 8);
156 #endif
157 buf += sizeof(x);
158 return x;
161 static uint32_t
162 ReadUint32(const uint8_t *&buf)
164 uint32_t x;
165 #ifdef IS_BIG_ENDIAN
166 x = ( (uint32_t) buf[3]) |
167 (((uint32_t) buf[2]) << 8) |
168 (((uint32_t) buf[1]) << 16) |
169 (((uint32_t) buf[0]) << 24);
170 #else
171 x = ( (uint32_t) buf[0]) |
172 (((uint32_t) buf[1]) << 8) |
173 (((uint32_t) buf[2]) << 16) |
174 (((uint32_t) buf[3]) << 24);
175 #endif
176 buf += sizeof(x);
177 return x;
180 typedef struct {
181 uint16_t length;
182 uint16_t capacity;
183 uint32_t offset;
184 } SecBuf;
186 static void
187 ReadSecBuf(SecBuf *s, const uint8_t *&buf)
189 s->length = ReadUint16(buf);
190 s->capacity = ReadUint16(buf);
191 s->offset = ReadUint32(buf);
194 static void
195 ReadType1MsgBody(const uint8_t *inBuf, uint32_t start)
197 const uint8_t *cursor = inBuf + start;
198 uint32_t flags;
200 PrintBuf("flags", cursor, 4);
201 // read flags
202 flags = ReadUint32(cursor);
203 PrintFlags(flags);
205 // type 1 message may not include trailing security buffers
206 if ((flags & kNegotiateDomainSupplied) |
207 (flags & kNegotiateWorkstationSupplied))
209 SecBuf secbuf;
210 ReadSecBuf(&secbuf, cursor);
211 PrintBuf("supplied domain", inBuf + secbuf.offset, secbuf.length);
213 ReadSecBuf(&secbuf, cursor);
214 PrintBuf("supplied workstation", inBuf + secbuf.offset, secbuf.length);
218 static void
219 ReadType2MsgBody(const uint8_t *inBuf, uint32_t start)
221 uint16_t targetLen, offset;
222 uint32_t flags;
223 const uint8_t *target;
224 const uint8_t *cursor = inBuf + start;
226 // read target name security buffer
227 targetLen = ReadUint16(cursor);
228 ReadUint16(cursor); // discard next 16-bit value
229 offset = ReadUint32(cursor); // get offset from inBuf
230 target = inBuf + offset;
232 PrintBuf("target", target, targetLen);
234 PrintBuf("flags", cursor, 4);
235 // read flags
236 flags = ReadUint32(cursor);
237 PrintFlags(flags);
239 // read challenge
240 PrintBuf("challenge", cursor, 8);
241 cursor += 8;
243 PrintBuf("context", cursor, 8);
244 cursor += 8;
246 SecBuf secbuf;
247 ReadSecBuf(&secbuf, cursor);
248 PrintBuf("target information", inBuf + secbuf.offset, secbuf.length);
251 static void
252 ReadType3MsgBody(const uint8_t *inBuf, uint32_t start)
254 const uint8_t *cursor = inBuf + start;
256 SecBuf secbuf;
258 ReadSecBuf(&secbuf, cursor); // LM response
259 PrintBuf("LM response", inBuf + secbuf.offset, secbuf.length);
261 ReadSecBuf(&secbuf, cursor); // NTLM response
262 PrintBuf("NTLM response", inBuf + secbuf.offset, secbuf.length);
264 ReadSecBuf(&secbuf, cursor); // domain name
265 PrintBuf("domain name", inBuf + secbuf.offset, secbuf.length);
267 ReadSecBuf(&secbuf, cursor); // user name
268 PrintBuf("user name", inBuf + secbuf.offset, secbuf.length);
270 ReadSecBuf(&secbuf, cursor); // workstation name
271 PrintBuf("workstation name", inBuf + secbuf.offset, secbuf.length);
273 ReadSecBuf(&secbuf, cursor); // session key
274 PrintBuf("session key", inBuf + secbuf.offset, secbuf.length);
276 uint32_t flags = ReadUint32(cursor);
277 PrintBuf("flags", (const uint8_t *) &flags, sizeof(flags));
278 PrintFlags(flags);
281 static void
282 ReadMsg(const char *base64buf, uint32_t bufLen)
284 uint8_t *inBuf = (uint8_t *) PL_Base64Decode(base64buf, bufLen, nullptr);
285 if (!inBuf)
287 printf("PL_Base64Decode failed\n");
288 return;
291 const uint8_t *cursor = inBuf;
293 PrintBuf("signature", cursor, 8);
295 // verify NTLMSSP signature
296 if (memcmp(cursor, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)) != 0)
298 printf("### invalid or corrupt NTLM signature\n");
300 cursor += sizeof(NTLM_SIGNATURE);
302 PrintBuf("message type", cursor, 4);
304 if (memcmp(cursor, NTLM_TYPE1_MARKER, sizeof(NTLM_MARKER_LEN)) == 0)
305 ReadType1MsgBody(inBuf, 12);
306 else if (memcmp(cursor, NTLM_TYPE2_MARKER, sizeof(NTLM_MARKER_LEN)) == 0)
307 ReadType2MsgBody(inBuf, 12);
308 else if (memcmp(cursor, NTLM_TYPE3_MARKER, sizeof(NTLM_MARKER_LEN)) == 0)
309 ReadType3MsgBody(inBuf, 12);
310 else
311 printf("### invalid or unknown message type\n");
313 PR_Free(inBuf);
316 int main(int argc, char **argv)
318 if (argc == 1)
320 printf("usage: ntlmread <msg>\n");
321 return -1;
323 ReadMsg(argv[1], (uint32_t) strlen(argv[1]));
324 return 0;