Skip to content
This repository has been archived by the owner on Jan 4, 2019. It is now read-only.

Commit

Permalink
Import password from Chrome
Browse files Browse the repository at this point in the history
fixes brave/browser-laptop#9434

Auditors: @bridiver, @bbondy, @diracdeltas, @bsclifton

Mac:
master password will store in Chrome/Chromium Safe Storage
so we will ask users to access it

Windows:
Using `CryptProtectData` and `CryptUnprotectData`
`Usually, the only user who can decrypt the data is a user with the same logon
credentials as the user who encrypted the data`

Linux:
Using NativeBackEnd.
gnome-keyring which will be removed soon is deprecated by libsecret
KDE has a bug traking it #238
  • Loading branch information
darkdh committed Jun 30, 2017
1 parent b1f130f commit a424588
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 0 deletions.
7 changes: 7 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,20 @@ source_set("utility") {
"//content/public/common",
]

defines = [ ]

deps = [
"chromium_src:importer",
"//chrome/common",
"//chrome/utility",
"//third_party/protobuf:protobuf_lite",
]

if (use_glib) {
defines += [ "USE_LIBSECRET" ]
deps += [ "//third_party/libsecret" ]
}

sources = [
"atom/utility/atom_content_utility_client.cc",
"atom/utility/atom_content_utility_client.h",
Expand Down
4 changes: 4 additions & 0 deletions atom/common/importer/chrome_importer_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,17 @@ bool ChromeImporterCanImport(const base::FilePath& profile,
profile.Append(base::FilePath::StringType(FILE_PATH_LITERAL("History")));
base::FilePath cookies =
profile.Append(base::FilePath::StringType(FILE_PATH_LITERAL("Cookies")));
base::FilePath passwords =
profile.Append(base::FilePath::StringType(FILE_PATH_LITERAL("Login Data")));

if (base::PathExists(bookmarks))
*services_supported |= importer::FAVORITES;
if (base::PathExists(history))
*services_supported |= importer::HISTORY;
if (base::PathExists(cookies))
*services_supported |= importer::COOKIES;
if (base::PathExists(passwords))
*services_supported |= importer::PASSWORDS;

return *services_supported != importer::NONE;
}
Expand Down
6 changes: 6 additions & 0 deletions atom/utility/atom_content_utility_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ bool AtomContentUtilityClient::OnMessageReceived(

bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AtomContentUtilityClient, message)
IPC_MESSAGE_HANDLER(BraveUtilityMsg_GetImportFromChrome, OnImportFromChrome)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()

Expand Down Expand Up @@ -145,4 +146,9 @@ void AtomContentUtilityClient::PreSandboxStartup() {
#endif
}

void AtomContentUtilityClient::OnImportFromChrome() {
auto command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitch("import-chrome");
}

} // namespace atom
2 changes: 2 additions & 0 deletions atom/utility/atom_content_utility_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class AtomContentUtilityClient : public content::ContentUtilityClient {
private:
void OnStartupPing();

void OnImportFromChrome();

typedef ScopedVector<UtilityMessageHandler> Handlers;
Handlers handlers_;

Expand Down
122 changes: 122 additions & 0 deletions brave/utility/importer/chrome_importer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,41 @@
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
#include "base/values.h"
#include "brave/common/importer/imported_cookie_entry.h"
#include "build/build_config.h"
#include "chrome/common/importer/imported_bookmark_entry.h"
#include "chrome/common/importer/importer_bridge.h"
#include "chrome/common/importer/importer_url_row.h"
#include "chrome/utility/importer/favicon_reencode.h"
#include "components/autofill/core/common/password_form.h"
#include "components/os_crypt/os_crypt.h"
#include "components/password_manager/core/browser/login_database.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/json_pref_store.h"
#include "components/prefs/pref_filter.h"
#include "sql/connection.h"
#include "sql/statement.h"
#include "url/gurl.h"

#if defined(USE_X11)
#if defined(USE_LIBSECRET)
#include "chrome/browser/password_manager/native_backend_libsecret.h"
#endif
#include "chrome/browser/password_manager/native_backend_kwallet_x.h"
#include "chrome/browser/password_manager/password_store_x.h"
#include "components/os_crypt/key_storage_util_linux.h"

base::nix::DesktopEnvironment ChromeImporter::GetDesktopEnvironment() {
std::unique_ptr<base::Environment> env(base::Environment::Create());
return base::nix::GetDesktopEnvironment(env.get());
}
#endif

ChromeImporter::ChromeImporter() {
}

Expand Down Expand Up @@ -55,6 +78,13 @@ void ChromeImporter::StartImport(const importer::SourceProfile& source_profile,
ImportCookies();
bridge_->NotifyItemEnded(importer::COOKIES);
}

if ((items & importer::PASSWORDS) && !cancelled()) {
bridge_->NotifyItemStarted(importer::PASSWORDS);
ImportPasswords();
bridge_->NotifyItemEnded(importer::PASSWORDS);
}

bridge_->NotifyEnded();
}

Expand Down Expand Up @@ -250,6 +280,98 @@ void ChromeImporter::ImportCookies() {
SetCookies(cookies);
}

