Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(614)

Side by Side Diff: net/http/http_auth_handler_ntlm_portable.cc

Issue 2904633002: Replace NTLMv1 implementation with a functionally equivalent one.
Patch Set: Cleanup Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_auth_handler_ntlm.h" 5 #include "net/http/http_auth_handler_ntlm.h"
6 6
7 #include <stdlib.h>
8 // For gethostname
9 #if defined(OS_POSIX)
10 #include <unistd.h>
11 #elif defined(OS_WIN)
12 #include <winsock2.h>
13 #endif
14
15 #include "base/md5.h"
16 #include "base/rand_util.h" 7 #include "base/rand_util.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/sys_string_conversions.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "net/base/net_errors.h" 8 #include "net/base/net_errors.h"
21 #include "net/base/network_interfaces.h" 9 #include "net/base/network_interfaces.h"
22 #include "net/ntlm/des.h"
23 #include "net/ntlm/md4.h"
24 10
25 namespace net { 11 namespace net {
26 12
27 // Based on mozilla/security/manager/ssl/src/nsNTLMAuthModule.cpp, 13 namespace {
28 // CVS rev. 1.14.
29 //
30 // TODO(wtc):
31 // - The IS_BIG_ENDIAN code is not tested.
32 // - Enable the logging code or just delete it.
33 // - Delete or comment out the LM code, which hasn't been tested and isn't
34 // being used.
35 14
36 /* ***** BEGIN LICENSE BLOCK ***** 15 void GenerateRandom(uint8_t* output, size_t n) {
37 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 16 base::RandBytes(output, n);
38 *
39 * The contents of this file are subject to the Mozilla Public License Version
40 * 1.1 (the "License"); you may not use this file except in compliance with
41 * the License. You may obtain a copy of the License at
42 * http://www.mozilla.org/MPL/
43 *
44 * Software distributed under the License is distributed on an "AS IS" basis,
45 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
46 * for the specific language governing rights and limitations under the
47 * License.
48 *
49 * The Original Code is Mozilla.
50 *
51 * The Initial Developer of the Original Code is IBM Corporation.
52 * Portions created by IBM Corporation are Copyright (C) 2003
53 * IBM Corporation. All Rights Reserved.
54 *
55 * Contributor(s):
56 * Darin Fisher <darin@meer.net>
57 *
58 * Alternatively, the contents of this file may be used under the terms of
59 * either the GNU General Public License Version 2 or later (the "GPL"), or
60 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
61 * in which case the provisions of the GPL or the LGPL are applicable instead
62 * of those above. If you wish to allow use of your version of this file only
63 * under the terms of either the GPL or the LGPL, and not to allow others to
64 * use your version of this file under the terms of the MPL, indicate your
65 * decision by deleting the provisions above and replace them with the notice
66 * and other provisions required by the GPL or the LGPL. If you do not delete
67 * the provisions above, a recipient may use your version of this file under
68 * the terms of any one of the MPL, the GPL or the LGPL.
69 *
70 * ***** END LICENSE BLOCK ***** */
71
72 #if defined(ARCH_CPU_LITTLE_ENDIAN)
73 #define IS_LITTLE_ENDIAN 1
74 #undef IS_BIG_ENDIAN
75 #elif defined(ARCH_CPU_BIG_ENDIAN)
76 #define IS_BIG_ENDIAN 1
77 #undef IS_LITTLE_ENDIAN
78 #else
79 #error "Unknown endianness"
80 #endif
81
82 #define NTLM_LOG(x) ((void)0)
83
84 //-----------------------------------------------------------------------------
85 // This file contains a cross-platform NTLM authentication implementation. It
86 // is based on documentation from: http://davenport.sourceforge.net/ntlm.html
87 //-----------------------------------------------------------------------------
88
89 enum {
90 NTLM_NegotiateUnicode = 0x00000001,
91 NTLM_NegotiateOEM = 0x00000002,
92 NTLM_RequestTarget = 0x00000004,
93 NTLM_Unknown1 = 0x00000008,
94 NTLM_NegotiateSign = 0x00000010,
95 NTLM_NegotiateSeal = 0x00000020,
96 NTLM_NegotiateDatagramStyle = 0x00000040,
97 NTLM_NegotiateLanManagerKey = 0x00000080,
98 NTLM_NegotiateNetware = 0x00000100,
99 NTLM_NegotiateNTLMKey = 0x00000200,
100 NTLM_Unknown2 = 0x00000400,
101 NTLM_Unknown3 = 0x00000800,
102 NTLM_NegotiateDomainSupplied = 0x00001000,
103 NTLM_NegotiateWorkstationSupplied = 0x00002000,
104 NTLM_NegotiateLocalCall = 0x00004000,
105 NTLM_NegotiateAlwaysSign = 0x00008000,
106 NTLM_TargetTypeDomain = 0x00010000,
107 NTLM_TargetTypeServer = 0x00020000,
108 NTLM_TargetTypeShare = 0x00040000,
109 NTLM_NegotiateNTLM2Key = 0x00080000,
110 NTLM_RequestInitResponse = 0x00100000,
111 NTLM_RequestAcceptResponse = 0x00200000,
112 NTLM_RequestNonNTSessionKey = 0x00400000,
113 NTLM_NegotiateTargetInfo = 0x00800000,
114 NTLM_Unknown4 = 0x01000000,
115 NTLM_Unknown5 = 0x02000000,
116 NTLM_Unknown6 = 0x04000000,
117 NTLM_Unknown7 = 0x08000000,
118 NTLM_Unknown8 = 0x10000000,
119 NTLM_Negotiate128 = 0x20000000,
120 NTLM_NegotiateKeyExchange = 0x40000000,
121 NTLM_Negotiate56 = 0x80000000
122 };
123
124 // We send these flags with our type 1 message.
125 enum {
126 NTLM_TYPE1_FLAGS =
127 (NTLM_NegotiateUnicode | NTLM_NegotiateOEM | NTLM_RequestTarget |
128 NTLM_NegotiateNTLMKey |
129 NTLM_NegotiateAlwaysSign |
130 NTLM_NegotiateNTLM2Key)
131 };
132
133 static const char NTLM_SIGNATURE[] = "NTLMSSP";
134 static const char NTLM_TYPE1_MARKER[] = {0x01, 0x00, 0x00, 0x00};
135 static const char NTLM_TYPE2_MARKER[] = {0x02, 0x00, 0x00, 0x00};
136 static const char NTLM_TYPE3_MARKER[] = {0x03, 0x00, 0x00, 0x00};
137
138 enum {
139 NTLM_TYPE1_HEADER_LEN = 32,
140 NTLM_TYPE2_HEADER_LEN = 32,
141 NTLM_TYPE3_HEADER_LEN = 64,
142
143 LM_HASH_LEN = 16,
144 LM_RESP_LEN = 24,
145
146 NTLM_HASH_LEN = 16,
147 NTLM_RESP_LEN = 24
148 };
149
150 //-----------------------------------------------------------------------------
151
152 #define LogFlags(x) ((void)0)
153 #define LogBuf(a, b, c) ((void)0)
154 #define LogToken(a, b, c) ((void)0)
155
156 //-----------------------------------------------------------------------------
157
158 // Byte order swapping.
159 #define SWAP16(x) ((((x)&0xff) << 8) | (((x) >> 8) & 0xff))
160 #define SWAP32(x) ((SWAP16((x)&0xffff) << 16) | (SWAP16((x) >> 16)))
161
162 static void* WriteBytes(void* buf, const void* data, uint32_t data_len) {
163 memcpy(buf, data, data_len);
164 return static_cast<char*>(buf) + data_len;
165 } 17 }
166 18
167 static void* WriteDWORD(void* buf, uint32_t dword) { 19 } // namespace
168 #ifdef IS_BIG_ENDIAN
169 // NTLM uses little endian on the wire.
170 dword = SWAP32(dword);
171 #endif
172 return WriteBytes(buf, &dword, sizeof(dword));
173 }
174
175 static void* WriteSecBuf(void* buf, uint16_t length, uint32_t offset) {
176 #ifdef IS_BIG_ENDIAN
177 length = SWAP16(length);
178 offset = SWAP32(offset);
179 #endif
180 // Len: 2 bytes.
181 buf = WriteBytes(buf, &length, sizeof(length));
182 // MaxLen: 2 bytes. The sender should set it to the value of Len. The
183 // recipient must ignore it.
184 buf = WriteBytes(buf, &length, sizeof(length));
185 // BufferOffset: 4 bytes.
186 buf = WriteBytes(buf, &offset, sizeof(offset));
187 return buf;
188 }
189
190 #ifdef IS_BIG_ENDIAN
191 /**
192 * WriteUnicodeLE copies a unicode string from one buffer to another. The
193 * resulting unicode string is in little-endian format. The input string is
194 * assumed to be in the native endianness of the local machine. It is safe
195 * to pass the same buffer as both input and output, which is a handy way to
196 * convert the unicode buffer to little-endian on big-endian platforms.
197 */
198 static void* WriteUnicodeLE(void* buf,
199 const base::char16* str,
200 uint32_t str_len) {
201 // Convert input string from BE to LE.
202 uint8_t* cursor = static_cast<uint8_t*>(buf);
203 const uint8_t* input = reinterpret_cast<const uint8_t*>(str);
204 for (uint32_t i = 0; i < str_len; ++i, input += 2, cursor += 2) {
205 // Allow for the case where |buf == str|.
206 uint8_t temp = input[0];
207 cursor[0] = input[1];
208 cursor[1] = temp;
209 }
210 return buf;
211 }
212 #endif
213
214 static uint16_t ReadUint16(const uint8_t*& buf) {
215 uint16_t x =
216 (static_cast<uint16_t>(buf[0])) | (static_cast<uint16_t>(buf[1]) << 8);
217 buf += sizeof(x);
218 return x;
219 }
220
221 static uint32_t ReadUint32(const uint8_t*& buf) {
222 uint32_t x = (static_cast<uint32_t>(buf[0])) |
223 (static_cast<uint32_t>(buf[1]) << 8) |
224 (static_cast<uint32_t>(buf[2]) << 16) |
225 (static_cast<uint32_t>(buf[3]) << 24);
226 buf += sizeof(x);
227 return x;
228 }
229
230 //-----------------------------------------------------------------------------
231
232 // NTLM_Hash computes the NTLM hash of the given password.
233 //
234 // param password
235 // null-terminated unicode password.
236 // param hash
237 // 16-byte result buffer
238 static void NTLM_Hash(const base::string16& password, uint8_t* hash) {
239 #ifdef IS_BIG_ENDIAN
240 uint32_t len = password.length();
241 uint8_t* passbuf;
242
243 passbuf = static_cast<uint8_t*>(malloc(len * 2));
244 WriteUnicodeLE(passbuf, password.data(), len);
245 weak_crypto::MD4Sum(passbuf, len * 2, hash);
246
247 free(passbuf);
248 #else
249 weak_crypto::MD4Sum(reinterpret_cast<const uint8_t*>(password.data()),
250 password.length() * 2, hash);
251 #endif
252 }
253
254 //-----------------------------------------------------------------------------
255
256 // LM_Response generates the LM response given a 16-byte password hash and the
257 // challenge from the Type-2 message.
258 //
259 // param hash
260 // 16-byte password hash
261 // param challenge
262 // 8-byte challenge from Type-2 message
263 // param response
264 // 24-byte buffer to contain the LM response upon return
265 static void LM_Response(const uint8_t* hash,
266 const uint8_t* challenge,
267 uint8_t* response) {
268 uint8_t keybytes[21], k1[8], k2[8], k3[8];
269
270 memcpy(keybytes, hash, 16);
271 memset(keybytes + 16, 0, 5);
272
273 DESMakeKey(keybytes, k1);
274 DESMakeKey(keybytes + 7, k2);
275 DESMakeKey(keybytes + 14, k3);
276
277 DESEncrypt(k1, challenge, response);
278 DESEncrypt(k2, challenge, response + 8);
279 DESEncrypt(k3, challenge, response + 16);
280 }
281
282 //-----------------------------------------------------------------------------
283
284 // Returns OK or a network error code.
285 static int GenerateType1Msg(void** out_buf, uint32_t* out_len) {
286 //
287 // Verify that buf_len is sufficient.
288 //
289 *out_len = NTLM_TYPE1_HEADER_LEN;
290 *out_buf = malloc(*out_len);
291 if (!*out_buf)
292 return ERR_OUT_OF_MEMORY;
293
294 //
295 // Write out type 1 message.
296 //
297 void* cursor = *out_buf;
298
299 // 0 : signature
300 cursor = WriteBytes(cursor, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE));
301
302 // 8 : marker
303 cursor = WriteBytes(cursor, NTLM_TYPE1_MARKER, sizeof(NTLM_TYPE1_MARKER));
304
305 // 12 : flags
306 cursor = WriteDWORD(cursor, NTLM_TYPE1_FLAGS);
307
308 //
309 // NOTE: It is common for the domain and workstation fields to be empty.
310 // This is true of Win2k clients, and my guess is that there is
311 // little utility to sending these strings before the charset has
312 // been negotiated. We follow suite -- anyways, it doesn't hurt
313 // to save some bytes on the wire ;-)
314 //
315
316 // 16 : supplied domain security buffer (empty)
317 cursor = WriteSecBuf(cursor, 0, 0);
318
319 // 24 : supplied workstation security buffer (empty)
320 cursor = WriteSecBuf(cursor, 0, 0);
321
322 return OK;
323 }
324
325 struct Type2Msg {
326 uint32_t flags; // NTLM_Xxx bitwise combination
327 uint8_t challenge[8]; // 8 byte challenge
328 const void* target; // target string (type depends on flags)
329 uint32_t target_len; // target length in bytes
330 };
331
332 // Returns OK or a network error code.
333 // TODO(wtc): This function returns ERR_UNEXPECTED when the input message is
334 // invalid. We should return a better error code.
335 static int ParseType2Msg(const void* in_buf, uint32_t in_len, Type2Msg* msg) {
336 // Make sure in_buf is long enough to contain a meaningful type2 msg.
337 //
338 // 0 NTLMSSP Signature
339 // 8 NTLM Message Type
340 // 12 Target Name
341 // 20 Flags
342 // 24 Challenge
343 // 32 end of header, start of optional data blocks
344 //
345 if (in_len < NTLM_TYPE2_HEADER_LEN)
346 return ERR_UNEXPECTED;
347
348 const uint8_t* cursor = (const uint8_t*)in_buf;
349
350 // verify NTLMSSP signature
351 if (memcmp(cursor, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)) != 0)
352 return ERR_UNEXPECTED;
353 cursor += sizeof(NTLM_SIGNATURE);
354
355 // verify Type-2 marker
356 if (memcmp(cursor, NTLM_TYPE2_MARKER, sizeof(NTLM_TYPE2_MARKER)) != 0)
357 return ERR_UNEXPECTED;
358 cursor += sizeof(NTLM_TYPE2_MARKER);
359
360 // read target name security buffer
361 uint32_t target_len = ReadUint16(cursor);
362 ReadUint16(cursor); // discard next 16-bit value
363 uint32_t offset = ReadUint32(cursor); // get offset from in_buf
364 msg->target_len = 0;
365 msg->target = NULL;
366
367 // Target length 0 is valid and indicates no target information.
368 if (target_len != 0) {
369 // Check the offset / length combo is in range of the input buffer,
370 // including integer overflow checking.
371 if (target_len <= in_len && in_len - offset >= target_len) {
372 msg->target_len = target_len;
373 msg->target = ((const uint8_t*)in_buf) + offset;
374 } else {
375 // Reject a message with a non-zero target length that
376 // would cause an overflow.
377 return ERR_UNEXPECTED;
378 }
379 }
380
381 // read flags
382 msg->flags = ReadUint32(cursor);
383
384 // read challenge
385 memcpy(msg->challenge, cursor, sizeof(msg->challenge));
386 cursor += sizeof(msg->challenge);
387
388 NTLM_LOG(("NTLM type 2 message:\n"));
389 LogBuf("target", (const uint8_t*)msg->target, msg->target_len);
390 LogBuf("flags", (const uint8_t*)&msg->flags, 4);
391 LogFlags(msg->flags);
392 LogBuf("challenge", msg->challenge, sizeof(msg->challenge));
393
394 // We currently do not implement LMv2/NTLMv2 or NTLM2 responses,
395 // so we can ignore target information. We may want to enable
396 // support for these alternate mechanisms in the future.
397 return OK;
398 }
399
400 static void GenerateRandom(uint8_t* output, size_t n) {
401 for (size_t i = 0; i < n; ++i)
402 output[i] = base::RandInt(0, 255);
403 }
404
405 // Returns OK or a network error code.
406 static int GenerateType3Msg(const base::string16& domain,
407 const base::string16& username,
408 const base::string16& password,
409 const std::string& hostname,
410 const void* rand_8_bytes,
411 const void* in_buf,
412 uint32_t in_len,
413 void** out_buf,
414 uint32_t* out_len) {
415 // in_buf contains Type-2 msg (the challenge) from server.
416
417 int rv;
418 Type2Msg msg;
419
420 rv = ParseType2Msg(in_buf, in_len, &msg);
421 if (rv != OK)
422 return rv;
423
424 bool unicode = (msg.flags & NTLM_NegotiateUnicode) != 0;
425
426 // Temporary buffers for unicode strings
427 #ifdef IS_BIG_ENDIAN
428 base::string16 ucs_domain_buf, ucs_user_buf;
429 #endif
430 base::string16 ucs_host_buf;
431 // Temporary buffers for oem strings
432 std::string oem_domain_buf, oem_user_buf;
433 // Pointers and lengths for the string buffers; encoding is unicode if
434 // the "negotiate unicode" flag was set in the Type-2 message.
435 const void* domain_ptr;
436 const void* user_ptr;
437 const void* host_ptr;
438 uint32_t domain_len, user_len, host_len;
439
440 //
441 // Get domain name.
442 //
443 if (unicode) {
444 #ifdef IS_BIG_ENDIAN
445 ucs_domain_buf = domain;
446 domain_ptr = ucs_domain_buf.data();
447 domain_len = ucs_domain_buf.length() * 2;
448 WriteUnicodeLE(const_cast<void*>(domain_ptr),
449 (const base::char16*)domain_ptr, ucs_domain_buf.length());
450 #else
451 domain_ptr = domain.data();
452 domain_len = domain.length() * 2;
453 #endif
454 } else {
455 oem_domain_buf = base::SysWideToNativeMB(base::UTF16ToWide(domain));
456 domain_ptr = oem_domain_buf.data();
457 domain_len = oem_domain_buf.length();
458 }
459
460 //
461 // Get user name.
462 //
463 if (unicode) {
464 #ifdef IS_BIG_ENDIAN
465 ucs_user_buf = username;
466 user_ptr = ucs_user_buf.data();
467 user_len = ucs_user_buf.length() * 2;
468 WriteUnicodeLE(const_cast<void*>(user_ptr), (const base::char16*)user_ptr,
469 ucs_user_buf.length());
470 #else
471 user_ptr = username.data();
472 user_len = username.length() * 2;
473 #endif
474 } else {
475 oem_user_buf = base::SysWideToNativeMB(base::UTF16ToWide(username));
476 user_ptr = oem_user_buf.data();
477 user_len = oem_user_buf.length();
478 }
479
480 //
481 // Get workstation name (use local machine's hostname).
482 //
483 if (unicode) {
484 // hostname is ASCII, so we can do a simple zero-pad expansion:
485 ucs_host_buf.assign(hostname.begin(), hostname.end());
486 host_ptr = ucs_host_buf.data();
487 host_len = ucs_host_buf.length() * 2;
488 #ifdef IS_BIG_ENDIAN
489 WriteUnicodeLE(const_cast<void*>(host_ptr), (const base::char16*)host_ptr,
490 ucs_host_buf.length());
491 #endif
492 } else {
493 host_ptr = hostname.data();
494 host_len = hostname.length();
495 }
496
497 //
498 // Now that we have generated all of the strings, we can allocate out_buf.
499 //
500 *out_len = NTLM_TYPE3_HEADER_LEN + host_len + domain_len + user_len +
501 LM_RESP_LEN + NTLM_RESP_LEN;
502 *out_buf = malloc(*out_len);
503 if (!*out_buf)
504 return ERR_OUT_OF_MEMORY;
505
506 //
507 // Next, we compute the LM and NTLM responses.
508 //
509 uint8_t lm_resp[LM_RESP_LEN];
510 uint8_t ntlm_resp[NTLM_RESP_LEN];
511 uint8_t ntlm_hash[NTLM_HASH_LEN];
512
513 // compute NTLM2 session response
514 base::MD5Digest session_hash;
515 uint8_t temp[16];
516
517 memcpy(lm_resp, rand_8_bytes, 8);
518 memset(lm_resp + 8, 0, LM_RESP_LEN - 8);
519
520 memcpy(temp, msg.challenge, 8);
521 memcpy(temp + 8, lm_resp, 8);
522 base::MD5Sum(temp, 16, &session_hash);
523
524 NTLM_Hash(password, ntlm_hash);
525 LM_Response(ntlm_hash, session_hash.a, ntlm_resp);
526
527 //
528 // Finally, we assemble the Type-3 msg :-)
529 //
530 void* cursor = *out_buf;
531 uint32_t offset;
532
533 // 0 : signature
534 cursor = WriteBytes(cursor, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE));
535
536 // 8 : marker
537 cursor = WriteBytes(cursor, NTLM_TYPE3_MARKER, sizeof(NTLM_TYPE3_MARKER));
538
539 // 12 : LM response sec buf
540 offset = NTLM_TYPE3_HEADER_LEN + domain_len + user_len + host_len;
541 cursor = WriteSecBuf(cursor, LM_RESP_LEN, offset);
542 memcpy(static_cast<uint8_t*>(*out_buf) + offset, lm_resp, LM_RESP_LEN);
543
544 // 20 : NTLM response sec buf
545 offset += LM_RESP_LEN;
546 cursor = WriteSecBuf(cursor, NTLM_RESP_LEN, offset);
547 memcpy(static_cast<uint8_t*>(*out_buf) + offset, ntlm_resp, NTLM_RESP_LEN);
548
549 // 28 : domain name sec buf
550 offset = NTLM_TYPE3_HEADER_LEN;
551 cursor = WriteSecBuf(cursor, domain_len, offset);
552 memcpy(static_cast<uint8_t*>(*out_buf) + offset, domain_ptr, domain_len);
553
554 // 36 : user name sec buf
555 offset += domain_len;
556 cursor = WriteSecBuf(cursor, user_len, offset);
557 memcpy(static_cast<uint8_t*>(*out_buf) + offset, user_ptr, user_len);
558
559 // 44 : workstation (host) name sec buf
560 offset += user_len;
561 cursor = WriteSecBuf(cursor, host_len, offset);
562 memcpy(static_cast<uint8_t*>(*out_buf) + offset, host_ptr, host_len);
563
564 // 52 : session key sec buf (not used)
565 cursor = WriteSecBuf(cursor, 0, 0);
566
567 // 60 : negotiated flags
568 cursor = WriteDWORD(cursor, msg.flags & NTLM_TYPE1_FLAGS);
569
570 return OK;
571 }
572
573 // NTLM authentication is specified in "NTLM Over HTTP Protocol Specification"
574 // [MS-NTHT].
575 20
576 // static 21 // static
577 HttpAuthHandlerNTLM::GenerateRandomProc 22 HttpAuthHandlerNTLM::GenerateRandomProc
578 HttpAuthHandlerNTLM::generate_random_proc_ = GenerateRandom; 23 HttpAuthHandlerNTLM::generate_random_proc_ = GenerateRandom;
579 24
580 // static 25 // static
581 HttpAuthHandlerNTLM::HostNameProc HttpAuthHandlerNTLM::get_host_name_proc_ = 26 HttpAuthHandlerNTLM::HostNameProc HttpAuthHandlerNTLM::get_host_name_proc_ =
582 GetHostName; 27 GetHostName;
583 28
584 HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() {} 29 HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() : ntlm_client_() {}
585 30
586 bool HttpAuthHandlerNTLM::NeedsIdentity() { 31 bool HttpAuthHandlerNTLM::NeedsIdentity() {
587 // This gets called for each round-trip. Only require identity on 32 // This gets called for each round-trip. Only require identity on
588 // the first call (when auth_data_ is empty). On subsequent calls, 33 // the first call (when auth_data_ is empty). On subsequent calls,
589 // we use the initially established identity. 34 // we use the initially established identity.
590 return auth_data_.empty(); 35 return auth_data_.empty();
591 } 36 }
592 37
593 bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() { 38 bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() {
594 // Default credentials are not supported in the portable implementation of 39 // Default credentials are not supported in the portable implementation of
(...skipping 20 matching lines...) Expand all
615 HostNameProc proc) { 60 HostNameProc proc) {
616 HostNameProc old_proc = get_host_name_proc_; 61 HostNameProc old_proc = get_host_name_proc_;
617 get_host_name_proc_ = proc; 62 get_host_name_proc_ = proc;
618 return old_proc; 63 return old_proc;
619 } 64 }
620 65
621 HttpAuthHandlerNTLM::Factory::Factory() {} 66 HttpAuthHandlerNTLM::Factory::Factory() {}
622 67
623 HttpAuthHandlerNTLM::Factory::~Factory() {} 68 HttpAuthHandlerNTLM::Factory::~Factory() {}
624 69
625 int HttpAuthHandlerNTLM::GetNextToken(const void* in_token, 70 ntlm::Buffer HttpAuthHandlerNTLM::GetNextToken(const ntlm::Buffer& in_token) {
626 uint32_t in_token_len, 71 // If in_token is non-empty, then assume it contains a challenge message,
627 void** out_token, 72 // and generate the Authenticate message in reply. Otherwise return the
628 uint32_t* out_token_len) { 73 // Negotiate message.
629 int rv = 0; 74 if (in_token.empty()) {
630 75 return ntlm_client_.GetNegotiateMessage();
631 // If in_token is non-null, then assume it contains a type 2 message... 76 } else {
632 if (in_token) {
633 LogToken("in-token", in_token, in_token_len);
634 std::string hostname = get_host_name_proc_(); 77 std::string hostname = get_host_name_proc_();
635 if (hostname.empty()) 78 if (hostname.empty())
636 return ERR_UNEXPECTED; 79 return ntlm::Buffer();
637 uint8_t rand_buf[8]; 80 uint8_t client_challenge[8];
638 generate_random_proc_(rand_buf, 8); 81 generate_random_proc_(client_challenge, 8);
639 rv = GenerateType3Msg(domain_, credentials_.username(), 82
640 credentials_.password(), hostname, rand_buf, in_token, 83 return ntlm_client_.GenerateAuthenticateMessage(
641 in_token_len, out_token, out_token_len); 84 domain_, credentials_.username(), credentials_.password(), hostname,
642 } else { 85 client_challenge, in_token);
643 rv = GenerateType1Msg(out_token, out_token_len);
644 } 86 }
645
646 if (rv == OK)
647 LogToken("out-token", *out_token, *out_token_len);
648
649 return rv;
650 } 87 }
651 88
652 int HttpAuthHandlerNTLM::Factory::CreateAuthHandler( 89 int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
653 HttpAuthChallengeTokenizer* challenge, 90 HttpAuthChallengeTokenizer* challenge,
654 HttpAuth::Target target, 91 HttpAuth::Target target,
655 const SSLInfo& ssl_info, 92 const SSLInfo& ssl_info,
656 const GURL& origin, 93 const GURL& origin,
657 CreateReason reason, 94 CreateReason reason,
658 int digest_nonce_count, 95 int digest_nonce_count,
659 const NetLogWithSource& net_log, 96 const NetLogWithSource& net_log,
660 std::unique_ptr<HttpAuthHandler>* handler) { 97 std::unique_ptr<HttpAuthHandler>* handler) {
661 if (reason == CREATE_PREEMPTIVE) 98 if (reason == CREATE_PREEMPTIVE)
662 return ERR_UNSUPPORTED_AUTH_SCHEME; 99 return ERR_UNSUPPORTED_AUTH_SCHEME;
663 // TODO(cbentzel): Move towards model of parsing in the factory 100 // TODO(cbentzel): Move towards model of parsing in the factory
664 // method and only constructing when valid. 101 // method and only constructing when valid.
665 // NOTE: Default credentials are not supported for the portable implementation 102 // NOTE: Default credentials are not supported for the portable implementation
666 // of NTLM. 103 // of NTLM.
667 std::unique_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM); 104 std::unique_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM);
668 if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin, 105 if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin,
669 net_log)) 106 net_log))
670 return ERR_INVALID_RESPONSE; 107 return ERR_INVALID_RESPONSE;
671 handler->swap(tmp_handler); 108 handler->swap(tmp_handler);
672 return OK; 109 return OK;
673 } 110 }
674 111
675 } // namespace net 112 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698