diff options
author | haibinlu <haibinlu@chromium.org> | 2015-12-08 17:43:21 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-09 01:45:07 +0000 |
commit | 9fa0095471e61a1de43d902974567355585157fe (patch) | |
tree | 45a69a6a7f1842bd70c562de941c242e8c9fb96a /blimp/net | |
parent | e313b496592d4ae6fd9d76f4b684265f03e350d2 (diff) | |
download | chromium_src-9fa0095471e61a1de43d902974567355585157fe.zip chromium_src-9fa0095471e61a1de43d902974567355585157fe.tar.gz chromium_src-9fa0095471e61a1de43d902974567355585157fe.tar.bz2 |
[Blimp Net] Add EngineAuthHandler.
It is a ConnectionHandler which expects each new connection to supply a StartConnection message with a valid client authentication token, verifies it, and if successful then hands the connection off to the main ConnectionHandler.
BUG=567817
Review URL: https://codereview.chromium.org/1492643003
Cr-Commit-Position: refs/heads/master@{#363880}
Diffstat (limited to 'blimp/net')
-rw-r--r-- | blimp/net/BUILD.gn | 3 | ||||
-rw-r--r-- | blimp/net/blimp_connection.cc | 2 | ||||
-rw-r--r-- | blimp/net/blimp_connection.h | 9 | ||||
-rw-r--r-- | blimp/net/engine_authentication_handler.cc | 126 | ||||
-rw-r--r-- | blimp/net/engine_authentication_handler.h | 40 | ||||
-rw-r--r-- | blimp/net/engine_authentication_handler_unittest.cc | 123 | ||||
-rw-r--r-- | blimp/net/test_common.cc | 4 | ||||
-rw-r--r-- | blimp/net/test_common.h | 15 |
8 files changed, 319 insertions, 3 deletions
diff --git a/blimp/net/BUILD.gn b/blimp/net/BUILD.gn index bd73b7a..c58fa77 100644 --- a/blimp/net/BUILD.gn +++ b/blimp/net/BUILD.gn @@ -27,6 +27,8 @@ component("blimp_net") { "common.h", "connection_error_observer.h", "connection_handler.h", + "engine_authentication_handler.cc", + "engine_authentication_handler.h", "engine_connection_manager.cc", "engine_connection_manager.h", "input_message_generator.cc", @@ -84,6 +86,7 @@ source_set("unit_tests") { "blimp_message_output_buffer_unittest.cc", "blimp_message_pump_unittest.cc", "client_connection_manager_unittest.cc", + "engine_authentication_handler_unittest.cc", "engine_connection_manager_unittest.cc", "input_message_unittest.cc", "stream_packet_reader_unittest.cc", diff --git a/blimp/net/blimp_connection.cc b/blimp/net/blimp_connection.cc index c5b0700..db2f63d 100644 --- a/blimp/net/blimp_connection.cc +++ b/blimp/net/blimp_connection.cc @@ -96,6 +96,8 @@ BlimpConnection::BlimpConnection(scoped_ptr<PacketReader> reader, DCHECK(writer_); } +BlimpConnection::BlimpConnection() {} + BlimpConnection::~BlimpConnection() {} void BlimpConnection::SetConnectionErrorObserver( diff --git a/blimp/net/blimp_connection.h b/blimp/net/blimp_connection.h index 9f48f50..f95a91c 100644 --- a/blimp/net/blimp_connection.h +++ b/blimp/net/blimp_connection.h @@ -27,15 +27,18 @@ class BLIMP_NET_EXPORT BlimpConnection { virtual ~BlimpConnection(); // Lets |observer| know when the network connection encounters an error. - void SetConnectionErrorObserver(ConnectionErrorObserver* observer); + virtual void SetConnectionErrorObserver(ConnectionErrorObserver* observer); // Sets the processor which will take incoming messages for this connection. // Can be set multiple times, but previously set processors are discarded. // Caller retains the ownership of |processor|. - void SetIncomingMessageProcessor(BlimpMessageProcessor* processor); + virtual void SetIncomingMessageProcessor(BlimpMessageProcessor* processor); // Gets a processor for BrowserSession->BlimpConnection message routing. - BlimpMessageProcessor* GetOutgoingMessageProcessor() const; + virtual BlimpMessageProcessor* GetOutgoingMessageProcessor() const; + + protected: + BlimpConnection(); private: scoped_ptr<PacketReader> reader_; diff --git a/blimp/net/engine_authentication_handler.cc b/blimp/net/engine_authentication_handler.cc new file mode 100644 index 0000000..e49f5ea --- /dev/null +++ b/blimp/net/engine_authentication_handler.cc @@ -0,0 +1,126 @@ +// Copyright 2015 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 "blimp/net/engine_authentication_handler.h" + +#include "base/callback_helpers.h" +#include "base/logging.h" +#include "base/timer/timer.h" +#include "blimp/common/proto/blimp_message.pb.h" +#include "blimp/net/blimp_connection.h" +#include "blimp/net/blimp_message_processor.h" +#include "blimp/net/blimp_transport.h" +#include "blimp/net/connection_error_observer.h" +#include "net/base/completion_callback.h" +#include "net/base/net_errors.h" + +namespace blimp { + +namespace { +// Expect Client to send the StartConnection within ten seconds of becoming +// connected. +const int kAuthTimeoutDurationInSeconds = 10; + +// Authenticates one connection. It deletes itself when +// * the connection is authenticated and passed to |connection_handler|. +// * the connection gets into an error state. +// * the auth message does not arrive within a reasonable time. +class Authenticator : public ConnectionErrorObserver, + public BlimpMessageProcessor { + public: + explicit Authenticator(scoped_ptr<BlimpConnection> connection, + base::WeakPtr<ConnectionHandler> connection_handler); + ~Authenticator() override; + + private: + // Processes authentication result and deletes |this|. + void OnConnectionAuthenticated(bool authenticated); + + // Handles timeout waiting for auth message, and deletes |this|. + void OnAuthenticationTimeout(); + + // ConnectionErrorObserver implementation. + void OnConnectionError(int error) override; + + // BlimpMessageProcessor implementation. + void ProcessMessage(scoped_ptr<BlimpMessage> message, + const net::CompletionCallback& callback) override; + + // The connection to be authenticated. + scoped_ptr<BlimpConnection> connection_; + + // Handler to pass successfully authenticated connections to. + base::WeakPtr<ConnectionHandler> connection_handler_; + + // A timer to fail authentication on timeout. + base::OneShotTimer timeout_timer_; + + DISALLOW_COPY_AND_ASSIGN(Authenticator); +}; + +Authenticator::Authenticator( + scoped_ptr<BlimpConnection> connection, + base::WeakPtr<ConnectionHandler> connection_handler) + : connection_(std::move(connection)), + connection_handler_(connection_handler) { + connection_->SetConnectionErrorObserver(this); + connection_->SetIncomingMessageProcessor(this); + timeout_timer_.Start( + FROM_HERE, base::TimeDelta::FromSeconds(kAuthTimeoutDurationInSeconds), + this, &Authenticator::OnAuthenticationTimeout); +} + +Authenticator::~Authenticator() {} + +void Authenticator::OnConnectionAuthenticated(bool authenticated) { + connection_->SetIncomingMessageProcessor(nullptr); + connection_->SetConnectionErrorObserver(nullptr); + + if (authenticated && connection_handler_) { + connection_handler_->HandleConnection(std::move(connection_)); + } + + delete this; +} + +void Authenticator::OnAuthenticationTimeout() { + DVLOG(1) << "Connection authentication timeout"; + OnConnectionAuthenticated(false); +} + +void Authenticator::OnConnectionError(int error) { + DVLOG(1) << "Connection error before authenticated " + << net::ErrorToString(error); + OnConnectionAuthenticated(false); +} + +void Authenticator::ProcessMessage(scoped_ptr<BlimpMessage> message, + const net::CompletionCallback& callback) { + if (message->type() == BlimpMessage::PROTOCOL_CONTROL) { + // TODO(haibinlu): check client token. + OnConnectionAuthenticated(true); + } else { + DVLOG(1) << "The first message is not START_CONNECTION"; + OnConnectionAuthenticated(false); + } + + callback.Run(net::OK); +} + +} // namespace + +EngineAuthenticationHandler::EngineAuthenticationHandler( + ConnectionHandler* connection_handler) + : connection_handler_weak_factory_(connection_handler) {} + +EngineAuthenticationHandler::~EngineAuthenticationHandler() {} + +void EngineAuthenticationHandler::HandleConnection( + scoped_ptr<BlimpConnection> connection) { + // Authenticator manages its own lifetime. + new Authenticator(std::move(connection), + connection_handler_weak_factory_.GetWeakPtr()); +} + +} // namespace blimp diff --git a/blimp/net/engine_authentication_handler.h b/blimp/net/engine_authentication_handler.h new file mode 100644 index 0000000..686a096 --- /dev/null +++ b/blimp/net/engine_authentication_handler.h @@ -0,0 +1,40 @@ +// Copyright 2015 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. + +#ifndef BLIMP_NET_ENGINE_AUTHENTICATION_HANDLER_H_ +#define BLIMP_NET_ENGINE_AUTHENTICATION_HANDLER_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "blimp/net/blimp_net_export.h" +#include "blimp/net/connection_handler.h" + +namespace blimp { + +class BlimpConnection; +class BlimpMessage; + +// Authenticates connections and passes successfully authenticated connections +// to |connection_handler|. +class BLIMP_NET_EXPORT EngineAuthenticationHandler : public ConnectionHandler { + public: + explicit EngineAuthenticationHandler(ConnectionHandler* connection_handler); + + ~EngineAuthenticationHandler() override; + + // ConnectionHandler implementation. + void HandleConnection(scoped_ptr<BlimpConnection> connection) override; + + private: + // Used to abandon pending authenticated connections if |this| is deleted. + base::WeakPtrFactory<ConnectionHandler> connection_handler_weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(EngineAuthenticationHandler); +}; + +} // namespace blimp + +#endif // BLIMP_NET_ENGINE_AUTHENTICATION_HANDLER_H_ diff --git a/blimp/net/engine_authentication_handler_unittest.cc b/blimp/net/engine_authentication_handler_unittest.cc new file mode 100644 index 0000000..9a3f4ca --- /dev/null +++ b/blimp/net/engine_authentication_handler_unittest.cc @@ -0,0 +1,123 @@ +// Copyright 2015 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 <stddef.h> +#include <string> + +#include "base/memory/ref_counted.h" +#include "base/test/test_mock_time_task_runner.h" +#include "base/thread_task_runner_handle.h" +#include "blimp/common/create_blimp_message.h" +#include "blimp/common/proto/blimp_message.pb.h" +#include "blimp/net/blimp_connection.h" +#include "blimp/net/blimp_transport.h" +#include "blimp/net/common.h" +#include "blimp/net/connection_error_observer.h" +#include "blimp/net/engine_authentication_handler.h" +#include "blimp/net/test_common.h" +#include "net/base/completion_callback.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::Eq; +using testing::SaveArg; + +namespace blimp { + +class EngineAuthenticationHandlerTest : public testing::Test { + public: + EngineAuthenticationHandlerTest() + : runner_(new base::TestMockTimeTaskRunner), + runner_handle_(runner_), + auth_handler_(new EngineAuthenticationHandler(&connection_handler_)), + connection_(new testing::StrictMock<MockBlimpConnection>()) {} + + ~EngineAuthenticationHandlerTest() override {} + + protected: + void ExpectOnConnection() { + EXPECT_CALL(*connection_, SetConnectionErrorObserver(_)) + .Times(2) + .WillRepeatedly(SaveArg<0>(&error_observer_)); + EXPECT_CALL(*connection_, SetIncomingMessageProcessor(_)) + .Times(2) + .WillRepeatedly(SaveArg<0>(&incoming_message_processor_)); + } + + scoped_refptr<base::TestMockTimeTaskRunner> runner_; + base::ThreadTaskRunnerHandle runner_handle_; + testing::StrictMock<MockConnectionHandler> connection_handler_; + scoped_ptr<EngineAuthenticationHandler> auth_handler_; + scoped_ptr<testing::StrictMock<MockBlimpConnection>> connection_; + ConnectionErrorObserver* error_observer_ = nullptr; + BlimpMessageProcessor* incoming_message_processor_ = nullptr; +}; + +TEST_F(EngineAuthenticationHandlerTest, AuthenticationSucceeds) { + ExpectOnConnection(); + EXPECT_CALL(connection_handler_, HandleConnectionPtr(Eq(connection_.get()))); + auth_handler_->HandleConnection(std::move(connection_)); + EXPECT_NE(nullptr, error_observer_); + EXPECT_NE(nullptr, incoming_message_processor_); + + scoped_ptr<BlimpMessage> blimp_message = CreateStartConnectionMessage("", 0); + net::TestCompletionCallback process_message_cb; + incoming_message_processor_->ProcessMessage(std::move(blimp_message), + process_message_cb.callback()); + EXPECT_EQ(net::OK, process_message_cb.WaitForResult()); + EXPECT_EQ(nullptr, error_observer_); + EXPECT_EQ(nullptr, incoming_message_processor_); +} + +TEST_F(EngineAuthenticationHandlerTest, WrongMessageReceived) { + ExpectOnConnection(); + auth_handler_->HandleConnection(std::move(connection_)); + + InputMessage* input_message; + scoped_ptr<BlimpMessage> blimp_message = CreateBlimpMessage(&input_message); + net::TestCompletionCallback process_message_cb; + incoming_message_processor_->ProcessMessage(std::move(blimp_message), + process_message_cb.callback()); + EXPECT_EQ(net::OK, process_message_cb.WaitForResult()); + EXPECT_EQ(nullptr, error_observer_); + EXPECT_EQ(nullptr, incoming_message_processor_); +} + +TEST_F(EngineAuthenticationHandlerTest, ConnectionError) { + ExpectOnConnection(); + auth_handler_->HandleConnection(std::move(connection_)); + EXPECT_NE(nullptr, error_observer_); + EXPECT_NE(nullptr, incoming_message_processor_); + error_observer_->OnConnectionError(net::ERR_FAILED); + EXPECT_EQ(nullptr, error_observer_); + EXPECT_EQ(nullptr, incoming_message_processor_); +} + +TEST_F(EngineAuthenticationHandlerTest, Timeout) { + ExpectOnConnection(); + auth_handler_->HandleConnection(std::move(connection_)); + EXPECT_NE(nullptr, error_observer_); + EXPECT_NE(nullptr, incoming_message_processor_); + + runner_->FastForwardBy(base::TimeDelta::FromSeconds(11)); + EXPECT_EQ(nullptr, error_observer_); + EXPECT_EQ(nullptr, incoming_message_processor_); +} + +TEST_F(EngineAuthenticationHandlerTest, AuthHandlerDeletedFirst) { + ExpectOnConnection(); + auth_handler_->HandleConnection(std::move(connection_)); + auth_handler_.reset(); + + scoped_ptr<BlimpMessage> blimp_message = CreateStartConnectionMessage("", 0); + net::TestCompletionCallback process_message_cb; + incoming_message_processor_->ProcessMessage(std::move(blimp_message), + process_message_cb.callback()); + EXPECT_EQ(net::OK, process_message_cb.WaitForResult()); +} + +} // namespace blimp diff --git a/blimp/net/test_common.cc b/blimp/net/test_common.cc index 06eddac..888841ae 100644 --- a/blimp/net/test_common.cc +++ b/blimp/net/test_common.cc @@ -47,6 +47,10 @@ MockPacketWriter::MockPacketWriter() {} MockPacketWriter::~MockPacketWriter() {} +MockBlimpConnection::MockBlimpConnection() {} + +MockBlimpConnection::~MockBlimpConnection() {} + MockConnectionErrorObserver::MockConnectionErrorObserver() {} MockConnectionErrorObserver::~MockConnectionErrorObserver() {} diff --git a/blimp/net/test_common.h b/blimp/net/test_common.h index 58ee2f6..b42c3d8 100644 --- a/blimp/net/test_common.h +++ b/blimp/net/test_common.h @@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "blimp/common/proto/blimp_message.pb.h" +#include "blimp/net/blimp_connection.h" #include "blimp/net/blimp_message_processor.h" #include "blimp/net/blimp_transport.h" #include "blimp/net/connection_error_observer.h" @@ -165,6 +166,20 @@ class MockPacketWriter : public PacketWriter { const net::CompletionCallback&)); }; +class MockBlimpConnection : public BlimpConnection { + public: + MockBlimpConnection(); + ~MockBlimpConnection() override; + + MOCK_METHOD1(SetConnectionErrorObserver, + void(ConnectionErrorObserver* observer)); + + MOCK_METHOD1(SetIncomingMessageProcessor, + void(BlimpMessageProcessor* processor)); + + MOCK_CONST_METHOD0(GetOutgoingMessageProcessor, BlimpMessageProcessor*()); +}; + class MockConnectionErrorObserver : public ConnectionErrorObserver { public: MockConnectionErrorObserver(); |