ssl_hmac_channel_authenticator_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/ssl_hmac_channel_authenticator.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/base64.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_timeouts.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/timer.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/rsa_private_key.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_data_directory.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/base/rsa_key_pair.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/connection_tester.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/fake_session.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::_;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::NotNull;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::SaveArg;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protocol {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTestSharedSecret[] = "1234-1234-5678";
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kTestSharedSecretBad[] = "0000-0000-0001";
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockChannelDoneCallback {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD2(OnDone, void(net::Error error, net::StreamSocket* socket));
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(QuitThreadOnCounter, counter) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --(*counter);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(*counter, 0);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*counter == 0)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoop::current()->Quit();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SslHmacChannelAuthenticatorTest : public testing::Test {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SslHmacChannelAuthenticatorTest() {}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SslHmacChannelAuthenticatorTest() {}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath certs_dir(net::GetTestCertsDirectory());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath cert_path = certs_dir.AppendASCII("unittest.selfsigned.der");
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(file_util::ReadFileToString(cert_path, &host_cert_));
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath key_path = certs_dir.AppendASCII("unittest.key.bin");
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string key_string;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(file_util::ReadFileToString(key_path, &key_string));
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string key_base64;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Base64Encode(key_string, &key_base64);
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    key_pair_ = RsaKeyPair::FromString(key_base64);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_TRUE(key_pair_);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunChannelAuth(bool expected_fail) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_fake_socket_.reset(new FakeSocket());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_fake_socket_.reset(new FakeSocket());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_fake_socket_->PairWith(host_fake_socket_.get());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_auth_->SecureAndAuthenticate(
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        client_fake_socket_.PassAs<net::StreamSocket>(),
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&SslHmacChannelAuthenticatorTest::OnClientConnected,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_auth_->SecureAndAuthenticate(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        host_fake_socket_.PassAs<net::StreamSocket>(),
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&SslHmacChannelAuthenticatorTest::OnHostConnected,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Expect two callbacks to be called - the client callback and the host
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // callback.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int callback_counter = 2;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected_fail) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_CALL(client_callback_, OnDone(net::ERR_FAILED, NULL))
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          .WillOnce(QuitThreadOnCounter(&callback_counter));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_CALL(host_callback_, OnDone(net::ERR_FAILED, NULL))
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          .WillOnce(QuitThreadOnCounter(&callback_counter));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_CALL(client_callback_, OnDone(net::OK, NotNull()))
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          .WillOnce(QuitThreadOnCounter(&callback_counter));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_CALL(host_callback_, OnDone(net::OK, NotNull()))
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          .WillOnce(QuitThreadOnCounter(&callback_counter));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure that .Run() does not run unbounded if the callbacks are never
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // called.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Timer shutdown_timer(false, false);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    shutdown_timer.Start(FROM_HERE, TestTimeouts::action_timeout(),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         MessageLoop::QuitClosure());
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_loop_.Run();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnHostConnected(net::Error error,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       scoped_ptr<net::StreamSocket> socket) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_callback_.OnDone(error, socket.get());
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_socket_ = socket.Pass();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnClientConnected(net::Error error,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         scoped_ptr<net::StreamSocket> socket) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_callback_.OnDone(error, socket.get());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_socket_ = socket.Pass();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop message_loop_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<RsaKeyPair> key_pair_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string host_cert_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<FakeSocket> client_fake_socket_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<FakeSocket> host_fake_socket_;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ChannelAuthenticator> client_auth_;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ChannelAuthenticator> host_auth_;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockChannelDoneCallback client_callback_;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockChannelDoneCallback host_callback_;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<net::StreamSocket> client_socket_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<net::StreamSocket> host_socket_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SslHmacChannelAuthenticatorTest);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that a channel can be connected using a valid shared secret.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SslHmacChannelAuthenticatorTest, SuccessfulAuth) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_auth_ = SslHmacChannelAuthenticator::CreateForClient(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_cert_, kTestSharedSecret);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host_auth_ = SslHmacChannelAuthenticator::CreateForHost(
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_cert_, key_pair_, kTestSharedSecret);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunChannelAuth(false);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(client_socket_.get() != NULL);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(host_socket_.get() != NULL);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                100, 2);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester.Start();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop_.Run();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester.CheckResults();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that channels cannot be using invalid shared secret.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SslHmacChannelAuthenticatorTest, InvalidChannelSecret) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_auth_ = SslHmacChannelAuthenticator::CreateForClient(
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_cert_, kTestSharedSecretBad);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host_auth_ = SslHmacChannelAuthenticator::CreateForHost(
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_cert_, key_pair_, kTestSharedSecret);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunChannelAuth(true);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(host_socket_.get() == NULL);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protocol
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
173