1 // Copyright 2013 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/fake_authenticator.h" 12 #include "remoting/protocol/third_party_authenticator_base.h" 13 #include "remoting/protocol/third_party_client_authenticator.h" 14 #include "remoting/protocol/third_party_host_authenticator.h" 15 #include "remoting/protocol/token_validator.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 { 25 26 const int kMessageSize = 100; 27 const int kMessages = 1; 28 29 const char kTokenUrl[] = "https://example.com/Issue"; 30 const char kTokenScope[] = "host:a (at) b.com/1 client:a (at) b.com/2"; 31 const char kToken[] = "abc123456xyz789"; 32 const char kSharedSecret[] = "1234-1234-5678"; 33 const char kSharedSecretBad[] = "0000-0000-0001"; 34 35 } // namespace 36 37 namespace remoting { 38 namespace protocol { 39 40 class ThirdPartyAuthenticatorTest : public AuthenticatorTestBase { 41 class FakeTokenFetcher : public ThirdPartyClientAuthenticator::TokenFetcher { 42 public: 43 virtual void FetchThirdPartyToken( 44 const GURL& token_url, 45 const std::string& scope, 46 const TokenFetchedCallback& token_fetched_callback) OVERRIDE { 47 ASSERT_EQ(token_url.spec(), kTokenUrl); 48 ASSERT_EQ(scope, kTokenScope); 49 ASSERT_FALSE(token_fetched_callback.is_null()); 50 on_token_fetched_ = token_fetched_callback; 51 } 52 53 void OnTokenFetched(const std::string& token, 54 const std::string& shared_secret) { 55 ASSERT_FALSE(on_token_fetched_.is_null()); 56 TokenFetchedCallback on_token_fetched = on_token_fetched_; 57 on_token_fetched_.Reset(); 58 on_token_fetched.Run(token, shared_secret); 59 } 60 61 private: 62 TokenFetchedCallback on_token_fetched_; 63 }; 64 65 class FakeTokenValidator : public TokenValidator { 66 public: 67 FakeTokenValidator() 68 : token_url_(kTokenUrl), 69 token_scope_(kTokenScope) {} 70 71 virtual ~FakeTokenValidator() {} 72 73 virtual void ValidateThirdPartyToken( 74 const std::string& token, 75 const TokenValidatedCallback& token_validated_callback) OVERRIDE { 76 ASSERT_FALSE(token_validated_callback.is_null()); 77 on_token_validated_ = token_validated_callback; 78 } 79 80 void OnTokenValidated(const std::string& shared_secret) { 81 ASSERT_FALSE(on_token_validated_.is_null()); 82 TokenValidatedCallback on_token_validated = on_token_validated_; 83 on_token_validated_.Reset(); 84 on_token_validated.Run(shared_secret); 85 } 86 87 virtual const GURL& token_url() const OVERRIDE { 88 return token_url_; 89 } 90 91 virtual const std::string& token_scope() const OVERRIDE { 92 return token_scope_; 93 } 94 95 private: 96 GURL token_url_; 97 std::string token_scope_; 98 base::Callback<void(const std::string& shared_secret)> on_token_validated_; 99 }; 100 101 public: 102 ThirdPartyAuthenticatorTest() {} 103 virtual ~ThirdPartyAuthenticatorTest() {} 104 105 protected: 106 void InitAuthenticators() { 107 scoped_ptr<TokenValidator> token_validator(new FakeTokenValidator()); 108 token_validator_ = static_cast<FakeTokenValidator*>(token_validator.get()); 109 host_.reset(new ThirdPartyHostAuthenticator( 110 host_cert_, key_pair_, token_validator.Pass())); 111 scoped_ptr<ThirdPartyClientAuthenticator::TokenFetcher> 112 token_fetcher(new FakeTokenFetcher()); 113 token_fetcher_ = static_cast<FakeTokenFetcher*>(token_fetcher.get()); 114 client_.reset(new ThirdPartyClientAuthenticator(token_fetcher.Pass())); 115 } 116 117 FakeTokenFetcher* token_fetcher_; 118 FakeTokenValidator* token_validator_; 119 120 private: 121 DISALLOW_COPY_AND_ASSIGN(ThirdPartyAuthenticatorTest); 122 }; 123 124 // These tests use net::SSLServerSocket which is not implemented for OpenSSL. 125 #if defined(USE_OPENSSL) 126 #define MAYBE(x) DISABLED_##x 127 #else 128 #define MAYBE(x) x 129 #endif 130 131 TEST_F(ThirdPartyAuthenticatorTest, MAYBE(SuccessfulAuth)) { 132 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 133 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 134 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 135 ASSERT_NO_FATAL_FAILURE(token_fetcher_->OnTokenFetched( 136 kToken, kSharedSecret)); 137 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 138 ASSERT_NO_FATAL_FAILURE( 139 token_validator_->OnTokenValidated(kSharedSecret)); 140 141 // Both sides have finished. 142 ASSERT_EQ(Authenticator::ACCEPTED, host_->state()); 143 ASSERT_EQ(Authenticator::ACCEPTED, client_->state()); 144 145 // An authenticated channel can be created after the authentication. 146 client_auth_ = client_->CreateChannelAuthenticator(); 147 host_auth_ = host_->CreateChannelAuthenticator(); 148 RunChannelAuth(false); 149 150 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), 151 kMessageSize, kMessages); 152 153 tester.Start(); 154 message_loop_.Run(); 155 tester.CheckResults(); 156 } 157 158 TEST_F(ThirdPartyAuthenticatorTest, MAYBE(ClientNoSecret)) { 159 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 160 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 161 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 162 ASSERT_NO_FATAL_FAILURE( 163 token_fetcher_->OnTokenFetched(kToken, std::string())); 164 165 // The end result is that the client rejected the connection, since it 166 // couldn't fetch the secret. 167 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 168 } 169 170 TEST_F(ThirdPartyAuthenticatorTest, MAYBE(InvalidToken)) { 171 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 172 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 173 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 174 ASSERT_NO_FATAL_FAILURE(token_fetcher_->OnTokenFetched( 175 kToken, kSharedSecret)); 176 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 177 ASSERT_NO_FATAL_FAILURE(token_validator_->OnTokenValidated(std::string())); 178 179 // The end result is that the host rejected the token. 180 ASSERT_EQ(Authenticator::REJECTED, host_->state()); 181 } 182 183 TEST_F(ThirdPartyAuthenticatorTest, MAYBE(CannotFetchToken)) { 184 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 185 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 186 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 187 ASSERT_NO_FATAL_FAILURE( 188 token_fetcher_->OnTokenFetched(std::string(), std::string())); 189 190 // The end result is that the client rejected the connection, since it 191 // couldn't fetch the token. 192 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 193 } 194 195 // Test that negotiation stops when the fake authentication is rejected. 196 TEST_F(ThirdPartyAuthenticatorTest, MAYBE(HostBadSecret)) { 197 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 198 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 199 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 200 ASSERT_NO_FATAL_FAILURE(token_fetcher_->OnTokenFetched( 201 kToken, kSharedSecret)); 202 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 203 ASSERT_NO_FATAL_FAILURE( 204 token_validator_->OnTokenValidated(kSharedSecretBad)); 205 206 // The end result is that the host rejected the fake authentication. 207 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 208 } 209 210 TEST_F(ThirdPartyAuthenticatorTest, MAYBE(ClientBadSecret)) { 211 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 212 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 213 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 214 ASSERT_NO_FATAL_FAILURE( 215 token_fetcher_->OnTokenFetched(kToken, kSharedSecretBad)); 216 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 217 ASSERT_NO_FATAL_FAILURE( 218 token_validator_->OnTokenValidated(kSharedSecret)); 219 220 // The end result is that the host rejected the fake authentication. 221 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 222 } 223 224 } // namespace protocol 225 } // namespace remoting 226