void ChromeImporter::ImportPasswords() {
#if !defined(USE_X11)
base::FilePath passwords_path =
source_path_.Append(
base::FilePath::StringType(FILE_PATH_LITERAL("Login Data")));

password_manager::LoginDatabase database(passwords_path);
if (!database.Init()) {
LOG(ERROR) << "LoginDatabase Init() failed";
return;
}

std::vector<std::unique_ptr<autofill::PasswordForm>> forms;
bool success = database.GetAutofillableLogins(&forms);
if (success) {
for (int i = 0; i < forms.size(); ++i) {
bridge_->SetPasswordForm(*forms[i].get());
}
}
std::vector<std::unique_ptr<autofill::PasswordForm>> blacklist;
success = database.GetBlacklistLogins(&blacklist);
if (success) {
for (int i = 0; i < blacklist.size(); ++i) {
bridge_->SetPasswordForm(*blacklist[i].get());
}
}
#else
base::FilePath prefs_path =
source_path_.Append(
base::FilePath::StringType(FILE_PATH_LITERAL("Preferences")));
const base::Value *value;
scoped_refptr<base::SequencedTaskRunner> file_task_runner =
base::CreateSequencedTaskRunnerWithTraits(base::TaskTraits().MayBlock());
scoped_refptr<JsonPrefStore> prefs = new JsonPrefStore(
prefs_path, file_task_runner, std::unique_ptr<PrefFilter>());
int local_profile_id;
if (prefs->ReadPrefs() != PersistentPrefStore::PREF_READ_ERROR_NONE) {
return;
}
if (!prefs->GetValue(password_manager::prefs::kLocalProfileId, &value)) {
return;
}
if (!value->GetAsInteger(&local_profile_id)) {
return;
}

std::unique_ptr<PasswordStoreX::NativeBackend> backend;
base::nix::DesktopEnvironment desktop_env = GetDesktopEnvironment();

os_crypt::SelectedLinuxBackend selected_backend =
os_crypt::SelectBackend(std::string(), desktop_env);
if (!backend &&
(selected_backend == os_crypt::SelectedLinuxBackend::KWALLET ||
selected_backend == os_crypt::SelectedLinuxBackend::KWALLET5)) {
base::nix::DesktopEnvironment used_desktop_env =
selected_backend == os_crypt::SelectedLinuxBackend::KWALLET
? base::nix::DESKTOP_ENVIRONMENT_KDE4
: base::nix::DESKTOP_ENVIRONMENT_KDE5;
backend.reset(new NativeBackendKWallet(local_profile_id,
used_desktop_env));
} else if (selected_backend == os_crypt::SelectedLinuxBackend::GNOME_ANY ||
selected_backend ==
os_crypt::SelectedLinuxBackend::GNOME_KEYRING ||
selected_backend ==
os_crypt::SelectedLinuxBackend::GNOME_LIBSECRET) {
#if defined(USE_LIBSECRET)
if (!backend &&
(selected_backend == os_crypt::SelectedLinuxBackend::GNOME_ANY ||
selected_backend == os_crypt::SelectedLinuxBackend::GNOME_LIBSECRET)) {
backend.reset(new NativeBackendLibsecret(local_profile_id));
}
#endif
}
if (backend && backend->Init()) {
std::vector<std::unique_ptr<autofill::PasswordForm>> forms;
bool success = backend->GetAutofillableLogins(&forms);
if (success) {
for (int i = 0; i < forms.size(); ++i) {
bridge_->SetPasswordForm(*forms[i].get());
}
}
std::vector<std::unique_ptr<autofill::PasswordForm>> blacklist;
success = backend->GetBlacklistLogins(&blacklist);
if (success) {
for (int i = 0; i < blacklist.size(); ++i) {
bridge_->SetPasswordForm(*blacklist[i].get());
}
}
}
#endif
}

