diff options
author | dcaiafa@chromium.org <dcaiafa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 16:47:31 +0000 |
---|---|---|
committer | dcaiafa@chromium.org <dcaiafa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-30 16:47:31 +0000 |
commit | 573e6777aa7fe9f4fcf66202f9e93e062d120b7c (patch) | |
tree | 836659f93e57cf8dabe7dec9435b41e686bead42 | |
parent | 71d94dfce9c1989595d60e2737e05420cf6a5d5e (diff) | |
download | chromium_src-573e6777aa7fe9f4fcf66202f9e93e062d120b7c.zip chromium_src-573e6777aa7fe9f4fcf66202f9e93e062d120b7c.tar.gz chromium_src-573e6777aa7fe9f4fcf66202f9e93e062d120b7c.tar.bz2 |
New policies: enable/disable relay; port range
Add new Chromoting policies:
"RemoteAccessHostAllowRelayedConnection"
bool, default true
It can be set to false to disable the use of relay servers if NAT
traversal is enabled.
"RemoteAccessHostUdpPortRange"
string, default ""
Can be used to specify a range in the form "<min-port>-<max-port>" to
restrict the range of UDP ports available to the host for connections.
E.g. "12400-12409"
BUG=355168
Review URL: https://codereview.chromium.org/209323002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267234 0039d316-1c4b-4281-b951-d872f2087c98
20 files changed, 353 insertions, 32 deletions
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 5d5d20b..d8e3239 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc @@ -275,6 +275,12 @@ const PolicyToPreferenceMapEntry kSimplePolicyMap[] = { { key::kRemoteAccessHostAllowGnubbyAuth, prefs::kRemoteAccessHostAllowGnubbyAuth, base::Value::TYPE_BOOLEAN }, + { key::kRemoteAccessHostAllowRelayedConnection, + prefs::kRemoteAccessHostAllowRelayedConnection, + base::Value::TYPE_BOOLEAN }, + { key::kRemoteAccessHostUdpPortRange, + prefs::kRemoteAccessHostUdpPortRange, + base::Value::TYPE_STRING }, { key::kCloudPrintProxyEnabled, prefs::kCloudPrintProxyEnabled, base::Value::TYPE_BOOLEAN }, diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index d791e37..cf188b6 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1883,6 +1883,17 @@ const char kRemoteAccessHostAllowClientPairing[] = const char kRemoteAccessHostAllowGnubbyAuth[] = "remote_access.host_allow_gnubby_auth"; +// Boolean that indicates whether the Chromoting host should allow connections +// using relay servers. +const char kRemoteAccessHostAllowRelayedConnection[] = + "remote_access.host_allow_relayed_connection"; + +// String containing the UDP port range that the Chromoting host should used +// when connecting to clients. The port range should be in the form: +// <min_port>-<max_port>. E.g. 12400-12409. +const char kRemoteAccessHostUdpPortRange[] = + "remote_access.host_udp_port_range"; + // The last used printer and its settings. const char kPrintPreviewStickySettings[] = "printing.print_preview_sticky_settings"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index e5d9b00..5a9538a 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -628,6 +628,8 @@ extern const char kRemoteAccessHostTalkGadgetPrefix[]; extern const char kRemoteAccessHostRequireCurtain[]; extern const char kRemoteAccessHostAllowClientPairing[]; extern const char kRemoteAccessHostAllowGnubbyAuth[]; +extern const char kRemoteAccessHostAllowRelayedConnection[]; +extern const char kRemoteAccessHostUdpPortRange[]; extern const char kPrintPreviewStickySettings[]; extern const char kCloudPrintRoot[]; diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index e54a6b3..f62c939 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json @@ -244,6 +244,22 @@ ] }, + "RemoteAccessHostAllowRelayedConnection": { + "os": [], + "test_policy": { "RemoteAccessHostAllowRelayedConnection": true }, + "pref_mappings": [ + { "pref": "remote_access.host_allow_relayed_connection" } + ] + }, + + "RemoteAccessHostUdpPortRange": { + "os": [], + "test_policy": { "RemoteAccessHostUdpPortRange": "12400-12409" }, + "pref_mappings": [ + { "pref": "remote_access.host_udp_port_range" } + ] + }, + "PrintingEnabled": { "os": ["win", "linux", "mac", "chromeos"], "test_policy": { "PrintingEnabled": false }, diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index a3930d2..22b54d4 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json @@ -118,7 +118,7 @@ # persistent IDs for all fields (but not for groups!) are needed. These are # specified by the 'id' keys of each policy. NEVER CHANGE EXISTING IDs, # because doing so would break the deployed wire format! -# For your editing convenience: highest ID currently used: 262 +# For your editing convenience: highest ID currently used: 264 # # Placeholders: # The following placeholder strings are automatically substituted: @@ -542,7 +542,7 @@ 'example_value': False, 'id': 95, 'caption': '''Enable firewall traversal from remote access host''', - 'desc': '''Enables usage of STUN and relay servers when remote clients are trying to establish a connection to this machine. + 'desc': '''Enables usage of STUN servers when remote clients are trying to establish a connection to this machine. If this setting is enabled, then remote clients can discover and connect to this machines even if they are separated by a firewall. @@ -658,6 +658,42 @@ If this setting is disabled or not configured, gnubby authentication requests will not be proxied.''', }, + { + 'name': 'RemoteAccessHostAllowRelayedConnection', + 'type': 'main', + 'schema': { 'type': 'boolean' }, + 'supported_on': ['chrome.*:36-'], + 'features': { + 'dynamic_refresh': True, + 'per_profile': False, + }, + 'example_value': False, + 'id': 263, + 'caption': '''Enable the use of relay servers by the remote access host''', + 'desc': '''Enables usage of relay servers when remote clients are trying to establish a connection to this machine. + + If this setting is enabled, then remote clients can use relay servers to connect to this machine when a direct connection is not available (e.g. due to firewall restrictions). + + Note that if the policy <ph name="REMOTEACCESSHOSTFIREWALLTRAVERSAL_POLICY_NAME">RemoteAccessHostFirewallTraversal</ph> is disabled, this policy will be ignored. + + If this policy is left not set the setting will be enabled.''', + }, + { + 'name': 'RemoteAccessHostUdpPortRange', + 'type': 'string', + 'schema': { 'type': 'string' }, + 'supported_on': ['chrome.*:36-'], + 'features': { + 'dynamic_refresh': True, + 'per_profile': False, + }, + 'example_value': '12400-12409', + 'id': 264, + 'caption': '''Restrict the UDP port range used by the remote access host''', + 'desc': '''Restricts the UDP port range used by the remote access host in this machine. + + If this policy is left not set, or if it is set to an empty string, the remote access host will be allowed to use any available port, unless the policy <ph name="REMOTEACCESSHOSTFIREWALLTRAVERSAL_POLICY_NAME">RemoteAccessHostFirewallTraversal</ph> is disabled, in which case the remote access host will use UDP ports in the 12400-12409 range.''', + }, ], }, { diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc index 883df5a..19e78971 100644 --- a/remoting/client/jni/chromoting_jni_instance.cc +++ b/remoting/client/jni/chromoting_jni_instance.cc @@ -332,7 +332,7 @@ void ChromotingJniInstance::ConnectToHostOnNetworkThread() { net::ClientSocketFactory::GetDefaultFactory(), jni_runtime_->url_requester(), xmpp_config_)); - NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_ENABLED); + NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_FULL); // Use Chrome's network stack to allocate ports for peer-to-peer channels. scoped_ptr<ChromiumPortAllocator> port_allocator( diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index fe4b540..5ea3065 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc @@ -676,7 +676,7 @@ void ChromotingInstance::ConnectWithConfig(const ClientConfig& config, scoped_ptr<protocol::TransportFactory> transport_factory( new protocol::LibjingleTransportFactory( signal_strategy_.get(), port_allocator.Pass(), - NetworkSettings(NetworkSettings::NAT_TRAVERSAL_ENABLED))); + NetworkSettings(NetworkSettings::NAT_TRAVERSAL_FULL))); // Kick off the connection. client_->Start(signal_strategy_.get(), transport_factory.Pass()); diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc index fec201f..505efde 100644 --- a/remoting/host/it2me/it2me_host.cc +++ b/remoting/host/it2me/it2me_host.cc @@ -184,7 +184,7 @@ void It2MeHost::FinishConnect() { HOST_LOG << "NAT state: " << nat_traversal_enabled_; NetworkSettings network_settings( nat_traversal_enabled_ ? - NetworkSettings::NAT_TRAVERSAL_ENABLED : + NetworkSettings::NAT_TRAVERSAL_FULL : NetworkSettings::NAT_TRAVERSAL_DISABLED); if (!nat_traversal_enabled_) { network_settings.min_port = NetworkSettings::kDefaultMinPort; diff --git a/remoting/host/policy_hack/policy_watcher.cc b/remoting/host/policy_hack/policy_watcher.cc index fd1a37b..e603cf5 100644 --- a/remoting/host/policy_hack/policy_watcher.cc +++ b/remoting/host/policy_hack/policy_watcher.cc @@ -107,6 +107,12 @@ const char PolicyWatcher::kHostAllowClientPairing[] = const char PolicyWatcher::kHostAllowGnubbyAuthPolicyName[] = "RemoteAccessHostAllowGnubbyAuth"; +const char PolicyWatcher::kRelayPolicyName[] = + "RemoteAccessHostAllowRelayedConnection"; + +const char PolicyWatcher::kUdpPortRangePolicyName[] = + "RemoteAccessHostUdpPortRange"; + const char PolicyWatcher::kHostDebugOverridePoliciesName[] = "RemoteAccessHostDebugOverridePolicies"; @@ -130,6 +136,8 @@ PolicyWatcher::PolicyWatcher( std::string()); default_values_->SetBoolean(kHostAllowClientPairing, true); default_values_->SetBoolean(kHostAllowGnubbyAuthPolicyName, true); + default_values_->SetBoolean(kRelayPolicyName, true); + default_values_->SetString(kUdpPortRangePolicyName, ""); #if !defined(NDEBUG) default_values_->SetString(kHostDebugOverridePoliciesName, std::string()); #endif @@ -138,6 +146,7 @@ PolicyWatcher::PolicyWatcher( // For most policies these match the defaults. bad_type_values_.reset(default_values_->DeepCopy()); bad_type_values_->SetBoolean(kNatPolicyName, false); + bad_type_values_->SetBoolean(kRelayPolicyName, false); } PolicyWatcher::~PolicyWatcher() { diff --git a/remoting/host/policy_hack/policy_watcher.h b/remoting/host/policy_hack/policy_watcher.h index a3afee0..0ced8f2 100644 --- a/remoting/host/policy_hack/policy_watcher.h +++ b/remoting/host/policy_hack/policy_watcher.h @@ -77,6 +77,12 @@ class PolicyWatcher { // The name of the policy for disabling gnubbyd forwarding. static const char kHostAllowGnubbyAuthPolicyName[]; + // The name of the policy for allowing use of relay servers. + static const char kRelayPolicyName[]; + + // The name of the policy that restricts the range of host UDP ports. + static const char kUdpPortRangePolicyName[]; + // The name of the policy for overriding policies, for use in testing. static const char kHostDebugOverridePoliciesName[]; diff --git a/remoting/host/policy_hack/policy_watcher_unittest.cc b/remoting/host/policy_hack/policy_watcher_unittest.cc index 729a7bb..0ed1a55 100644 --- a/remoting/host/policy_hack/policy_watcher_unittest.cc +++ b/remoting/host/policy_hack/policy_watcher_unittest.cc @@ -75,6 +75,13 @@ class PolicyWatcherTest : public testing::Test { true); gnubby_auth_false_.SetBoolean(PolicyWatcher::kHostAllowGnubbyAuthPolicyName, false); + relay_true_.SetBoolean(PolicyWatcher::kRelayPolicyName, true); + relay_false_.SetBoolean(PolicyWatcher::kRelayPolicyName, false); + port_range_full_.SetString(PolicyWatcher::kUdpPortRangePolicyName, + kPortRange); + port_range_empty_.SetString(PolicyWatcher::kUdpPortRangePolicyName, + std::string()); + #if !defined(NDEBUG) SetDefaults(nat_false_overridden_others_default_); nat_false_overridden_others_default_.SetBoolean( @@ -99,6 +106,7 @@ class PolicyWatcherTest : public testing::Test { } static const char* kHostDomain; + static const char* kPortRange; base::MessageLoop message_loop_; scoped_refptr<base::MessageLoopProxy> message_loop_proxy_; MockPolicyCallback mock_policy_callback_; @@ -126,10 +134,16 @@ class PolicyWatcherTest : public testing::Test { base::DictionaryValue pairing_false_; base::DictionaryValue gnubby_auth_true_; base::DictionaryValue gnubby_auth_false_; + base::DictionaryValue relay_true_; + base::DictionaryValue relay_false_; + base::DictionaryValue port_range_full_; + base::DictionaryValue port_range_empty_; private: void SetDefaults(base::DictionaryValue& dict) { dict.SetBoolean(PolicyWatcher::kNatPolicyName, true); + dict.SetBoolean(PolicyWatcher::kRelayPolicyName, true); + dict.SetString(PolicyWatcher::kUdpPortRangePolicyName, ""); dict.SetBoolean(PolicyWatcher::kHostRequireTwoFactorPolicyName, false); dict.SetString(PolicyWatcher::kHostDomainPolicyName, std::string()); dict.SetBoolean(PolicyWatcher::kHostMatchUsernamePolicyName, false); @@ -150,6 +164,7 @@ class PolicyWatcherTest : public testing::Test { }; const char* PolicyWatcherTest::kHostDomain = "google.com"; +const char* PolicyWatcherTest::kPortRange = "12400-12409"; MATCHER_P(IsPolicies, dict, "") { return arg->Equals(dict); @@ -355,5 +370,37 @@ TEST_F(PolicyWatcherTest, GnubbyAuth) { StopWatching(); } +TEST_F(PolicyWatcherTest, Relay) { + testing::InSequence sequence; + EXPECT_CALL(mock_policy_callback_, + OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); + EXPECT_CALL(mock_policy_callback_, + OnPolicyUpdatePtr(IsPolicies(&relay_false_))); + EXPECT_CALL(mock_policy_callback_, + OnPolicyUpdatePtr(IsPolicies(&relay_true_))); + + StartWatching(); + policy_watcher_->SetPolicies(&empty_); + policy_watcher_->SetPolicies(&relay_false_); + policy_watcher_->SetPolicies(&relay_true_); + StopWatching(); +} + +TEST_F(PolicyWatcherTest, UdpPortRange) { + testing::InSequence sequence; + EXPECT_CALL(mock_policy_callback_, + OnPolicyUpdatePtr(IsPolicies(&nat_true_others_default_))); + EXPECT_CALL(mock_policy_callback_, + OnPolicyUpdatePtr(IsPolicies(&port_range_full_))); + EXPECT_CALL(mock_policy_callback_, + OnPolicyUpdatePtr(IsPolicies(&port_range_empty_))); + + StartWatching(); + policy_watcher_->SetPolicies(&empty_); + policy_watcher_->SetPolicies(&port_range_full_); + policy_watcher_->SetPolicies(&port_range_empty_); + StopWatching(); +} + } // namespace policy_hack } // namespace remoting diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index b9f4057..5d33b02 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc @@ -36,6 +36,7 @@ #include "remoting/base/constants.h" #include "remoting/base/logging.h" #include "remoting/base/rsa_key_pair.h" +#include "remoting/base/util.h" #include "remoting/host/branding.h" #include "remoting/host/chromoting_host.h" #include "remoting/host/chromoting_host_context.h" @@ -227,6 +228,8 @@ class HostProcess bool OnUsernamePolicyUpdate(bool curtain_required, bool username_match_required); bool OnNatPolicyUpdate(bool nat_traversal_enabled); + bool OnRelayPolicyUpdate(bool allow_relay); + bool OnUdpPortPolicyUpdate(const std::string& udp_port_range); void OnCurtainPolicyUpdate(bool curtain_required); bool OnHostTalkGadgetPrefixPolicyUpdate(const std::string& talkgadget_prefix); bool OnHostTokenUrlPolicyUpdate( @@ -287,6 +290,9 @@ class HostProcess bool use_service_account_; scoped_ptr<policy_hack::PolicyWatcher> policy_watcher_; bool allow_nat_traversal_; + bool allow_relay_; + int min_udp_port_; + int max_udp_port_; std::string talkgadget_prefix_; bool allow_pairing_; @@ -324,6 +330,9 @@ HostProcess::HostProcess(scoped_ptr<ChromotingHostContext> context, state_(HOST_INITIALIZING), use_service_account_(false), allow_nat_traversal_(true), + allow_relay_(true), + min_udp_port_(0), + max_udp_port_(0), allow_pairing_(true), curtain_required_(false), enable_gnubby_auth_(false), @@ -836,6 +845,16 @@ void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) { &bool_value)) { restart_required |= OnNatPolicyUpdate(bool_value); } + if (policies->GetBoolean(policy_hack::PolicyWatcher::kRelayPolicyName, + &bool_value)) { + restart_required |= OnRelayPolicyUpdate(bool_value); + } + std::string udp_port_range; + if (policies->GetString(policy_hack::PolicyWatcher::kUdpPortRangePolicyName, + &udp_port_range)) { + restart_required |= OnUdpPortPolicyUpdate(udp_port_range); + } + if (policies->GetString( policy_hack::PolicyWatcher::kHostTalkGadgetPrefixPolicyName, &string_value)) { @@ -942,6 +961,49 @@ bool HostProcess::OnNatPolicyUpdate(bool nat_traversal_enabled) { return false; } +bool HostProcess::OnRelayPolicyUpdate(bool allow_relay) { + // Returns true if the host has to be restarted after this policy update. + DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); + + if (allow_relay_ != allow_relay) { + if (allow_relay) + HOST_LOG << "Policy enables use of relay server."; + else + HOST_LOG << "Policy disables use of relay server."; + allow_relay_ = allow_relay; + return true; + } + return false; +} + +bool HostProcess::OnUdpPortPolicyUpdate(const std::string& udp_port_range) { + // Returns true if the host has to be restarted after this policy update. + DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); + + // Use default values if policy setting is empty or invalid. + int min_udp_port = 0; + int max_udp_port = 0; + if (!udp_port_range.empty() && + !NetworkSettings::ParsePortRange(udp_port_range, &min_udp_port, + &max_udp_port)) { + LOG(WARNING) << "Invalid port range policy: \"" << udp_port_range + << "\". Using default values."; + } + + if (min_udp_port_ != min_udp_port || max_udp_port_ != max_udp_port) { + if (min_udp_port != 0 && max_udp_port != 0) { + HOST_LOG << "Policy restricts UDP port range to [" << min_udp_port + << ", " << max_udp_port << "]"; + } else { + HOST_LOG << "Policy does not restrict UDP port range."; + } + min_udp_port_ = min_udp_port; + max_udp_port_ = max_udp_port; + return true; + } + return false; +} + void HostProcess::OnCurtainPolicyUpdate(bool curtain_required) { // Returns true if the host has to be restarted after this policy update. DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); @@ -1087,11 +1149,24 @@ void HostProcess::StartHost() { signaling_connector_->EnableOAuth(oauth_token_getter_.get()); } - NetworkSettings network_settings( - allow_nat_traversal_ ? - NetworkSettings::NAT_TRAVERSAL_ENABLED : - NetworkSettings::NAT_TRAVERSAL_DISABLED); - if (!allow_nat_traversal_) { + uint32 network_flags = allow_nat_traversal_ ? + NetworkSettings::NAT_TRAVERSAL_STUN : 0; + + if (allow_relay_) + network_flags |= NetworkSettings::NAT_TRAVERSAL_RELAY; + + if (allow_relay_ || allow_nat_traversal_) + network_flags |= NetworkSettings::NAT_TRAVERSAL_OUTGOING; + + NetworkSettings network_settings(network_flags); + + if (min_udp_port_ && max_udp_port_) { + network_settings.min_port = min_udp_port_; + network_settings.max_port = max_udp_port_; + } else if (!allow_nat_traversal_) { + // For legacy reasons we have to restrict the port range to a set of default + // values when nat traversal is disabled, even if the port range was not + // set in policy. network_settings.min_port = NetworkSettings::kDefaultMinPort; network_settings.max_port = NetworkSettings::kDefaultMaxPort; } diff --git a/remoting/jingle_glue/chromium_port_allocator.cc b/remoting/jingle_glue/chromium_port_allocator.cc index a179650..278cb6c 100644 --- a/remoting/jingle_glue/chromium_port_allocator.cc +++ b/remoting/jingle_glue/chromium_port_allocator.cc @@ -147,11 +147,13 @@ scoped_ptr<ChromiumPortAllocator> ChromiumPortAllocator::Create( int flags = cricket::PORTALLOCATOR_DISABLE_TCP | cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG | cricket::PORTALLOCATOR_ENABLE_IPV6; - if (network_settings.nat_traversal_mode != - NetworkSettings::NAT_TRAVERSAL_ENABLED) { - flags |= cricket::PORTALLOCATOR_DISABLE_STUN | - cricket::PORTALLOCATOR_DISABLE_RELAY; - } + + if (!(network_settings.flags & NetworkSettings::NAT_TRAVERSAL_STUN)) + flags |= cricket::PORTALLOCATOR_DISABLE_STUN; + + if (!(network_settings.flags & NetworkSettings::NAT_TRAVERSAL_RELAY)) + flags |= cricket::PORTALLOCATOR_DISABLE_RELAY; + result->set_flags(flags); result->SetPortRange(network_settings.min_port, network_settings.max_port); diff --git a/remoting/jingle_glue/network_settings.cc b/remoting/jingle_glue/network_settings.cc new file mode 100644 index 0000000..d3e464c --- /dev/null +++ b/remoting/jingle_glue/network_settings.cc @@ -0,0 +1,45 @@ +// Copyright 2014 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/jingle_glue/network_settings.h" + +#include <limits.h> +#include <stdlib.h> + +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" + +namespace remoting { + +// static + bool NetworkSettings::ParsePortRange(const std::string& port_range, + int* out_min_port, + int* out_max_port) { + size_t separator_index = port_range.find('-'); + if (separator_index == std::string::npos) + return false; + + std::string min_port_string, max_port_string; + base::TrimWhitespaceASCII(port_range.substr(0, separator_index), + base::TRIM_ALL, + &min_port_string); + base::TrimWhitespaceASCII(port_range.substr(separator_index + 1), + base::TRIM_ALL, + &max_port_string); + + unsigned min_port, max_port; + if (!base::StringToUint(min_port_string, &min_port) || + !base::StringToUint(max_port_string, &max_port)) { + return false; + } + + if (min_port == 0 || min_port > max_port || max_port > USHRT_MAX) + return false; + + *out_min_port = static_cast<int>(min_port); + *out_max_port = static_cast<int>(max_port); + return true; +} + +} // namespace remoting diff --git a/remoting/jingle_glue/network_settings.h b/remoting/jingle_glue/network_settings.h index a37b0bc..1ff83eb 100644 --- a/remoting/jingle_glue/network_settings.h +++ b/remoting/jingle_glue/network_settings.h @@ -5,6 +5,11 @@ #ifndef REMOTING_JINGLE_GLUE_NETWORK_SETTINGS_H_ #define REMOTING_JINGLE_GLUE_NETWORK_SETTINGS_H_ +#include <string> + +#include "base/basictypes.h" +#include "base/logging.h" + namespace remoting { struct NetworkSettings { @@ -15,33 +20,48 @@ struct NetworkSettings { static const int kDefaultMinPort = 12400; static const int kDefaultMaxPort = 12409; - enum NatTraversalMode { - // Active NAT traversal using STUN and relay servers. - NAT_TRAVERSAL_ENABLED, - + enum Flags { // Don't use STUN or relay servers. Accept incoming P2P connection // attempts, but don't initiate any. This ensures that the peer is // on the same network. Note that connection will always fail if // both ends use this mode. - NAT_TRAVERSAL_DISABLED, + NAT_TRAVERSAL_DISABLED = 0x0, + + // Allow outgoing connections, even when STUN and RELAY are not enabled. + NAT_TRAVERSAL_OUTGOING = 0x1, - // Don't use STUN or relay servers but make outgoing connections. - NAT_TRAVERSAL_OUTGOING, + // Active NAT traversal using STUN. + NAT_TRAVERSAL_STUN = 0x2, + + // Allow the use of relay servers when a direct connection is not available. + NAT_TRAVERSAL_RELAY = 0x4, + + // Active NAT traversal using STUN and relay servers. + NAT_TRAVERSAL_FULL = NAT_TRAVERSAL_STUN | NAT_TRAVERSAL_RELAY | + NAT_TRAVERSAL_OUTGOING }; NetworkSettings() - : nat_traversal_mode(NAT_TRAVERSAL_DISABLED), + : flags(NAT_TRAVERSAL_DISABLED), min_port(0), max_port(0) { + DCHECK(!(flags & (NAT_TRAVERSAL_STUN | NAT_TRAVERSAL_RELAY)) || + (flags & NAT_TRAVERSAL_OUTGOING)); } - explicit NetworkSettings(NatTraversalMode nat_traversal_mode) - : nat_traversal_mode(nat_traversal_mode), + explicit NetworkSettings(uint32 flags) + : flags(flags), min_port(0), max_port(0) { } - NatTraversalMode nat_traversal_mode; + // Parse string in the form "<min_port>-<max_port>". E.g. "12400-12409". + // Returns true if string was parsed successfuly. + static bool ParsePortRange(const std::string& port_range, + int* out_min_port, + int* out_max_port); + + uint32 flags; // |min_port| and |max_port| specify range (inclusive) of ports used by // P2P sessions. Any port can be used when both values are set to 0. diff --git a/remoting/jingle_glue/network_settings_unittest.cc b/remoting/jingle_glue/network_settings_unittest.cc new file mode 100644 index 0000000..4a00636 --- /dev/null +++ b/remoting/jingle_glue/network_settings_unittest.cc @@ -0,0 +1,41 @@ +// Copyright 2014 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/jingle_glue/network_settings.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace remoting { + +TEST(ParsePortRange, Basic) { + int min, max; + + // Valid range + EXPECT_TRUE(NetworkSettings::ParsePortRange("1-65535", &min, &max)); + EXPECT_EQ(1, min); + EXPECT_EQ(65535, max); + + EXPECT_TRUE(NetworkSettings::ParsePortRange(" 1 - 65535 ", &min, &max)); + EXPECT_EQ(1, min); + EXPECT_EQ(65535, max); + + EXPECT_TRUE(NetworkSettings::ParsePortRange("12400-12400", &min, &max)); + EXPECT_EQ(12400, min); + EXPECT_EQ(12400, max); + + // Invalid + EXPECT_FALSE(NetworkSettings::ParsePortRange("", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("-65535", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("1-", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("-", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("-1-65535", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("1--65535", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("1-65535-", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("0-65535", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("1-65536", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("1-4294967295", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("10-1", &min, &max)); + EXPECT_FALSE(NetworkSettings::ParsePortRange("1foo-2bar", &min, &max)); +} + +} // namespace remoting diff --git a/remoting/protocol/libjingle_transport_factory.cc b/remoting/protocol/libjingle_transport_factory.cc index b37cbb4..332665d 100644 --- a/remoting/protocol/libjingle_transport_factory.cc +++ b/remoting/protocol/libjingle_transport_factory.cc @@ -205,10 +205,8 @@ void LibjingleStreamTransport::DoStart() { this, &LibjingleStreamTransport::OnRouteChange); channel_->SignalWritableState.connect( this, &LibjingleStreamTransport::OnWritableState); - if (network_settings_.nat_traversal_mode == - NetworkSettings::NAT_TRAVERSAL_DISABLED) { - channel_->set_incoming_only(true); - } + channel_->set_incoming_only( + !(network_settings_.flags & NetworkSettings::NAT_TRAVERSAL_OUTGOING)); channel_->Connect(); @@ -452,8 +450,9 @@ LibjingleTransportFactory::CreateDatagramTransport() { } void LibjingleTransportFactory::EnsureFreshJingleInfo() { - if (network_settings_.nat_traversal_mode != - NetworkSettings::NAT_TRAVERSAL_ENABLED || + uint32 stun_or_relay_flags = NetworkSettings::NAT_TRAVERSAL_STUN | + NetworkSettings::NAT_TRAVERSAL_RELAY; + if (!(network_settings_.flags & stun_or_relay_flags) || jingle_info_request_) { return; } diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi index ed2a260..8e6222a 100644 --- a/remoting/remoting_srcs.gypi +++ b/remoting/remoting_srcs.gypi @@ -73,6 +73,7 @@ 'jingle_glue/iq_sender.h', 'jingle_glue/jingle_info_request.cc', 'jingle_glue/jingle_info_request.h', + 'jingle_glue/network_settings.cc', 'jingle_glue/network_settings.h', 'jingle_glue/signal_strategy.h', 'jingle_glue/xmpp_signal_strategy.cc', diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi index f70456f..7be4640 100644 --- a/remoting/remoting_test.gypi +++ b/remoting/remoting_test.gypi @@ -121,6 +121,7 @@ 'jingle_glue/iq_sender_unittest.cc', 'jingle_glue/mock_objects.cc', 'jingle_glue/mock_objects.h', + 'jingle_glue/network_settings_unittest.cc', 'protocol/authenticator_test_base.cc', 'protocol/authenticator_test_base.h', 'protocol/buffered_socket_writer_unittest.cc', diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 1d99d3f..49a2ceb 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -32751,6 +32751,10 @@ Therefore, the affected-histogram name has to have at least one dot in it. <int value="260" label="Media keys default to function keys"/> <int value="261" label="Enable WPAD quick check"/> <int value="262" label="Wallpaper image"/> + <int value="263" + label="Enable the use of relay servers by the remote access host"/> + <int value="264" + label="Restrict the UDP port range used by the remote access host"/> </enum> <enum name="EnterprisePolicyInvalidations" type="int"> |