blob: efc1cd43f816f34f6293a5e774abd3c909f04c74 [file] [log] [blame]
[email protected]de702112012-01-30 23:31:431// Copyright (c) 2012 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
Jinho Bang138fde32018-01-18 23:13:425#include <memory>
6
[email protected]de702112012-01-30 23:31:437#include "base/bind.h"
avi5a080f012015-12-22 23:15:438#include "base/macros.h"
fdoray6d056ff2016-07-04 21:56:429#include "base/run_loop.h"
[email protected]de702112012-01-30 23:31:4310#include "net/base/net_errors.h"
[email protected]8f1504b2013-03-07 13:43:1011#include "remoting/base/rsa_key_pair.h"
sergeyu42cb6f9f2016-03-09 05:37:0312#include "remoting/protocol/auth_util.h"
[email protected]de702112012-01-30 23:31:4313#include "remoting/protocol/authenticator_test_base.h"
14#include "remoting/protocol/channel_authenticator.h"
15#include "remoting/protocol/connection_tester.h"
[email protected]76cfd032013-04-03 10:49:4416#include "remoting/protocol/negotiating_authenticator_base.h"
17#include "remoting/protocol/negotiating_client_authenticator.h"
18#include "remoting/protocol/negotiating_host_authenticator.h"
[email protected]88356922013-06-04 06:26:0119#include "remoting/protocol/pairing_registry.h"
[email protected]40dade32013-06-14 07:08:1120#include "remoting/protocol/protocol_mock_objects.h"
[email protected]de702112012-01-30 23:31:4321#include "testing/gmock/include/gmock/gmock.h"
22#include "testing/gtest/include/gtest/gtest.h"
kjellanderf0e410b2017-01-04 14:45:0123#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
[email protected]de702112012-01-30 23:31:4324
25using testing::_;
26using testing::DeleteArg;
27using testing::SaveArg;
28
29namespace remoting {
30namespace protocol {
31
32namespace {
33
34const int kMessageSize = 100;
35const int kMessages = 1;
36
[email protected]6434bfe2013-05-22 09:00:2337const char kNoClientId[] = "";
38const char kNoPairedSecret[] = "";
[email protected]df5189f2013-06-18 12:12:0539const char kTestClientName[] = "client-name";
[email protected]6434bfe2013-05-22 09:00:2340const char kTestClientId[] = "client-id";
[email protected]de702112012-01-30 23:31:4341const char kTestHostId[] = "12345678910123456";
42
sergeyu4357fda52016-03-12 07:23:2443const char kClientJid[] = "[email protected]/abc";
44const char kHostJid[] = "[email protected]/123";
45
[email protected]6434bfe2013-05-22 09:00:2346const char kTestPairedSecret[] = "1111-2222-3333";
47const char kTestPairedSecretBad[] = "4444-5555-6666";
48const char kTestPin[] = "123456";
49const char kTestPinBad[] = "654321";
[email protected]de702112012-01-30 23:31:4350
51} // namespace
52
53class NegotiatingAuthenticatorTest : public AuthenticatorTestBase {
54 public:
Chris Watkins6fe52aa2017-11-28 03:24:0555 NegotiatingAuthenticatorTest() = default;
56 ~NegotiatingAuthenticatorTest() override = default;
[email protected]de702112012-01-30 23:31:4357
58 protected:
sergeyu410cd112016-03-17 06:15:0059 virtual void InitAuthenticators(const std::string& client_id,
60 const std::string& client_paired_secret,
61 const std::string& client_interactive_pin,
sergeyud5d7539f2016-03-17 18:08:0362 const std::string& host_secret) {
63 std::string host_secret_hash =
64 GetSharedSecretHash(kTestHostId, host_secret);
dcheng0765c492016-04-06 22:41:5365 std::unique_ptr<NegotiatingHostAuthenticator> host =
sergeyud5d7539f2016-03-17 18:08:0366 NegotiatingHostAuthenticator::CreateWithSharedSecret(
67 kHostJid, kClientJid, host_cert_, key_pair_, host_secret_hash,
68 pairing_registry_);
69 host_as_negotiating_authenticator_ = host.get();
70 host_ = std::move(host);
[email protected]de702112012-01-30 23:31:4371
sergeyu396d9332016-03-12 01:58:5872 protocol::ClientAuthenticationConfig client_auth_config;
73 client_auth_config.host_id = kTestHostId;
74 client_auth_config.pairing_client_id = client_id;
sergeyu410cd112016-03-17 06:15:0075 client_auth_config.pairing_secret = client_paired_secret;
sergeyuc5f104b2015-01-09 19:33:2476 bool pairing_expected = pairing_registry_.get() != nullptr;
sergeyu396d9332016-03-12 01:58:5877 client_auth_config.fetch_secret_callback =
[email protected]f9d8a772013-06-01 04:33:1778 base::Bind(&NegotiatingAuthenticatorTest::FetchSecret,
sergeyu396d9332016-03-12 01:58:5879 client_interactive_pin, pairing_expected);
sergeyu4357fda52016-03-12 07:23:2480 client_as_negotiating_authenticator_ = new NegotiatingClientAuthenticator(
81 kClientJid, kHostJid, client_auth_config);
[email protected]6434bfe2013-05-22 09:00:2382 client_.reset(client_as_negotiating_authenticator_);
83 }
84
sergeyu410cd112016-03-17 06:15:0085 void DisableMethodOnClient(NegotiatingAuthenticatorBase::Method method) {
86 auto* methods = &(client_as_negotiating_authenticator_->methods_);
87 auto iter = std::find(methods->begin(), methods->end(), method);
88 ASSERT_TRUE(iter != methods->end());
89 methods->erase(iter);
90 }
91
92 void DisableMethodOnHost(NegotiatingAuthenticatorBase::Method method) {
93 auto* methods = &(host_as_negotiating_authenticator_->methods_);
94 auto iter = std::find(methods->begin(), methods->end(), method);
95 ASSERT_TRUE(iter != methods->end());
96 methods->erase(iter);
97 }
98
[email protected]40dade32013-06-14 07:08:1199 void CreatePairingRegistry(bool with_paired_client) {
[email protected]378466032013-08-02 01:35:16100 pairing_registry_ = new SynchronousPairingRegistry(
Jinho Bang138fde32018-01-18 23:13:42101 std::make_unique<MockPairingRegistryDelegate>());
[email protected]40dade32013-06-14 07:08:11102 if (with_paired_client) {
[email protected]df5189f2013-06-18 12:12:05103 PairingRegistry::Pairing pairing(
104 base::Time(), kTestClientName, kTestClientId, kTestPairedSecret);
[email protected]b1ae9012013-06-23 14:10:30105 pairing_registry_->AddPairing(pairing);
[email protected]6434bfe2013-05-22 09:00:23106 }
[email protected]de702112012-01-30 23:31:43107 }
108
[email protected]21257522013-03-23 18:39:13109 static void FetchSecret(
110 const std::string& client_secret,
[email protected]4cc63fc2013-05-24 07:06:39111 bool pairing_supported,
112 bool pairing_expected,
[email protected]21257522013-03-23 18:39:13113 const protocol::SecretFetchedCallback& secret_fetched_callback) {
114 secret_fetched_callback.Run(client_secret);
[email protected]4cc63fc2013-05-24 07:06:39115 ASSERT_EQ(pairing_supported, pairing_expected);
[email protected]21257522013-03-23 18:39:13116 }
[email protected]6434bfe2013-05-22 09:00:23117
[email protected]de702112012-01-30 23:31:43118 void VerifyRejected(Authenticator::RejectionReason reason) {
[email protected]6434bfe2013-05-22 09:00:23119 ASSERT_TRUE(client_->state() == Authenticator::REJECTED ||
120 host_->state() == Authenticator::REJECTED);
121 if (client_->state() == Authenticator::REJECTED) {
122 ASSERT_EQ(client_->rejection_reason(), reason);
123 }
124 if (host_->state() == Authenticator::REJECTED) {
125 ASSERT_EQ(host_->rejection_reason(), reason);
126 }
[email protected]de702112012-01-30 23:31:43127 }
128
sergeyu410cd112016-03-17 06:15:00129 virtual void VerifyAccepted() {
[email protected]21257522013-03-23 18:39:13130 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
131
132 ASSERT_EQ(Authenticator::ACCEPTED, host_->state());
133 ASSERT_EQ(Authenticator::ACCEPTED, client_->state());
134
135 client_auth_ = client_->CreateChannelAuthenticator();
136 host_auth_ = host_->CreateChannelAuthenticator();
137 RunChannelAuth(false);
138
sergeyuc5f104b2015-01-09 19:33:24139 EXPECT_TRUE(client_socket_.get() != nullptr);
140 EXPECT_TRUE(host_socket_.get() != nullptr);
[email protected]21257522013-03-23 18:39:13141
142 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
143 kMessageSize, kMessages);
144
145 tester.Start();
fdoray6d056ff2016-07-04 21:56:42146 base::RunLoop().Run();
[email protected]21257522013-03-23 18:39:13147 tester.CheckResults();
sergeyu410cd112016-03-17 06:15:00148 }
149
150 NegotiatingAuthenticatorBase::Method current_method() {
151 return client_as_negotiating_authenticator_->current_method_;
[email protected]21257522013-03-23 18:39:13152 }
153
[email protected]6434bfe2013-05-22 09:00:23154 // Use a bare pointer because the storage is managed by the base class.
sergeyu410cd112016-03-17 06:15:00155 NegotiatingHostAuthenticator* host_as_negotiating_authenticator_;
[email protected]6434bfe2013-05-22 09:00:23156 NegotiatingClientAuthenticator* client_as_negotiating_authenticator_;
157
[email protected]21257522013-03-23 18:39:13158 private:
[email protected]40dade32013-06-14 07:08:11159 scoped_refptr<PairingRegistry> pairing_registry_;
160
[email protected]de702112012-01-30 23:31:43161 DISALLOW_COPY_AND_ASSIGN(NegotiatingAuthenticatorTest);
162};
163
sergeyu410cd112016-03-17 06:15:00164struct PairingTestParameters {
165 bool p224_on_client;
166 bool curve25519_on_client;
167 bool p224_on_host;
168 bool curve25519_on_host;
169
170 bool expect_curve25519_used;
171};
172
173class NegotiatingPairingAuthenticatorTest
174 : public NegotiatingAuthenticatorTest,
175 public testing::WithParamInterface<PairingTestParameters> {
176public:
177 void InitAuthenticators(const std::string& client_id,
178 const std::string& client_paired_secret,
179 const std::string& client_interactive_pin,
sergeyud5d7539f2016-03-17 18:08:03180 const std::string& host_secret) override {
sergeyu410cd112016-03-17 06:15:00181 NegotiatingAuthenticatorTest::InitAuthenticators(
sergeyud5d7539f2016-03-17 18:08:03182 client_id, client_paired_secret, client_interactive_pin, host_secret);
sergeyu410cd112016-03-17 06:15:00183 if (!GetParam().p224_on_client) {
184 DisableMethodOnClient(
185 NegotiatingAuthenticatorBase::Method::PAIRED_SPAKE2_P224);
186 }
187 if (!GetParam().curve25519_on_client) {
188 DisableMethodOnClient(
189 NegotiatingAuthenticatorBase::Method::PAIRED_SPAKE2_CURVE25519);
190 }
191 if (!GetParam().p224_on_host) {
192 DisableMethodOnHost(
193 NegotiatingAuthenticatorBase::Method::PAIRED_SPAKE2_P224);
194 }
195 if (!GetParam().curve25519_on_host) {
196 DisableMethodOnHost(
197 NegotiatingAuthenticatorBase::Method::PAIRED_SPAKE2_CURVE25519);
198 }
199 }
200
201 void VerifyAccepted() override {
202 NegotiatingAuthenticatorTest::VerifyAccepted();
203 EXPECT_TRUE(
204 current_method() ==
205 NegotiatingAuthenticatorBase::Method::PAIRED_SPAKE2_P224 ||
206 current_method() ==
207 NegotiatingAuthenticatorBase::Method::PAIRED_SPAKE2_CURVE25519);
208 }
209};
210
211INSTANTIATE_TEST_CASE_P(
212 PairingParams,
213 NegotiatingPairingAuthenticatorTest,
214 testing::Values(
215 // Only P224.
216 PairingTestParameters{true, false, true, false},
217
218 // Only curve25519.
219 PairingTestParameters{false, true, false, true},
220
221 // Both P224 and curve25519.
222 PairingTestParameters{true, true, true, true},
223
224 // One end supports both, the other supports only P224 or curve25519.
225 PairingTestParameters{false, true, true, true},
226 PairingTestParameters{true, false, true, true},
227 PairingTestParameters{true, true, false, true},
228 PairingTestParameters{true, true, true, false}));
229
sergeyud5d7539f2016-03-17 18:08:03230TEST_F(NegotiatingAuthenticatorTest, SuccessfulAuthSharedSecret) {
sergeyu3c759242016-03-04 21:34:33231 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(kNoClientId, kNoPairedSecret,
sergeyud5d7539f2016-03-17 18:08:03232 kTestPin, kTestPin));
sergeyu410cd112016-03-17 06:15:00233 VerifyAccepted();
234 EXPECT_EQ(
235 NegotiatingAuthenticatorBase::Method::SHARED_SECRET_SPAKE2_CURVE25519,
236 current_method());
[email protected]de702112012-01-30 23:31:43237}
238
sergeyud5d7539f2016-03-17 18:08:03239TEST_F(NegotiatingAuthenticatorTest, InvalidSharedSecret) {
sergeyu3c759242016-03-04 21:34:33240 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(kNoClientId, kNoPairedSecret,
sergeyud5d7539f2016-03-17 18:08:03241 kTestPinBad, kTestPin));
[email protected]de702112012-01-30 23:31:43242 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
243
244 VerifyRejected(Authenticator::INVALID_CREDENTIALS);
245}
246
[email protected]591cffcd2014-08-18 20:02:30247TEST_F(NegotiatingAuthenticatorTest, IncompatibleMethods) {
sergeyud5d7539f2016-03-17 18:08:03248 ASSERT_NO_FATAL_FAILURE(
249 InitAuthenticators(kNoClientId, kNoPairedSecret, kTestPin, kTestPinBad));
sergeyu410cd112016-03-17 06:15:00250 DisableMethodOnClient(
sergeyud5d7539f2016-03-17 18:08:03251 NegotiatingAuthenticatorBase::Method::SHARED_SECRET_SPAKE2_P224);
252 DisableMethodOnHost(
253 NegotiatingAuthenticatorBase::Method::SHARED_SECRET_SPAKE2_CURVE25519);
sergeyu42cb6f9f2016-03-09 05:37:03254
[email protected]de702112012-01-30 23:31:43255 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
256
257 VerifyRejected(Authenticator::PROTOCOL_ERROR);
258}
259
[email protected]591cffcd2014-08-18 20:02:30260TEST_F(NegotiatingAuthenticatorTest, PairingNotSupported) {
sergeyud5d7539f2016-03-17 18:08:03261 ASSERT_NO_FATAL_FAILURE(
262 InitAuthenticators(kTestClientId, kTestPairedSecret, kTestPin, kTestPin));
[email protected]6434bfe2013-05-22 09:00:23263 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
sergeyu410cd112016-03-17 06:15:00264 VerifyAccepted();
265 EXPECT_EQ(
266 NegotiatingAuthenticatorBase::Method::SHARED_SECRET_SPAKE2_CURVE25519,
267 current_method());
[email protected]6434bfe2013-05-22 09:00:23268}
269
sergeyu410cd112016-03-17 06:15:00270TEST_P(NegotiatingPairingAuthenticatorTest, PairingSupportedButNotPaired) {
[email protected]40dade32013-06-14 07:08:11271 CreatePairingRegistry(false);
sergeyud5d7539f2016-03-17 18:08:03272 ASSERT_NO_FATAL_FAILURE(
273 InitAuthenticators(kNoClientId, kNoPairedSecret, kTestPin, kTestPin));
[email protected]6434bfe2013-05-22 09:00:23274 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
sergeyu410cd112016-03-17 06:15:00275 VerifyAccepted();
[email protected]6434bfe2013-05-22 09:00:23276}
277
sergeyu410cd112016-03-17 06:15:00278TEST_P(NegotiatingPairingAuthenticatorTest, PairingRevokedPinOkay) {
[email protected]40dade32013-06-14 07:08:11279 CreatePairingRegistry(false);
sergeyud5d7539f2016-03-17 18:08:03280 ASSERT_NO_FATAL_FAILURE(
281 InitAuthenticators(kTestClientId, kTestPairedSecret, kTestPin, kTestPin));
[email protected]6434bfe2013-05-22 09:00:23282 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
sergeyu410cd112016-03-17 06:15:00283 VerifyAccepted();
[email protected]6434bfe2013-05-22 09:00:23284}
285
sergeyu410cd112016-03-17 06:15:00286TEST_P(NegotiatingPairingAuthenticatorTest, PairingRevokedPinBad) {
[email protected]40dade32013-06-14 07:08:11287 CreatePairingRegistry(false);
sergeyu42cb6f9f2016-03-09 05:37:03288 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(kTestClientId, kTestPairedSecret,
sergeyud5d7539f2016-03-17 18:08:03289 kTestPinBad, kTestPin));
[email protected]6434bfe2013-05-22 09:00:23290 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
291 VerifyRejected(Authenticator::INVALID_CREDENTIALS);
292}
293
sergeyu410cd112016-03-17 06:15:00294TEST_P(NegotiatingPairingAuthenticatorTest, PairingSucceeded) {
[email protected]40dade32013-06-14 07:08:11295 CreatePairingRegistry(true);
sergeyu42cb6f9f2016-03-09 05:37:03296 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(kTestClientId, kTestPairedSecret,
sergeyud5d7539f2016-03-17 18:08:03297 kTestPinBad, kTestPin));
[email protected]6434bfe2013-05-22 09:00:23298 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
sergeyu410cd112016-03-17 06:15:00299 VerifyAccepted();
[email protected]6434bfe2013-05-22 09:00:23300}
301
sergeyu410cd112016-03-17 06:15:00302TEST_P(NegotiatingPairingAuthenticatorTest,
[email protected]591cffcd2014-08-18 20:02:30303 PairingSucceededInvalidSecretButPinOkay) {
[email protected]40dade32013-06-14 07:08:11304 CreatePairingRegistry(true);
[email protected]6434bfe2013-05-22 09:00:23305 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
sergeyud5d7539f2016-03-17 18:08:03306 kTestClientId, kTestPairedSecretBad, kTestPin, kTestPin));
[email protected]6434bfe2013-05-22 09:00:23307 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
sergeyu410cd112016-03-17 06:15:00308 VerifyAccepted();
[email protected]6434bfe2013-05-22 09:00:23309}
310
sergeyu410cd112016-03-17 06:15:00311TEST_P(NegotiatingPairingAuthenticatorTest, PairingFailedInvalidSecretAndPin) {
[email protected]40dade32013-06-14 07:08:11312 CreatePairingRegistry(true);
sergeyu42cb6f9f2016-03-09 05:37:03313 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
sergeyud5d7539f2016-03-17 18:08:03314 kTestClientId, kTestPairedSecretBad, kTestPinBad, kTestPin));
[email protected]6434bfe2013-05-22 09:00:23315 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
316 VerifyRejected(Authenticator::INVALID_CREDENTIALS);
317}
318
[email protected]de702112012-01-30 23:31:43319} // namespace protocol
320} // namespace remoting