diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-29 20:19:59 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-29 20:19:59 +0000 |
commit | 1f249e24c736c7e8a330567b1403d8893f57ea49 (patch) | |
tree | 6feaa0669f1d1f0f2c6071a4cb66ee799015db46 /remoting | |
parent | 72851a9a7d4f40ae41d26ac1a94f02544ac495be (diff) | |
download | chromium_src-1f249e24c736c7e8a330567b1403d8893f57ea49.zip chromium_src-1f249e24c736c7e8a330567b1403d8893f57ea49.tar.gz chromium_src-1f249e24c736c7e8a330567b1403d8893f57ea49.tar.bz2 |
Remove AccessVerifier interface.
AccessVerifier will be replaced with the new
protocol::Authenticator interface. This also changes behavior
of Session interface when session is rejected due to bad
auth: now the session is first accepted by ChromotingHost
but then goes to FAILED state with the new
AUTHENTICATION_FAILED error. Temporarily auth token is
verified in JingleSession::AcceptConnection(). Later
Authenticator implementation will be used instead.
BUG=105214
Review URL: http://codereview.chromium.org/8662001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112009 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
28 files changed, 119 insertions, 423 deletions
diff --git a/remoting/host/access_verifier.h b/remoting/host/access_verifier.h deleted file mode 100644 index 00a8d66..0000000 --- a/remoting/host/access_verifier.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2011 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 REMOTING_HOST_ACCESS_VERIFIER_H_ -#define REMOTING_HOST_ACCESS_VERIFIER_H_ - -#include <string> - -#include "base/basictypes.h" - -namespace remoting { - -// AccessVerifier is used by ChromotingHost to verify that access to -// the host. There are two implementations: SelfAccessVerifier is used -// in the Me2Me scenario, SupportAccessVerifier is used for Me2Mom. -class AccessVerifier { - public: - AccessVerifier() { } - virtual ~AccessVerifier() { } - - virtual bool VerifyPermissions(const std::string& client_jid, - const std::string& encoded_client_token) = 0; -}; - -} // namespace remoting - -#endif // REMOTING_HOST_ACCESS_VERIFIER_H_ diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index 60cc6cbd..b5365c6 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc @@ -20,7 +20,6 @@ #include "remoting/host/host_config.h" #include "remoting/host/host_key_pair.h" #include "remoting/host/screen_recorder.h" -#include "remoting/host/user_authenticator.h" #include "remoting/jingle_glue/xmpp_signal_strategy.h" #include "remoting/protocol/connection_to_client.h" #include "remoting/protocol/client_stub.h" @@ -38,21 +37,17 @@ namespace remoting { ChromotingHost* ChromotingHost::Create(ChromotingHostContext* context, MutableHostConfig* config, DesktopEnvironment* environment, - AccessVerifier* access_verifier, bool allow_nat_traversal) { - return new ChromotingHost(context, config, environment, access_verifier, - allow_nat_traversal); + return new ChromotingHost(context, config, environment, allow_nat_traversal); } ChromotingHost::ChromotingHost(ChromotingHostContext* context, MutableHostConfig* config, DesktopEnvironment* environment, - AccessVerifier* access_verifier, bool allow_nat_traversal) : context_(context), desktop_environment_(environment), config_(config), - access_verifier_(access_verifier), allow_nat_traversal_(allow_nat_traversal), stopping_recorders_(0), state_(kInitial), @@ -76,7 +71,6 @@ void ChromotingHost::Start() { LOG(INFO) << "Starting host"; DCHECK(!signal_strategy_.get()); - DCHECK(access_verifier_.get()); // Make sure this object is not started. if (state_ != kInitial) @@ -208,6 +202,14 @@ void ChromotingHost::OnSessionAuthenticated(ClientSession* client) { desktop_environment_->OnConnect(username); } +void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) { + // Notify observers. + for (StatusObserverList::iterator it = status_observers_.begin(); + it != status_observers_.end(); ++it) { + (*it)->OnAccessDenied(); + } +} + void ChromotingHost::OnSessionClosed(ClientSession* client) { DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); @@ -303,19 +305,6 @@ void ChromotingHost::OnIncomingSession( return; } - // Check that the client has access to the host. - if (!access_verifier_->VerifyPermissions(session->jid(), - session->initiator_token())) { - *response = protocol::SessionManager::DECLINE; - - // Notify observers. - for (StatusObserverList::iterator it = status_observers_.begin(); - it != status_observers_.end(); ++it) { - (*it)->OnAccessDenied(); - } - return; - } - // If we are running Me2Mom and already have an authenticated client then // one of the connections may be an attacker, so both are suspect. if (is_it2me_ && AuthenticatedClientsCount() > 0) { @@ -341,9 +330,6 @@ void ChromotingHost::OnIncomingSession( } session->set_config(config); - session->set_receiver_token( - GenerateHostAuthToken(session->initiator_token())); - // Provide the Access Code as shared secret for SSL channel authentication. session->set_shared_secret(access_code_); @@ -416,12 +402,6 @@ Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { return NULL; } -std::string ChromotingHost::GenerateHostAuthToken( - const std::string& encoded_client_token) { - // TODO(ajwong): Return the signature of this instead. - return encoded_client_token; -} - int ChromotingHost::AuthenticatedClientsCount() const { DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index c5651cc..0f112e5 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h @@ -11,7 +11,6 @@ #include "base/memory/scoped_ptr.h" #include "base/threading/thread.h" #include "remoting/base/encoder.h" -#include "remoting/host/access_verifier.h" #include "remoting/host/capturer.h" #include "remoting/host/client_session.h" #include "remoting/host/desktop_environment.h" @@ -66,14 +65,12 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, public protocol::SessionManager::Listener { public: // Factory methods that must be used to create ChromotingHost - // instances. Returned instance takes ownership of - // |access_verifier|. It does NOT take ownership of |context|, - // and |environment|, but they should not be deleted until - // returned host is destroyed. + // instances. It does NOT take ownership of |context|, and + // |environment|, but they should not be deleted until returned host + // is destroyed. static ChromotingHost* Create(ChromotingHostContext* context, MutableHostConfig* config, DesktopEnvironment* environment, - AccessVerifier* access_verifier, bool allow_nat_traversal); // Asynchronously start the host process. @@ -103,6 +100,7 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, //////////////////////////////////////////////////////////////////////////// // ClientSession::EventHandler implementation. virtual void OnSessionAuthenticated(ClientSession* client) OVERRIDE; + virtual void OnSessionAuthenticationFailed(ClientSession* client) OVERRIDE; virtual void OnSessionClosed(ClientSession* session) OVERRIDE; virtual void OnSessionSequenceNumber(ClientSession* session, int64 sequence_number) OVERRIDE; @@ -152,12 +150,10 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, kStopped, }; - // Takes ownership of |access_verifier|, and adds a reference to - // |config|. Caller keeps ownership of |context| and |environment|. + // Caller keeps ownership of |context| and |environment|. ChromotingHost(ChromotingHostContext* context, MutableHostConfig* config, DesktopEnvironment* environment, - AccessVerifier* access_verifier, bool allow_nat_traversal); virtual ~ChromotingHost(); @@ -187,7 +183,6 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, ChromotingHostContext* context_; DesktopEnvironment* desktop_environment_; scoped_refptr<MutableHostConfig> config_; - scoped_ptr<AccessVerifier> access_verifier_; bool allow_nat_traversal_; // Connection objects. diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc index ad2bca8..f8081fd 100644 --- a/remoting/host/chromoting_host_unittest.cc +++ b/remoting/host/chromoting_host_unittest.cc @@ -97,11 +97,9 @@ class ChromotingHostTest : public testing::Test { new DesktopEnvironment(&context_, capturer, event_executor_, curtain_, disconnect_window_, continue_window_, local_input_monitor_)); - MockAccessVerifier* access_verifier = new MockAccessVerifier(); - host_ = ChromotingHost::Create(&context_, config_, - desktop_environment_.get(), - access_verifier, false); + host_ = ChromotingHost::Create( + &context_, config_,desktop_environment_.get(), false); session_ = new MockSession(); session2_ = new MockSession(); session_config_ = SessionConfig::GetDefault(); diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index e063fda..df75407 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc @@ -109,9 +109,12 @@ void ClientSession::OnConnectionClosed( } void ClientSession::OnConnectionFailed( - protocol::ConnectionToClient* connection) { + protocol::ConnectionToClient* connection, + protocol::Session::Error error) { DCHECK(CalledOnValidThread()); DCHECK_EQ(connection_.get(), connection); + if (error == protocol::Session::AUTHENTICATION_FAILED) + event_handler_->OnSessionAuthenticationFailed(this); // TODO(sergeyu): Log failure reason? event_handler_->OnSessionClosed(this); } diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h index a301ff9..9dd8ff0 100644 --- a/remoting/host/client_session.h +++ b/remoting/host/client_session.h @@ -31,8 +31,19 @@ class ClientSession : public protocol::HostStub, public: virtual ~EventHandler() {} + // Called after authentication has finished successfully. virtual void OnSessionAuthenticated(ClientSession* client) = 0; + + // Called after authentication has failed. Must not tear down this + // object. OnSessionClosed() is notified after this handler + // returns. + virtual void OnSessionAuthenticationFailed(ClientSession* client) = 0; + + // Called after connection has failed or after the client closed it. virtual void OnSessionClosed(ClientSession* client) = 0; + + // Called to notify of each message's sequence number. The + // callback must not tear down this object. virtual void OnSessionSequenceNumber(ClientSession* client, int64 sequence_number) = 0; }; @@ -54,8 +65,8 @@ class ClientSession : public protocol::HostStub, protocol::ConnectionToClient* connection) OVERRIDE; virtual void OnConnectionClosed( protocol::ConnectionToClient* connection) OVERRIDE; - virtual void OnConnectionFailed( - protocol::ConnectionToClient* connection) OVERRIDE; + virtual void OnConnectionFailed(protocol::ConnectionToClient* connection, + protocol::Session::Error error) OVERRIDE; virtual void OnSequenceNumberUpdated( protocol::ConnectionToClient* connection, int64 sequence_number) OVERRIDE; diff --git a/remoting/host/host_mock_objects.cc b/remoting/host/host_mock_objects.cc index 3fd1e36..fe8d71d 100644 --- a/remoting/host/host_mock_objects.cc +++ b/remoting/host/host_mock_objects.cc @@ -63,8 +63,4 @@ MockUserAuthenticator::MockUserAuthenticator() {} MockUserAuthenticator::~MockUserAuthenticator() {} -MockAccessVerifier::MockAccessVerifier() {} - -MockAccessVerifier::~MockAccessVerifier() {} - } // namespace remoting diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h index 3810714..7548775 100644 --- a/remoting/host/host_mock_objects.h +++ b/remoting/host/host_mock_objects.h @@ -5,7 +5,6 @@ #ifndef REMOTING_HOST_HOST_MOCK_OBJECTS_H_ #define REMOTING_HOST_HOST_MOCK_OBJECTS_H_ -#include "remoting/host/access_verifier.h" #include "remoting/host/capturer.h" #include "remoting/host/curtain.h" #include "remoting/host/chromoting_host_context.h" @@ -99,6 +98,7 @@ class MockClientSessionEventHandler : public ClientSession::EventHandler { virtual ~MockClientSessionEventHandler(); MOCK_METHOD1(OnSessionAuthenticated, void(ClientSession* client)); + MOCK_METHOD1(OnSessionAuthenticationFailed, void(ClientSession* client)); MOCK_METHOD1(OnSessionClosed, void(ClientSession* client)); MOCK_METHOD1(OnSessionFailed, void(ClientSession* client)); MOCK_METHOD2(OnSessionSequenceNumber, void(ClientSession* client, @@ -131,18 +131,6 @@ class MockUserAuthenticator : public UserAuthenticator { DISALLOW_COPY_AND_ASSIGN(MockUserAuthenticator); }; -class MockAccessVerifier : public AccessVerifier { - public: - MockAccessVerifier(); - virtual ~MockAccessVerifier(); - - MOCK_METHOD2(VerifyPermissions, bool(const std::string& client_jid, - const std::string& token)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockAccessVerifier); -}; - } // namespace remoting #endif // REMOTING_HOST_HOST_MOCK_OBJECTS_H_ diff --git a/remoting/host/host_secret.cc b/remoting/host/host_secret.cc new file mode 100644 index 0000000..1ed8622 --- /dev/null +++ b/remoting/host/host_secret.cc @@ -0,0 +1,35 @@ +// Copyright (c) 2011 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/host/host_secret.h" + +#include <vector> + +#include "base/logging.h" +#include "base/rand_util.h" +#include "base/string_number_conversions.h" + +namespace remoting { + +namespace { + +// 5 digits means 100K possible host secrets with uniform distribution, which +// should be enough for short-term passwords, given that we rate-limit guesses +// in the cloud and expire access codes after a small number of attempts. +const int kMaxHostSecret = 100000; + +// Generates cryptographically strong random number in the range [0, max). +int CryptoRandomInt(int max) { + uint64 random_int32; + base::RandBytes(&random_int32, sizeof(random_int32)); + return random_int32 % max; +} + +} // namespace + +std::string GenerateSupportHostSecret() { + return base::IntToString(CryptoRandomInt(kMaxHostSecret)); +} + +} // namespace remoting diff --git a/remoting/host/host_secret.h b/remoting/host/host_secret.h new file mode 100644 index 0000000..63fe590 --- /dev/null +++ b/remoting/host/host_secret.h @@ -0,0 +1,12 @@ +// Copyright (c) 2011 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 <string> + +namespace remoting { + +// Generates random host secret. +std::string GenerateSupportHostSecret(); + +} // namespace remoting diff --git a/remoting/host/plugin/host_script_object.cc b/remoting/host/plugin/host_script_object.cc index 779aae3..d835da8 100644 --- a/remoting/host/plugin/host_script_object.cc +++ b/remoting/host/plugin/host_script_object.cc @@ -16,11 +16,11 @@ #include "remoting/host/desktop_environment.h" #include "remoting/host/host_config.h" #include "remoting/host/host_key_pair.h" +#include "remoting/host/host_secret.h" #include "remoting/host/in_memory_host_config.h" #include "remoting/host/plugin/host_log_handler.h" #include "remoting/host/plugin/policy_hack/nat_policy.h" #include "remoting/host/register_support_host_request.h" -#include "remoting/host/support_access_verifier.h" namespace remoting { @@ -480,10 +480,6 @@ void HostNPScriptObject::FinishConnect( host_config->SetString(kXmppAuthTokenConfigPath, auth_token); host_config->SetString(kXmppAuthServiceConfigPath, auth_service); - // Create an access verifier and fetch the host secret. - scoped_ptr<SupportAccessVerifier> access_verifier; - access_verifier.reset(new SupportAccessVerifier()); - // Generate a key pair for the Host to use. // TODO(wez): Move this to the worker thread. HostKeyPair host_key_pair; @@ -496,8 +492,7 @@ void HostNPScriptObject::FinishConnect( if (!register_request->Init( host_config.get(), base::Bind(&HostNPScriptObject::OnReceivedSupportID, - base::Unretained(this), - access_verifier.get()))) { + base::Unretained(this)))) { SetState(kError); return; } @@ -517,7 +512,7 @@ void HostNPScriptObject::FinishConnect( LOG(INFO) << "NAT state: " << nat_traversal_enabled_; host_ = ChromotingHost::Create( &host_context_, host_config_, desktop_environment_.get(), - access_verifier.release(), nat_traversal_enabled_); + nat_traversal_enabled_); host_->AddStatusObserver(this); host_->AddStatusObserver(register_request_.get()); if (enable_log_to_server_) { @@ -644,7 +639,6 @@ void HostNPScriptObject::OnNatPolicyUpdate(bool nat_traversal_enabled) { } void HostNPScriptObject::OnReceivedSupportID( - SupportAccessVerifier* access_verifier, bool success, const std::string& support_id, const base::TimeDelta& lifetime) { @@ -657,8 +651,8 @@ void HostNPScriptObject::OnReceivedSupportID( return; } - access_verifier->OnIT2MeHostRegistered(success, support_id); - std::string access_code = support_id + access_verifier->host_secret(); + std::string host_secret = GenerateSupportHostSecret(); + std::string access_code = support_id + host_secret; host_->set_access_code(access_code); { diff --git a/remoting/host/plugin/host_script_object.h b/remoting/host/plugin/host_script_object.h index d52ce71..11be26c 100644 --- a/remoting/host/plugin/host_script_object.h +++ b/remoting/host/plugin/host_script_object.h @@ -118,8 +118,7 @@ class HostNPScriptObject : public HostStatusObserver { void LogDebugInfo(const std::string& message); // Callbacks invoked during session setup. - void OnReceivedSupportID(remoting::SupportAccessVerifier* access_verifier, - bool success, + void OnReceivedSupportID(bool success, const std::string& support_id, const base::TimeDelta& lifetime); void NotifyAccessCode(bool success); diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index b16fafa..f55f9c8 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc @@ -28,7 +28,6 @@ #include "remoting/host/heartbeat_sender.h" #include "remoting/host/host_config.h" #include "remoting/host/json_host_config.h" -#include "remoting/host/self_access_verifier.h" #if defined(TOOLKIT_USES_GTK) #include "ui/gfx/gtk_util.h" @@ -87,21 +86,12 @@ class HostProcess { return 1; } - // Initialize AccessVerifier. - scoped_ptr<remoting::SelfAccessVerifier> self_access_verifier( - new remoting::SelfAccessVerifier()); - if (!self_access_verifier->Init(host_config_)) { - context.Stop(); - return 1; - } - // Create the DesktopEnvironment and ChromotingHost. scoped_ptr<DesktopEnvironment> desktop_environment( DesktopEnvironment::Create(&context)); - host_ = ChromotingHost::Create(&context, host_config_, - desktop_environment.get(), - self_access_verifier.release(), false); + host_ = ChromotingHost::Create( + &context, host_config_, desktop_environment.get(), false); // Initialize HeartbeatSender. scoped_ptr<remoting::HeartbeatSender> heartbeat_sender( diff --git a/remoting/host/self_access_verifier.cc b/remoting/host/self_access_verifier.cc deleted file mode 100644 index 939ed4d..0000000 --- a/remoting/host/self_access_verifier.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2011 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/host/self_access_verifier.h" - -#include "base/logging.h" -#include "base/string_util.h" -#include "remoting/host/host_config.h" - -namespace remoting { - -SelfAccessVerifier::SelfAccessVerifier() - : initialized_(false) { -} - -SelfAccessVerifier::~SelfAccessVerifier() { } - -bool SelfAccessVerifier::Init(HostConfig* config) { - std::string host_jid; - - if (!config->GetString(kXmppLoginConfigPath, &host_jid) || - host_jid.empty()) { - LOG(ERROR) << "XMPP credentials are not defined in the config."; - return false; - } - - host_jid_prefix_ = host_jid + '/'; - initialized_ = true; - - return true; -} - -bool SelfAccessVerifier::VerifyPermissions( - const std::string& client_jid, - const std::string& encoded_access_token) { - CHECK(initialized_); - - // Reject incoming connection if the client's jid is not an ASCII string. - if (!IsStringASCII(client_jid)) { - LOG(ERROR) << "Rejecting incoming connection from " << client_jid; - return false; - } - - // Check that the client has the same bare jid as the host, i.e. - // client's full JID starts with host's bare jid. Comparison is case - // insensitive. - if (!StartsWithASCII(client_jid, host_jid_prefix_, false)) { - LOG(ERROR) << "Rejecting incoming connection from " << client_jid; - return false; - } - - // Kick off directory access permissions. - // TODO(ajwong): Actually implement this. - return true; -} - -} // namespace remoting diff --git a/remoting/host/self_access_verifier.h b/remoting/host/self_access_verifier.h deleted file mode 100644 index 29b07ed..0000000 --- a/remoting/host/self_access_verifier.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2011 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 REMOTING_HOST_SELF_ACCESS_VERIFIER_H_ -#define REMOTING_HOST_SELF_ACCESS_VERIFIER_H_ - -#include "remoting/host/access_verifier.h" - -#include "base/compiler_specific.h" - -namespace remoting { - -class HostConfig; - -namespace protocol { -class ClientAuthToken; -} // namespace protocol - -// SelfAccessVerifier is used by to verify that the client has access -// to the host in the Me2Me scenario. Currently it -// -// 1) Checks that host and client have the same bare JID. -// 2) Verifies that the access token can be decoded. -// -// TODO(sergeyu): Remove the bare-JID check, and instead ask the directory to -// perform user authorization. -class SelfAccessVerifier : public AccessVerifier { - public: - SelfAccessVerifier(); - virtual ~SelfAccessVerifier(); - - bool Init(HostConfig* config); - - // AccessVerifier interface. - virtual bool VerifyPermissions( - const std::string& client_jid, - const std::string& encoded_client_token) OVERRIDE; - - private: - bool DecodeClientAuthToken(const std::string& encoded_client_token, - protocol::ClientAuthToken* client_token); - - std::string host_jid_prefix_; - bool initialized_; - - DISALLOW_COPY_AND_ASSIGN(SelfAccessVerifier); -}; - -} // namespace remoting - -#endif // REMOTING_HOST_SELF_ACCESS_VERIFIER_H_ diff --git a/remoting/host/self_access_verifier_unittest.cc b/remoting/host/self_access_verifier_unittest.cc deleted file mode 100644 index f0fd179..0000000 --- a/remoting/host/self_access_verifier_unittest.cc +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2011 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 "base/memory/ref_counted.h" -#include "base/task.h" -#include "remoting/host/in_memory_host_config.h" -#include "remoting/host/self_access_verifier.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace remoting { - -namespace { -const char kTestJid[] = "host@domain.com"; -} // namespace - -class SelfAccessVerifierTest : public testing::Test { - protected: - virtual void SetUp() { - config_ = new InMemoryHostConfig(); - } - - void InitConfig() { - config_->SetString(kXmppLoginConfigPath, kTestJid); - } - - scoped_refptr<InMemoryHostConfig> config_; -}; - -TEST_F(SelfAccessVerifierTest, InvalidConfig) { - SelfAccessVerifier target; - EXPECT_FALSE(target.Init(config_)); -} - -TEST_F(SelfAccessVerifierTest, VerifyPermissions) { - SelfAccessVerifier target; - InitConfig(); - ASSERT_TRUE(target.Init(config_)); - EXPECT_TRUE(target.VerifyPermissions("host@domain.com/123123", "")); - EXPECT_TRUE(target.VerifyPermissions("hOsT@domain.com/123123", "")); - EXPECT_FALSE(target.VerifyPermissions("host@domain.com", "")); - EXPECT_FALSE(target.VerifyPermissions("otherhost@domain.com/123123", "")); - EXPECT_FALSE(target.VerifyPermissions("host@otherdomain.com/123123", "")); - EXPECT_FALSE(target.VerifyPermissions("", "")); - EXPECT_FALSE(target.VerifyPermissions("host@domain.co/saf", "")); - EXPECT_FALSE(target.VerifyPermissions("host@domain.com.other/blah", "")); - - // Non ASCII string. - EXPECT_FALSE(target.VerifyPermissions("абв@domain.com/saf", "")); -} - -} // namespace remoting diff --git a/remoting/host/simple_host_process.cc b/remoting/host/simple_host_process.cc index 99af071..293ad27 100644 --- a/remoting/host/simple_host_process.cc +++ b/remoting/host/simple_host_process.cc @@ -41,12 +41,11 @@ #include "remoting/host/disconnect_window.h" #include "remoting/host/event_executor.h" #include "remoting/host/heartbeat_sender.h" +#include "remoting/host/host_secret.h" #include "remoting/host/local_input_monitor.h" #include "remoting/host/log_to_server.h" #include "remoting/host/json_host_config.h" #include "remoting/host/register_support_host_request.h" -#include "remoting/host/self_access_verifier.h" -#include "remoting/host/support_access_verifier.h" #include "remoting/proto/video.pb.h" #if defined(TOOLKIT_USES_GTK) @@ -133,27 +132,16 @@ class SimpleHost { // ChromotingHost could cause a crash condition if SetIT2MeAccessCode is // called after the ChromotingHost is destroyed (for example, at shutdown). // Fix this. - scoped_ptr<remoting::AccessVerifier> access_verifier; scoped_ptr<remoting::RegisterSupportHostRequest> register_request; scoped_ptr<remoting::HeartbeatSender> heartbeat_sender; scoped_ptr<remoting::LogToServer> log_to_server; if (is_it2me_) { - scoped_ptr<remoting::SupportAccessVerifier> support_access_verifier( - new remoting::SupportAccessVerifier()); register_request.reset(new remoting::RegisterSupportHostRequest()); if (!register_request->Init( config, base::Bind(&SimpleHost::SetIT2MeAccessCode, - base::Unretained(this), - support_access_verifier.get()))) { + base::Unretained(this)))) { return 1; } - access_verifier.reset(support_access_verifier.release()); - } else { - scoped_ptr<remoting::SelfAccessVerifier> self_access_verifier( - new remoting::SelfAccessVerifier()); - if (!self_access_verifier->Init(config)) - return 1; - access_verifier.reset(self_access_verifier.release()); } log_to_server.reset(new remoting::LogToServer( context.network_message_loop())); @@ -181,8 +169,8 @@ class SimpleHost { desktop_environment.reset(DesktopEnvironment::Create(&context)); } - host_ = ChromotingHost::Create(&context, config, desktop_environment.get(), - access_verifier.release(), false); + host_ = ChromotingHost::Create( + &context, config, desktop_environment.get(), false); host_->set_it2me(is_it2me_); if (protocol_config_.get()) { @@ -227,12 +215,11 @@ class SimpleHost { private: // TODO(wez): This only needs to be a member because it needs access to the // ChromotingHost, which has to be created after the SupportAccessVerifier. - void SetIT2MeAccessCode(remoting::SupportAccessVerifier* access_verifier, - bool successful, const std::string& support_id, + void SetIT2MeAccessCode(bool successful, const std::string& support_id, const base::TimeDelta& lifetime) { - access_verifier->OnIT2MeHostRegistered(successful, support_id); if (successful) { - std::string access_code = support_id + access_verifier->host_secret(); + std::string host_secret = remoting::GenerateSupportHostSecret(); + std::string access_code = support_id + host_secret; std::cout << "Support id: " << access_code << std::endl; // Tell the ChromotingHost the access code, to use as shared-secret. diff --git a/remoting/host/support_access_verifier.cc b/remoting/host/support_access_verifier.cc deleted file mode 100644 index ab2238e..0000000 --- a/remoting/host/support_access_verifier.cc +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2011 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/host/support_access_verifier.h" - -#include <stdlib.h> -#include <vector> - -#include "base/logging.h" -#include "base/rand_util.h" -#include "base/string_util.h" -#include "remoting/host/host_config.h" -#include "remoting/protocol/auth_util.h" - -namespace remoting { - -namespace { -// 5 digits means 100K possible host secrets with uniform distribution, which -// should be enough for short-term passwords, given that we rate-limit guesses -// in the cloud and expire access codes after a small number of attempts. -const int kHostSecretLength = 5; -const char kHostSecretAlphabet[] = "0123456789"; - -// Generates cryptographically strong random number in the range [0, max). -int CryptoRandomInt(int max) { - uint32 random_int32; - base::RandBytes(&random_int32, sizeof(random_int32)); - return random_int32 % max; -} - -std::string GenerateRandomHostSecret() { - std::vector<char> result; - int alphabet_size = strlen(kHostSecretAlphabet); - result.resize(kHostSecretLength); - for (int i = 0; i < kHostSecretLength; ++i) { - result[i] = kHostSecretAlphabet[CryptoRandomInt(alphabet_size)]; - } - return std::string(result.begin(), result.end()); -} - -} // namespace - -SupportAccessVerifier::SupportAccessVerifier() { - host_secret_ = GenerateRandomHostSecret(); -} - -SupportAccessVerifier::~SupportAccessVerifier() { } - -bool SupportAccessVerifier::VerifyPermissions( - const std::string& client_jid, - const std::string& encoded_access_token) { - if (support_id_.empty()) - return false; - std::string access_code = support_id_ + host_secret_; - return protocol::VerifySupportAuthToken( - client_jid, access_code, encoded_access_token); -} - -void SupportAccessVerifier::OnIT2MeHostRegistered( - bool successful, const std::string& support_id) { - if (successful) { - support_id_ = support_id; - } else { - LOG(ERROR) << "Failed to register support host"; - } -} - -} // namespace remoting diff --git a/remoting/host/support_access_verifier.h b/remoting/host/support_access_verifier.h deleted file mode 100644 index b6b7c7a..0000000 --- a/remoting/host/support_access_verifier.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2011 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 REMOTING_HOST_SUPPORT_ACCESS_VERIFIER_H_ -#define REMOTING_HOST_SUPPORT_ACCESS_VERIFIER_H_ - -#include <string> - -#include "remoting/host/access_verifier.h" - -#include "base/compiler_specific.h" - -namespace remoting { - -// SupportAccessVerifier is used in Me2Mom scenario to verify that the -// client knows the host secret. -class SupportAccessVerifier : public AccessVerifier { - public: - SupportAccessVerifier(); - virtual ~SupportAccessVerifier(); - - const std::string& host_secret() const { return host_secret_; } - - // AccessVerifier interface. - virtual bool VerifyPermissions( - const std::string& client_jid, - const std::string& encoded_client_token) OVERRIDE; - - void OnIT2MeHostRegistered(bool successful, const std::string& support_id); - - private: - std::string host_secret_; - std::string support_id_; - - DISALLOW_COPY_AND_ASSIGN(SupportAccessVerifier); -}; - -} // namespace remoting - -#endif // REMOTING_HOST_SUPPORT_ACCESS_VERIFIER_H_ diff --git a/remoting/protocol/connection_to_client.cc b/remoting/protocol/connection_to_client.cc index 4219cc9..e247770 100644 --- a/remoting/protocol/connection_to_client.cc +++ b/remoting/protocol/connection_to_client.cc @@ -157,7 +157,7 @@ void ConnectionToClient::NotifyIfChannelsReady() { void ConnectionToClient::CloseOnError() { CloseChannels(); - handler_->OnConnectionFailed(this); + handler_->OnConnectionFailed(this, session_->error()); } void ConnectionToClient::CloseChannels() { diff --git a/remoting/protocol/connection_to_client.h b/remoting/protocol/connection_to_client.h index b9fecb3..1b3490f 100644 --- a/remoting/protocol/connection_to_client.h +++ b/remoting/protocol/connection_to_client.h @@ -39,7 +39,8 @@ class ConnectionToClient : public base::NonThreadSafe { virtual void OnConnectionClosed(ConnectionToClient* connection) = 0; // Called when the network connection has failed. - virtual void OnConnectionFailed(ConnectionToClient* connection) = 0; + virtual void OnConnectionFailed(ConnectionToClient* connection, + Session::Error error) = 0; // Called when sequence number is updated. virtual void OnSequenceNumberUpdated(ConnectionToClient* connection, diff --git a/remoting/protocol/connection_to_client_unittest.cc b/remoting/protocol/connection_to_client_unittest.cc index 6bd0515..41f299c 100644 --- a/remoting/protocol/connection_to_client_unittest.cc +++ b/remoting/protocol/connection_to_client_unittest.cc @@ -98,7 +98,9 @@ TEST_F(ConnectionToClientTest, StateChange) { session_->state_change_callback().Run(protocol::Session::CLOSED); message_loop_.RunAllPending(); - EXPECT_CALL(handler_, OnConnectionFailed(viewer_.get())); + EXPECT_CALL(handler_, OnConnectionFailed( + viewer_.get(), Session::SESSION_REJECTED)); + session_->set_error(Session::SESSION_REJECTED); session_->state_change_callback().Run(protocol::Session::FAILED); message_loop_.RunAllPending(); } diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc index 53bc030..84c2a3f 100644 --- a/remoting/protocol/connection_to_host.cc +++ b/remoting/protocol/connection_to_host.cc @@ -167,6 +167,7 @@ void ConnectionToHost::OnSessionStateChange( CloseOnError(HOST_IS_OFFLINE); break; case Session::SESSION_REJECTED: + case Session::AUTHENTICATION_FAILED: CloseOnError(SESSION_REJECTED); break; case Session::INCOMPATIBLE_PROTOCOL: diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc index ef0dfad..b008bb4a 100644 --- a/remoting/protocol/jingle_session.cc +++ b/remoting/protocol/jingle_session.cc @@ -14,6 +14,7 @@ #include "net/base/net_errors.h" #include "net/socket/stream_socket.h" #include "remoting/base/constants.h" +#include "remoting/protocol/auth_util.h" #include "remoting/protocol/jingle_datagram_connector.h" #include "remoting/protocol/jingle_session_manager.h" #include "remoting/protocol/jingle_stream_connector.h" @@ -99,6 +100,7 @@ void JingleSession::CloseInternal(int result, Error error) { reason = cricket::STR_TERMINATE_SUCCESS; break; case SESSION_REJECTED: + case AUTHENTICATION_FAILED: reason = cricket::STR_TERMINATE_DECLINE; break; case INCOMPATIBLE_PROTOCOL: @@ -395,6 +397,9 @@ void JingleSession::AcceptConnection() { delete this; return; } + + if (!VerifySupportAuthToken(jid_, shared_secret_, initiator_token())) + CloseInternal(net::ERR_CONNECTION_FAILED, AUTHENTICATION_FAILED); } void JingleSession::AddChannelConnector( diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc index 7ac4c3a..4b91b13 100644 --- a/remoting/protocol/jingle_session_unittest.cc +++ b/remoting/protocol/jingle_session_unittest.cc @@ -15,6 +15,7 @@ #include "net/base/net_errors.h" #include "net/socket/socket.h" #include "net/socket/stream_socket.h" +#include "remoting/protocol/auth_util.h" #include "remoting/protocol/jingle_session.h" #include "remoting/protocol/jingle_session_manager.h" #include "remoting/jingle_glue/jingle_thread.h" @@ -54,7 +55,6 @@ const int kMessageSize = 1024; const int kMessages = 100; const int kTestDataSize = kMessages * kMessageSize; const int kUdpWriteDelayMs = 10; -const char kTestToken[] = "a_dummy_token"; const char kChannelName[] = "test_channel"; const char kHostJid[] = "host1@gmail.com/123"; @@ -244,7 +244,8 @@ class JingleSessionTest : public testing::Test { } client_session_.reset(client_server_->Connect( - kHostJid, kTestHostPublicKey, kTestToken, + kHostJid, kTestHostPublicKey, + GenerateSupportAuthToken(kClientJid, kTestSharedSecret), CandidateSessionConfig::CreateDefault(), base::Bind(&MockSessionCallback::OnStateChange, base::Unretained(&client_connection_callback_)))); @@ -669,7 +670,8 @@ TEST_F(JingleSessionTest, RejectConnection) { } client_session_.reset(client_server_->Connect( - kHostJid, kTestHostPublicKey, kTestToken, + kHostJid, kTestHostPublicKey, + GenerateSupportAuthToken(kClientJid, kTestSharedSecret), CandidateSessionConfig::CreateDefault(), base::Bind(&MockSessionCallback::OnStateChange, base::Unretained(&client_connection_callback_)))); diff --git a/remoting/protocol/protocol_mock_objects.h b/remoting/protocol/protocol_mock_objects.h index 61d7602..26b4b8e 100644 --- a/remoting/protocol/protocol_mock_objects.h +++ b/remoting/protocol/protocol_mock_objects.h @@ -44,7 +44,8 @@ class MockConnectionToClientEventHandler : MOCK_METHOD1(OnConnectionOpened, void(ConnectionToClient* connection)); MOCK_METHOD1(OnConnectionClosed, void(ConnectionToClient* connection)); - MOCK_METHOD1(OnConnectionFailed, void(ConnectionToClient* connection)); + MOCK_METHOD2(OnConnectionFailed, void(ConnectionToClient* connection, + Session::Error error)); MOCK_METHOD2(OnSequenceNumberUpdated, void(ConnectionToClient* connection, int64 sequence_number)); diff --git a/remoting/protocol/session.h b/remoting/protocol/session.h index 346fb28..de85666 100644 --- a/remoting/protocol/session.h +++ b/remoting/protocol/session.h @@ -38,7 +38,7 @@ class Session : public base::NonThreadSafe { // session-accept. CONNECTING, - // Session has been accepted, but channels are connected yet. + // Session has been accepted. CONNECTED, // Session has been closed. @@ -54,6 +54,7 @@ class Session : public base::NonThreadSafe { PEER_IS_OFFLINE, SESSION_REJECTED, INCOMPATIBLE_PROTOCOL, + AUTHENTICATION_FAILED, CHANNEL_CONNECTION_ERROR, }; diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index de106f7..e81aa68 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -495,7 +495,6 @@ '../crypto/crypto.gyp:crypto', ], 'sources': [ - 'host/access_verifier.h', 'host/capturer.h', 'host/capturer_helper.cc', 'host/capturer_helper.h', @@ -539,6 +538,8 @@ 'host/host_config.h', 'host/host_key_pair.cc', 'host/host_key_pair.h', + 'host/host_secret.cc', + 'host/host_secret.h', 'host/host_status_observer.h', 'host/in_memory_host_config.cc', 'host/in_memory_host_config.h', @@ -556,14 +557,10 @@ 'host/log_to_server.h', 'host/register_support_host_request.cc', 'host/register_support_host_request.h', - 'host/self_access_verifier.cc', - 'host/self_access_verifier.h', 'host/screen_recorder.cc', 'host/screen_recorder.h', 'host/server_log_entry.cc', 'host/server_log_entry.h', - 'host/support_access_verifier.cc', - 'host/support_access_verifier.h', 'host/ui_strings.cc', 'host/ui_strings.h', 'host/user_authenticator.h', @@ -914,7 +911,6 @@ 'host/log_to_server_unittest.cc', 'host/register_support_host_request_unittest.cc', 'host/screen_recorder_unittest.cc', - 'host/self_access_verifier_unittest.cc', 'host/server_log_entry_unittest.cc', 'host/test_key_pair.h', 'jingle_glue/fake_signal_strategy.cc', |