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 20 using testing::_; 21 using testing::DeleteArg; 22 using testing::SaveArg; 23 24 namespace remoting { 25 namespace protocol { 26 27 namespace { 28 29 const int kMessageSize = 100; 30 const int kMessages = 1; 31 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"; 37 38 const char kTestPairedSecret[] = "1111-2222-3333"; 39 const char kTestPairedSecretBad[] = "4444-5555-6666"; 40 const char kTestPin[] = "123456"; 41 const char kTestPinBad[] = "654321"; 42 43 } // namespace 44 45 class 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 150 // These tests use net::SSLServerSocket which is not implemented for OpenSSL. 151 #if defined(USE_OPENSSL) 152 #define MAYBE(x) DISABLED_##x 153 #else 154 #define MAYBE(x) x 155 #endif 156 157 TEST_F(NegotiatingAuthenticatorTest, MAYBE(SuccessfulAuthHmac)) { 158 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 159 kNoClientId, kNoPairedSecret, kTestPin, kTestPin, 160 AuthenticationMethod::HMAC_SHA256, false)); 161 VerifyAccepted( 162 AuthenticationMethod::Spake2(AuthenticationMethod::HMAC_SHA256)); 163 } 164 165 TEST_F(NegotiatingAuthenticatorTest, MAYBE(SuccessfulAuthPlain)) { 166 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 167 kNoClientId, kNoPairedSecret, kTestPin, kTestPin, 168 AuthenticationMethod::NONE, false)); 169 VerifyAccepted(AuthenticationMethod::Spake2(AuthenticationMethod::NONE)); 170 } 171 172 TEST_F(NegotiatingAuthenticatorTest, MAYBE(InvalidSecretHmac)) { 173 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 174 kNoClientId, kNoPairedSecret, kTestPinBad, kTestPin, 175 AuthenticationMethod::HMAC_SHA256, false)); 176 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 177 178 VerifyRejected(Authenticator::INVALID_CREDENTIALS); 179 } 180 181 TEST_F(NegotiatingAuthenticatorTest, MAYBE(InvalidSecretPlain)) { 182 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 183 kNoClientId, kNoPairedSecret, kTestPin, kTestPinBad, 184 AuthenticationMethod::NONE, false)); 185 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 186 187 VerifyRejected(Authenticator::INVALID_CREDENTIALS); 188 } 189 190 TEST_F(NegotiatingAuthenticatorTest, MAYBE(IncompatibleMethods)) { 191 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 192 kNoClientId, kNoPairedSecret, kTestPin, kTestPinBad, 193 AuthenticationMethod::NONE, true)); 194 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 195 196 VerifyRejected(Authenticator::PROTOCOL_ERROR); 197 } 198 199 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingNotSupported)) { 200 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 201 kTestClientId, kTestPairedSecret, kTestPin, kTestPin, 202 AuthenticationMethod::HMAC_SHA256, false)); 203 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 204 VerifyAccepted( 205 AuthenticationMethod::Spake2(AuthenticationMethod::HMAC_SHA256)); 206 } 207 208 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingSupportedButNotPaired)) { 209 CreatePairingRegistry(false); 210 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 211 kNoClientId, kNoPairedSecret, kTestPin, kTestPin, 212 AuthenticationMethod::HMAC_SHA256, false)); 213 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 214 VerifyAccepted(AuthenticationMethod::Spake2Pair()); 215 } 216 217 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingRevokedPinOkay)) { 218 CreatePairingRegistry(false); 219 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 220 kTestClientId, kTestPairedSecret, kTestPin, kTestPin, 221 AuthenticationMethod::HMAC_SHA256, false)); 222 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 223 VerifyAccepted(AuthenticationMethod::Spake2Pair()); 224 } 225 226 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingRevokedPinBad)) { 227 CreatePairingRegistry(false); 228 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 229 kTestClientId, kTestPairedSecret, kTestPinBad, kTestPin, 230 AuthenticationMethod::HMAC_SHA256, false)); 231 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 232 VerifyRejected(Authenticator::INVALID_CREDENTIALS); 233 } 234 235 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingSucceeded)) { 236 CreatePairingRegistry(true); 237 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 238 kTestClientId, kTestPairedSecret, kTestPinBad, kTestPin, 239 AuthenticationMethod::HMAC_SHA256, false)); 240 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 241 VerifyAccepted(AuthenticationMethod::Spake2Pair()); 242 } 243 244 TEST_F(NegotiatingAuthenticatorTest, 245 MAYBE(PairingSucceededInvalidSecretButPinOkay)) { 246 CreatePairingRegistry(true); 247 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 248 kTestClientId, kTestPairedSecretBad, kTestPin, kTestPin, 249 AuthenticationMethod::HMAC_SHA256, false)); 250 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 251 VerifyAccepted(AuthenticationMethod::Spake2Pair()); 252 } 253 254 TEST_F(NegotiatingAuthenticatorTest, MAYBE(PairingFailedInvalidSecretAndPin)) { 255 CreatePairingRegistry(true); 256 ASSERT_NO_FATAL_FAILURE(InitAuthenticators( 257 kTestClientId, kTestPairedSecretBad, kTestPinBad, kTestPin, 258 AuthenticationMethod::HMAC_SHA256, false)); 259 ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); 260 VerifyRejected(Authenticator::INVALID_CREDENTIALS); 261 } 262 263 } // namespace protocol 264 } // namespace remoting 265