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