 Chromium Code Reviews
 Chromium Code Reviews Issue 2150543002:
  OSCrypt supports encryption with KWallet  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 2150543002:
  OSCrypt supports encryption with KWallet  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| 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..be5d57f7542958460ce2110b1ccfd474733ef5dc | 
| --- /dev/null | 
| +++ b/components/os_crypt/key_storage_kwallet.cc | 
| @@ -0,0 +1,142 @@ | 
| +// 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" | 
| + | 
| +namespace { | 
| + | 
| +#if defined(OFFICIAL_BUILD) | 
| +const char kFolderName[] = "Chrome Keys"; | 
| 
Lei Zhang
2016/07/20 01:08:26
Any chance we can share these with the libsecret i
 
cfroussios
2016/07/20 15:22:46
I moved them to KeyStorageLinux, mostly because th
 | 
| +const char kKey[] = "Chrome Safe Storage"; | 
| +#else | 
| +const char kFolderName[] = "Chromium Keys"; | 
| +const char kKey[] = "Chromium Safe Storage"; | 
| +#endif | 
| + | 
| +} // namespace | 
| + | 
| +KeyStorageKWallet::KeyStorageKWallet(base::nix::DesktopEnvironment desktop_env, | 
| + std::string app_name) | 
| + : desktop_env_(desktop_env), handle_(0), app_name_(std::move(app_name)) {} | 
| 
Lei Zhang
2016/07/20 01:08:26
Should |handle_| be initialized to -1? Is 0 a vali
 
cfroussios
2016/07/20 15:22:46
Both are invalid values, but let's just use -1, si
 | 
| + | 
| +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)); | 
| + } | 
| + | 
| + // If KWallet might not have started, attempt to start it and retry. | 
| + InitResult result = InitWallet(); | 
| + if (result == InitResult::TEMPORARY_FAIL) | 
| 
Lei Zhang
2016/07/20 01:08:26
if (result == InitResult::TEMPORARY_FAIL && kwalle
 
cfroussios
2016/07/20 15:22:46
I am not a big fan of conditions where the order o
 
Lei Zhang
2016/07/20 19:15:07
But ordering of execution in if statements do matt
 
cfroussios
2016/07/21 11:49:45
There might have been a miscommunication. I didn't
 
Lei Zhang
2016/07/21 21:07:39
My objection is also about readability, but I just
 
cfroussios
2016/07/22 11:25:25
"Every time I've seen code in Chrome" is not compa
 | 
| + if (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_, kFolderName, 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_, kFolderName, 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_, kFolderName, app_name_, &has_folder); | 
| + if (error) | 
| + return false; | 
| + | 
| + if (!has_folder) { | 
| + bool success = false; | 
| + error = | 
| + kwallet_dbus_->CreateFolder(handle_, kFolderName, app_name_, &success); | 
| + if (error || !success) | 
| + return false; | 
| + } | 
| + | 
| + return true; | 
| +} |