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 "testing/gmock/include/gmock/gmock.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" 18 19 using testing::_; 20 using testing::DeleteArg; 21 using testing::SaveArg; 22 23 namespace { 24 25 const int kMessageSize = 100; 26 const int kMessages = 1; 27 28 const char kTokenUrl[] = "https://example.com/Issue"; 29 const char kTokenScope[] = "host:a (at) b.com/1 client:a (at) b.com/2"; 30 const char kToken[] = "abc123456xyz789"; 31 const char kSharedSecret[] = "1234-1234-5678"; 32 const char kSharedSecretBad[] = "0000-0000-0001"; 33 34 } // namespace 35 36 namespace remoting { 37 namespace protocol { 38 39 class ThirdPartyAuthenticatorTest : public AuthenticatorTestBase { 40 class FakeTokenFetcher : public ThirdPartyClientAuthenticator::TokenFetcher { 41 public: 42 virtual void FetchThirdPartyToken( 43 const GURL& token_url, 44 const std::string& scope, 45 const TokenFetchedCallback& token_fetched_callback) OVERRIDE { 46 ASSERT_EQ(token_url.spec(), kTokenUrl); 47 ASSERT_EQ(scope, kTokenScope); 48 ASSERT_FALSE(token_fetched_callback.is_null()); 49 on_token_fetched_ = token_fetched_callback; 50 } 51 52 void OnTokenFetched(const std::string& token, 53 const std::string& shared_secret) { 54 ASSERT_FALSE(on_token_fetched_.is_null()); 55 TokenFetchedCallback on_token_fetched = on_token_fetched_; 56 on_token_fetched_.Reset(); 57 on_token_fetched.Run(token, shared_secret); 58 } 59 60 private: 61 TokenFetchedCallback on_token_fetched_; 62 }; 63 64 class FakeTokenValidator 65 : public ThirdPartyHostAuthenticator::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<ThirdPartyHostAuthenticator::TokenValidator> 108 token_validator(new FakeTokenValidator()); 109 token_validator_ = static_cast<FakeTokenValidator*>(token_validator.get()); 110 host_.reset(new ThirdPartyHostAuthenticator( 111 host_cert_, key_pair_, token_validator.Pass())); 112 scoped_ptr<ThirdPartyClientAuthenticator::TokenFetcher> 113 token_fetcher(new FakeTokenFetcher()); 114 token_fetcher_ = static_cast<FakeTokenFetcher*>(token_fetcher.get()); 115 client_.reset(new ThirdPartyClientAuthenticator(token_fetcher.Pass())); 116 } 117 118 FakeTokenFetcher* token_fetcher_; 119 FakeTokenValidator* token_validator_; 120 121 private: 122 DISALLOW_COPY_AND_ASSIGN(ThirdPartyAuthenticatorTest); 123 }; 124 125 TEST_F(ThirdPartyAuthenticatorTest, SuccessfulAuth) { 126 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 127 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 128 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 129 ASSERT_NO_FATAL_FAILURE(token_fetcher_->OnTokenFetched( 130 kToken, kSharedSecret)); 131 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 132 ASSERT_NO_FATAL_FAILURE( 133 token_validator_->OnTokenValidated(kSharedSecret)); 134 135 // Both sides have finished. 136 ASSERT_EQ(Authenticator::ACCEPTED, host_->state()); 137 ASSERT_EQ(Authenticator::ACCEPTED, client_->state()); 138 139 // An authenticated channel can be created after the authentication. 140 client_auth_ = client_->CreateChannelAuthenticator(); 141 host_auth_ = host_->CreateChannelAuthenticator(); 142 RunChannelAuth(false); 143 144 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), 145 kMessageSize, kMessages); 146 147 tester.Start(); 148 message_loop_.Run(); 149 tester.CheckResults(); 150 } 151 152 TEST_F(ThirdPartyAuthenticatorTest, ClientNoSecret) { 153 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 154 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 155 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 156 ASSERT_NO_FATAL_FAILURE( 157 token_fetcher_->OnTokenFetched(kToken, std::string())); 158 159 // The end result is that the client rejected the connection, since it 160 // couldn't fetch the secret. 161 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 162 } 163 164 TEST_F(ThirdPartyAuthenticatorTest, InvalidToken) { 165 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 166 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 167 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 168 ASSERT_NO_FATAL_FAILURE(token_fetcher_->OnTokenFetched( 169 kToken, kSharedSecret)); 170 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 171 ASSERT_NO_FATAL_FAILURE(token_validator_->OnTokenValidated(std::string())); 172 173 // The end result is that the host rejected the token. 174 ASSERT_EQ(Authenticator::REJECTED, host_->state()); 175 } 176 177 TEST_F(ThirdPartyAuthenticatorTest, CannotFetchToken) { 178 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 179 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 180 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 181 ASSERT_NO_FATAL_FAILURE( 182 token_fetcher_->OnTokenFetched(std::string(), std::string())); 183 184 // The end result is that the client rejected the connection, since it 185 // couldn't fetch the token. 186 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 187 } 188 189 // Test that negotiation stops when the fake authentication is rejected. 190 TEST_F(ThirdPartyAuthenticatorTest, HostBadSecret) { 191 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 192 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 193 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 194 ASSERT_NO_FATAL_FAILURE(token_fetcher_->OnTokenFetched( 195 kToken, kSharedSecret)); 196 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 197 ASSERT_NO_FATAL_FAILURE( 198 token_validator_->OnTokenValidated(kSharedSecretBad)); 199 200 // The end result is that the host rejected the fake authentication. 201 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 202 } 203 204 TEST_F(ThirdPartyAuthenticatorTest, ClientBadSecret) { 205 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 206 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 207 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 208 ASSERT_NO_FATAL_FAILURE( 209 token_fetcher_->OnTokenFetched(kToken, kSharedSecretBad)); 210 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 211 ASSERT_NO_FATAL_FAILURE( 212 token_validator_->OnTokenValidated(kSharedSecret)); 213 214 // The end result is that the host rejected the fake authentication. 215 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 216 } 217 218 } // namespace protocol 219 } // namespace remoting 220