1 // Copyright 2013 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 "components/autofill/core/browser/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/compiler_specific.h" 14 #include "base/logging.h" 15 #include "base/strings/string16.h" 16 #include "base/win/registry.h" 17 #include "components/autofill/core/browser/autofill_country.h" 18 #include "components/autofill/core/browser/autofill_profile.h" 19 #include "components/autofill/core/browser/credit_card.h" 20 #include "components/autofill/core/browser/crypto/rc4_decryptor.h" 21 #include "components/autofill/core/browser/field_types.h" 22 #include "components/autofill/core/browser/form_group.h" 23 #include "components/autofill/core/browser/personal_data_manager.h" 24 #include "components/autofill/core/browser/personal_data_manager_observer.h" 25 #include "components/autofill/core/browser/phone_number.h" 26 #include "components/autofill/core/browser/phone_number_i18n.h" 27 #include "components/webdata/encryptor/encryptor.h" 28 29 using base::win::RegKey; 30 31 namespace autofill { 32 33 // Forward declaration. This function is not in unnamed namespace as it 34 // is referenced in the unittest. 35 bool ImportCurrentUserProfiles(const std::string& app_locale, 36 std::vector<AutofillProfile>* profiles, 37 std::vector<CreditCard>* credit_cards); 38 namespace { 39 40 const wchar_t* const kProfileKey = 41 L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Profiles"; 42 const wchar_t* const kCreditCardKey = 43 L"Software\\Google\\Google Toolbar\\4.0\\Autofill\\Credit Cards"; 44 const wchar_t* const kPasswordHashValue = L"password_hash"; 45 const wchar_t* const kSaltValue = L"salt"; 46 47 // This string is stored along with saved addresses and credit cards in the 48 // WebDB, and hence should not be modified, so that it remains consistent over 49 // time. 50 const char kIEToolbarImportOrigin[] = "Imported from Internet Explorer"; 51 52 // This is RC4 decryption for Toolbar credit card data. This is necessary 53 // because it is not standard, so Crypto API cannot be used. 54 std::wstring DecryptCCNumber(const std::wstring& data) { 55 const wchar_t* kEmptyKey = 56 L"\x3605\xCEE5\xCE49\x44F7\xCF4E\xF6CC\x604B\xFCBE\xC70A\x08FD"; 57 const size_t kMacLen = 10; 58 59 if (data.length() <= kMacLen) 60 return std::wstring(); 61 62 RC4Decryptor rc4_algorithm(kEmptyKey); 63 return rc4_algorithm.Run(data.substr(kMacLen)); 64 } 65 66 bool IsEmptySalt(std::wstring const& salt) { 67 // Empty salt in IE Toolbar is \x1\x2...\x14 68 if (salt.length() != 20) 69 return false; 70 for (size_t i = 0; i < salt.length(); ++i) { 71 if (salt[i] != i + 1) 72 return false; 73 } 74 return true; 75 } 76 77 base::string16 ReadAndDecryptValue(const RegKey& key, 78 const wchar_t* value_name) { 79 DWORD data_type = REG_BINARY; 80 DWORD data_size = 0; 81 LONG result = key.ReadValue(value_name, NULL, &data_size, &data_type); 82 if ((result != ERROR_SUCCESS) || !data_size || data_type != REG_BINARY) 83 return base::string16(); 84 std::string data; 85 data.resize(data_size); 86 result = key.ReadValue(value_name, &(data[0]), &data_size, &data_type); 87 if (result == ERROR_SUCCESS) { 88 std::string out_data; 89 if (Encryptor::DecryptString(data, &out_data)) { 90 // The actual data is in UTF16 already. 91 if (!(out_data.size() & 1) && (out_data.size() > 2) && 92 !out_data[out_data.size() - 1] && !out_data[out_data.size() - 2]) { 93 return base::string16( 94 reinterpret_cast<const wchar_t *>(out_data.c_str())); 95 } 96 } 97 } 98 return base::string16(); 99 } 100 101 struct { 102 ServerFieldType field_type; 103 const wchar_t *reg_value_name; 104 } profile_reg_values[] = { 105 { NAME_FIRST, L"name_first" }, 106 { NAME_MIDDLE, L"name_middle" }, 107 { NAME_LAST, L"name_last" }, 108 { NAME_SUFFIX, L"name_suffix" }, 109 { EMAIL_ADDRESS, L"email" }, 110 { COMPANY_NAME, L"company_name" }, 111 { PHONE_HOME_NUMBER, L"phone_home_number" }, 112 { PHONE_HOME_CITY_CODE, L"phone_home_city_code" }, 113 { PHONE_HOME_COUNTRY_CODE, L"phone_home_country_code" }, 114 { ADDRESS_HOME_LINE1, L"address_home_line1" }, 115 { ADDRESS_HOME_LINE2, L"address_home_line2" }, 116 { ADDRESS_HOME_CITY, L"address_home_city" }, 117 { ADDRESS_HOME_STATE, L"address_home_state" }, 118 { ADDRESS_HOME_ZIP, L"address_home_zip" }, 119 { ADDRESS_HOME_COUNTRY, L"address_home_country" }, 120 { ADDRESS_BILLING_LINE1, L"address_billing_line1" }, 121 { ADDRESS_BILLING_LINE2, L"address_billing_line2" }, 122 { ADDRESS_BILLING_CITY, L"address_billing_city" }, 123 { ADDRESS_BILLING_STATE, L"address_billing_state" }, 124 { ADDRESS_BILLING_ZIP, L"address_billing_zip" }, 125 { ADDRESS_BILLING_COUNTRY, L"address_billing_country" }, 126 { CREDIT_CARD_NAME, L"credit_card_name" }, 127 { CREDIT_CARD_NUMBER, L"credit_card_number" }, 128 { CREDIT_CARD_EXP_MONTH, L"credit_card_exp_month" }, 129 { CREDIT_CARD_EXP_4_DIGIT_YEAR, L"credit_card_exp_4_digit_year" }, 130 { CREDIT_CARD_TYPE, L"credit_card_type" }, 131 // We do not import verification code. 132 }; 133 134 typedef std::map<std::wstring, ServerFieldType> RegToFieldMap; 135 136 // Imports address or credit card data from the given registry |key| into the 137 // given |form_group|, with the help of |reg_to_field|. When importing address 138 // data, writes the phone data into |phone|; otherwise, |phone| should be null. 139 // Returns true if any fields were set, false otherwise. 140 bool ImportSingleFormGroup(const RegKey& key, 141 const RegToFieldMap& reg_to_field, 142 const std::string& app_locale, 143 FormGroup* form_group, 144 PhoneNumber::PhoneCombineHelper* phone) { 145 if (!key.Valid()) 146 return false; 147 148 bool has_non_empty_fields = false; 149 150 for (uint32 i = 0; i < key.GetValueCount(); ++i) { 151 std::wstring value_name; 152 if (key.GetValueNameAt(i, &value_name) != ERROR_SUCCESS) 153 continue; 154 155 RegToFieldMap::const_iterator it = reg_to_field.find(value_name); 156 if (it == reg_to_field.end()) 157 continue; // This field is not imported. 158 159 base::string16 field_value = ReadAndDecryptValue(key, value_name.c_str()); 160 if (!field_value.empty()) { 161 if (it->second == CREDIT_CARD_NUMBER) 162 field_value = DecryptCCNumber(field_value); 163 164 // Phone numbers are stored piece-by-piece, and then reconstructed from 165 // the pieces. The rest of the fields are set "as is". 166 if (!phone || !phone->SetInfo(AutofillType(it->second), field_value)) { 167 has_non_empty_fields = true; 168 form_group->SetInfo(AutofillType(it->second), field_value, app_locale); 169 } 170 } 171 } 172 173 return has_non_empty_fields; 174 } 175 176 // Imports address data from the given registry |key| into the given |profile|, 177 // with the help of |reg_to_field|. Returns true if any fields were set, false 178 // otherwise. 179 bool ImportSingleProfile(const std::string& app_locale, 180 const RegKey& key, 181 const RegToFieldMap& reg_to_field, 182 AutofillProfile* profile) { 183 PhoneNumber::PhoneCombineHelper phone; 184 bool has_non_empty_fields = 185 ImportSingleFormGroup(key, reg_to_field, app_locale, profile, &phone); 186 187 // Now re-construct the phones if needed. 188 base::string16 constructed_number; 189 if (phone.ParseNumber(*profile, app_locale, &constructed_number)) { 190 has_non_empty_fields = true; 191 profile->SetRawInfo(PHONE_HOME_WHOLE_NUMBER, constructed_number); 192 } 193 194 return has_non_empty_fields; 195 } 196 197 // Imports profiles from the IE toolbar and stores them. Asynchronous 198 // if PersonalDataManager has not been loaded yet. Deletes itself on completion. 199 class AutofillImporter : public PersonalDataManagerObserver { 200 public: 201 explicit AutofillImporter(PersonalDataManager* personal_data_manager) 202 : personal_data_manager_(personal_data_manager) { 203 personal_data_manager_->AddObserver(this); 204 } 205 206 bool ImportProfiles() { 207 if (!ImportCurrentUserProfiles(personal_data_manager_->app_locale(), 208 &profiles_, 209 &credit_cards_)) { 210 delete this; 211 return false; 212 } 213 if (personal_data_manager_->IsDataLoaded()) 214 OnPersonalDataChanged(); 215 return true; 216 } 217 218 // PersonalDataManagerObserver: 219 virtual void OnPersonalDataChanged() OVERRIDE { 220 for (std::vector<AutofillProfile>::const_iterator iter = profiles_.begin(); 221 iter != profiles_.end(); ++iter) { 222 personal_data_manager_->AddProfile(*iter); 223 } 224 for (std::vector<CreditCard>::const_iterator iter = credit_cards_.begin(); 225 iter != credit_cards_.end(); ++iter) { 226 personal_data_manager_->AddCreditCard(*iter); 227 } 228 delete this; 229 } 230 231 private: 232 ~AutofillImporter() { 233 personal_data_manager_->RemoveObserver(this); 234 } 235 236 PersonalDataManager* personal_data_manager_; 237 std::vector<AutofillProfile> profiles_; 238 std::vector<CreditCard> credit_cards_; 239 }; 240 241 } // namespace 242 243 // Imports Autofill profiles and credit cards from IE Toolbar if present and not 244 // password protected. Returns true if data is successfully retrieved. False if 245 // there is no data, data is password protected or error occurred. 246 bool ImportCurrentUserProfiles(const std::string& app_locale, 247 std::vector<AutofillProfile>* profiles, 248 std::vector<CreditCard>* credit_cards) { 249 DCHECK(profiles); 250 DCHECK(credit_cards); 251 252 // Create a map of possible fields for a quick access. 253 RegToFieldMap reg_to_field; 254 for (size_t i = 0; i < arraysize(profile_reg_values); ++i) { 255 reg_to_field[std::wstring(profile_reg_values[i].reg_value_name)] = 256 profile_reg_values[i].field_type; 257 } 258 259 base::win::RegistryKeyIterator iterator_profiles(HKEY_CURRENT_USER, 260 kProfileKey); 261 for (; iterator_profiles.Valid(); ++iterator_profiles) { 262 std::wstring key_name(kProfileKey); 263 key_name.append(L"\\"); 264 key_name.append(iterator_profiles.Name()); 265 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ); 266 AutofillProfile profile; 267 profile.set_origin(kIEToolbarImportOrigin); 268 if (ImportSingleProfile(app_locale, key, reg_to_field, &profile)) { 269 // Combine phones into whole phone #. 270 profiles->push_back(profile); 271 } 272 } 273 base::string16 password_hash; 274 base::string16 salt; 275 RegKey cc_key(HKEY_CURRENT_USER, kCreditCardKey, KEY_READ); 276 if (cc_key.Valid()) { 277 password_hash = ReadAndDecryptValue(cc_key, kPasswordHashValue); 278 salt = ReadAndDecryptValue(cc_key, kSaltValue); 279 } 280 281 // We import CC profiles only if they are not password protected. 282 if (password_hash.empty() && IsEmptySalt(salt)) { 283 base::win::RegistryKeyIterator iterator_cc(HKEY_CURRENT_USER, 284 kCreditCardKey); 285 for (; iterator_cc.Valid(); ++iterator_cc) { 286 std::wstring key_name(kCreditCardKey); 287 key_name.append(L"\\"); 288 key_name.append(iterator_cc.Name()); 289 RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_READ); 290 CreditCard credit_card; 291 credit_card.set_origin(kIEToolbarImportOrigin); 292 if (ImportSingleFormGroup( 293 key, reg_to_field, app_locale, &credit_card, NULL)) { 294 base::string16 cc_number = credit_card.GetRawInfo(CREDIT_CARD_NUMBER); 295 if (!cc_number.empty()) 296 credit_cards->push_back(credit_card); 297 } 298 } 299 } 300 return (profiles->size() + credit_cards->size()) > 0; 301 } 302 303 bool ImportAutofillDataWin(PersonalDataManager* pdm) { 304 // In incognito mode we do not have PDM - and we should not import anything. 305 if (!pdm) 306 return false; 307 AutofillImporter *importer = new AutofillImporter(pdm); 308 // importer will self delete. 309 return importer->ImportProfiles(); 310 } 311 312 } // namespace autofill 313