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. 4 5#include "base/bind.h" 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" 19 20using testing::_; 21using testing::DeleteArg; 22using testing::SaveArg; 23 24namespace remoting { 25namespace protocol { 26 27namespace { 28 29const int kMessageSize = 100; 30const int kMessages = 1; 31 32const char kNoClientId[] = ""; 33const char kNoPairedSecret[] = ""; 34const char kTestClientName[] = "client-name"; 35const char kTestClientId[] = "client-id"; 36const char kTestHostId[] = "12345678910123456"; 37 38const char kTestPairedSecret[] = "1111-2222-3333"; 39const char kTestPairedSecretBad[] = "4444-5555-6666"; 40const char kTestPin[] = "123456"; 41const char kTestPinBad[] = "654321"; 42 43} // namespace 44 45class NegotiatingAuthenticatorTest : public AuthenticatorTestBase { 46 public: 47 NegotiatingAuthenticatorTest() { 48 } 49 virtual ~NegotiatingAuthenticatorTest() { 50 } 51 52 protected: 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, 64 pairing_registry_); 65 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)); 73 } 74 bool pairing_expected = pairing_registry_.get() != NULL; 75 FetchSecretCallback fetch_secret_callback = 76 base::Bind(&NegotiatingAuthenticatorTest::FetchSecret, 77 client_interactive_pin, 78 pairing_expected); 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_); 84 } 85 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); 94 } 95 } 96 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); 104 } 105 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); 111 } 112 if (host_->state() == Authenticator::REJECTED) { 113 ASSERT_EQ(host_->rejection_reason(), reason); 114 } 115 } 116 117 void VerifyAccepted(const AuthenticationMethod& expected_method) { 118 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 119 120 ASSERT_EQ(Authenticator::ACCEPTED, host_->state()); 121 ASSERT_EQ(Authenticator::ACCEPTED, client_->state()); 122 123 client_auth_ = client_->CreateChannelAuthenticator(); 124 host_auth_ = host_->CreateChannelAuthenticator(); 125 RunChannelAuth(false); 126 127 EXPECT_TRUE(client_socket_.get() != NULL); 128 EXPECT_TRUE(host_socket_.get() != NULL); 129 130 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), 131 kMessageSize, kMessages); 132 133 tester.Start(); 134 message_loop_.Run(); 135 tester.CheckResults(); 136 EXPECT_EQ( 137 expected_method, 138 client_as_negotiating_authenticator_->current_method_for_testing()); 139 } 140 141 // Use a bare pointer because the storage is managed by the base class. 142 NegotiatingClientAuthenticator* client_as_negotiating_authenticator_; 143 144 private: 145 scoped_refptr<PairingRegistry> pairing_registry_; 146 147 DISALLOW_COPY_AND_ASSIGN(NegotiatingAuthenticatorTest); 148}; 149 150TEST_F(NegotiatingAuthenticatorTest, SuccessfulAuthHmac) { 151 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 152 kNoClientId, kNoPairedSecret, kTestPin, kTestPin, 153 AuthenticationMethod::HMAC_SHA256, false)); 154 VerifyAccepted( 155 AuthenticationMethod::Spake2(AuthenticationMethod::HMAC_SHA256)); 156} 157 158TEST_F(NegotiatingAuthenticatorTest, SuccessfulAuthPlain) { 159 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 160 kNoClientId, kNoPairedSecret, kTestPin, kTestPin, 161 AuthenticationMethod::NONE, false)); 162 VerifyAccepted(AuthenticationMethod::Spake2(AuthenticationMethod::NONE)); 163} 164 165TEST_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()); 170 171 VerifyRejected(Authenticator::INVALID_CREDENTIALS); 172} 173 174TEST_F(NegotiatingAuthenticatorTest, InvalidSecretPlain) { 175 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 176 kNoClientId, kNoPairedSecret, kTestPin, kTestPinBad, 177 AuthenticationMethod::NONE, false)); 178 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 179 180 VerifyRejected(Authenticator::INVALID_CREDENTIALS); 181} 182 183TEST_F(NegotiatingAuthenticatorTest, IncompatibleMethods) { 184 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 185 kNoClientId, kNoPairedSecret, kTestPin, kTestPinBad, 186 AuthenticationMethod::NONE, true)); 187 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 188 189 VerifyRejected(Authenticator::PROTOCOL_ERROR); 190} 191 192TEST_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()); 197 VerifyAccepted( 198 AuthenticationMethod::Spake2(AuthenticationMethod::HMAC_SHA256)); 199} 200 201TEST_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()); 208} 209 210TEST_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()); 217} 218 219TEST_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); 226} 227 228TEST_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()); 235} 236 237TEST_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()); 244} 245 246TEST_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); 253} 254 255} // namespace protocol 256} // namespace remoting 257