Part of bug 382647 (move xpfe bookmarks to suite) - do the xpfe removals. r=KaiRo...
[mozilla-central.git] / netwerk / test / ReadNTLM.cpp
blob5b4656613600d3ddb6467c78b74ce186d7ae9c72
1 /* vim: set ts=2 sw=2 et cindent: */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is Mozilla.
17 * The Initial Developer of the Original Code is IBM Corporation.
18 * Portions created by IBM Corporation are Copyright (C) 2003
19 * IBM Corporation. All Rights Reserved.
21 * Contributor(s):
22 * Darin Fisher <darin@meer.net>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <ctype.h>
42 #include "plbase64.h"
43 #include "nsStringAPI.h"
44 #include "prmem.h"
47 * ReadNTLM : reads NTLM messages.
49 * based on http://davenport.sourceforge.net/ntlm.html
52 #define kNegotiateUnicode 0x00000001
53 #define kNegotiateOEM 0x00000002
54 #define kRequestTarget 0x00000004
55 #define kUnknown1 0x00000008
56 #define kNegotiateSign 0x00000010
57 #define kNegotiateSeal 0x00000020
58 #define kNegotiateDatagramStyle 0x00000040
59 #define kNegotiateLanManagerKey 0x00000080
60 #define kNegotiateNetware 0x00000100
61 #define kNegotiateNTLMKey 0x00000200
62 #define kUnknown2 0x00000400
63 #define kUnknown3 0x00000800
64 #define kNegotiateDomainSupplied 0x00001000
65 #define kNegotiateWorkstationSupplied 0x00002000
66 #define kNegotiateLocalCall 0x00004000
67 #define kNegotiateAlwaysSign 0x00008000
68 #define kTargetTypeDomain 0x00010000
69 #define kTargetTypeServer 0x00020000
70 #define kTargetTypeShare 0x00040000
71 #define kNegotiateNTLM2Key 0x00080000
72 #define kRequestInitResponse 0x00100000
73 #define kRequestAcceptResponse 0x00200000
74 #define kRequestNonNTSessionKey 0x00400000
75 #define kNegotiateTargetInfo 0x00800000
76 #define kUnknown4 0x01000000
77 #define kUnknown5 0x02000000
78 #define kUnknown6 0x04000000
79 #define kUnknown7 0x08000000
80 #define kUnknown8 0x10000000
81 #define kNegotiate128 0x20000000
82 #define kNegotiateKeyExchange 0x40000000
83 #define kNegotiate56 0x80000000
85 static const char NTLM_SIGNATURE[] = "NTLMSSP";
86 static const char NTLM_TYPE1_MARKER[] = { 0x01, 0x00, 0x00, 0x00 };
87 static const char NTLM_TYPE2_MARKER[] = { 0x02, 0x00, 0x00, 0x00 };
88 static const char NTLM_TYPE3_MARKER[] = { 0x03, 0x00, 0x00, 0x00 };
90 #define NTLM_MARKER_LEN 4
91 #define NTLM_TYPE1_HEADER_LEN 32
92 #define NTLM_TYPE2_HEADER_LEN 32
93 #define NTLM_TYPE3_HEADER_LEN 64
95 #define LM_HASH_LEN 16
96 #define LM_RESP_LEN 24
98 #define NTLM_HASH_LEN 16
99 #define NTLM_RESP_LEN 24
101 static void PrintFlags(PRUint32 flags)
103 #define TEST(_flag) \
104 if (flags & k ## _flag) \
105 printf(" 0x%08x (" # _flag ")\n", k ## _flag)
107 TEST(NegotiateUnicode);
108 TEST(NegotiateOEM);
109 TEST(RequestTarget);
110 TEST(Unknown1);
111 TEST(NegotiateSign);
112 TEST(NegotiateSeal);
113 TEST(NegotiateDatagramStyle);
114 TEST(NegotiateLanManagerKey);
115 TEST(NegotiateNetware);
116 TEST(NegotiateNTLMKey);
117 TEST(Unknown2);
118 TEST(Unknown3);
119 TEST(NegotiateDomainSupplied);
120 TEST(NegotiateWorkstationSupplied);
121 TEST(NegotiateLocalCall);
122 TEST(NegotiateAlwaysSign);
123 TEST(TargetTypeDomain);
124 TEST(TargetTypeServer);
125 TEST(TargetTypeShare);
126 TEST(NegotiateNTLM2Key);
127 TEST(RequestInitResponse);
128 TEST(RequestAcceptResponse);
129 TEST(RequestNonNTSessionKey);
130 TEST(NegotiateTargetInfo);
131 TEST(Unknown4);
132 TEST(Unknown5);
133 TEST(Unknown6);
134 TEST(Unknown7);
135 TEST(Unknown8);
136 TEST(Negotiate128);
137 TEST(NegotiateKeyExchange);
138 TEST(Negotiate56);
140 #undef TEST
143 static void
144 PrintBuf(const char *tag, const PRUint8 *buf, PRUint32 bufLen)
146 int i;
148 printf("%s =\n", tag);
149 while (bufLen > 0)
151 int count = bufLen;
152 if (count > 8)
153 count = 8;
155 printf(" ");
156 for (i=0; i<count; ++i)
158 printf("0x%02x ", int(buf[i]));
160 for (; i<8; ++i)
162 printf(" ");
165 printf(" ");
166 for (i=0; i<count; ++i)
168 if (isprint(buf[i]))
169 printf("%c", buf[i]);
170 else
171 printf(".");
173 printf("\n");
175 bufLen -= count;
176 buf += count;
180 static PRUint16
181 ReadUint16(const PRUint8 *&buf)
183 PRUint16 x;
184 #ifdef IS_BIG_ENDIAN
185 x = ((PRUint16) buf[1]) | ((PRUint16) buf[0] << 8);
186 #else
187 x = ((PRUint16) buf[0]) | ((PRUint16) buf[1] << 8);
188 #endif
189 buf += sizeof(x);
190 return x;
193 static PRUint32
194 ReadUint32(const PRUint8 *&buf)
196 PRUint32 x;
197 #ifdef IS_BIG_ENDIAN
198 x = ( (PRUint32) buf[3]) |
199 (((PRUint32) buf[2]) << 8) |
200 (((PRUint32) buf[1]) << 16) |
201 (((PRUint32) buf[0]) << 24);
202 #else
203 x = ( (PRUint32) buf[0]) |
204 (((PRUint32) buf[1]) << 8) |
205 (((PRUint32) buf[2]) << 16) |
206 (((PRUint32) buf[3]) << 24);
207 #endif
208 buf += sizeof(x);
209 return x;
212 typedef struct {
213 PRUint16 length;
214 PRUint16 capacity;
215 PRUint32 offset;
216 } SecBuf;
218 static void
219 ReadSecBuf(SecBuf *s, const PRUint8 *&buf)
221 s->length = ReadUint16(buf);
222 s->capacity = ReadUint16(buf);
223 s->offset = ReadUint32(buf);
226 static void
227 ReadType1MsgBody(const PRUint8 *inBuf, PRUint32 start)
229 const PRUint8 *cursor = inBuf + start;
230 PRUint32 flags;
232 PrintBuf("flags", cursor, 4);
233 // read flags
234 flags = ReadUint32(cursor);
235 PrintFlags(flags);
237 // type 1 message may not include trailing security buffers
238 if ((flags & kNegotiateDomainSupplied) |
239 (flags & kNegotiateWorkstationSupplied))
241 SecBuf secbuf;
242 ReadSecBuf(&secbuf, cursor);
243 PrintBuf("supplied domain", inBuf + secbuf.offset, secbuf.length);
245 ReadSecBuf(&secbuf, cursor);
246 PrintBuf("supplied workstation", inBuf + secbuf.offset, secbuf.length);
250 static void
251 ReadType2MsgBody(const PRUint8 *inBuf, PRUint32 start)
253 PRUint16 targetLen, offset;
254 PRUint32 flags;
255 const PRUint8 *target;
256 const PRUint8 *cursor = inBuf + start;
258 // read target name security buffer
259 targetLen = ReadUint16(cursor);
260 ReadUint16(cursor); // discard next 16-bit value
261 offset = ReadUint32(cursor); // get offset from inBuf
262 target = inBuf + offset;
264 PrintBuf("target", target, targetLen);
266 PrintBuf("flags", cursor, 4);
267 // read flags
268 flags = ReadUint32(cursor);
269 PrintFlags(flags);
271 // read challenge
272 PrintBuf("challenge", cursor, 8);
273 cursor += 8;
275 PrintBuf("context", cursor, 8);
276 cursor += 8;
278 SecBuf secbuf;
279 ReadSecBuf(&secbuf, cursor);
280 PrintBuf("target information", inBuf + secbuf.offset, secbuf.length);
283 static void
284 ReadType3MsgBody(const PRUint8 *inBuf, PRUint32 start)
286 const PRUint8 *cursor = inBuf + start;
288 SecBuf secbuf;
290 ReadSecBuf(&secbuf, cursor); // LM response
291 PrintBuf("LM response", inBuf + secbuf.offset, secbuf.length);
293 ReadSecBuf(&secbuf, cursor); // NTLM response
294 PrintBuf("NTLM response", inBuf + secbuf.offset, secbuf.length);
296 ReadSecBuf(&secbuf, cursor); // domain name
297 PrintBuf("domain name", inBuf + secbuf.offset, secbuf.length);
299 ReadSecBuf(&secbuf, cursor); // user name
300 PrintBuf("user name", inBuf + secbuf.offset, secbuf.length);
302 ReadSecBuf(&secbuf, cursor); // workstation name
303 PrintBuf("workstation name", inBuf + secbuf.offset, secbuf.length);
305 ReadSecBuf(&secbuf, cursor); // session key
306 PrintBuf("session key", inBuf + secbuf.offset, secbuf.length);
308 PRUint32 flags = ReadUint32(cursor);
309 PrintBuf("flags", (const PRUint8 *) &flags, sizeof(flags));
310 PrintFlags(flags);
313 static void
314 ReadMsg(const char *base64buf, PRUint32 bufLen)
316 PRUint8 *inBuf = (PRUint8 *) PL_Base64Decode(base64buf, bufLen, NULL);
317 if (!inBuf)
319 printf("PL_Base64Decode failed\n");
320 return;
323 const PRUint8 *cursor = inBuf;
325 PrintBuf("signature", cursor, 8);
327 // verify NTLMSSP signature
328 if (memcmp(cursor, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)) != 0)
330 printf("### invalid or corrupt NTLM signature\n");
332 cursor += sizeof(NTLM_SIGNATURE);
334 PrintBuf("message type", cursor, 4);
336 if (memcmp(cursor, NTLM_TYPE1_MARKER, sizeof(NTLM_MARKER_LEN)) == 0)
337 ReadType1MsgBody(inBuf, 12);
338 else if (memcmp(cursor, NTLM_TYPE2_MARKER, sizeof(NTLM_MARKER_LEN)) == 0)
339 ReadType2MsgBody(inBuf, 12);
340 else if (memcmp(cursor, NTLM_TYPE3_MARKER, sizeof(NTLM_MARKER_LEN)) == 0)
341 ReadType3MsgBody(inBuf, 12);
342 else
343 printf("### invalid or unknown message type\n");
345 PR_Free(inBuf);
348 int main(int argc, char **argv)
350 if (argc == 1)
352 printf("usage: ntlmread <msg>\n");
353 return -1;
355 ReadMsg(argv[1], (PRUint32) strlen(argv[1]));
356 return 0;