1 // 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.
6 #include "net/base/net_errors.h"
7 #include "remoting/base/rsa_key_pair.h"
8 #include "remoting/protocol/authenticator_test_base.h"
9 #include "remoting/protocol/channel_authenticator.h"
10 #include "remoting/protocol/connection_tester.h"
11 #include "remoting/protocol/negotiating_authenticator_base.h"
12 #include "remoting/protocol/negotiating_client_authenticator.h"
13 #include "remoting/protocol/negotiating_host_authenticator.h"
14 #include "remoting/protocol/pairing_registry.h"
15 #include "remoting/protocol/protocol_mock_objects.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
21 using testing::DeleteArg
;
22 using testing::SaveArg
;
29 const int kMessageSize
= 100;
30 const int kMessages
= 1;
32 const char kNoClientId
[] = "";
33 const char kNoPairedSecret
[] = "";
34 const char kTestClientName
[] = "client-name";
35 const char kTestClientId
[] = "client-id";
36 const char kTestHostId
[] = "12345678910123456";
38 const char kTestPairedSecret
[] = "1111-2222-3333";
39 const char kTestPairedSecretBad
[] = "4444-5555-6666";
40 const char kTestPin
[] = "123456";
41 const char kTestPinBad
[] = "654321";
45 class NegotiatingAuthenticatorTest
: public AuthenticatorTestBase
{
47 NegotiatingAuthenticatorTest() {
49 virtual ~NegotiatingAuthenticatorTest() {
53 void InitAuthenticators(
54 const std::string
& client_id
,
55 const std::string
& client_paired_secret
,
56 const std::string
& client_interactive_pin
,
57 const std::string
& host_secret
,
58 AuthenticationMethod::HashFunction hash_function
,
59 bool client_hmac_only
) {
60 std::string host_secret_hash
= AuthenticationMethod::ApplyHashFunction(
61 hash_function
, kTestHostId
, host_secret
);
62 host_
= NegotiatingHostAuthenticator::CreateWithSharedSecret(
63 host_cert_
, key_pair_
, host_secret_hash
, hash_function
,
66 std::vector
<AuthenticationMethod
> methods
;
67 methods
.push_back(AuthenticationMethod::Spake2Pair());
68 methods
.push_back(AuthenticationMethod::Spake2(
69 AuthenticationMethod::HMAC_SHA256
));
70 if (!client_hmac_only
) {
71 methods
.push_back(AuthenticationMethod::Spake2(
72 AuthenticationMethod::NONE
));
74 bool pairing_expected
= pairing_registry_
.get() != NULL
;
75 FetchSecretCallback fetch_secret_callback
=
76 base::Bind(&NegotiatingAuthenticatorTest::FetchSecret
,
77 client_interactive_pin
,
79 client_as_negotiating_authenticator_
= new NegotiatingClientAuthenticator(
80 client_id
, client_paired_secret
,
81 kTestHostId
, fetch_secret_callback
,
82 scoped_ptr
<ThirdPartyClientAuthenticator::TokenFetcher
>(), methods
);
83 client_
.reset(client_as_negotiating_authenticator_
);
86 void CreatePairingRegistry(bool with_paired_client
) {
87 pairing_registry_
= new SynchronousPairingRegistry(
88 scoped_ptr
<PairingRegistry::Delegate
>(
89 new MockPairingRegistryDelegate()));
90 if (with_paired_client
) {
91 PairingRegistry::Pairing
pairing(
92 base::Time(), kTestClientName
, kTestClientId
, kTestPairedSecret
);
93 pairing_registry_
->AddPairing(pairing
);
97 static void FetchSecret(
98 const std::string
& client_secret
,
99 bool pairing_supported
,
100 bool pairing_expected
,
101 const protocol::SecretFetchedCallback
& secret_fetched_callback
) {
102 secret_fetched_callback
.Run(client_secret
);
103 ASSERT_EQ(pairing_supported
, pairing_expected
);
106 void VerifyRejected(Authenticator::RejectionReason reason
) {
107 ASSERT_TRUE(client_
->state() == Authenticator::REJECTED
||
108 host_
->state() == Authenticator::REJECTED
);
109 if (client_
->state() == Authenticator::REJECTED
) {
110 ASSERT_EQ(client_
->rejection_reason(), reason
);
112 if (host_
->state() == Authenticator::REJECTED
) {
113 ASSERT_EQ(host_
->rejection_reason(), reason
);
117 void VerifyAccepted(const AuthenticationMethod
& expected_method
) {
118 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
120 ASSERT_EQ(Authenticator::ACCEPTED
, host_
->state());
121 ASSERT_EQ(Authenticator::ACCEPTED
, client_
->state());
123 client_auth_
= client_
->CreateChannelAuthenticator();
124 host_auth_
= host_
->CreateChannelAuthenticator();
125 RunChannelAuth(false);
127 EXPECT_TRUE(client_socket_
.get() != NULL
);
128 EXPECT_TRUE(host_socket_
.get() != NULL
);
130 StreamConnectionTester
tester(host_socket_
.get(), client_socket_
.get(),
131 kMessageSize
, kMessages
);
135 tester
.CheckResults();
138 client_as_negotiating_authenticator_
->current_method_for_testing());
141 // Use a bare pointer because the storage is managed by the base class.
142 NegotiatingClientAuthenticator
* client_as_negotiating_authenticator_
;
145 scoped_refptr
<PairingRegistry
> pairing_registry_
;
147 DISALLOW_COPY_AND_ASSIGN(NegotiatingAuthenticatorTest
);
150 TEST_F(NegotiatingAuthenticatorTest
, SuccessfulAuthHmac
) {
151 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
152 kNoClientId
, kNoPairedSecret
, kTestPin
, kTestPin
,
153 AuthenticationMethod::HMAC_SHA256
, false));
155 AuthenticationMethod::Spake2(AuthenticationMethod::HMAC_SHA256
));
158 TEST_F(NegotiatingAuthenticatorTest
, SuccessfulAuthPlain
) {
159 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
160 kNoClientId
, kNoPairedSecret
, kTestPin
, kTestPin
,
161 AuthenticationMethod::NONE
, false));
162 VerifyAccepted(AuthenticationMethod::Spake2(AuthenticationMethod::NONE
));
165 TEST_F(NegotiatingAuthenticatorTest
, InvalidSecretHmac
) {
166 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
167 kNoClientId
, kNoPairedSecret
, kTestPinBad
, kTestPin
,
168 AuthenticationMethod::HMAC_SHA256
, false));
169 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
171 VerifyRejected(Authenticator::INVALID_CREDENTIALS
);
174 TEST_F(NegotiatingAuthenticatorTest
, InvalidSecretPlain
) {
175 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
176 kNoClientId
, kNoPairedSecret
, kTestPin
, kTestPinBad
,
177 AuthenticationMethod::NONE
, false));
178 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
180 VerifyRejected(Authenticator::INVALID_CREDENTIALS
);
183 TEST_F(NegotiatingAuthenticatorTest
, IncompatibleMethods
) {
184 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
185 kNoClientId
, kNoPairedSecret
, kTestPin
, kTestPinBad
,
186 AuthenticationMethod::NONE
, true));
187 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
189 VerifyRejected(Authenticator::PROTOCOL_ERROR
);
192 TEST_F(NegotiatingAuthenticatorTest
, PairingNotSupported
) {
193 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
194 kTestClientId
, kTestPairedSecret
, kTestPin
, kTestPin
,
195 AuthenticationMethod::HMAC_SHA256
, false));
196 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
198 AuthenticationMethod::Spake2(AuthenticationMethod::HMAC_SHA256
));
201 TEST_F(NegotiatingAuthenticatorTest
, PairingSupportedButNotPaired
) {
202 CreatePairingRegistry(false);
203 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
204 kNoClientId
, kNoPairedSecret
, kTestPin
, kTestPin
,
205 AuthenticationMethod::HMAC_SHA256
, false));
206 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
207 VerifyAccepted(AuthenticationMethod::Spake2Pair());
210 TEST_F(NegotiatingAuthenticatorTest
, PairingRevokedPinOkay
) {
211 CreatePairingRegistry(false);
212 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
213 kTestClientId
, kTestPairedSecret
, kTestPin
, kTestPin
,
214 AuthenticationMethod::HMAC_SHA256
, false));
215 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
216 VerifyAccepted(AuthenticationMethod::Spake2Pair());
219 TEST_F(NegotiatingAuthenticatorTest
, PairingRevokedPinBad
) {
220 CreatePairingRegistry(false);
221 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
222 kTestClientId
, kTestPairedSecret
, kTestPinBad
, kTestPin
,
223 AuthenticationMethod::HMAC_SHA256
, false));
224 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
225 VerifyRejected(Authenticator::INVALID_CREDENTIALS
);
228 TEST_F(NegotiatingAuthenticatorTest
, PairingSucceeded
) {
229 CreatePairingRegistry(true);
230 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
231 kTestClientId
, kTestPairedSecret
, kTestPinBad
, kTestPin
,
232 AuthenticationMethod::HMAC_SHA256
, false));
233 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
234 VerifyAccepted(AuthenticationMethod::Spake2Pair());
237 TEST_F(NegotiatingAuthenticatorTest
, PairingSucceededInvalidSecretButPinOkay
) {
238 CreatePairingRegistry(true);
239 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
240 kTestClientId
, kTestPairedSecretBad
, kTestPin
, kTestPin
,
241 AuthenticationMethod::HMAC_SHA256
, false));
242 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
243 VerifyAccepted(AuthenticationMethod::Spake2Pair());
246 TEST_F(NegotiatingAuthenticatorTest
, PairingFailedInvalidSecretAndPin
) {
247 CreatePairingRegistry(true);
248 ASSERT_NO_FATAL_FAILURE(InitAuthenticators(
249 kTestClientId
, kTestPairedSecretBad
, kTestPinBad
, kTestPin
,
250 AuthenticationMethod::HMAC_SHA256
, false));
251 ASSERT_NO_FATAL_FAILURE(RunAuthExchange());
252 VerifyRejected(Authenticator::INVALID_CREDENTIALS
);
255 } // namespace protocol
256 } // namespace remoting