| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |  | 
| 2 // Use of this source code is governed by a BSD-style license that can be |  | 
| 3 // found in the LICENSE file. |  | 
| 4 |  | 
| 5 #include "chrome/browser/password_manager/ie7_password.h" |  | 
| 6 |  | 
| 7 #include <wincrypt.h> |  | 
| 8 #include <string> |  | 
| 9 #include <vector> |  | 
| 10 |  | 
| 11 #include "base/memory/scoped_ptr.h" |  | 
| 12 #include "base/sha1.h" |  | 
| 13 #include "base/string_util.h" |  | 
| 14 #include "base/stringprintf.h" |  | 
| 15 |  | 
| 16 namespace { |  | 
| 17 |  | 
| 18 // Structures that IE7/IE8 use to store a username/password. |  | 
| 19 // Some of the fields might have been incorrectly reverse engineered. |  | 
| 20 struct PreHeader { |  | 
| 21   DWORD pre_header_size;  // Size of this header structure. Always 12. |  | 
| 22   DWORD header_size;      // Size of the real Header: sizeof(Header) + |  | 
| 23                           // item_count * sizeof(Entry); |  | 
| 24   DWORD data_size;        // Size of the data referenced by the entries. |  | 
| 25 }; |  | 
| 26 |  | 
| 27 struct Header { |  | 
| 28   char wick[4];             // The string "WICK". I don't know what it means. |  | 
| 29   DWORD fixed_header_size;  // The size of this structure without the entries: |  | 
| 30                             // sizeof(Header). |  | 
| 31   DWORD item_count;         // Number of entries. It should always be 2. One for |  | 
| 32                             // the username, and one for the password. |  | 
| 33   wchar_t two_letters[2];   // Two unknown bytes. |  | 
| 34   DWORD unknown[2];         // Two unknown DWORDs. |  | 
| 35 }; |  | 
| 36 |  | 
| 37 struct Entry { |  | 
| 38   DWORD offset;         // Offset where the data referenced by this entry is |  | 
| 39                         // located. |  | 
| 40   FILETIME time_stamp;  // Timestamp when the password got added. |  | 
| 41   DWORD string_length;  // The length of the data string. |  | 
| 42 }; |  | 
| 43 |  | 
| 44 // Main data structure. |  | 
| 45 struct PasswordEntry { |  | 
| 46   PreHeader pre_header;  // Contains the size of the different sections. |  | 
| 47   Header header;         // Contains the number of items. |  | 
| 48   Entry entry[1];        // List of entries containing a string. The first one |  | 
| 49                          // is the username, the second one if the password. |  | 
| 50 }; |  | 
| 51 |  | 
| 52 }  // namespace |  | 
| 53 |  | 
| 54 namespace ie7_password { |  | 
| 55 |  | 
| 56 bool GetUserPassFromData(const std::vector<unsigned char>& data, |  | 
| 57                          std::wstring* username, |  | 
| 58                          std::wstring* password) { |  | 
| 59   const PasswordEntry* information = |  | 
| 60       reinterpret_cast<const PasswordEntry*>(&data.front()); |  | 
| 61 |  | 
| 62   // Some expected values. If it's not what we expect we don't even try to |  | 
| 63   // understand the data. |  | 
| 64   if (information->pre_header.pre_header_size != sizeof(PreHeader)) |  | 
| 65     return false; |  | 
| 66 |  | 
| 67   if (information->header.item_count != 2)  // Username and Password |  | 
| 68     return false; |  | 
| 69 |  | 
| 70   if (information->header.fixed_header_size != sizeof(Header)) |  | 
| 71     return false; |  | 
| 72 |  | 
| 73   const uint8* ptr = &data.front(); |  | 
| 74   const uint8* offset_to_data = ptr + information->pre_header.header_size + |  | 
| 75                                 information->pre_header.pre_header_size; |  | 
| 76 |  | 
| 77   const Entry* user_entry = information->entry; |  | 
| 78   const Entry* pass_entry = user_entry+1; |  | 
| 79 |  | 
| 80   *username = reinterpret_cast<const wchar_t*>(offset_to_data + |  | 
| 81                                                user_entry->offset); |  | 
| 82   *password = reinterpret_cast<const wchar_t*>(offset_to_data + |  | 
| 83                                                pass_entry->offset); |  | 
| 84   return true; |  | 
| 85 } |  | 
| 86 |  | 
| 87 std::wstring GetUrlHash(const std::wstring& url) { |  | 
| 88   std::wstring lower_case_url = StringToLowerASCII(url); |  | 
| 89   // Get a data buffer out of our std::wstring to pass to SHA1HashString. |  | 
| 90   std::string url_buffer( |  | 
| 91       reinterpret_cast<const char*>(lower_case_url.c_str()), |  | 
| 92       (lower_case_url.size() + 1) * sizeof(wchar_t)); |  | 
| 93   std::string hash_bin = base::SHA1HashString(url_buffer); |  | 
| 94 |  | 
| 95   std::wstring url_hash; |  | 
| 96 |  | 
| 97   // Transform the buffer to an hexadecimal string. |  | 
| 98   unsigned char checksum = 0; |  | 
| 99   for (size_t i = 0; i < hash_bin.size(); ++i) { |  | 
| 100     // std::string gives signed chars, which mess with StringPrintf and |  | 
| 101     // check_sum. |  | 
| 102     unsigned char hash_byte = static_cast<unsigned char>(hash_bin[i]); |  | 
| 103     checksum += hash_byte; |  | 
| 104     url_hash += base::StringPrintf(L"%2.2X", static_cast<unsigned>(hash_byte)); |  | 
| 105   } |  | 
| 106   url_hash += base::StringPrintf(L"%2.2X", checksum); |  | 
| 107 |  | 
| 108   return url_hash; |  | 
| 109 } |  | 
| 110 |  | 
| 111 bool DecryptPassword(const std::wstring& url, |  | 
| 112                      const std::vector<unsigned char>& data, |  | 
| 113                      std::wstring* username, std::wstring* password) { |  | 
| 114   std::wstring lower_case_url = StringToLowerASCII(url); |  | 
| 115   DATA_BLOB input = {0}; |  | 
| 116   DATA_BLOB output = {0}; |  | 
| 117   DATA_BLOB url_key = {0}; |  | 
| 118 |  | 
| 119   input.pbData = const_cast<unsigned char*>(&data.front()); |  | 
| 120   input.cbData = static_cast<DWORD>((data.size()) * |  | 
| 121                                     sizeof(std::string::value_type)); |  | 
| 122 |  | 
| 123   url_key.pbData = reinterpret_cast<unsigned char*>( |  | 
| 124                       const_cast<wchar_t*>(lower_case_url.data())); |  | 
| 125   url_key.cbData = static_cast<DWORD>((lower_case_url.size() + 1) * |  | 
| 126                                       sizeof(std::wstring::value_type)); |  | 
| 127 |  | 
| 128   if (CryptUnprotectData(&input, NULL, &url_key, NULL, NULL, |  | 
| 129                          CRYPTPROTECT_UI_FORBIDDEN, &output)) { |  | 
| 130     // Now that we have the decrypted information, we need to understand it. |  | 
| 131     std::vector<unsigned char> decrypted_data; |  | 
| 132     decrypted_data.resize(output.cbData); |  | 
| 133     memcpy(&decrypted_data.front(), output.pbData, output.cbData); |  | 
| 134 |  | 
| 135     GetUserPassFromData(decrypted_data, username, password); |  | 
| 136 |  | 
| 137     LocalFree(output.pbData); |  | 
| 138     return true; |  | 
| 139   } |  | 
| 140 |  | 
| 141   return false; |  | 
| 142 } |  | 
| 143 |  | 
| 144 }  // namespace ie7_password |  | 
| OLD | NEW | 
|---|