// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "remoting/protocol/negotiating_authenticator.h" #include "base/bind.h" #include "net/base/net_errors.h" #include "remoting/protocol/authenticator_test_base.h" #include "remoting/protocol/channel_authenticator.h" #include "remoting/protocol/connection_tester.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" using testing::_; using testing::DeleteArg; using testing::SaveArg; namespace remoting { namespace protocol { namespace { const int kMessageSize = 100; const int kMessages = 1; const char kTestHostId[] = "12345678910123456"; const char kTestSharedSecret[] = "1234-1234-5678"; const char kTestSharedSecretBad[] = "0000-0000-0001"; } // namespace class NegotiatingAuthenticatorTest : public AuthenticatorTestBase { public: NegotiatingAuthenticatorTest() { } virtual ~NegotiatingAuthenticatorTest() { } protected: void InitAuthenticators( const std::string& client_secret, const std::string& host_secret, AuthenticationMethod::HashFunction hash_function, bool client_hmac_only) { std::string host_secret_hash = AuthenticationMethod::ApplyHashFunction( hash_function, kTestHostId, host_secret); host_ = NegotiatingAuthenticator::CreateForHost( host_cert_, *private_key_, host_secret_hash, hash_function); std::vector methods; methods.push_back(AuthenticationMethod::Spake2( AuthenticationMethod::HMAC_SHA256)); if (!client_hmac_only) { methods.push_back(AuthenticationMethod::Spake2( AuthenticationMethod::NONE)); } client_ = NegotiatingAuthenticator::CreateForClient( kTestHostId, client_secret, methods); } void VerifyRejected(Authenticator::RejectionReason reason) { ASSERT_TRUE((client_->state() == Authenticator::REJECTED && (client_->rejection_reason() == reason)) || (host_->state() == Authenticator::REJECTED && (host_->rejection_reason() == reason))); } DISALLOW_COPY_AND_ASSIGN(NegotiatingAuthenticatorTest); }; TEST_F(NegotiatingAuthenticatorTest, SuccessfulAuthHmac) { ASSERT_NO_FATAL_FAILURE(InitAuthenticators( kTestSharedSecret, kTestSharedSecret, AuthenticationMethod::HMAC_SHA256, false)); ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); ASSERT_EQ(Authenticator::ACCEPTED, host_->state()); ASSERT_EQ(Authenticator::ACCEPTED, client_->state()); client_auth_ = client_->CreateChannelAuthenticator(); host_auth_ = host_->CreateChannelAuthenticator(); RunChannelAuth(false); EXPECT_TRUE(client_socket_.get() != NULL); EXPECT_TRUE(host_socket_.get() != NULL); StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), kMessageSize, kMessages); tester.Start(); message_loop_.Run(); tester.CheckResults(); } TEST_F(NegotiatingAuthenticatorTest, SuccessfulAuthPlain) { ASSERT_NO_FATAL_FAILURE(InitAuthenticators( kTestSharedSecret, kTestSharedSecret, AuthenticationMethod::NONE, false)); ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); ASSERT_EQ(Authenticator::ACCEPTED, host_->state()); ASSERT_EQ(Authenticator::ACCEPTED, client_->state()); client_auth_ = client_->CreateChannelAuthenticator(); host_auth_ = host_->CreateChannelAuthenticator(); RunChannelAuth(false); EXPECT_TRUE(client_socket_.get() != NULL); EXPECT_TRUE(host_socket_.get() != NULL); StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), kMessageSize, kMessages); tester.Start(); message_loop_.Run(); tester.CheckResults(); } TEST_F(NegotiatingAuthenticatorTest, InvalidSecretHmac) { ASSERT_NO_FATAL_FAILURE(InitAuthenticators( kTestSharedSecret, kTestSharedSecretBad, AuthenticationMethod::HMAC_SHA256, false)); ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); VerifyRejected(Authenticator::INVALID_CREDENTIALS); } TEST_F(NegotiatingAuthenticatorTest, InvalidSecretPlain) { ASSERT_NO_FATAL_FAILURE(InitAuthenticators( kTestSharedSecret, kTestSharedSecretBad, AuthenticationMethod::NONE, false)); ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); VerifyRejected(Authenticator::INVALID_CREDENTIALS); } TEST_F(NegotiatingAuthenticatorTest, IncompatibleMethods) { ASSERT_NO_FATAL_FAILURE(InitAuthenticators( kTestSharedSecret, kTestSharedSecretBad, AuthenticationMethod::NONE, true)); ASSERT_NO_FATAL_FAILURE(RunAuthExchange()); VerifyRejected(Authenticator::PROTOCOL_ERROR); } } // namespace protocol } // namespace remoting