ssl_hmac_channel_authenticator_unittest.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
1d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// found in the LICENSE file. 4d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 5d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "remoting/protocol/ssl_hmac_channel_authenticator.h" 6d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 7d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "base/base64.h" 8197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "base/bind.h" 9d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "base/file_util.h" 10d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "base/files/file_path.h" 1107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "base/message_loop/message_loop.h" 12d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "base/path_service.h" 13c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "base/test/test_timeouts.h" 14d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "base/timer/timer.h" 1507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "crypto/rsa_private_key.h" 1607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "net/base/net_errors.h" 17d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "net/base/test_data_directory.h" 18d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "remoting/base/rsa_key_pair.h" 19d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "remoting/protocol/connection_tester.h" 20d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "remoting/protocol/fake_session.h" 21d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 22d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 2307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" 2407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 25323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)using testing::_; 26d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)using testing::NotNull; 27d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)using testing::SaveArg; 2807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 29d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)namespace remoting { 30d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)namespace protocol { 31d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 32d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)namespace { 33d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 34d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)const char kTestSharedSecret[] = "1234-1234-5678"; 35d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)const char kTestSharedSecretBad[] = "0000-0000-0001"; 36d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 37d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)class MockChannelDoneCallback { 38d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) public: 39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) MOCK_METHOD2(OnDone, void(net::Error error, net::StreamSocket* socket)); 40d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}; 41d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 4207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben MurdochACTION_P(QuitThreadOnCounter, counter) { 43d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) --(*counter); 4407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch EXPECT_GE(*counter, 0); 45d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (*counter == 0) 46d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::MessageLoop::current()->Quit(); 47d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 48d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 4907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch} // namespace 5007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 51323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)class SslHmacChannelAuthenticatorTest : public testing::Test { 52d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) public: 53d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) SslHmacChannelAuthenticatorTest() {} 5407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch virtual ~SslHmacChannelAuthenticatorTest() {} 55d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 56d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) protected: 5707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch virtual void SetUp() OVERRIDE { 58d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::FilePath certs_dir(net::GetTestCertsDirectory()); 5907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 6007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch base::FilePath cert_path = certs_dir.AppendASCII("unittest.selfsigned.der"); 61d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ASSERT_TRUE(file_util::ReadFileToString(cert_path, &host_cert_)); 62d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 63d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::FilePath key_path = certs_dir.AppendASCII("unittest.key.bin"); 64d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) std::string key_string; 65d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ASSERT_TRUE(file_util::ReadFileToString(key_path, &key_string)); 6607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch std::string key_base64; 67d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::Base64Encode(key_string, &key_base64); 6807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch key_pair_ = RsaKeyPair::FromString(key_base64); 69d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ASSERT_TRUE(key_pair_.get()); 70d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 71d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 72d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) void RunChannelAuth(bool expected_fail) { 7307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch client_fake_socket_.reset(new FakeSocket()); 7407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch host_fake_socket_.reset(new FakeSocket()); 75323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles) client_fake_socket_->PairWith(host_fake_socket_.get()); 76d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 77d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) client_auth_->SecureAndAuthenticate( 7807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch client_fake_socket_.PassAs<net::StreamSocket>(), 79d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::Bind(&SslHmacChannelAuthenticatorTest::OnClientConnected, 80d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::Unretained(this))); 8107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 82d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) host_auth_->SecureAndAuthenticate( 8307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch host_fake_socket_.PassAs<net::StreamSocket>(), 8407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch base::Bind(&SslHmacChannelAuthenticatorTest::OnHostConnected, 85d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::Unretained(this))); 86d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 87d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Expect two callbacks to be called - the client callback and the host 88d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // callback. 89d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) int callback_counter = 2; 9007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 91d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) if (expected_fail) { 9207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch EXPECT_CALL(client_callback_, OnDone(net::ERR_FAILED, NULL)) 93d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) .WillOnce(QuitThreadOnCounter(&callback_counter)); 94d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_CALL(host_callback_, OnDone(net::ERR_FAILED, NULL)) 9507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch .WillOnce(QuitThreadOnCounter(&callback_counter)); 96d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } else { 9707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch EXPECT_CALL(client_callback_, OnDone(net::OK, NotNull())) 98d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) .WillOnce(QuitThreadOnCounter(&callback_counter)); 99d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_CALL(host_callback_, OnDone(net::OK, NotNull())) 100d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) .WillOnce(QuitThreadOnCounter(&callback_counter)); 10107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch } 102d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 103d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Ensure that .Run() does not run unbounded if the callbacks are never 10407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch // called. 105d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::Timer shutdown_timer(false, false); 106d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) shutdown_timer.Start(FROM_HERE, 107d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) TestTimeouts::action_timeout(), 108d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::MessageLoop::QuitClosure()); 10907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch message_loop_.Run(); 110d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 111d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 11207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch void OnHostConnected(net::Error error, 11307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch scoped_ptr<net::StreamSocket> socket) { 11407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch host_callback_.OnDone(error, socket.get()); 115d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) host_socket_ = socket.Pass(); 116d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 11707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 11807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch void OnClientConnected(net::Error error, 119d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) scoped_ptr<net::StreamSocket> socket) { 12007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch client_callback_.OnDone(error, socket.get()); 121d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) client_socket_ = socket.Pass(); 122d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 123d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 124d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) base::MessageLoop message_loop_; 125d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 12607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch scoped_refptr<RsaKeyPair> key_pair_; 127d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) std::string host_cert_; 128d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) scoped_ptr<FakeSocket> client_fake_socket_; 12907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch scoped_ptr<FakeSocket> host_fake_socket_; 130d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) scoped_ptr<ChannelAuthenticator> client_auth_; 131d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) scoped_ptr<ChannelAuthenticator> host_auth_; 132d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) MockChannelDoneCallback client_callback_; 13307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch MockChannelDoneCallback host_callback_; 134d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) scoped_ptr<net::StreamSocket> client_socket_; 135d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) scoped_ptr<net::StreamSocket> host_socket_; 136d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 137d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SslHmacChannelAuthenticatorTest); 138d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}; 13907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 140d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Verify that a channel can be connected using a valid shared secret. 14107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben MurdochTEST_F(SslHmacChannelAuthenticatorTest, SuccessfulAuth) { 142d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) client_auth_ = SslHmacChannelAuthenticator::CreateForClient( 143d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) host_cert_, kTestSharedSecret); 144d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) host_auth_ = SslHmacChannelAuthenticator::CreateForHost( 145d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) host_cert_, key_pair_, kTestSharedSecret); 14607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 14707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch RunChannelAuth(false); 14807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 149d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ASSERT_TRUE(client_socket_.get() != NULL); 150d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ASSERT_TRUE(host_socket_.get() != NULL); 15107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 15207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), 153d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 100, 2); 15407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch 155d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) tester.Start(); 15607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch message_loop_.Run(); 15707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch tester.CheckResults(); 158d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 159d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 160d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Verify that channels cannot be using invalid shared secret. 161d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)TEST_F(SslHmacChannelAuthenticatorTest, InvalidChannelSecret) { 162d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) client_auth_ = SslHmacChannelAuthenticator::CreateForClient( 163d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) host_cert_, kTestSharedSecretBad); 164d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) host_auth_ = SslHmacChannelAuthenticator::CreateForHost( 165d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) host_cert_, key_pair_, kTestSharedSecret); 166d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 167d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) RunChannelAuth(true); 168 169 ASSERT_TRUE(host_socket_.get() == NULL); 170} 171 172} // namespace protocol 173} // namespace remoting 174