diff options
author | joi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-24 15:31:02 +0000 |
---|---|---|
committer | joi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-24 15:31:02 +0000 |
commit | e2a5768bd0101579ba6416e00dcb131bd9fb930a (patch) | |
tree | 30eeb8dba2310e0f48df97f0a8325b8679390584 /components | |
parent | 88364961eeb66f0d812c2f8854832b9c49b09ddd (diff) | |
download | chromium_src-e2a5768bd0101579ba6416e00dcb131bd9fb930a.zip chromium_src-e2a5768bd0101579ba6416e00dcb131bd9fb930a.tar.gz chromium_src-e2a5768bd0101579ba6416e00dcb131bd9fb930a.tar.bz2 |
Move ie7_password namespace to //components, so it can be used by components.
This will soon be used by the log-in related bits of WebData, which
will be extracted along with the sign-in logic to //components/signin.
TBR=ben@chromium.org
BUG=233552
Review URL: https://codereview.chromium.org/14348027
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@196154 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components')
-rw-r--r-- | components/webdata.gypi | 7 | ||||
-rw-r--r-- | components/webdata/encryptor/ie7_password.cc | 144 | ||||
-rw-r--r-- | components/webdata/encryptor/ie7_password.h | 46 |
3 files changed, 197 insertions, 0 deletions
diff --git a/components/webdata.gypi b/components/webdata.gypi index ef99c61..bba421e 100644 --- a/components/webdata.gypi +++ b/components/webdata.gypi @@ -21,8 +21,15 @@ 'webdata/encryptor/encryptor_password_mac.mm', 'webdata/encryptor/encryptor_posix.cc', 'webdata/encryptor/encryptor_win.cc', + 'webdata/encryptor/ie7_password.cc', + 'webdata/encryptor/ie7_password.h', ], 'conditions': [ + ['OS!="win"', { + 'sources!': [ + 'webdata/encryptor/ie7_password.cc' + ], + }], ['OS=="mac"', { 'sources!': [ 'webdata/encryptor/encryptor_posix.cc', diff --git a/components/webdata/encryptor/ie7_password.cc b/components/webdata/encryptor/ie7_password.cc new file mode 100644 index 0000000..793fde8 --- /dev/null +++ b/components/webdata/encryptor/ie7_password.cc @@ -0,0 +1,144 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/webdata/encryptor/ie7_password.h" + +#include <wincrypt.h> +#include <string> +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "base/sha1.h" +#include "base/string_util.h" +#include "base/stringprintf.h" + +namespace { + +// Structures that IE7/IE8 use to store a username/password. +// Some of the fields might have been incorrectly reverse engineered. +struct PreHeader { + DWORD pre_header_size; // Size of this header structure. Always 12. + DWORD header_size; // Size of the real Header: sizeof(Header) + + // item_count * sizeof(Entry); + DWORD data_size; // Size of the data referenced by the entries. +}; + +struct Header { + char wick[4]; // The string "WICK". I don't know what it means. + DWORD fixed_header_size; // The size of this structure without the entries: + // sizeof(Header). + DWORD item_count; // Number of entries. It should always be 2. One for + // the username, and one for the password. + wchar_t two_letters[2]; // Two unknown bytes. + DWORD unknown[2]; // Two unknown DWORDs. +}; + +struct Entry { + DWORD offset; // Offset where the data referenced by this entry is + // located. + FILETIME time_stamp; // Timestamp when the password got added. + DWORD string_length; // The length of the data string. +}; + +// Main data structure. +struct PasswordEntry { + PreHeader pre_header; // Contains the size of the different sections. + Header header; // Contains the number of items. + Entry entry[1]; // List of entries containing a string. The first one + // is the username, the second one if the password. +}; + +} // namespace + +namespace ie7_password { + +bool GetUserPassFromData(const std::vector<unsigned char>& data, + std::wstring* username, + std::wstring* password) { + const PasswordEntry* information = + reinterpret_cast<const PasswordEntry*>(&data.front()); + + // Some expected values. If it's not what we expect we don't even try to + // understand the data. + if (information->pre_header.pre_header_size != sizeof(PreHeader)) + return false; + + if (information->header.item_count != 2) // Username and Password + return false; + + if (information->header.fixed_header_size != sizeof(Header)) + return false; + + const uint8* ptr = &data.front(); + const uint8* offset_to_data = ptr + information->pre_header.header_size + + information->pre_header.pre_header_size; + + const Entry* user_entry = information->entry; + const Entry* pass_entry = user_entry+1; + + *username = reinterpret_cast<const wchar_t*>(offset_to_data + + user_entry->offset); + *password = reinterpret_cast<const wchar_t*>(offset_to_data + + pass_entry->offset); + return true; +} + +std::wstring GetUrlHash(const std::wstring& url) { + std::wstring lower_case_url = StringToLowerASCII(url); + // Get a data buffer out of our std::wstring to pass to SHA1HashString. + std::string url_buffer( + reinterpret_cast<const char*>(lower_case_url.c_str()), + (lower_case_url.size() + 1) * sizeof(wchar_t)); + std::string hash_bin = base::SHA1HashString(url_buffer); + + std::wstring url_hash; + + // Transform the buffer to an hexadecimal string. + unsigned char checksum = 0; + for (size_t i = 0; i < hash_bin.size(); ++i) { + // std::string gives signed chars, which mess with StringPrintf and + // check_sum. + unsigned char hash_byte = static_cast<unsigned char>(hash_bin[i]); + checksum += hash_byte; + url_hash += base::StringPrintf(L"%2.2X", static_cast<unsigned>(hash_byte)); + } + url_hash += base::StringPrintf(L"%2.2X", checksum); + + return url_hash; +} + +bool DecryptPassword(const std::wstring& url, + const std::vector<unsigned char>& data, + std::wstring* username, std::wstring* password) { + std::wstring lower_case_url = StringToLowerASCII(url); + DATA_BLOB input = {0}; + DATA_BLOB output = {0}; + DATA_BLOB url_key = {0}; + + input.pbData = const_cast<unsigned char*>(&data.front()); + input.cbData = static_cast<DWORD>((data.size()) * + sizeof(std::string::value_type)); + + url_key.pbData = reinterpret_cast<unsigned char*>( + const_cast<wchar_t*>(lower_case_url.data())); + url_key.cbData = static_cast<DWORD>((lower_case_url.size() + 1) * + sizeof(std::wstring::value_type)); + + if (CryptUnprotectData(&input, NULL, &url_key, NULL, NULL, + CRYPTPROTECT_UI_FORBIDDEN, &output)) { + // Now that we have the decrypted information, we need to understand it. + std::vector<unsigned char> decrypted_data; + decrypted_data.resize(output.cbData); + memcpy(&decrypted_data.front(), output.pbData, output.cbData); + + GetUserPassFromData(decrypted_data, username, password); + + LocalFree(output.pbData); + return true; + } + + return false; +} + +} // namespace ie7_password diff --git a/components/webdata/encryptor/ie7_password.h b/components/webdata/encryptor/ie7_password.h new file mode 100644 index 0000000..812dae3 --- /dev/null +++ b/components/webdata/encryptor/ie7_password.h @@ -0,0 +1,46 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_WEBDATA_ENCRYPTOR_IE7_PASSWORD_H_ +#define COMPONENTS_WEBDATA_ENCRYPTOR_IE7_PASSWORD_H_ + +#include <windows.h> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/time.h" + +// Contains the information read from the IE7/IE8 Storage2 key in the registry. +struct IE7PasswordInfo { + // Hash of the url. + std::wstring url_hash; + + // Encrypted data containing the username, password and some more undocumented + // fields. + std::vector<unsigned char> encrypted_data; + + // When the login was imported. + base::Time date_created; +}; + +namespace ie7_password { + +// Parses a data structure to find the password and the username. +bool GetUserPassFromData(const std::vector<unsigned char>& data, + std::wstring* username, + std::wstring* password); + +// Decrypts the username and password for a given data vector using the url as +// the key. +bool DecryptPassword(const std::wstring& url, + const std::vector<unsigned char>& data, + std::wstring* username, std::wstring* password); + +// Returns the hash of a url. +std::wstring GetUrlHash(const std::wstring& url); + +} // namespace ie7_password + +#endif // COMPONENTS_WEBDATA_ENCRYPTOR_IE7_PASSWORD_H_ |