Commit 2e6729a4 authored by cfroussios's avatar cfroussios Committed by Commit bot

OSCrypt supports encryption with KWallet

Implemented KeyStorageLinux for KWallet.

BUG=602624

Review-Url: https://codereview.chromium.org/2150543002
Cr-Commit-Position: refs/heads/master@{#407746}
parent 3d1d8ade
......@@ -58,9 +58,10 @@ void ChromeBrowserMainPartsLinux::PreProfileInit() {
#if !defined(OS_CHROMEOS)
// Forward to os_crypt the flag to use a specific password store.
std::string password_store =
parsed_command_line().GetSwitchValueASCII(switches::kPasswordStore);
OSCrypt::SetStore(password_store);
OSCrypt::SetStore(
parsed_command_line().GetSwitchValueASCII(switches::kPasswordStore));
// Forward the product name
OSCrypt::SetProductName(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME));
#endif
ChromeBrowserMainPartsPosix::PreProfileInit();
......
......@@ -1610,6 +1610,7 @@
}],
['OS=="linux" and chromeos!=1', {
'sources': [
'os_crypt/key_storage_kwallet_unittest.cc',
'os_crypt/kwallet_dbus_unittest.cc',
'os_crypt/os_crypt_linux_unittest.cc',
'os_crypt/os_crypt_util_linux_unittest.cc',
......
......@@ -79,6 +79,8 @@
}],
['use_dbus==1', {
'sources': [
'os_crypt/key_storage_kwallet.cc',
'os_crypt/key_storage_kwallet.h',
'os_crypt/kwallet_dbus.cc',
'os_crypt/kwallet_dbus.h',
],
......
......@@ -66,6 +66,8 @@ static_library("os_crypt") {
}
if (use_dbus) {
sources += [
"key_storage_kwallet.cc",
"key_storage_kwallet.h",
"kwallet_dbus.cc",
"kwallet_dbus.h",
]
......@@ -91,8 +93,13 @@ static_library("test_support") {
"os_crypt_mocker_linux.cc",
"os_crypt_mocker_linux.h",
]
deps += [ "//third_party/libsecret" ]
defines = [ "USE_LIBSECRET" ]
defines = []
if (use_glib) {
defines += [ "USE_LIBSECRET" ]
}
if (use_dbus) {
defines += [ "USE_KWALLET" ]
}
}
}
......@@ -122,7 +129,10 @@ source_set("unit_tests") {
defines += [ "USE_LIBSECRET" ]
}
if (use_dbus) {
sources += [ "kwallet_dbus_unittest.cc" ]
sources += [
"key_storage_kwallet_unittest.cc",
"kwallet_dbus_unittest.cc",
]
deps += [ "//dbus:test_support" ]
defines += [ "USE_KWALLET" ]
}
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/os_crypt/key_storage_kwallet.h"
#include <utility>
#include "base/base64.h"
#include "base/rand_util.h"
#include "components/os_crypt/kwallet_dbus.h"
#include "dbus/bus.h"
KeyStorageKWallet::KeyStorageKWallet(base::nix::DesktopEnvironment desktop_env,
std::string app_name)
: desktop_env_(desktop_env), handle_(-1), app_name_(std::move(app_name)) {}
KeyStorageKWallet::~KeyStorageKWallet() {
// The handle is shared between programs that are using the same wallet.
// Closing the wallet is a nop in the typical case.
bool success = true;
ignore_result(kwallet_dbus_->Close(handle_, false, app_name_, &success));
kwallet_dbus_->GetSessionBus()->ShutdownAndBlock();
}
bool KeyStorageKWallet::Init() {
// Initialize using the production KWalletDBus.
return InitWithKWalletDBus(nullptr);
}
bool KeyStorageKWallet::InitWithKWalletDBus(
std::unique_ptr<KWalletDBus> optional_kwallet_dbus_ptr) {
if (optional_kwallet_dbus_ptr) {
kwallet_dbus_ = std::move(optional_kwallet_dbus_ptr);
} else {
// Initializing with production KWalletDBus
kwallet_dbus_.reset(new KWalletDBus(desktop_env_));
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SESSION;
options.connection_type = dbus::Bus::PRIVATE;
kwallet_dbus_->SetSessionBus(new dbus::Bus(options));
}
InitResult result = InitWallet();
// If KWallet might not have started, attempt to start it and retry.
if (result == InitResult::TEMPORARY_FAIL && kwallet_dbus_->StartKWalletd())
result = InitWallet();
return result == InitResult::SUCCESS;
}
KeyStorageKWallet::InitResult KeyStorageKWallet::InitWallet() {
// Check that KWallet is enabled.
bool enabled = false;
KWalletDBus::Error error = kwallet_dbus_->IsEnabled(&enabled);
switch (error) {
case KWalletDBus::Error::CANNOT_CONTACT:
return InitResult::TEMPORARY_FAIL;
case KWalletDBus::Error::CANNOT_READ:
return InitResult::PERMANENT_FAIL;
case KWalletDBus::Error::SUCCESS:
break;
}
if (!enabled)
return InitResult::PERMANENT_FAIL;
// Get the wallet name.
error = kwallet_dbus_->NetworkWallet(&wallet_name_);
switch (error) {
case KWalletDBus::Error::CANNOT_CONTACT:
return InitResult::TEMPORARY_FAIL;
case KWalletDBus::Error::CANNOT_READ:
return InitResult::PERMANENT_FAIL;
case KWalletDBus::Error::SUCCESS:
return InitResult::SUCCESS;
}
NOTREACHED();
return InitResult::PERMANENT_FAIL;
}
std::string KeyStorageKWallet::GetKey() {
// Get handle
KWalletDBus::Error error =
kwallet_dbus_->Open(wallet_name_, app_name_, &handle_);
if (error || handle_ == -1)
return std::string();
// Create folder
if (!InitFolder())
return std::string();
// Read password
std::string password;
error =
kwallet_dbus_->ReadPassword(handle_, KeyStorageLinux::kFolderName,
KeyStorageLinux::kKey, app_name_, &password);
if (error)
return std::string();
// If there is no entry, generate and write a new password.
if (password.empty()) {
base::Base64Encode(base::RandBytesAsString(16), &password);
bool success;
error = kwallet_dbus_->WritePassword(handle_, KeyStorageLinux::kFolderName,
KeyStorageLinux::kKey, password,
app_name_, &success);
if (error || !success)
return std::string();
}
return password;
}
bool KeyStorageKWallet::InitFolder() {
bool has_folder = false;
KWalletDBus::Error error = kwallet_dbus_->HasFolder(
handle_, KeyStorageLinux::kFolderName, app_name_, &has_folder);
if (error)
return false;
if (!has_folder) {
bool success = false;
error = kwallet_dbus_->CreateFolder(handle_, KeyStorageLinux::kFolderName,
app_name_, &success);
if (error || !success)
return false;
}
return true;
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_OS_CRYPT_KEY_STORAGE_KWALLET_H_
#define COMPONENTS_OS_CRYPT_KEY_STORAGE_KWALLET_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "components/os_crypt/key_storage_linux.h"
#include "components/os_crypt/kwallet_dbus.h"
class KeyStorageKWallet : public KeyStorageLinux {
public:
KeyStorageKWallet(base::nix::DesktopEnvironment desktop_env,
std::string app_name);
~KeyStorageKWallet() override;
// KeyStorageLinux
std::string GetKey() override;
// Initialize using an optional KWalletDBus mock.
// A DBus session will not be created if a mock is provided.
bool InitWithKWalletDBus(
std::unique_ptr<KWalletDBus> optional_kwallet_dbus_ptr);
protected:
// KeyStorageLinux
bool Init() override;
private:
enum class InitResult {
SUCCESS,
TEMPORARY_FAIL,
PERMANENT_FAIL,
};
// Check whether KWallet is enabled and set |wallet_name_|
InitResult InitWallet();
// Create Chrome's folder in the wallet, if it doesn't exist.
bool InitFolder();
const base::nix::DesktopEnvironment desktop_env_;
int32_t handle_;
std::string wallet_name_;
const std::string app_name_;
std::unique_ptr<KWalletDBus> kwallet_dbus_;
DISALLOW_COPY_AND_ASSIGN(KeyStorageKWallet);
};
#endif // COMPONENTS_OS_CRYPT_KEY_STORAGE_KWALLET_H_
This diff is collapsed.
......@@ -11,12 +11,6 @@
namespace {
#if defined(OFFICIAL_BUILD)
const char kKeyStorageEntryName[] = "Chrome Safe Storage";
#else
const char kKeyStorageEntryName[] = "Chromium Safe Storage";
#endif
const SecretSchema kKeystoreSchema = {
"chrome_libsecret_os_crypt_password",
SECRET_SCHEMA_NONE,
......@@ -24,12 +18,14 @@ const SecretSchema kKeystoreSchema = {
{nullptr, SECRET_SCHEMA_ATTRIBUTE_STRING},
}};
std::string AddRandomPasswordInLibsecret() {
} // namespace
std::string KeyStorageLibsecret::AddRandomPasswordInLibsecret() {
std::string password;
base::Base64Encode(base::RandBytesAsString(16), &password);
GError* error = nullptr;
LibsecretLoader::secret_password_store_sync(
&kKeystoreSchema, nullptr, kKeyStorageEntryName, password.c_str(),
&kKeystoreSchema, nullptr, KeyStorageLinux::kKey, password.c_str(),
nullptr, &error, nullptr);
if (error) {
......@@ -39,8 +35,6 @@ std::string AddRandomPasswordInLibsecret() {
return password;
}
} // namespace
std::string KeyStorageLibsecret::GetKey() {
GError* error = nullptr;
LibsecretAttributesBuilder attrs;
......
......@@ -24,6 +24,8 @@ class KeyStorageLibsecret : public KeyStorageLinux {
bool Init() override;
private:
std::string AddRandomPasswordInLibsecret();
DISALLOW_COPY_AND_ASSIGN(KeyStorageLibsecret);
};
......
......@@ -4,8 +4,6 @@
#include "components/os_crypt/key_storage_linux.h"
#include <string.h>
#include "base/environment.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
......@@ -15,24 +13,42 @@
#include "components/os_crypt/key_storage_libsecret.h"
#endif
base::LazyInstance<std::string> g_store_ = LAZY_INSTANCE_INITIALIZER;
#if defined(USE_KWALLET)
#include "components/os_crypt/key_storage_kwallet.h"
#endif
#if defined(OFFICIAL_BUILD)
const char KeyStorageLinux::kFolderName[] = "Chrome Keys";
const char KeyStorageLinux::kKey[] = "Chrome Safe Storage";
#else
const char KeyStorageLinux::kFolderName[] = "Chromium Keys";
const char KeyStorageLinux::kKey[] = "Chromium Safe Storage";
#endif
base::LazyInstance<std::string> g_store = LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<std::string> g_product_name = LAZY_INSTANCE_INITIALIZER;
// static
void KeyStorageLinux::SetStore(const std::string& store_type) {
g_store_.Get() = store_type;
g_store.Get() = store_type;
VLOG(1) << "OSCrypt store set to " << store_type;
}
// static
void KeyStorageLinux::SetProductName(const std::string& product_name) {
g_product_name.Get() = product_name;
}
// static
std::unique_ptr<KeyStorageLinux> KeyStorageLinux::CreateService() {
base::nix::DesktopEnvironment used_desktop_env;
if (g_store_.Get() == "kwallet") {
if (g_store.Get() == "kwallet") {
used_desktop_env = base::nix::DESKTOP_ENVIRONMENT_KDE4;
} else if (g_store_.Get() == "kwallet5") {
} else if (g_store.Get() == "kwallet5") {
used_desktop_env = base::nix::DESKTOP_ENVIRONMENT_KDE5;
} else if (g_store_.Get() == "gnome") {
} else if (g_store.Get() == "gnome") {
used_desktop_env = base::nix::DESKTOP_ENVIRONMENT_GNOME;
} else if (g_store_.Get() == "basic") {
} else if (g_store.Get() == "basic") {
used_desktop_env = base::nix::DESKTOP_ENVIRONMENT_OTHER;
} else {
std::unique_ptr<base::Environment> env(base::Environment::Create());
......@@ -50,6 +66,17 @@ std::unique_ptr<KeyStorageLinux> KeyStorageLinux::CreateService() {
VLOG(1) << "OSCrypt using Libsecret as backend.";
return key_storage;
}
#endif
} else if (used_desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE4 ||
used_desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE5) {
#if defined(USE_KWALLET)
DCHECK(!g_product_name.Get().empty());
key_storage.reset(
new KeyStorageKWallet(used_desktop_env, g_product_name.Get()));
if (key_storage->Init()) {
VLOG(1) << "OSCrypt using KWallet as backend.";
return key_storage;
}
#endif
}
......
......@@ -20,6 +20,9 @@ class KeyStorageLinux {
// Force OSCrypt to use a specific linux password store.
static void SetStore(const std::string& store_type);
// The product name to use for permission prompts.
static void SetProductName(const std::string& product_name);
// Tries to load the appropriate key storage. Returns null if none succeed.
static std::unique_ptr<KeyStorageLinux> CreateService();
......@@ -31,6 +34,11 @@ class KeyStorageLinux {
// Loads the key storage. Returns false if the service is not available.
virtual bool Init() = 0;
// The name of the group, if any, containing the key.
static const char kFolderName[];
// The name of the entry with the encryption key.
static const char kKey[];
private:
DISALLOW_COPY_AND_ASSIGN(KeyStorageLinux);
};
......
......@@ -68,7 +68,7 @@ bool KWalletDBus::StartKWalletd() {
builder.AppendBool(false); // blind
std::unique_ptr<dbus::Response> response(klauncher->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting klauncher to start " << kwalletd_name_;
return false;
}
......@@ -96,7 +96,7 @@ KWalletDBus::Error KWalletDBus::IsEnabled(bool* enabled) {
dbus::MethodCall method_call(kKWalletInterface, "isEnabled");
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (isEnabled)";
return CANNOT_CONTACT;
}
......@@ -119,7 +119,7 @@ KWalletDBus::Error KWalletDBus::NetworkWallet(std::string* wallet_name) {
dbus::MethodCall method_call(kKWalletInterface, "networkWallet");
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (networkWallet)";
return CANNOT_CONTACT;
}
......@@ -143,7 +143,7 @@ KWalletDBus::Error KWalletDBus::Open(const std::string& wallet_name,
builder.AppendString(app_name); // appid
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (open)";
return CANNOT_CONTACT;
}
......@@ -169,7 +169,7 @@ KWalletDBus::Error KWalletDBus::HasEntry(const int wallet_handle,
builder.AppendString(app_name); // appid
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (hasEntry)";
return CANNOT_CONTACT;
}
......@@ -195,7 +195,7 @@ KWalletDBus::Error KWalletDBus::ReadEntry(const int wallet_handle,
builder.AppendString(app_name); // appid
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (readEntry)";
return CANNOT_CONTACT;
}
......@@ -227,7 +227,7 @@ KWalletDBus::Error KWalletDBus::EntryList(
builder.AppendString(app_name); // appid
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (entryList)";
return CANNOT_CONTACT;
}
......@@ -253,7 +253,7 @@ KWalletDBus::Error KWalletDBus::RemoveEntry(const int wallet_handle,
builder.AppendString(app_name); // appid
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (removeEntry)";
return CANNOT_CONTACT;
}
......@@ -282,7 +282,7 @@ KWalletDBus::Error KWalletDBus::WriteEntry(const int wallet_handle,
builder.AppendString(app_name); // appid
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (writeEntry)";
return CANNOT_CONTACT;
}
......@@ -306,7 +306,7 @@ KWalletDBus::Error KWalletDBus::HasFolder(const int handle,
builder.AppendString(app_name); // appid
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (hasFolder)";
return CANNOT_CONTACT;
}
......@@ -330,8 +330,8 @@ KWalletDBus::Error KWalletDBus::CreateFolder(const int handle,
builder.AppendString(app_name); // appid
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response.get()) {
LOG(ERROR) << "Error contacting << " << kwalletd_name_ << " (createFolder)";
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (createFolder)";
return CANNOT_CONTACT;
}
dbus::MessageReader reader(response.get());
......@@ -342,3 +342,85 @@ KWalletDBus::Error KWalletDBus::CreateFolder(const int handle,
}
return SUCCESS;
}
KWalletDBus::Error KWalletDBus::WritePassword(const int handle,
const std::string& folder_name,
const std::string& key,
const std::string& password,
const std::string& app_name,
bool* const write_success_ptr) {
dbus::MethodCall method_call(kKWalletInterface, "writePassword");
dbus::MessageWriter builder(&method_call);
builder.AppendInt32(handle);
builder.AppendString(folder_name);
builder.AppendString(key);
builder.AppendString(password);
builder.AppendString(app_name);
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (writePassword)";
return CANNOT_CONTACT;
}
dbus::MessageReader reader(response.get());
int return_code;
if (!reader.PopInt32(&return_code)) {
LOG(ERROR) << "Error reading response from " << kwalletd_name_
<< " (writePassword): " << response->ToString();
return CANNOT_READ;
}
*write_success_ptr = return_code == 0;
return SUCCESS;
}
KWalletDBus::Error KWalletDBus::ReadPassword(const int handle,
const std::string& folder_name,
const std::string& key,
const std::string& app_name,
std::string* const password_ptr) {
dbus::MethodCall method_call(kKWalletInterface, "readPassword");
dbus::MessageWriter builder(&method_call);
builder.AppendInt32(handle);
builder.AppendString(folder_name);
builder.AppendString(key);
builder.AppendString(app_name);
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (readPassword)";
return CANNOT_CONTACT;
}
dbus::MessageReader reader(response.get());
if (!reader.PopString(password_ptr)) {
LOG(ERROR) << "Error reading response from " << kwalletd_name_
<< " (readPassword): " << response->ToString();
return CANNOT_READ;
}
return SUCCESS;
}
KWalletDBus::Error KWalletDBus::Close(const int handle,
const bool force,
const std::string& app_name,
bool* success_ptr) {
dbus::MethodCall method_call(kKWalletInterface, "close");
dbus::MessageWriter builder(&method_call);
builder.AppendInt32(handle);
builder.AppendBool(force);
builder.AppendString(app_name);
std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
if (!response) {
LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (close)";
return CANNOT_CONTACT;
}
dbus::MessageReader reader(response.get());
int return_code = 1;
if (!reader.PopInt32(&return_code)) {
LOG(ERROR) << "Error reading response from " << kwalletd_name_
<< " (close): " << response->ToString();
return CANNOT_READ;
}
*success_ptr = return_code == 0;
return SUCCESS;
}
......@@ -24,17 +24,17 @@ class KWalletDBus {
enum Error { SUCCESS = 0, CANNOT_CONTACT, CANNOT_READ };
explicit KWalletDBus(base::nix::DesktopEnvironment desktop_env);
~KWalletDBus();
virtual ~KWalletDBus();
// Set the bus that we will use. Required before any other operation.
// The owner of KWalletDBus is responsible for killing the bus.
void SetSessionBus(scoped_refptr<dbus::Bus> session_bus);
virtual void SetSessionBus(scoped_refptr<dbus::Bus> session_bus);
// Expose the bus so that shutdown can be scheduled asynchronously.
dbus::Bus* GetSessionBus();
virtual dbus::Bus* GetSessionBus();
// Use KLauncher to start the KWallet service. Returns true if successful.
bool StartKWalletd() WARN_UNUSED_RESULT;
virtual bool StartKWalletd() WARN_UNUSED_RESULT;
// The functions below are wrappers for calling the eponymous KWallet dbus
// methods. They take pointers to locations where the return values will be
......@@ -42,65 +42,89 @@ class KWalletDBus {
// https://api.kde.org/4.12-api/kdelibs-apidocs/kdeui/html/classKWallet_1_1Wallet.html
// Determine if the KDE wallet is enabled.
Error IsEnabled(bool* enabled) WARN_UNUSED_RESULT;
virtual Error IsEnabled(bool* enabled) WARN_UNUSED_RESULT;
// Get the name of the wallet used to store network passwords.
Error NetworkWallet(std::string* wallet_name_ptr) WARN_UNUSED_RESULT;
virtual Error NetworkWallet(std::string* wallet_name_ptr) WARN_UNUSED_RESULT;
// Open the |wallet_name| wallet for use.
Error Open(const std::string& wallet_name,
const std::string& app_name,
int* handle_ptr) WARN_UNUSED_RESULT;
virtual Error Open(const std::string& wallet_name,
const std::string& app_name,
int* handle_ptr) WARN_UNUSED_RESULT;
// Determine if the current folder has they entry key.
Error HasEntry(int wallet_handle,
const std::string& folder_name,
const std::string& signon_realm,
const std::string& app_name,
bool* has_entry_ptr) WARN_UNUSED_RESULT;
virtual Error HasEntry(int wallet_handle,
const std::string& folder_name,
const std::string& signon_realm,
const std::string& app_name,
bool* has_entry_ptr) WARN_UNUSED_RESULT;
// Read the entry key from the current folder.
Error ReadEntry(int wallet_handle,
const std::string& folder_name,
const std::string& signon_realm,
const std::string& app_name,
std::vector<uint8_t>* bytes_ptr) WARN_UNUSED_RESULT;
virtual Error ReadEntry(int wallet_handle,
const std::string& folder_name,
const std::string& signon_realm,
const std::string& app_name,
std::vector<uint8_t>* bytes_ptr) WARN_UNUSED_RESULT;
// Return the list of keys of all entries in this folder.
Error EntryList(int wallet_handle,
const std::string& folder_name,
const std::string& app_name,
std::vector<std::string>* entry_list_ptr) WARN_UNUSED_RESULT;
virtual Error EntryList(int wallet_handle,
const std::string& folder_name,
const std::string& app_name,
std::vector<std::string>* entry_list_ptr)
WARN_UNUSED_RESULT;
// Remove the entry key from the current folder.
// |*return_code_ptr| is 0 on success.
Error RemoveEntry(int wallet_handle,
const std::string& folder_name,
const std::string& signon_realm,
const std::string& app_name,
int* return_code_ptr) WARN_UNUSED_RESULT;
virtual Error RemoveEntry(int wallet_handle,
const std::string& folder_name,
const std::string& signon_realm,
const std::string& app_name,
int* return_code_ptr) WARN_UNUSED_RESULT;
// Write a binary entry to the current folder.
// |*return_code_ptr| is 0 on success.
Error WriteEntry(int wallet_handle,
const std::string& folder_name,
const std::string& signon_realm,
const std::string& app_name,
const uint8_t* data,
size_t length,
int* return_code_ptr) WARN_UNUSED_RESULT;
virtual Error WriteEntry(int wallet_handle,
const std::string& folder_name,
const std::string& signon_realm,
const std::string& app_name,
const uint8_t* data,
size_t length,
int* return_code_ptr) WARN_UNUSED_RESULT;
// Determine if the folder |folder_name| exists in the wallet.
Error HasFolder(int handle,
const std::string& folder_name,
const std::string& app_name,
bool* has_folder_ptr) WARN_UNUSED_RESULT;
// Created the folder |folder_name|.
Error CreateFolder(int handle,
const std::string& folder_name,
const std::string& app_name,
bool* success_ptr) WARN_UNUSED_RESULT;
virtual Error HasFolder(int handle,
const std::string& folder_name,
const std::string& app_name,
bool* has_folder_ptr) WARN_UNUSED_RESULT;
// Create the folder |folder_name|.
virtual Error CreateFolder(int handle,
const std::string& folder_name,
const std::string& app_name,
bool* success_ptr) WARN_UNUSED_RESULT;
// Write a password to the current folder.
virtual Error WritePassword(int handle,
const std::string& folder_name,
const std::string& key,
const std::string& password,
const std::string& app_name,
bool* write_success_ptr) WARN_UNUSED_RESULT;
// Read the password for |key| from |folder_name|.
// Clear |password_ptr| if no such password exists.
virtual Error ReadPassword(int handle,
const std::string& folder_name,
const std::string& key,
const std::string& app_name,
std::string* password_ptr) WARN_UNUSED_RESULT;
// Close the wallet. The wallet will only be closed if it is open but not in
// use (rare), or if it is forced closed.
virtual Error Close(int handle,
bool force,
const std::string& app_name,
bool* success_ptr) WARN_UNUSED_RESULT;
private:
// DBus handle for communication with klauncher and kwalletd.
......
......@@ -272,6 +272,61 @@ MATCHER_P5(ArgumentsAreStringStringsStringsStringBool,
return true;
}
MATCHER_P5(ArgumentsAreIntStringStringStringString,
int_1,
str_2,
str_3,
str_4,
str_5,
"") {
dbus::MessageReader reader(arg);
int32_t i;
EXPECT_TRUE(reader.PopInt32(&i));
if (int_1 != i)
return false;
std::string str;
EXPECT_TRUE(reader.PopString(&str));
if (str_2 != str)
return false;
EXPECT_TRUE(reader.PopString(&str));
if (str_3 != str)
return false;
EXPECT_TRUE(reader.PopString(&str));
if (str_4 != str)
return false;
EXPECT_TRUE(reader.PopString(&str));
if (str_5 != str)
return false;
return true;
}
MATCHER_P3(ArgumentsAreIntBoolString, int_1, bool_2, str_3, "") {
dbus::MessageReader reader(arg);
int32_t i;
EXPECT_TRUE(reader.PopInt32(&i));
if (int_1 != i)
return false;
bool b;
EXPECT_TRUE(reader.PopBool(&b));
if (bool_2 != b)
return false;
std::string str;
EXPECT_TRUE(reader.PopString(&str));
if (str_3 != str)
return false;
return true;
}
TEST_P(KWalletDBusTest, StartWalletd) {
// The receiver of the message takes ownership of the response object.
dbus::Response* response_success = RespondEmpty();
......@@ -693,4 +748,145 @@ TEST_P(KWalletDBusTest, CreateFolderErrorContact) {
kwallet_dbus_.CreateFolder(123, "folder", "app", &created_folder));
}
TEST_P(KWalletDBusTest, WritePassword) {
EXPECT_CALL(*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(
AllOf(Calls(kKWalletInterface, "writePassword"),
ArgumentsAreIntStringStringStringString(
123, "folder", "key", "password", "app")),
_))
.WillOnce(Return(RespondInt32(0)));
bool write_success = false;
EXPECT_EQ(KWalletDBus::Error::SUCCESS,
kwallet_dbus_.WritePassword(123, "folder", "key", "password", "app",
&write_success));
EXPECT_TRUE(write_success);
}
TEST_P(KWalletDBusTest, WritePasswordRejected) {
EXPECT_CALL(*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(
AllOf(Calls(kKWalletInterface, "writePassword"),
ArgumentsAreIntStringStringStringString(
123, "folder", "key", "password", "app")),
_))
.WillOnce(Return(RespondInt32(-1)));
bool write_success = true;
EXPECT_EQ(KWalletDBus::Error::SUCCESS,
kwallet_dbus_.WritePassword(123, "folder", "key", "password", "app",
&write_success));
EXPECT_FALSE(write_success);
}
TEST_P(KWalletDBusTest, WritePasswordErrorRead) {
EXPECT_CALL(
*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(Calls(kKWalletInterface, "writePassword"), _))
.WillOnce(Return(RespondEmpty()));
bool write_success = false;
EXPECT_EQ(KWalletDBus::Error::CANNOT_READ,
kwallet_dbus_.WritePassword(123, "folder", "key", "password", "app",
&write_success));
}
TEST_P(KWalletDBusTest, WritePasswordErrorContact) {
EXPECT_CALL(
*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(Calls(kKWalletInterface, "writePassword"), _))
.WillOnce(Return(nullptr));
bool write_success = false;
EXPECT_EQ(KWalletDBus::Error::CANNOT_CONTACT,
kwallet_dbus_.WritePassword(123, "folder", "key", "password", "app",
&write_success));
}
TEST_P(KWalletDBusTest, ReadPassword) {
EXPECT_CALL(
*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(
AllOf(Calls(kKWalletInterface, "readPassword"),
ArgumentsAreIntStringStringString(123, "folder", "key", "app")),
_))
.WillOnce(Return(RespondString("password")));
std::string password;
EXPECT_EQ(KWalletDBus::Error::SUCCESS,
kwallet_dbus_.ReadPassword(123, "folder", "key", "app", &password));
EXPECT_EQ("password", password);
}
TEST_P(KWalletDBusTest, ReadPasswordErrorRead) {
EXPECT_CALL(
*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(Calls(kKWalletInterface, "readPassword"), _))
.WillOnce(Return(RespondEmpty()));
std::string password;
EXPECT_EQ(KWalletDBus::Error::CANNOT_READ,
kwallet_dbus_.ReadPassword(123, "folder", "key", "app", &password));
}
TEST_P(KWalletDBusTest, ReadPasswordErrorContact) {
EXPECT_CALL(
*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(Calls(kKWalletInterface, "readPassword"), _))
.WillOnce(Return(nullptr));
std::string password;
EXPECT_EQ(KWalletDBus::Error::CANNOT_CONTACT,
kwallet_dbus_.ReadPassword(123, "folder", "key", "app", &password));
}
TEST_P(KWalletDBusTest, CloseSuccess) {
EXPECT_CALL(*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(
AllOf(Calls(kKWalletInterface, "close"),
ArgumentsAreIntBoolString(123, false, "app")),
_))
.WillOnce(Return(RespondInt32(0)));
bool success = false;
EXPECT_EQ(KWalletDBus::Error::SUCCESS,
kwallet_dbus_.Close(123, false, "app", &success));
EXPECT_TRUE(success);
}
TEST_P(KWalletDBusTest, CloseUnsuccessful) {
EXPECT_CALL(*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(
AllOf(Calls(kKWalletInterface, "close"),
ArgumentsAreIntBoolString(123, false, "app")),
_))
.WillOnce(Return(RespondInt32(1)));
bool success = true;
EXPECT_EQ(KWalletDBus::Error::SUCCESS,
kwallet_dbus_.Close(123, false, "app", &success));
EXPECT_FALSE(success);
}
TEST_P(KWalletDBusTest, CloseErrorRead) {
EXPECT_CALL(*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(Calls(kKWalletInterface, "close"), _))
.WillOnce(Return(RespondEmpty()));
bool success = true;
EXPECT_EQ(KWalletDBus::Error::CANNOT_READ,
kwallet_dbus_.Close(123, false, "app", &success));
}
TEST_P(KWalletDBusTest, CloseErrorContact) {
EXPECT_CALL(*mock_kwallet_proxy_.get(),
MockCallMethodAndBlock(Calls(kKWalletInterface, "close"), _))
.WillOnce(Return(nullptr));
bool success = true;
EXPECT_EQ(KWalletDBus::Error::CANNOT_CONTACT,
kwallet_dbus_.Close(123, false, "app", &success));
}
} // namespace
......@@ -26,6 +26,10 @@ class OSCrypt {
// In any other case, we default to auto-detecting the store.
// This should not be changed after OSCrypt has been used.
static void SetStore(const std::string& store_type);
// Some password stores may prompt the user for permission and show the
// application name.
static void SetProductName(const std::string& product_name);
#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
// Encrypt a string16. The output (second argument) is really an array of
......
......@@ -218,6 +218,14 @@ void OSCrypt::SetStore(const std::string& store_type) {
KeyStorageLinux::SetStore(store_type);
}
// static
void OSCrypt::SetProductName(const std::string& product_name) {
// Setting the product name makes no sense after initializing.
DCHECK(!g_cache.Get().is_key_storage_cached);
KeyStorageLinux::SetProductName(product_name);
}
void UseMockKeyStorageForTesting(KeyStorageLinux* (*get_key_storage_mock)(),
std::string* (*get_password_v11_mock)()) {
// Save the real implementation to restore it later.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment