OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <chrome/browser/password_manager/kwallet_dbus.h> |
| 6 |
| 7 #include <algorithm> |
| 8 #include <memory> |
| 9 |
| 10 #include "base/logging.h" |
| 11 #include "dbus/bus.h" |
| 12 #include "dbus/message.h" |
| 13 #include "dbus/object_proxy.h" |
| 14 |
| 15 namespace { |
| 16 |
| 17 // DBus service, path, and interface names for klauncher and kwalletd. |
| 18 const char kKWalletDName[] = "kwalletd"; |
| 19 const char kKWalletD5Name[] = "kwalletd5"; |
| 20 const char kKWalletServiceName[] = "org.kde.kwalletd"; |
| 21 const char kKWallet5ServiceName[] = "org.kde.kwalletd5"; |
| 22 const char kKWalletPath[] = "/modules/kwalletd"; |
| 23 const char kKWallet5Path[] = "/modules/kwalletd5"; |
| 24 const char kKWalletInterface[] = "org.kde.KWallet"; |
| 25 const char kKLauncherServiceName[] = "org.kde.klauncher"; |
| 26 const char kKLauncherPath[] = "/KLauncher"; |
| 27 const char kKLauncherInterface[] = "org.kde.KLauncher"; |
| 28 |
| 29 } // namespace |
| 30 |
| 31 KWalletDBus::KWalletDBus(base::nix::DesktopEnvironment desktop_env) |
| 32 : session_bus_(nullptr), kwallet_proxy_(nullptr) { |
| 33 if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE5) { |
| 34 dbus_service_name_ = kKWallet5ServiceName; |
| 35 dbus_path_ = kKWallet5Path; |
| 36 kwalletd_name_ = kKWalletD5Name; |
| 37 } else { |
| 38 dbus_service_name_ = kKWalletServiceName; |
| 39 dbus_path_ = kKWalletPath; |
| 40 kwalletd_name_ = kKWalletDName; |
| 41 } |
| 42 } |
| 43 |
| 44 KWalletDBus::~KWalletDBus() = default; |
| 45 |
| 46 dbus::Bus* KWalletDBus::GetSessionBus() { |
| 47 return session_bus_.get(); |
| 48 } |
| 49 |
| 50 void KWalletDBus::SetSessionBus(scoped_refptr<dbus::Bus> session_bus) { |
| 51 session_bus_ = session_bus; |
| 52 kwallet_proxy_ = session_bus_->GetObjectProxy(dbus_service_name_, |
| 53 dbus::ObjectPath(dbus_path_)); |
| 54 } |
| 55 |
| 56 bool KWalletDBus::StartKWalletd() { |
| 57 dbus::ObjectProxy* klauncher = session_bus_->GetObjectProxy( |
| 58 kKLauncherServiceName, dbus::ObjectPath(kKLauncherPath)); |
| 59 |
| 60 dbus::MethodCall method_call(kKLauncherInterface, |
| 61 "start_service_by_desktop_name"); |
| 62 dbus::MessageWriter builder(&method_call); |
| 63 std::vector<std::string> empty; |
| 64 builder.AppendString(kwalletd_name_); // serviceName |
| 65 builder.AppendArrayOfStrings(empty); // urls |
| 66 builder.AppendArrayOfStrings(empty); // envs |
| 67 builder.AppendString(std::string()); // startup_id |
| 68 builder.AppendBool(false); // blind |
| 69 std::unique_ptr<dbus::Response> response(klauncher->CallMethodAndBlock( |
| 70 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 71 if (!response.get()) { |
| 72 LOG(ERROR) << "Error contacting klauncher to start " << kwalletd_name_; |
| 73 return false; |
| 74 } |
| 75 dbus::MessageReader reader(response.get()); |
| 76 int32_t ret = -1; |
| 77 std::string dbus_name; |
| 78 std::string error; |
| 79 int32_t pid = -1; |
| 80 if (!reader.PopInt32(&ret) || !reader.PopString(&dbus_name) || |
| 81 !reader.PopString(&error) || !reader.PopInt32(&pid)) { |
| 82 LOG(ERROR) << "Error reading response from klauncher to start " |
| 83 << kwalletd_name_ << ": " << response->ToString(); |
| 84 return false; |
| 85 } |
| 86 if (!error.empty() || ret) { |
| 87 LOG(ERROR) << "Error launching " << kwalletd_name_ << ": error '" << error |
| 88 << "' (code " << ret << ")"; |
| 89 return false; |
| 90 } |
| 91 |
| 92 return true; |
| 93 } |
| 94 |
| 95 KWalletDBus::Error KWalletDBus::IsEnabled(bool* enabled) { |
| 96 dbus::MethodCall method_call(kKWalletInterface, "isEnabled"); |
| 97 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 98 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 99 if (!response.get()) { |
| 100 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (isEnabled)"; |
| 101 return CANNOT_CONTACT; |
| 102 } |
| 103 dbus::MessageReader reader(response.get()); |
| 104 if (!reader.PopBool(enabled)) { |
| 105 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 106 << " (isEnabled): " << response->ToString(); |
| 107 return CANNOT_READ; |
| 108 } |
| 109 // Not enabled? Don't use KWallet. But also don't warn here. |
| 110 if (!enabled) { |
| 111 VLOG(1) << kwalletd_name_ << " reports that KWallet is not enabled."; |
| 112 } |
| 113 |
| 114 return SUCCESS; |
| 115 } |
| 116 |
| 117 KWalletDBus::Error KWalletDBus::NetworkWallet(std::string* wallet_name) { |
| 118 // Get the wallet name. |
| 119 dbus::MethodCall method_call(kKWalletInterface, "networkWallet"); |
| 120 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 121 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 122 if (!response.get()) { |
| 123 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (networkWallet)"; |
| 124 return CANNOT_CONTACT; |
| 125 } |
| 126 dbus::MessageReader reader(response.get()); |
| 127 if (!reader.PopString(wallet_name)) { |
| 128 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 129 << " (networkWallet): " << response->ToString(); |
| 130 return CANNOT_READ; |
| 131 } |
| 132 |
| 133 return SUCCESS; |
| 134 } |
| 135 |
| 136 KWalletDBus::Error KWalletDBus::Open(const std::string& wallet_name, |
| 137 const std::string& app_name, |
| 138 int* handle_ptr) { |
| 139 dbus::MethodCall method_call(kKWalletInterface, "open"); |
| 140 dbus::MessageWriter builder(&method_call); |
| 141 builder.AppendString(wallet_name); // wallet |
| 142 builder.AppendInt64(0); // wid |
| 143 builder.AppendString(app_name); // appid |
| 144 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 145 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 146 if (!response.get()) { |
| 147 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (open)"; |
| 148 return CANNOT_CONTACT; |
| 149 } |
| 150 dbus::MessageReader reader(response.get()); |
| 151 if (!reader.PopInt32(handle_ptr)) { |
| 152 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 153 << " (open): " << response->ToString(); |
| 154 return CANNOT_READ; |
| 155 } |
| 156 return SUCCESS; |
| 157 } |
| 158 |
| 159 KWalletDBus::Error KWalletDBus::HasEntry(const int wallet_handle, |
| 160 const std::string& folder_name, |
| 161 const std::string& signon_realm, |
| 162 const std::string& app_name, |
| 163 bool* has_entry) { |
| 164 dbus::MethodCall method_call(kKWalletInterface, "hasEntry"); |
| 165 dbus::MessageWriter builder(&method_call); |
| 166 builder.AppendInt32(wallet_handle); // handle |
| 167 builder.AppendString(folder_name); // folder |
| 168 builder.AppendString(signon_realm); // key |
| 169 builder.AppendString(app_name); // appid |
| 170 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 171 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 172 if (!response.get()) { |
| 173 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (hasEntry)"; |
| 174 return CANNOT_CONTACT; |
| 175 } |
| 176 dbus::MessageReader reader(response.get()); |
| 177 if (!reader.PopBool(has_entry)) { |
| 178 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 179 << " (hasEntry): " << response->ToString(); |
| 180 return CANNOT_READ; |
| 181 } |
| 182 return SUCCESS; |
| 183 } |
| 184 |
| 185 KWalletDBus::Error KWalletDBus::ReadEntry(const int wallet_handle, |
| 186 const std::string& folder_name, |
| 187 const std::string& signon_realm, |
| 188 const std::string& app_name, |
| 189 std::vector<uint8_t>* bytes_ptr) { |
| 190 dbus::MethodCall method_call(kKWalletInterface, "readEntry"); |
| 191 dbus::MessageWriter builder(&method_call); |
| 192 builder.AppendInt32(wallet_handle); // handle |
| 193 builder.AppendString(folder_name); // folder |
| 194 builder.AppendString(signon_realm); // key |
| 195 builder.AppendString(app_name); // appid |
| 196 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 197 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 198 if (!response.get()) { |
| 199 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (readEntry)"; |
| 200 return CANNOT_CONTACT; |
| 201 } |
| 202 size_t length = -1; |
| 203 const uint8_t* bytes_temp = nullptr; |
| 204 dbus::MessageReader reader(response.get()); |
| 205 if (!reader.PopArrayOfBytes(&bytes_temp, &length)) { |
| 206 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 207 << " (readEntry): " << response->ToString(); |
| 208 return CANNOT_READ; |
| 209 } |
| 210 if (bytes_temp) { |
| 211 bytes_ptr->assign(bytes_temp, bytes_temp + length); |
| 212 } else { |
| 213 bytes_ptr->clear(); |
| 214 } |
| 215 return SUCCESS; |
| 216 } |
| 217 |
| 218 KWalletDBus::Error KWalletDBus::EntryList( |
| 219 const int wallet_handle, |
| 220 const std::string& folder_name, |
| 221 const std::string& app_name, |
| 222 std::vector<std::string>* entry_list_ptr) { |
| 223 dbus::MethodCall method_call(kKWalletInterface, "entryList"); |
| 224 dbus::MessageWriter builder(&method_call); |
| 225 builder.AppendInt32(wallet_handle); // handle |
| 226 builder.AppendString(folder_name); // folder |
| 227 builder.AppendString(app_name); // appid |
| 228 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 229 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 230 if (!response.get()) { |
| 231 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (entryList)"; |
| 232 return CANNOT_CONTACT; |
| 233 } |
| 234 dbus::MessageReader reader(response.get()); |
| 235 if (!reader.PopArrayOfStrings(entry_list_ptr)) { |
| 236 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 237 << "(entryList): " << response->ToString(); |
| 238 return CANNOT_READ; |
| 239 } |
| 240 return SUCCESS; |
| 241 } |
| 242 |
| 243 KWalletDBus::Error KWalletDBus::RemoveEntry(const int wallet_handle, |
| 244 const std::string& folder_name, |
| 245 const std::string& signon_realm, |
| 246 const std::string& app_name, |
| 247 int* return_code_ptr) { |
| 248 dbus::MethodCall method_call(kKWalletInterface, "removeEntry"); |
| 249 dbus::MessageWriter builder(&method_call); |
| 250 builder.AppendInt32(wallet_handle); // handle |
| 251 builder.AppendString(folder_name); // folder |
| 252 builder.AppendString(signon_realm); // key |
| 253 builder.AppendString(app_name); // appid |
| 254 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 255 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 256 if (!response.get()) { |
| 257 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (removeEntry)"; |
| 258 return CANNOT_CONTACT; |
| 259 } |
| 260 dbus::MessageReader reader(response.get()); |
| 261 if (!reader.PopInt32(return_code_ptr)) { |
| 262 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 263 << " (removeEntry): " << response->ToString(); |
| 264 return CANNOT_READ; |
| 265 } |
| 266 return SUCCESS; |
| 267 } |
| 268 |
| 269 KWalletDBus::Error KWalletDBus::WriteEntry(const int wallet_handle, |
| 270 const std::string& folder_name, |
| 271 const std::string& signon_realm, |
| 272 const std::string& app_name, |
| 273 const uint8_t* data, |
| 274 const size_t length, |
| 275 int* return_code_ptr) { |
| 276 dbus::MethodCall method_call(kKWalletInterface, "writeEntry"); |
| 277 dbus::MessageWriter builder(&method_call); |
| 278 builder.AppendInt32(wallet_handle); // handle |
| 279 builder.AppendString(folder_name); // folder |
| 280 builder.AppendString(signon_realm); // key |
| 281 builder.AppendArrayOfBytes(data, length); // value |
| 282 builder.AppendString(app_name); // appid |
| 283 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 284 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 285 if (!response.get()) { |
| 286 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (writeEntry)"; |
| 287 return CANNOT_CONTACT; |
| 288 } |
| 289 dbus::MessageReader reader(response.get()); |
| 290 if (!reader.PopInt32(return_code_ptr)) { |
| 291 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 292 << " (writeEntry): " << response->ToString(); |
| 293 return CANNOT_READ; |
| 294 } |
| 295 return SUCCESS; |
| 296 } |
| 297 |
| 298 KWalletDBus::Error KWalletDBus::HasFolder(const int handle, |
| 299 const std::string& folder_name, |
| 300 const std::string& app_name, |
| 301 bool* has_folder_ptr) { |
| 302 dbus::MethodCall method_call(kKWalletInterface, "hasFolder"); |
| 303 dbus::MessageWriter builder(&method_call); |
| 304 builder.AppendInt32(handle); // handle |
| 305 builder.AppendString(folder_name); // folder |
| 306 builder.AppendString(app_name); // appid |
| 307 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 308 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 309 if (!response.get()) { |
| 310 LOG(ERROR) << "Error contacting " << kwalletd_name_ << " (hasFolder)"; |
| 311 return CANNOT_CONTACT; |
| 312 } |
| 313 dbus::MessageReader reader(response.get()); |
| 314 if (!reader.PopBool(has_folder_ptr)) { |
| 315 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 316 << " (hasFolder): " << response->ToString(); |
| 317 return CANNOT_READ; |
| 318 } |
| 319 return SUCCESS; |
| 320 } |
| 321 |
| 322 KWalletDBus::Error KWalletDBus::CreateFolder(const int handle, |
| 323 const std::string& folder_name, |
| 324 const std::string& app_name, |
| 325 bool* success_ptr) { |
| 326 dbus::MethodCall method_call(kKWalletInterface, "createFolder"); |
| 327 dbus::MessageWriter builder(&method_call); |
| 328 builder.AppendInt32(handle); // handle |
| 329 builder.AppendString(folder_name); // folder |
| 330 builder.AppendString(app_name); // appid |
| 331 std::unique_ptr<dbus::Response> response(kwallet_proxy_->CallMethodAndBlock( |
| 332 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)); |
| 333 if (!response.get()) { |
| 334 LOG(ERROR) << "Error contacting << " << kwalletd_name_ << " (createFolder)"; |
| 335 return CANNOT_CONTACT; |
| 336 } |
| 337 dbus::MessageReader reader(response.get()); |
| 338 if (!reader.PopBool(success_ptr)) { |
| 339 LOG(ERROR) << "Error reading response from " << kwalletd_name_ |
| 340 << " (createFolder): " << response->ToString(); |
| 341 return CANNOT_READ; |
| 342 } |
| 343 return SUCCESS; |
| 344 } |
OLD | NEW |