| Index: components/os_crypt/key_storage_kwallet.cc
|
| diff --git a/components/os_crypt/key_storage_kwallet.cc b/components/os_crypt/key_storage_kwallet.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b1d34cc5a974a83a4b1362d6c36eb0dd450d0ab9
|
| --- /dev/null
|
| +++ b/components/os_crypt/key_storage_kwallet.cc
|
| @@ -0,0 +1,131 @@
|
| +// 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;
|
| +}
|
|
|