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 "components/os_crypt/key_storage_kwallet.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/nix/xdg_util.h" |
| 9 #include "dbus/message.h" |
| 10 #include "dbus/mock_bus.h" |
| 11 #include "dbus/mock_object_proxy.h" |
| 12 #include "dbus/object_path.h" |
| 13 #include "dbus/object_proxy.h" |
| 14 #include "testing/gmock/include/gmock/gmock.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 |
| 17 namespace { |
| 18 |
| 19 using testing::_; |
| 20 using testing::DoAll; |
| 21 using testing::Return; |
| 22 using testing::SaveArg; |
| 23 using testing::SetArgPointee; |
| 24 using testing::StrictMock; |
| 25 |
| 26 constexpr KWalletDBus::Error SUCCESS = KWalletDBus::Error::SUCCESS; |
| 27 constexpr KWalletDBus::Error CANNOT_READ = KWalletDBus::Error::CANNOT_READ; |
| 28 constexpr KWalletDBus::Error CANNOT_CONTACT = |
| 29 KWalletDBus::Error::CANNOT_CONTACT; |
| 30 |
| 31 // These names are not allowed to change in prod, unless we intentionally |
| 32 // migrate. |
| 33 #if defined(OFFICIAL_BUILD) |
| 34 const char kExpectedFolderName[] = "Chrome Keys"; |
| 35 const char kExpectedEntryName[] = "Chrome Safe Storage"; |
| 36 #else |
| 37 const char kExpectedFolderName[] = "Chromium Keys"; |
| 38 const char kExpectedEntryName[] = "Chromium Safe Storage"; |
| 39 #endif |
| 40 |
| 41 // Environment-specific behavior is handled and tested with KWalletDBus, not |
| 42 // here, but we still need a value to instantiate. |
| 43 const base::nix::DesktopEnvironment kDesktopEnv = |
| 44 base::nix::DesktopEnvironment::DESKTOP_ENVIRONMENT_KDE5; |
| 45 |
| 46 class MockKWalletDBus : public KWalletDBus { |
| 47 public: |
| 48 MockKWalletDBus() : KWalletDBus(kDesktopEnv) { |
| 49 // On destruction, GetSessionBus() is called to get the bus and shut it |
| 50 // down. Here we create a mock to be returned by GetSessionBus(). |
| 51 mock_session_bus_ = new dbus::MockBus(dbus::Bus::Options()); |
| 52 } |
| 53 |
| 54 dbus::MockBus* GetSessionBus() override { return mock_session_bus_.get(); } |
| 55 |
| 56 MOCK_METHOD0(StartKWalletd, bool()); |
| 57 |
| 58 MOCK_METHOD1(IsEnabled, KWalletDBus::Error(bool*)); |
| 59 |
| 60 MOCK_METHOD1(NetworkWallet, KWalletDBus::Error(std::string*)); |
| 61 |
| 62 MOCK_METHOD3(Open, |
| 63 KWalletDBus::Error(const std::string&, |
| 64 const std::string&, |
| 65 int*)); |
| 66 |
| 67 MOCK_METHOD4( |
| 68 HasFolder, |
| 69 KWalletDBus::Error(int, const std::string&, const std::string&, bool*)); |
| 70 |
| 71 MOCK_METHOD4( |
| 72 CreateFolder, |
| 73 KWalletDBus::Error(int, const std::string&, const std::string&, bool*)); |
| 74 |
| 75 MOCK_METHOD5(ReadPassword, |
| 76 KWalletDBus::Error(int, |
| 77 const std::string&, |
| 78 const std::string&, |
| 79 const std::string&, |
| 80 std::string*)); |
| 81 |
| 82 MOCK_METHOD6(WritePassword, |
| 83 KWalletDBus::Error(int, |
| 84 const std::string&, |
| 85 const std::string&, |
| 86 const std::string&, |
| 87 const std::string&, |
| 88 bool*)); |
| 89 |
| 90 MOCK_METHOD4(Close, KWalletDBus::Error(int, bool, const std::string&, bool*)); |
| 91 |
| 92 private: |
| 93 scoped_refptr<dbus::MockBus> mock_session_bus_; |
| 94 }; |
| 95 |
| 96 class KeyStorageKWalletTest : public testing::Test { |
| 97 public: |
| 98 KeyStorageKWalletTest() : key_storage_kwallet_(kDesktopEnv, "test-app") {} |
| 99 |
| 100 void SetUp() override { |
| 101 kwallet_dbus_mock_ = new StrictMock<MockKWalletDBus>(); |
| 102 |
| 103 // Calls from |key_storage_kwallet_|'s destructor |
| 104 EXPECT_CALL(*kwallet_dbus_mock_, Close(_, false, _, _)) |
| 105 .WillOnce(DoAll(SetArgPointee<3>(true), Return(SUCCESS))); |
| 106 EXPECT_CALL(*kwallet_dbus_mock_->GetSessionBus(), ShutdownAndBlock()) |
| 107 .Times(1); |
| 108 } |
| 109 |
| 110 void SuccessfulInit() { |
| 111 EXPECT_CALL(*kwallet_dbus_mock_, IsEnabled(_)) |
| 112 .WillOnce(DoAll(SetArgPointee<0>(true), Return(SUCCESS))); |
| 113 EXPECT_CALL(*kwallet_dbus_mock_, NetworkWallet(_)) |
| 114 .WillOnce( |
| 115 DoAll(SetArgPointee<0>(std::string("mollet")), Return(SUCCESS))); |
| 116 |
| 117 EXPECT_TRUE(key_storage_kwallet_.InitWithKWalletDBus( |
| 118 std::unique_ptr<MockKWalletDBus>(kwallet_dbus_mock_))); |
| 119 } |
| 120 |
| 121 protected: |
| 122 StrictMock<MockKWalletDBus>* kwallet_dbus_mock_; |
| 123 KeyStorageKWallet key_storage_kwallet_; |
| 124 const std::string wallet_name_ = "mollet"; |
| 125 |
| 126 private: |
| 127 DISALLOW_COPY_AND_ASSIGN(KeyStorageKWalletTest); |
| 128 }; |
| 129 |
| 130 TEST_F(KeyStorageKWalletTest, InitializeFolder) { |
| 131 SuccessfulInit(); |
| 132 EXPECT_CALL(*kwallet_dbus_mock_, Open(_, _, _)) |
| 133 .WillOnce(DoAll(SetArgPointee<2>(123), Return(SUCCESS))); |
| 134 EXPECT_CALL(*kwallet_dbus_mock_, HasFolder(123, kExpectedFolderName, _, _)) |
| 135 .WillOnce(DoAll(SetArgPointee<3>(false), Return(SUCCESS))); |
| 136 EXPECT_CALL(*kwallet_dbus_mock_, CreateFolder(123, kExpectedFolderName, _, _)) |
| 137 .WillOnce(DoAll(SetArgPointee<3>(true), Return(SUCCESS))); |
| 138 EXPECT_CALL(*kwallet_dbus_mock_, |
| 139 ReadPassword(123, kExpectedFolderName, kExpectedEntryName, _, _)) |
| 140 .WillOnce(DoAll(SetArgPointee<4>("butter"), Return(SUCCESS))); |
| 141 |
| 142 EXPECT_EQ("butter", key_storage_kwallet_.GetKey()); |
| 143 } |
| 144 |
| 145 TEST_F(KeyStorageKWalletTest, ExistingPassword) { |
| 146 SuccessfulInit(); |
| 147 EXPECT_CALL(*kwallet_dbus_mock_, Open(_, _, _)) |
| 148 .WillOnce(DoAll(SetArgPointee<2>(123), Return(SUCCESS))); |
| 149 EXPECT_CALL(*kwallet_dbus_mock_, HasFolder(123, kExpectedFolderName, _, _)) |
| 150 .WillOnce(DoAll(SetArgPointee<3>(true), Return(SUCCESS))); |
| 151 EXPECT_CALL(*kwallet_dbus_mock_, |
| 152 ReadPassword(123, kExpectedFolderName, kExpectedEntryName, _, _)) |
| 153 .WillOnce(DoAll(SetArgPointee<4>("butter"), Return(SUCCESS))); |
| 154 |
| 155 EXPECT_EQ("butter", key_storage_kwallet_.GetKey()); |
| 156 } |
| 157 |
| 158 TEST_F(KeyStorageKWalletTest, GenerateNewPassword) { |
| 159 SuccessfulInit(); |
| 160 std::string generated_password; |
| 161 EXPECT_CALL(*kwallet_dbus_mock_, Open(_, _, _)) |
| 162 .WillOnce(DoAll(SetArgPointee<2>(123), Return(SUCCESS))); |
| 163 EXPECT_CALL(*kwallet_dbus_mock_, HasFolder(123, kExpectedFolderName, _, _)) |
| 164 .WillOnce(DoAll(SetArgPointee<3>(true), Return(SUCCESS))); |
| 165 EXPECT_CALL(*kwallet_dbus_mock_, |
| 166 ReadPassword(123, kExpectedFolderName, kExpectedEntryName, _, _)) |
| 167 .WillOnce(DoAll(SetArgPointee<4>(""), Return(SUCCESS))); |
| 168 EXPECT_CALL(*kwallet_dbus_mock_, WritePassword(123, kExpectedFolderName, |
| 169 kExpectedEntryName, _, _, _)) |
| 170 .WillOnce(DoAll(SaveArg<3>(&generated_password), SetArgPointee<5>(true), |
| 171 Return(SUCCESS))); |
| 172 |
| 173 EXPECT_EQ(generated_password, key_storage_kwallet_.GetKey()); |
| 174 } |
| 175 |
| 176 TEST_F(KeyStorageKWalletTest, InitKWalletNotEnabled) { |
| 177 EXPECT_CALL(*kwallet_dbus_mock_, IsEnabled(_)) |
| 178 .WillOnce(DoAll(SetArgPointee<0>(false), Return(SUCCESS))); |
| 179 |
| 180 EXPECT_FALSE(key_storage_kwallet_.InitWithKWalletDBus( |
| 181 std::unique_ptr<MockKWalletDBus>(kwallet_dbus_mock_))); |
| 182 } |
| 183 |
| 184 TEST_F(KeyStorageKWalletTest, InitCannotStart) { |
| 185 EXPECT_CALL(*kwallet_dbus_mock_, IsEnabled(_)) |
| 186 .WillOnce(Return(CANNOT_CONTACT)); |
| 187 EXPECT_CALL(*kwallet_dbus_mock_, StartKWalletd()).WillOnce(Return(false)); |
| 188 |
| 189 EXPECT_FALSE(key_storage_kwallet_.InitWithKWalletDBus( |
| 190 std::unique_ptr<MockKWalletDBus>(kwallet_dbus_mock_))); |
| 191 } |
| 192 |
| 193 TEST_F(KeyStorageKWalletTest, InitFailTwice) { |
| 194 EXPECT_CALL(*kwallet_dbus_mock_, IsEnabled(_)) |
| 195 .WillOnce(Return(CANNOT_CONTACT)) |
| 196 .WillOnce(Return(CANNOT_CONTACT)); |
| 197 EXPECT_CALL(*kwallet_dbus_mock_, StartKWalletd()).WillOnce(Return(true)); |
| 198 |
| 199 EXPECT_FALSE(key_storage_kwallet_.InitWithKWalletDBus( |
| 200 std::unique_ptr<MockKWalletDBus>(kwallet_dbus_mock_))); |
| 201 } |
| 202 |
| 203 TEST_F(KeyStorageKWalletTest, InitTryTwiceAndFail) { |
| 204 EXPECT_CALL(*kwallet_dbus_mock_, IsEnabled(_)) |
| 205 .WillOnce(Return(CANNOT_CONTACT)) |
| 206 .WillOnce(DoAll(SetArgPointee<0>(true), Return(SUCCESS))); |
| 207 EXPECT_CALL(*kwallet_dbus_mock_, StartKWalletd()).WillOnce(Return(true)); |
| 208 EXPECT_CALL(*kwallet_dbus_mock_, NetworkWallet(_)) |
| 209 .WillOnce(Return(CANNOT_CONTACT)); |
| 210 |
| 211 EXPECT_FALSE(key_storage_kwallet_.InitWithKWalletDBus( |
| 212 std::unique_ptr<MockKWalletDBus>(kwallet_dbus_mock_))); |
| 213 } |
| 214 |
| 215 TEST_F(KeyStorageKWalletTest, InitTryTwiceAndSuccess) { |
| 216 EXPECT_CALL(*kwallet_dbus_mock_, IsEnabled(_)) |
| 217 .WillOnce(Return(CANNOT_CONTACT)) |
| 218 .WillOnce(DoAll(SetArgPointee<0>(true), Return(SUCCESS))); |
| 219 EXPECT_CALL(*kwallet_dbus_mock_, StartKWalletd()).WillOnce(Return(true)); |
| 220 EXPECT_CALL(*kwallet_dbus_mock_, NetworkWallet(_)) |
| 221 .WillOnce(DoAll(SetArgPointee<0>(wallet_name_), Return(SUCCESS))); |
| 222 |
| 223 EXPECT_TRUE(key_storage_kwallet_.InitWithKWalletDBus( |
| 224 std::unique_ptr<MockKWalletDBus>(kwallet_dbus_mock_))); |
| 225 } |
| 226 |
| 227 // Tests for a dbus connection that fails after initialization. |
| 228 // Any error is expected to return an empty password. |
| 229 class KeyStorageKWalletFailuresTest |
| 230 : public testing::TestWithParam<KWalletDBus::Error> { |
| 231 public: |
| 232 KeyStorageKWalletFailuresTest() |
| 233 : key_storage_kwallet_(kDesktopEnv, "test-app") {} |
| 234 |
| 235 void SetUp() override { |
| 236 // |key_storage_kwallet_| will take ownership of |kwallet_dbus_mock_|. |
| 237 kwallet_dbus_mock_ = new StrictMock<MockKWalletDBus>(); |
| 238 |
| 239 // Successful initialization. |
| 240 EXPECT_CALL(*kwallet_dbus_mock_, IsEnabled(_)) |
| 241 .WillOnce(DoAll(SetArgPointee<0>(true), Return(SUCCESS))); |
| 242 EXPECT_CALL(*kwallet_dbus_mock_, NetworkWallet(_)) |
| 243 .WillOnce( |
| 244 DoAll(SetArgPointee<0>(std::string("mollet")), Return(SUCCESS))); |
| 245 |
| 246 EXPECT_TRUE(key_storage_kwallet_.InitWithKWalletDBus( |
| 247 std::unique_ptr<MockKWalletDBus>(kwallet_dbus_mock_))); |
| 248 |
| 249 // Calls from |key_storage_kwallet_|'s destructor. |
| 250 EXPECT_CALL(*kwallet_dbus_mock_, Close(_, false, _, _)) |
| 251 .WillOnce(DoAll(SetArgPointee<3>(true), Return(SUCCESS))); |
| 252 EXPECT_CALL(*kwallet_dbus_mock_->GetSessionBus(), ShutdownAndBlock()) |
| 253 .Times(1); |
| 254 } |
| 255 |
| 256 protected: |
| 257 StrictMock<MockKWalletDBus>* kwallet_dbus_mock_; |
| 258 KeyStorageKWallet key_storage_kwallet_; |
| 259 const std::string wallet_name_ = "mollet"; |
| 260 |
| 261 private: |
| 262 DISALLOW_COPY_AND_ASSIGN(KeyStorageKWalletFailuresTest); |
| 263 }; |
| 264 |
| 265 INSTANTIATE_TEST_CASE_P(, |
| 266 KeyStorageKWalletFailuresTest, |
| 267 ::testing::Values(CANNOT_READ, CANNOT_CONTACT)); |
| 268 |
| 269 TEST_P(KeyStorageKWalletFailuresTest, PostInitFailureOpen) { |
| 270 EXPECT_CALL(*kwallet_dbus_mock_, Open(_, _, _)).WillOnce(Return(GetParam())); |
| 271 |
| 272 EXPECT_EQ("", key_storage_kwallet_.GetKey()); |
| 273 } |
| 274 |
| 275 TEST_P(KeyStorageKWalletFailuresTest, PostInitFailureHasFolder) { |
| 276 EXPECT_CALL(*kwallet_dbus_mock_, Open(_, _, _)) |
| 277 .WillOnce(DoAll(SetArgPointee<2>(123), Return(SUCCESS))); |
| 278 EXPECT_CALL(*kwallet_dbus_mock_, HasFolder(123, _, _, _)) |
| 279 .WillOnce(Return(GetParam())); |
| 280 |
| 281 EXPECT_EQ("", key_storage_kwallet_.GetKey()); |
| 282 } |
| 283 |
| 284 TEST_P(KeyStorageKWalletFailuresTest, PostInitFailureCreateFolder) { |
| 285 EXPECT_CALL(*kwallet_dbus_mock_, Open(_, _, _)) |
| 286 .WillOnce(DoAll(SetArgPointee<2>(123), Return(SUCCESS))); |
| 287 EXPECT_CALL(*kwallet_dbus_mock_, HasFolder(123, _, _, _)) |
| 288 .WillOnce(DoAll(SetArgPointee<3>(false), Return(SUCCESS))); |
| 289 EXPECT_CALL(*kwallet_dbus_mock_, CreateFolder(123, _, _, _)) |
| 290 .WillOnce(Return(GetParam())); |
| 291 |
| 292 EXPECT_EQ("", key_storage_kwallet_.GetKey()); |
| 293 } |
| 294 |
| 295 TEST_P(KeyStorageKWalletFailuresTest, PostInitFailureReadPassword) { |
| 296 EXPECT_CALL(*kwallet_dbus_mock_, Open(_, _, _)) |
| 297 .WillOnce(DoAll(SetArgPointee<2>(123), Return(SUCCESS))); |
| 298 EXPECT_CALL(*kwallet_dbus_mock_, HasFolder(123, _, _, _)) |
| 299 .WillOnce(DoAll(SetArgPointee<3>(true), Return(SUCCESS))); |
| 300 EXPECT_CALL(*kwallet_dbus_mock_, ReadPassword(123, _, _, _, _)) |
| 301 .WillOnce(Return(GetParam())); |
| 302 |
| 303 EXPECT_EQ("", key_storage_kwallet_.GetKey()); |
| 304 } |
| 305 |
| 306 TEST_P(KeyStorageKWalletFailuresTest, PostInitFailureWritePassword) { |
| 307 EXPECT_CALL(*kwallet_dbus_mock_, Open(_, _, _)) |
| 308 .WillOnce(DoAll(SetArgPointee<2>(123), Return(SUCCESS))); |
| 309 EXPECT_CALL(*kwallet_dbus_mock_, HasFolder(123, _, _, _)) |
| 310 .WillOnce(DoAll(SetArgPointee<3>(true), Return(SUCCESS))); |
| 311 EXPECT_CALL(*kwallet_dbus_mock_, ReadPassword(123, _, _, _, _)) |
| 312 .WillOnce(DoAll(SetArgPointee<4>(""), Return(SUCCESS))); |
| 313 EXPECT_CALL(*kwallet_dbus_mock_, WritePassword(123, _, _, _, _, _)) |
| 314 .WillOnce(Return(GetParam())); |
| 315 |
| 316 EXPECT_EQ("", key_storage_kwallet_.GetKey()); |
| 317 } |
| 318 |
| 319 } // namespace |
OLD | NEW |