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/webrtc/libjingle/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 TEST_F(ThirdPartyAuthenticatorTest, SuccessfulAuth) { 125 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 126 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 127 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 128 ASSERT_NO_FATAL_FAILURE(token_fetcher_->OnTokenFetched( 129 kToken, kSharedSecret)); 130 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 131 ASSERT_NO_FATAL_FAILURE( 132 token_validator_->OnTokenValidated(kSharedSecret)); 133 134 // Both sides have finished. 135 ASSERT_EQ(Authenticator::ACCEPTED, host_->state()); 136 ASSERT_EQ(Authenticator::ACCEPTED, client_->state()); 137 138 // An authenticated channel can be created after the authentication. 139 client_auth_ = client_->CreateChannelAuthenticator(); 140 host_auth_ = host_->CreateChannelAuthenticator(); 141 RunChannelAuth(false); 142 143 StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), 144 kMessageSize, kMessages); 145 146 tester.Start(); 147 message_loop_.Run(); 148 tester.CheckResults(); 149 } 150 151 TEST_F(ThirdPartyAuthenticatorTest, ClientNoSecret) { 152 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 153 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 154 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 155 ASSERT_NO_FATAL_FAILURE( 156 token_fetcher_->OnTokenFetched(kToken, std::string())); 157 158 // The end result is that the client rejected the connection, since it 159 // couldn't fetch the secret. 160 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 161 } 162 163 TEST_F(ThirdPartyAuthenticatorTest, InvalidToken) { 164 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 165 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 166 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 167 ASSERT_NO_FATAL_FAILURE(token_fetcher_->OnTokenFetched( 168 kToken, kSharedSecret)); 169 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 170 ASSERT_NO_FATAL_FAILURE(token_validator_->OnTokenValidated(std::string())); 171 172 // The end result is that the host rejected the token. 173 ASSERT_EQ(Authenticator::REJECTED, host_->state()); 174 } 175 176 TEST_F(ThirdPartyAuthenticatorTest, CannotFetchToken) { 177 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 178 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 179 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 180 ASSERT_NO_FATAL_FAILURE( 181 token_fetcher_->OnTokenFetched(std::string(), std::string())); 182 183 // The end result is that the client rejected the connection, since it 184 // couldn't fetch the token. 185 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 186 } 187 188 // Test that negotiation stops when the fake authentication is rejected. 189 TEST_F(ThirdPartyAuthenticatorTest, HostBadSecret) { 190 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 191 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 192 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 193 ASSERT_NO_FATAL_FAILURE(token_fetcher_->OnTokenFetched( 194 kToken, kSharedSecret)); 195 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 196 ASSERT_NO_FATAL_FAILURE( 197 token_validator_->OnTokenValidated(kSharedSecretBad)); 198 199 // The end result is that the host rejected the fake authentication. 200 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 201 } 202 203 TEST_F(ThirdPartyAuthenticatorTest, ClientBadSecret) { 204 ASSERT_NO_FATAL_FAILURE(InitAuthenticators()); 205 ASSERT_NO_FATAL_FAILURE(RunHostInitiatedAuthExchange()); 206 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, client_->state()); 207 ASSERT_NO_FATAL_FAILURE( 208 token_fetcher_->OnTokenFetched(kToken, kSharedSecretBad)); 209 ASSERT_EQ(Authenticator::PROCESSING_MESSAGE, host_->state()); 210 ASSERT_NO_FATAL_FAILURE( 211 token_validator_->OnTokenValidated(kSharedSecret)); 212 213 // The end result is that the host rejected the fake authentication. 214 ASSERT_EQ(Authenticator::REJECTED, client_->state()); 215 } 216 217 } // namespace protocol 218 } // namespace remoting 219