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 authored and bridiver committed Jul 13, 2017
1 parent cc98aca commit e163956
Show file tree
Hide file tree
Showing 6 changed files with 173 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
9 changes: 9 additions & 0 deletions brave/utility/brave_profile_import_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
#include "brave/utility/brave_profile_import_handler.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
Expand Down Expand Up @@ -51,6 +54,12 @@ void BraveProfileImportHandler::StartImport(

items_to_import_ = items;

if (base::StartsWith(base::UTF16ToUTF8(source_profile.importer_name),
"Chrome", base::CompareCase::SENSITIVE)) {
auto command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitch("import-chrome");
}

// Create worker thread in which importer runs.
import_thread_.reset(new base::Thread("import_thread"));
#if defined(OS_WIN)
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
27 changes: 27 additions & 0 deletions patches/master_patch.patch
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,33 @@ index bc36a92f4ad97e84d65c5213acbb68fc89aae8d9..9567f7f130181a40917751fff899b439
}

// static
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 32b0451b60dd100d57ec67a31a94673f2ebd5359..ba98bd0c470bb155177bdd4fd0e268535f0c24d2 100644
--- a/components/printing/common/print_messages.h
Expand Down

0 comments on commit e163956

Please sign in to comment.