Skip to content

Commit

Permalink
Merge pull request #5300 from brave/fix_password_import_failure_on_wi…
Browse files Browse the repository at this point in the history
…ndows

Fix chrome password importing is failed on Win
  • Loading branch information
simonhong authored Apr 24, 2020
2 parents 0fe7506 + 80bfef0 commit 4b8cb48
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 5 deletions.
87 changes: 85 additions & 2 deletions utility/importer/chrome_importer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,78 @@
#include "ui/base/l10n/l10n_util.h"
#endif // defined(OS_LINUX)

#if defined(OS_WIN)
#include "base/base64.h"
#include "base/win/wincrypt_shim.h"
#endif

using base::Time;

namespace {

// Most of below code is copied from os_crypt_win.cc
#if defined(OS_WIN)
// Contains base64 random key encrypted with DPAPI.
const char kOsCryptEncryptedKeyPrefName[] = "os_crypt.encrypted_key";

// Key prefix for a key encrypted with DPAPI.
const char kDPAPIKeyPrefix[] = "DPAPI";

bool DecryptStringWithDPAPI(const std::string& ciphertext,
std::string* plaintext) {
DATA_BLOB input;
input.pbData =
const_cast<BYTE*>(reinterpret_cast<const BYTE*>(ciphertext.data()));
input.cbData = static_cast<DWORD>(ciphertext.length());

DATA_BLOB output;
BOOL result = CryptUnprotectData(&input, nullptr, nullptr, nullptr, nullptr,
0, &output);
if (!result) {
PLOG(ERROR) << "Failed to decrypt";
return false;
}

plaintext->assign(reinterpret_cast<char*>(output.pbData), output.cbData);
LocalFree(output.pbData);
return true;
}

// Return false if encryption key setting is failed.
// Fetch chrome's raw encryption key and use it to get chrome's password data.
bool SetEncryptionKeyForPasswordImporting(
const base::FilePath& local_state_path) {
std::string local_state_content;
base::ReadFileToString(local_state_path, &local_state_content);
base::Optional<base::Value> local_state =
base::JSONReader::Read(local_state_content);
if (auto* base64_encrypted_key =
local_state->FindStringPath(kOsCryptEncryptedKeyPrefName)) {
std::string encrypted_key_with_header;

base::Base64Decode(*base64_encrypted_key, &encrypted_key_with_header);

if (!base::StartsWith(encrypted_key_with_header, kDPAPIKeyPrefix,
base::CompareCase::SENSITIVE)) {
return false;
}
std::string encrypted_key =
encrypted_key_with_header.substr(sizeof(kDPAPIKeyPrefix) - 1);
std::string key;
// This DPAPI decryption can fail if the user's password has been reset
// by an Administrator.
if (DecryptStringWithDPAPI(encrypted_key, &key)) {
OSCrypt::SetRawEncryptionKey(key);
return true;
}
}

return false;
}
#endif

} // namespace

ChromeImporter::ChromeImporter() {
}

Expand Down Expand Up @@ -69,7 +139,7 @@ void ChromeImporter::StartImport(const importer::SourceProfile& source_profile,

if ((items & importer::PASSWORDS) && !cancelled()) {
bridge_->NotifyItemStarted(importer::PASSWORDS);
ImportPasswords(base::FilePath(FILE_PATH_LITERAL("Preferences")));
ImportPasswords();
bridge_->NotifyItemEnded(importer::PASSWORDS);
}

Expand Down Expand Up @@ -290,7 +360,7 @@ double ChromeImporter::chromeTimeToDouble(int64_t time) {
return ((time * 10 - 0x19DB1DED53E8000) / 10000) / 1000;
}

void ChromeImporter::ImportPasswords(const base::FilePath& prefs_filename) {
void ChromeImporter::ImportPasswords() {
#if defined(OS_LINUX)
// Set up crypt config.
std::unique_ptr<os_crypt::Config> config(new os_crypt::Config());
Expand All @@ -299,9 +369,22 @@ void ChromeImporter::ImportPasswords(const base::FilePath& prefs_filename) {
config->user_data_path = source_path_;
OSCrypt::SetConfig(std::move(config));
#endif

#if defined(OS_WIN)
base::FilePath local_state_path = source_path_.DirName().Append(
base::FilePath::StringType(FILE_PATH_LITERAL("Local State")));
if (!base::PathExists(local_state_path))
return;
if (!SetEncryptionKeyForPasswordImporting(local_state_path))
return;
#endif

base::FilePath passwords_path = source_path_.Append(
base::FilePath::StringType(FILE_PATH_LITERAL("Login Data")));

if (!base::PathExists(passwords_path))
return;

password_manager::LoginDatabase database(
passwords_path, password_manager::IsAccountStore(false));
if (!database.Init()) {
Expand Down
4 changes: 1 addition & 3 deletions utility/importer/chrome_importer.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,9 @@ class ChromeImporter : public Importer {
protected:
~ChromeImporter() override;

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

void ImportBookmarks();
void ImportHistory();
void ImportPasswords(const base::FilePath& prefs_filename);
void ImportPasswords();

double chromeTimeToDouble(int64_t time);

Expand Down

0 comments on commit 4b8cb48

Please sign in to comment.