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/autofill/autofill_ie_toolbar_import_win.h" 6 7 #include <stddef.h> 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/logging.h" 14 #include "base/string16.h" 15 #include "base/win/registry.h" 16 #include "chrome/browser/autofill/autofill_profile.h" 17 #include "chrome/browser/autofill/credit_card.h" 18 #include "chrome/browser/autofill/crypto/rc4_decryptor.h" 19 #include "chrome/browser/autofill/field_types.h" 20 #include "chrome/browser/autofill/form_group.h" 21 #include "chrome/browser/autofill/personal_data_manager.h" 22 #include "chrome/browser/sync/util/data_encryption.h" 23 24 using base::win::RegKey; 25 26 // Forward declaration. This function is not in unnamed namespace as it 27 // is referenced in the unittest. 28 bool ImportCurrentUserProfiles(std::vector<AutofillProfile>* profiles, 29 std::vector<CreditCard>* credit_cards); 30 namespace { 31 32 const wchar_t* const kProfileKey = 33 L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Profiles"; 34 const wchar_t* const kCreditCardKey = 35 L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Credit Cards"; 36 const wchar_t* const kPasswordHashValue = L"password_hash"; 37 const wchar_t* const kSaltValue = L"salt"; 38 39 // This is RC4 decryption for Toolbar credit card data. This is necessary 40 // because it is not standard, so Crypto API cannot be used. 41 std::wstring DecryptCCNumber(const std::wstring& data) { 42 const wchar_t* kEmptyKey = 43 L"\x3605\xCEE5\xCE49\x44F7\xCF4E\xF6CC\x604B\xFCBE\xC70A\x08FD"; 44 const size_t kMacLen = 10; 45 46 if (data.length() <= kMacLen) 47 return std::wstring(); 48 49 RC4Decryptor rc4_algorithm(kEmptyKey); 50 return rc4_algorithm.Run(data.substr(kMacLen)); 51 } 52 53 bool IsEmptySalt(std::wstring const& salt) { 54 // Empty salt in IE Toolbar is \x1\x2...\x14 55 if (salt.length() != 20) 56 return false; 57 for (size_t i = 0; i < salt.length(); ++i) { 58 if (salt[i] != i + 1) 59 return false; 60 } 61 return true; 62 } 63 64 string16 ReadAndDecryptValue(RegKey* key, const wchar_t* value_name) { 65 DWORD data_type = REG_BINARY; 66 DWORD data_size = 0; 67 LONG result = key->ReadValue(value_name, NULL, &data_size, &data_type); 68 if ((result != ERROR_SUCCESS) || !data_size || data_type != REG_BINARY) 69 return string16(); 70 std::vector<uint8> data; 71 data.resize(data_size); 72 result = key->ReadValue(value_name, &(data[0]), &data_size, &data_type); 73 if (result == ERROR_SUCCESS) { 74 std::string out_data; 75 if (DecryptData(data, &out_data)) { 76 // The actual data is in UTF16 already. 77 if (!(out_data.size() & 1) && (out_data.size() > 2) && 78 !out_data[out_data.size() - 1] && !out_data[out_data.size() - 2]) { 79 return string16( 80 reinterpret_cast<const wchar_t *>(out_data.c_str())); 81 } 82 } 83 } 84 return string16(); 85 } 86 87 struct { 88 AutofillFieldType field_type; 89 const wchar_t *reg_value_name; 90 } profile_reg_values[] = { 91 { NAME_FIRST, L"name_first" }, 92 { NAME_MIDDLE, L"name_middle" }, 93 { NAME_LAST, L"name_last" }, 94 { NAME_SUFFIX, L"name_suffix" }, 95 { EMAIL_ADDRESS, L"email" }, 96 { COMPANY_NAME, L"company_name" }, 97 { PHONE_HOME_NUMBER, L"phone_home_number" }, 98 { PHONE_HOME_CITY_CODE, L"phone_home_city_code" }, 99 { PHONE_HOME_COUNTRY_CODE, L"phone_home_country_code" }, 100 { PHONE_FAX_NUMBER, L"phone_fax_number" }, 101 { PHONE_FAX_CITY_CODE, L"phone_fax_city_code" }, 102 { PHONE_FAX_COUNTRY_CODE, L"phone_fax_country_code" }, 103 { ADDRESS_HOME_LINE1, L"address_home_line1" }, 104 { ADDRESS_HOME_LINE2, L"address_home_line2" }, 105 { ADDRESS_HOME_CITY, L"address_home_city" }, 106 { ADDRESS_HOME_STATE, L"address_home_state" }, 107 { ADDRESS_HOME_ZIP, L"address_home_zip" }, 108 { ADDRESS_HOME_COUNTRY, L"address_home_country" }, 109 { ADDRESS_BILLING_LINE1, L"address_billing_line1" }, 110 { ADDRESS_BILLING_LINE2, L"address_billing_line2" }, 111 { ADDRESS_BILLING_CITY, L"address_billing_city" }, 112 { ADDRESS_BILLING_STATE, L"address_billing_state" }, 113 { ADDRESS_BILLING_ZIP, L"address_billing_zip" }, 114 { ADDRESS_BILLING_COUNTRY, L"address_billing_country" }, 115 { CREDIT_CARD_NAME, L"credit_card_name" }, 116 { CREDIT_CARD_NUMBER, L"credit_card_number" }, 117 { CREDIT_CARD_EXP_MONTH, L"credit_card_exp_month" }, 118 { CREDIT_CARD_EXP_4_DIGIT_YEAR, L"credit_card_exp_4_digit_year" }, 119 { CREDIT_CARD_TYPE, L"credit_card_type" }, 120 // We do not import verification code. 121 }; 122 123 typedef std::map<std::wstring, AutofillFieldType> RegToFieldMap; 124 125 bool ImportSingleProfile(FormGroup* profile, 126 RegKey* key, 127 const RegToFieldMap& reg_to_field ) { 128 DCHECK(profile != NULL); 129 if (!key->Valid()) 130 return false; 131 132 bool has_non_empty_fields = false; 133 134 for (uint32 value_index = 0; value_index < key->ValueCount(); ++value_index) { 135 std::wstring value_name; 136 if (key->ReadName(value_index, &value_name) != ERROR_SUCCESS) 137 continue; 138 RegToFieldMap::const_iterator it = reg_to_field.find(value_name); 139 if (it == reg_to_field.end()) 140 continue; // This field is not imported. 141 string16 field_value = ReadAndDecryptValue(key, value_name.c_str()); 142 if (!field_value.empty()) { 143 has_non_empty_fields = true; 144 if (it->second == CREDIT_CARD_NUMBER) { 145 field_value = DecryptCCNumber(field_value); 146 } 147 profile->SetInfo(it->second, field_value); 148 } 149 } 150 return has_non_empty_fields; 151 } 152 153 // Imports profiles from the IE toolbar and stores them. Asynchronous 154 // if PersonalDataManager has not been loaded yet. Deletes itself on completion. 155 class AutofillImporter : public PersonalDataManager::Observer { 156 public: 157 explicit AutofillImporter(PersonalDataManager* personal_data_manager) 158 : personal_data_manager_(personal_data_manager) { 159 personal_data_manager_->SetObserver(this); 160 } 161 162 bool ImportProfiles() { 163 if (!ImportCurrentUserProfiles(&profiles_, &credit_cards_)) { 164 delete this; 165 return false; 166 } 167 if (personal_data_manager_->IsDataLoaded()) 168 OnPersonalDataLoaded(); 169 return true; 170 } 171 172 // PersonalDataManager::Observer methods: 173 virtual void OnPersonalDataLoaded() { 174 if (!profiles_.empty()) 175 personal_data_manager_->SetProfiles(&profiles_); 176 if (!credit_cards_.empty()) 177 personal_data_manager_->SetCreditCards(&credit_cards_); 178 delete this; 179 } 180 181 private: 182 ~AutofillImporter() { 183 personal_data_manager_->RemoveObserver(this); 184 } 185 186 PersonalDataManager* personal_data_manager_; 187 std::vector<AutofillProfile> profiles_; 188 std::vector<CreditCard> credit_cards_; 189 }; 190 191 } // namespace 192 193 // Imports Autofill profiles and credit cards from IE Toolbar if present and not 194 // password protected. Returns true if data is successfully retrieved. False if 195 // there is no data, data is password protected or error occurred. 196 bool ImportCurrentUserProfiles(std::vector<AutofillProfile>* profiles, 197 std::vector<CreditCard>* credit_cards) { 198 DCHECK(profiles); 199 DCHECK(credit_cards); 200 201 // Create a map of possible fields for a quick access. 202 RegToFieldMap reg_to_field; 203 for (size_t i = 0; i < arraysize(profile_reg_values); ++i) { 204 reg_to_field[std::wstring(profile_reg_values[i].reg_value_name)] = 205 profile_reg_values[i].field_type; 206 } 207 208 base::win::RegistryKeyIterator iterator_profiles(HKEY_CURRENT_USER, 209 kProfileKey); 210 for (; iterator_profiles.Valid(); ++iterator_profiles) { 211 std::wstring key_name(kProfileKey); 212 key_name.append(L"\\"); 213 key_name.append(iterator_profiles.Name()); 214 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ); 215 AutofillProfile profile; 216 if (ImportSingleProfile(&profile, &key, reg_to_field)) { 217 // Combine phones into whole phone #. 218 string16 phone; 219 phone = profile.GetInfo(PHONE_HOME_COUNTRY_CODE); 220 phone.append(profile.GetInfo(PHONE_HOME_CITY_CODE)); 221 phone.append(profile.GetInfo(PHONE_HOME_NUMBER)); 222 profile.SetInfo(PHONE_HOME_WHOLE_NUMBER, phone); 223 phone = profile.GetInfo(PHONE_FAX_COUNTRY_CODE); 224 phone.append(profile.GetInfo(PHONE_FAX_CITY_CODE)); 225 phone.append(profile.GetInfo(PHONE_FAX_NUMBER)); 226 profile.SetInfo(PHONE_FAX_WHOLE_NUMBER, phone); 227 profiles->push_back(profile); 228 } 229 } 230 string16 password_hash; 231 string16 salt; 232 RegKey cc_key(HKEY_CURRENT_USER, kCreditCardKey, KEY_READ); 233 if (cc_key.Valid()) { 234 password_hash = ReadAndDecryptValue(&cc_key, kPasswordHashValue); 235 salt = ReadAndDecryptValue(&cc_key, kSaltValue); 236 } 237 238 // We import CC profiles only if they are not password protected. 239 if (password_hash.empty() && IsEmptySalt(salt)) { 240 base::win::RegistryKeyIterator iterator_cc(HKEY_CURRENT_USER, 241 kCreditCardKey); 242 for (; iterator_cc.Valid(); ++iterator_cc) { 243 std::wstring key_name(kCreditCardKey); 244 key_name.append(L"\\"); 245 key_name.append(iterator_cc.Name()); 246 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ); 247 CreditCard credit_card; 248 if (ImportSingleProfile(&credit_card, &key, reg_to_field)) { 249 string16 cc_number = credit_card.GetInfo(CREDIT_CARD_NUMBER); 250 if (!cc_number.empty()) 251 credit_cards->push_back(credit_card); 252 } 253 } 254 } 255 return (profiles->size() + credit_cards->size()) > 0; 256 } 257 258 bool ImportAutofillDataWin(PersonalDataManager* pdm) { 259 // In incognito mode we do not have PDM - and we should not import anything. 260 if (!pdm) 261 return false; 262 AutofillImporter *importer = new AutofillImporter(pdm); 263 // importer will self delete. 264 return importer->ImportProfiles(); 265 } 266 267