void ChromeImporter::RecursiveReadBookmarksFolder(
const base::DictionaryValue* folder,
const std::vector<base::string16>& parent_path,
Expand Down
4 changes: 4 additions & 0 deletions brave/utility/importer/chrome_importer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/nix/xdg_util.h"
#include "build/build_config.h"
#include "chrome/utility/importer/importer.h"
#include "components/favicon_base/favicon_usage_data.h"
Expand All @@ -40,9 +41,12 @@ class ChromeImporter : public Importer {
private:
~ChromeImporter() override;

static base::nix::DesktopEnvironment GetDesktopEnvironment();

void ImportBookmarks();
void ImportHistory();
void ImportCookies();
void ImportPasswords();

// Multiple URLs can share the same favicon; this is a map
// of URLs -> IconIDs that we load as a temporary step before
Expand Down
68 changes: 68 additions & 0 deletions patches/master_patch.patch
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,35 @@ index 801f3b6f7a52b8a693e14222ee87510defbfa38c..9a777a7830b83e055aeeb004f11cd672
scoped_refptr<SiteInstance> site_instance =
ProcessManager::Get(context)->GetSiteInstanceForURL(
Extension::GetBaseURLFromExtensionId(extension_id));
diff --git a/chrome/browser/importer/external_process_importer_client.cc b/chrome/browser/importer/external_process_importer_client.cc
index 7c9a4064a5d4ed1c921929d51a12503b1cbe5e75..a84ad9bd0602687453c854e1d24105ba60537012 100644
--- a/chrome/browser/importer/external_process_importer_client.cc
+++ b/chrome/browser/importer/external_process_importer_client.cc
@@ -9,10 +9,13 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/importer/external_process_importer_host.h"
#include "chrome/browser/importer/in_process_importer_bridge.h"
+#include "chrome/common/chrome_utility_messages.h"
#include "chrome/common/importer/firefox_importer_utils.h"
#include "chrome/common/importer/imported_bookmark_entry.h"
#include "chrome/grit/generated_resources.h"
@@ -296,6 +299,10 @@ void ExternalProcessImporterClient::StartProcessOnIOThread(
utility_process_host->SetName(
l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_PROFILE_IMPORTER_NAME));
utility_process_host->DisableSandbox();
+ if (base::StartsWith(base::UTF16ToUTF8(source_profile_.importer_name),
+ "Chrome", base::CompareCase::SENSITIVE)) {
+ utility_process_host->Send(new BraveUtilityMsg_GetImportFromChrome());
+ }

#if defined(OS_MACOSX)
base::EnvironmentMap env;
diff --git a/chrome/browser/importer/external_process_importer_client.h b/chrome/browser/importer/external_process_importer_client.h
index edf5cc054ac3c703cc049509aed223313a875001..6c5f76eb7f8082afa02f6d0721efa3dc09a996d5 100644
--- a/chrome/browser/importer/external_process_importer_client.h
Expand Down Expand Up @@ -601,6 +630,18 @@ index d0bbbf72ff0e356e424dc280eeb1441c990b5770..8e96ea5706f87ea98ba55fcb583b16a8
const char* outer_app_dir_c = outer_app_dir.value().c_str();
NSString* outer_app_dir_ns = [NSString stringWithUTF8String:outer_app_dir_c];

diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h
index 744fca1bc568ef1e1f9a5f57f15fed8ab6fd36e6..a5f782718c1b31df2d6f9a67cf295438e0617c43 100644
--- a/chrome/common/chrome_utility_messages.h
+++ b/chrome/common/chrome_utility_messages.h
@@ -155,6 +155,7 @@ IPC_MESSAGE_CONTROL5(ChromeUtilityMsg_GetOpenFileName,
IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_GetSaveFileName,
ChromeUtilityMsg_GetSaveFileName_Params /* params */)
#endif // defined(OS_WIN)
+IPC_MESSAGE_CONTROL0(BraveUtilityMsg_GetImportFromChrome)

//------------------------------------------------------------------------------
// Utility process host messages:
diff --git a/chrome/common/chrome_utility_printing_messages.h b/chrome/common/chrome_utility_printing_messages.h
index f5712a7a5bb8fabf279088631141cad405c8be8d..da8ff4065d721d49c1ca443a5c64c45e9f59ca4d 100644
--- a/chrome/common/chrome_utility_printing_messages.h
Expand Down Expand Up @@ -1017,6 +1058,33 @@ index 1c68e13912c2dfa7cc842bab169029c58677811a..3731fe3df76b0ac1dbf155c221fc64e2
}

content::WebContents* GuestViewManager::GetGuestByInstanceIDSafely(
diff --git a/components/os_crypt/keychain_password_mac.mm b/components/os_crypt/keychain_password_mac.mm
index 2b38db266f9aa1f4141c8649c021042ede4e5589..ea0387b11f4b00f87596d738c152aa4cc43b2beb 100644
--- a/components/os_crypt/keychain_password_mac.mm
+++ b/components/os_crypt/keychain_password_mac.mm
@@ -7,6 +7,7 @@
#import <Security/Security.h>

#include "base/base64.h"
+#include "base/command_line.h"
#include "base/mac/mac_logging.h"
#include "base/rand_util.h"
#include "crypto/apple_keychain.h"
@@ -61,6 +62,14 @@ const char KeychainPassword::account_name[] = "Chromium";
std::string KeychainPassword::GetPassword() const {
UInt32 password_length = 0;
void* password_data = NULL;
+ const char *service_name, *account_name;
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch("import-chrome")) {
+ service_name = "Chrome Safe Storage";
+ account_name = "Chrome";
+ } else {
+ service_name = ::KeychainPassword::service_name;
+ account_name = ::KeychainPassword::account_name;
+ }
OSStatus error = keychain_.FindGenericPassword(
nullptr, strlen(service_name), service_name, strlen(account_name),
account_name, &password_length, &password_data, NULL);
diff --git a/components/printing/common/print_messages.h b/components/printing/common/print_messages.h
index d11d28dee8d067d142cf9b16f4130c1aeba63a03..1cc8f14d464bf4f20e69c7009fdfacb895eab605 100644
--- a/components/printing/common/print_messages.h
Expand Down

0 comments on commit a424588

Please sign in to comment.