| OLD | NEW |
| 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> | 7 #include <stdlib.h> |
| 8 // For gethostname | 8 // For gethostname |
| 9 #if defined(OS_POSIX) | 9 #if defined(OS_POSIX) |
| 10 #include <unistd.h> | 10 #include <unistd.h> |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 | 143 |
| 144 LM_HASH_LEN = 16, | 144 LM_HASH_LEN = 16, |
| 145 LM_RESP_LEN = 24, | 145 LM_RESP_LEN = 24, |
| 146 | 146 |
| 147 NTLM_HASH_LEN = 16, | 147 NTLM_HASH_LEN = 16, |
| 148 NTLM_RESP_LEN = 24 | 148 NTLM_RESP_LEN = 24 |
| 149 }; | 149 }; |
| 150 | 150 |
| 151 //----------------------------------------------------------------------------- | 151 //----------------------------------------------------------------------------- |
| 152 | 152 |
| 153 // The return value of this function controls whether or not the LM hash will | |
| 154 // be included in response to a NTLM challenge. | |
| 155 // | |
| 156 // In Mozilla, this function returns the value of the boolean preference | |
| 157 // "network.ntlm.send-lm-response". By default, the preference is disabled | |
| 158 // since servers should almost never need the LM hash, and the LM hash is what | |
| 159 // makes NTLM authentication less secure. See | |
| 160 // https://bugzilla.mozilla.org/show_bug.cgi?id=250691 for further details. | |
| 161 // | |
| 162 // We just return a hardcoded false. | |
| 163 static bool SendLM() { | |
| 164 return false; | |
| 165 } | |
| 166 | |
| 167 //----------------------------------------------------------------------------- | |
| 168 | |
| 169 #define LogFlags(x) ((void)0) | 153 #define LogFlags(x) ((void)0) |
| 170 #define LogBuf(a, b, c) ((void)0) | 154 #define LogBuf(a, b, c) ((void)0) |
| 171 #define LogToken(a, b, c) ((void)0) | 155 #define LogToken(a, b, c) ((void)0) |
| 172 | 156 |
| 173 //----------------------------------------------------------------------------- | 157 //----------------------------------------------------------------------------- |
| 174 | 158 |
| 175 // Byte order swapping. | 159 // Byte order swapping. |
| 176 #define SWAP16(x) ((((x)&0xff) << 8) | (((x) >> 8) & 0xff)) | 160 #define SWAP16(x) ((((x)&0xff) << 8) | (((x) >> 8) & 0xff)) |
| 177 #define SWAP32(x) ((SWAP16((x)&0xffff) << 16) | (SWAP16((x) >> 16))) | 161 #define SWAP32(x) ((SWAP16((x)&0xffff) << 16) | (SWAP16((x) >> 16))) |
| 178 | 162 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 uint32_t x = (static_cast<uint32_t>(buf[0])) | | 223 uint32_t x = (static_cast<uint32_t>(buf[0])) | |
| 240 (static_cast<uint32_t>(buf[1]) << 8) | | 224 (static_cast<uint32_t>(buf[1]) << 8) | |
| 241 (static_cast<uint32_t>(buf[2]) << 16) | | 225 (static_cast<uint32_t>(buf[2]) << 16) | |
| 242 (static_cast<uint32_t>(buf[3]) << 24); | 226 (static_cast<uint32_t>(buf[3]) << 24); |
| 243 buf += sizeof(x); | 227 buf += sizeof(x); |
| 244 return x; | 228 return x; |
| 245 } | 229 } |
| 246 | 230 |
| 247 //----------------------------------------------------------------------------- | 231 //----------------------------------------------------------------------------- |
| 248 | 232 |
| 249 // LM_Hash computes the LM hash of the given password. | |
| 250 // | |
| 251 // param password | |
| 252 // unicode password. | |
| 253 // param hash | |
| 254 // 16-byte result buffer | |
| 255 // | |
| 256 // Note: This function is not being used because our SendLM() function always | |
| 257 // returns false. | |
| 258 static void LM_Hash(const base::string16& password, uint8_t* hash) { | |
| 259 static const uint8_t LM_MAGIC[] = "KGS!@#$%"; | |
| 260 | |
| 261 // Convert password to OEM character set. We'll just use the native | |
| 262 // filesystem charset. | |
| 263 std::string passbuf = base::SysWideToNativeMB(base::UTF16ToWide(password)); | |
| 264 passbuf = base::ToUpperASCII(passbuf); | |
| 265 passbuf.resize(14, '\0'); | |
| 266 | |
| 267 uint8_t k1[8], k2[8]; | |
| 268 DESMakeKey(reinterpret_cast<const uint8_t*>(passbuf.data()), k1); | |
| 269 DESMakeKey(reinterpret_cast<const uint8_t*>(passbuf.data()) + 7, k2); | |
| 270 ZapString(&passbuf); | |
| 271 | |
| 272 // Use password keys to hash LM magic string twice. | |
| 273 DESEncrypt(k1, LM_MAGIC, hash); | |
| 274 DESEncrypt(k2, LM_MAGIC, hash + 8); | |
| 275 } | |
| 276 | |
| 277 // NTLM_Hash computes the NTLM hash of the given password. | 233 // NTLM_Hash computes the NTLM hash of the given password. |
| 278 // | 234 // |
| 279 // param password | 235 // param password |
| 280 // null-terminated unicode password. | 236 // null-terminated unicode password. |
| 281 // param hash | 237 // param hash |
| 282 // 16-byte result buffer | 238 // 16-byte result buffer |
| 283 static void NTLM_Hash(const base::string16& password, uint8_t* hash) { | 239 static void NTLM_Hash(const base::string16& password, uint8_t* hash) { |
| 284 #ifdef IS_BIG_ENDIAN | 240 #ifdef IS_BIG_ENDIAN |
| 285 uint32_t len = password.length(); | 241 uint32_t len = password.length(); |
| 286 uint8_t* passbuf; | 242 uint8_t* passbuf; |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 *out_buf = malloc(*out_len); | 496 *out_buf = malloc(*out_len); |
| 541 if (!*out_buf) | 497 if (!*out_buf) |
| 542 return ERR_OUT_OF_MEMORY; | 498 return ERR_OUT_OF_MEMORY; |
| 543 | 499 |
| 544 // | 500 // |
| 545 // Next, we compute the LM and NTLM responses. | 501 // Next, we compute the LM and NTLM responses. |
| 546 // | 502 // |
| 547 uint8_t lm_resp[LM_RESP_LEN]; | 503 uint8_t lm_resp[LM_RESP_LEN]; |
| 548 uint8_t ntlm_resp[NTLM_RESP_LEN]; | 504 uint8_t ntlm_resp[NTLM_RESP_LEN]; |
| 549 uint8_t ntlm_hash[NTLM_HASH_LEN]; | 505 uint8_t ntlm_hash[NTLM_HASH_LEN]; |
| 550 if (msg.flags & NTLM_NegotiateNTLM2Key) { | |
| 551 // compute NTLM2 session response | |
| 552 base::MD5Digest session_hash; | |
| 553 uint8_t temp[16]; | |
| 554 | 506 |
| 555 memcpy(lm_resp, rand_8_bytes, 8); | 507 // compute NTLM2 session response |
| 556 memset(lm_resp + 8, 0, LM_RESP_LEN - 8); | 508 base::MD5Digest session_hash; |
| 509 uint8_t temp[16]; |
| 557 | 510 |
| 558 memcpy(temp, msg.challenge, 8); | 511 memcpy(lm_resp, rand_8_bytes, 8); |
| 559 memcpy(temp + 8, lm_resp, 8); | 512 memset(lm_resp + 8, 0, LM_RESP_LEN - 8); |
| 560 base::MD5Sum(temp, 16, &session_hash); | |
| 561 | 513 |
| 562 NTLM_Hash(password, ntlm_hash); | 514 memcpy(temp, msg.challenge, 8); |
| 563 LM_Response(ntlm_hash, session_hash.a, ntlm_resp); | 515 memcpy(temp + 8, lm_resp, 8); |
| 564 } else { | 516 base::MD5Sum(temp, 16, &session_hash); |
| 565 NTLM_Hash(password, ntlm_hash); | |
| 566 LM_Response(ntlm_hash, msg.challenge, ntlm_resp); | |
| 567 | 517 |
| 568 if (SendLM()) { | 518 NTLM_Hash(password, ntlm_hash); |
| 569 uint8_t lm_hash[LM_HASH_LEN]; | 519 LM_Response(ntlm_hash, session_hash.a, ntlm_resp); |
| 570 LM_Hash(password, lm_hash); | |
| 571 LM_Response(lm_hash, msg.challenge, lm_resp); | |
| 572 } else { | |
| 573 // According to http://davenport.sourceforge.net/ntlm.html#ntlmVersion2, | |
| 574 // the correct way to not send the LM hash is to send the NTLM hash twice | |
| 575 // in both the LM and NTLM response fields. | |
| 576 LM_Response(ntlm_hash, msg.challenge, lm_resp); | |
| 577 } | |
| 578 } | |
| 579 | 520 |
| 580 // | 521 // |
| 581 // Finally, we assemble the Type-3 msg :-) | 522 // Finally, we assemble the Type-3 msg :-) |
| 582 // | 523 // |
| 583 void* cursor = *out_buf; | 524 void* cursor = *out_buf; |
| 584 uint32_t offset; | 525 uint32_t offset; |
| 585 | 526 |
| 586 // 0 : signature | 527 // 0 : signature |
| 587 cursor = WriteBytes(cursor, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); | 528 cursor = WriteBytes(cursor, NTLM_SIGNATURE, sizeof(NTLM_SIGNATURE)); |
| 588 | 529 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 // of NTLM. | 662 // of NTLM. |
| 722 std::unique_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM); | 663 std::unique_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM); |
| 723 if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin, | 664 if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin, |
| 724 net_log)) | 665 net_log)) |
| 725 return ERR_INVALID_RESPONSE; | 666 return ERR_INVALID_RESPONSE; |
| 726 handler->swap(tmp_handler); | 667 handler->swap(tmp_handler); |
| 727 return OK; | 668 return OK; |
| 728 } | 669 } |
| 729 | 670 |
| 730 } // namespace net | 671 } // namespace net |
| OLD | NEW |