summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrmsousa@chromium.org <rmsousa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-06 04:50:43 +0000
committerrmsousa@chromium.org <rmsousa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-06 04:50:43 +0000
commit4386f0a9e032a669a6e6c311965ff3a9903850b9 (patch)
treed98e16fb9510c3391b780459c7d0f4b864af02d7
parent46ad339269e5805bb499ebb76ce1077ff8c8d5be (diff)
downloadchromium_src-4386f0a9e032a669a6e6c311965ff3a9903850b9.zip
chromium_src-4386f0a9e032a669a6e6c311965ff3a9903850b9.tar.gz
chromium_src-4386f0a9e032a669a6e6c311965ff3a9903850b9.tar.bz2
Host-side third party token validation
This creates a TokenValidator implementation on the host, that upon receiving a token: Signs the token with its private key. Uses URLFetcher to request the exchange of the token for a secret from the Token Validation URL. On receiving a reply, checks that the scope in the reply matches the one required for this connection. Uses the callback to send the shared_token back to the authentication layer. (The server will authenticate the host by checking that the token signature matches the host public key that the client included in the token request) BUG=115899 Review URL: https://chromiumcodereview.appspot.com/12313085 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192701 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/host/policy_hack/policy_watcher.cc12
-rw-r--r--remoting/host/policy_hack/policy_watcher.h4
-rw-r--r--remoting/host/policy_hack/policy_watcher_unittest.cc2
-rw-r--r--remoting/host/remoting_me2me_host.cc61
-rw-r--r--remoting/host/token_validator_factory_impl.cc184
-rw-r--r--remoting/host/token_validator_factory_impl.h50
-rw-r--r--remoting/protocol/it2me_host_authenticator_factory.cc4
-rw-r--r--remoting/protocol/me2me_host_authenticator_factory.cc57
-rw-r--r--remoting/protocol/me2me_host_authenticator_factory.h23
-rw-r--r--remoting/protocol/negotiating_authenticator_unittest.cc4
-rw-r--r--remoting/protocol/negotiating_host_authenticator.cc52
-rw-r--r--remoting/protocol/negotiating_host_authenticator.h20
-rw-r--r--remoting/protocol/third_party_host_authenticator.h13
-rw-r--r--remoting/remoting.gyp2
14 files changed, 457 insertions, 31 deletions
diff --git a/remoting/host/policy_hack/policy_watcher.cc b/remoting/host/policy_hack/policy_watcher.cc
index 7194bae..3f0ef7a 100644
--- a/remoting/host/policy_hack/policy_watcher.cc
+++ b/remoting/host/policy_hack/policy_watcher.cc
@@ -92,6 +92,12 @@ const char PolicyWatcher::kHostTalkGadgetPrefixPolicyName[] =
const char PolicyWatcher::kHostRequireCurtainPolicyName[] =
"RemoteAccessHostRequireCurtain";
+const char PolicyWatcher::kHostTokenUrlPolicyName[] =
+ "RemoteAccessHostTokenUrl";
+
+const char PolicyWatcher::kHostTokenValidationUrlPolicyName[] =
+ "RemoteAccessHostTokenValidationUrl";
+
const char PolicyWatcher::kHostDebugOverridePoliciesName[] =
"RemoteAccessHostDebugOverridePolicies";
@@ -106,11 +112,13 @@ PolicyWatcher::PolicyWatcher(
default_values_->SetBoolean(kHostRequireTwoFactorPolicyName, false);
default_values_->SetBoolean(kHostRequireCurtainPolicyName, false);
default_values_->SetBoolean(kHostMatchUsernamePolicyName, false);
- default_values_->SetString(kHostDomainPolicyName, "");
+ default_values_->SetString(kHostDomainPolicyName, std::string());
default_values_->SetString(kHostTalkGadgetPrefixPolicyName,
kDefaultHostTalkGadgetPrefix);
+ default_values_->SetString(kHostTokenUrlPolicyName, std::string());
+ default_values_->SetString(kHostTokenValidationUrlPolicyName, std::string());
#if !defined(NDEBUG)
- default_values_->SetString(kHostDebugOverridePoliciesName, "");
+ default_values_->SetString(kHostDebugOverridePoliciesName, std::string());
#endif
// Initialize the fall-back values to use for unreadable policies.
diff --git a/remoting/host/policy_hack/policy_watcher.h b/remoting/host/policy_hack/policy_watcher.h
index 433dd66..23e2209 100644
--- a/remoting/host/policy_hack/policy_watcher.h
+++ b/remoting/host/policy_hack/policy_watcher.h
@@ -64,6 +64,10 @@ class PolicyWatcher {
// The name of the policy for requiring curtain-mode.
static const char kHostRequireCurtainPolicyName[];
+ // The names of the policies for token authentication URLs.
+ static const char kHostTokenUrlPolicyName[];
+ static const char kHostTokenValidationUrlPolicyName[];
+
// 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 6d89673..d323718 100644
--- a/remoting/host/policy_hack/policy_watcher_unittest.cc
+++ b/remoting/host/policy_hack/policy_watcher_unittest.cc
@@ -122,6 +122,8 @@ class PolicyWatcherTest : public testing::Test {
dict.SetString(PolicyWatcher::kHostTalkGadgetPrefixPolicyName,
kDefaultHostTalkGadgetPrefix);
dict.SetBoolean(PolicyWatcher::kHostRequireCurtainPolicyName, false);
+ dict.SetString(PolicyWatcher::kHostTokenUrlPolicyName, "");
+ dict.SetString(PolicyWatcher::kHostTokenValidationUrlPolicyName, "");
#if !defined(NDEBUG)
dict.SetString(PolicyWatcher::kHostDebugOverridePoliciesName, "");
#endif
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc
index 3e358a8..8242ee6 100644
--- a/remoting/host/remoting_me2me_host.cc
+++ b/remoting/host/remoting_me2me_host.cc
@@ -34,6 +34,7 @@
#include "remoting/base/auto_thread_task_runner.h"
#include "remoting/base/breakpad.h"
#include "remoting/base/constants.h"
+#include "remoting/base/rsa_key_pair.h"
#include "remoting/base/util.h"
#include "remoting/host/branding.h"
#include "remoting/host/chromoting_host.h"
@@ -63,6 +64,7 @@
#include "remoting/host/service_urls.h"
#include "remoting/host/session_manager_factory.h"
#include "remoting/host/signaling_connector.h"
+#include "remoting/host/token_validator_factory_impl.h"
#include "remoting/host/ui_strings.h"
#include "remoting/host/usage_stats_consent.h"
#include "remoting/jingle_glue/xmpp_signal_strategy.h"
@@ -204,6 +206,8 @@ class HostProcess
bool OnNatPolicyUpdate(bool nat_traversal_enabled);
bool OnCurtainPolicyUpdate(bool curtain_required);
bool OnHostTalkGadgetPrefixPolicyUpdate(const std::string& talkgadget_prefix);
+ bool OnHostTokenUrlPolicyUpdate(const GURL& token_url,
+ const GURL& token_validation_url);
void StartHost();
@@ -267,6 +271,8 @@ class HostProcess
scoped_ptr<CurtainMode> curtain_;
scoped_ptr<CurtainingHostObserver> curtaining_host_observer_;
bool curtain_required_;
+ GURL token_url_;
+ GURL token_validation_url_;
scoped_ptr<XmppSignalStrategy> signal_strategy_;
scoped_ptr<SignalingConnector> signaling_connector_;
@@ -476,10 +482,29 @@ void HostProcess::CreateAuthenticatorFactory() {
ShutdownHost(kInitializationFailed);
return;
}
+ scoped_ptr<protocol::AuthenticatorFactory> factory;
+
+ if (token_url_.is_empty() && token_validation_url_.is_empty()) {
+ factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
+ local_certificate, key_pair_, host_secret_hash_);
+ } else if (token_url_.is_valid() && token_validation_url_.is_valid()) {
+ scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidatorFactory>
+ token_validator_factory(new TokenValidatorFactoryImpl(
+ token_url_, token_validation_url_, key_pair_,
+ context_->url_request_context_getter()));
+ factory = protocol::Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
+ local_certificate, key_pair_, token_validator_factory.Pass());
+ } else {
+ // TODO(rmsousa): If the policy is bad the host should not go online. It
+ // should keep running, but not connected, until the policies are fixed.
+ // Having it show up as online and then reject all clients is misleading.
+ LOG(ERROR) << "One of the third-party token URLs is empty or invalid. "
+ << "Host will reject all clients until policies are corrected. "
+ << "TokenUrl: " << token_url_ << ", "
+ << "TokenValidationUrl: " << token_validation_url_;
+ factory = protocol::Me2MeHostAuthenticatorFactory::CreateRejecting();
+ }
- scoped_ptr<protocol::AuthenticatorFactory> factory(
- new protocol::Me2MeHostAuthenticatorFactory(
- local_certificate, key_pair_, host_secret_hash_));
#if defined(OS_POSIX)
// On Linux and Mac, perform a PAM authorization step after authentication.
factory.reset(new PamAuthorizationFactory(factory.Pass()));
@@ -718,6 +743,16 @@ void HostProcess::OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
&bool_value)) {
restart_required |= OnCurtainPolicyUpdate(bool_value);
}
+ std::string token_url_string, token_validation_url_string;
+ if (policies->GetString(
+ policy_hack::PolicyWatcher::kHostTokenUrlPolicyName,
+ &token_url_string) &&
+ policies->GetString(
+ policy_hack::PolicyWatcher::kHostTokenValidationUrlPolicyName,
+ &token_validation_url_string)) {
+ restart_required |= OnHostTokenUrlPolicyUpdate(
+ GURL(token_url_string), GURL(token_validation_url_string));
+ }
if (state_ == HOST_INITIALIZING) {
StartHost();
@@ -841,6 +876,26 @@ bool HostProcess::OnHostTalkGadgetPrefixPolicyUpdate(
return false;
}
+bool HostProcess::OnHostTokenUrlPolicyUpdate(
+ const GURL& token_url,
+ const GURL& token_validation_url) {
+ // Returns true if the host has to be restarted after this policy update.
+ DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
+
+ if (token_url_ != token_url ||
+ token_validation_url_ != token_validation_url) {
+ LOG(INFO) << "Policy sets third-party token URLs: "
+ << "TokenUrl: " << token_url << ", "
+ << "TokenValidationUrl: " << token_validation_url;
+
+ token_url_ = token_url;
+ token_validation_url_ = token_validation_url;
+ return true;
+ }
+
+ return false;
+}
+
void HostProcess::StartHost() {
DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
DCHECK(!host_);
diff --git a/remoting/host/token_validator_factory_impl.cc b/remoting/host/token_validator_factory_impl.cc
new file mode 100644
index 0000000..a61bfaa
--- /dev/null
+++ b/remoting/host/token_validator_factory_impl.cc
@@ -0,0 +1,184 @@
+// Copyright 2013 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/token_validator_factory_impl.h"
+
+#include <set>
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/json/json_reader.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
+#include "base/values.h"
+#include "crypto/random.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/escape.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_status.h"
+#include "remoting/base/rsa_key_pair.h"
+
+namespace {
+
+// Length in bytes of the cryptographic nonce used to salt the token scope.
+const size_t kNonceLength = 16; // 128 bits.
+
+}
+
+namespace remoting {
+
+class TokenValidatorImpl
+ : public net::URLFetcherDelegate,
+ public protocol::ThirdPartyHostAuthenticator::TokenValidator {
+ public:
+ TokenValidatorImpl(
+ const GURL& token_url,
+ const GURL& token_validation_url,
+ scoped_refptr<RsaKeyPair> key_pair,
+ const std::string& local_jid,
+ const std::string& remote_jid,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter)
+ : token_url_(token_url),
+ token_validation_url_(token_validation_url),
+ key_pair_(key_pair),
+ request_context_getter_(request_context_getter) {
+ DCHECK(token_url_.is_valid());
+ DCHECK(token_validation_url_.is_valid());
+ DCHECK(key_pair_);
+ token_scope_ = CreateScope(local_jid, remote_jid);
+ }
+
+ virtual ~TokenValidatorImpl() {
+ }
+
+ // TokenValidator interface.
+ virtual void ValidateThirdPartyToken(
+ const std::string& token,
+ const base::Callback<void(
+ const std::string& shared_secret)>& on_token_validated) OVERRIDE {
+ DCHECK(!request_);
+ DCHECK(!on_token_validated.is_null());
+
+ on_token_validated_ = on_token_validated;
+
+ std::string post_body =
+ "code=" + net::EscapeUrlEncodedData(token, true) +
+ "&client_id=" + net::EscapeUrlEncodedData(
+ key_pair_->GetPublicKey(), true) +
+ "&client_secret=" + net::EscapeUrlEncodedData(
+ key_pair_->SignMessage(token), true) +
+ "&grant_type=authorization_code";
+ request_.reset(net::URLFetcher::Create(
+ token_validation_url_, net::URLFetcher::POST, this));
+ request_->SetUploadData("application/x-www-form-urlencoded", post_body);
+ request_->SetRequestContext(request_context_getter_);
+ request_->Start();
+ }
+
+ virtual const GURL& token_url() const OVERRIDE {
+ return token_url_;
+ }
+
+ virtual const std::string& token_scope() const OVERRIDE {
+ return token_scope_;
+ }
+
+ // URLFetcherDelegate interface.
+ virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
+ DCHECK_EQ(request_.get(), source);
+ std::string shared_token = ProcessResponse();
+ on_token_validated_.Run(shared_token);
+ request_.reset();
+ }
+
+ private:
+ bool IsValidScope(const std::string& token_scope) {
+ // TODO(rmsousa): Deal with reordering/subsets/supersets/aliases/etc.
+ return token_scope == token_scope_;
+ }
+
+ static std::string CreateScope(const std::string& local_jid,
+ const std::string& remote_jid) {
+ char nonce_bytes[kNonceLength];
+ crypto::RandBytes(nonce_bytes, kNonceLength);
+ std::string nonce;
+ bool success = base::Base64Encode(nonce_bytes, &nonce);
+ DCHECK(success);
+ return "client:" + remote_jid + " host:" + local_jid + " nonce:" + nonce;
+ }
+
+ std::string ProcessResponse() {
+ // Verify that we got a successful response.
+ int response = request_->GetResponseCode();
+ net::URLRequestStatus status = request_->GetStatus();
+ std::string data;
+ if (!status.is_success() || response != 200) {
+ LOG(ERROR)
+ << "Error " << response << " validating token: '" << data << "'";
+ return std::string();
+ }
+
+ // Decode the JSON data from the response.
+ request_->GetResponseAsString(&data);
+ scoped_ptr<base::Value> value(base::JSONReader::Read(data));
+ DictionaryValue* dict;
+ if (!value.get() || value->GetType() != base::Value::TYPE_DICTIONARY ||
+ !value->GetAsDictionary(&dict)) {
+ LOG(ERROR) << "Invalid token validation response: '" << data << "'";
+ return std::string();
+ }
+
+ std::string token_scope;
+ dict->GetStringWithoutPathExpansion("scope", &token_scope);
+ if (!IsValidScope(token_scope)) {
+ LOG(ERROR) << "Invalid scope: '" << token_scope
+ << "', expected: '" << token_scope_ <<"'.";
+ return std::string();
+ }
+
+ std::string shared_secret;
+ // Everything is valid, so return the shared secret to the caller.
+ dict->GetStringWithoutPathExpansion("access_token", &shared_secret);
+ return shared_secret;
+ }
+
+ scoped_ptr<net::URLFetcher> request_;
+ GURL token_url_;
+ GURL token_validation_url_;
+ scoped_refptr<RsaKeyPair> key_pair_;
+ std::string token_scope_;
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+ base::Callback<void(const std::string& shared_secret)> on_token_validated_;
+
+ DISALLOW_COPY_AND_ASSIGN(TokenValidatorImpl);
+};
+
+TokenValidatorFactoryImpl::TokenValidatorFactoryImpl(
+ const GURL& token_url,
+ const GURL& token_validation_url,
+ scoped_refptr<RsaKeyPair> key_pair,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter)
+ : token_url_(token_url),
+ token_validation_url_(token_validation_url),
+ key_pair_(key_pair),
+ request_context_getter_(request_context_getter) {
+}
+
+TokenValidatorFactoryImpl::~TokenValidatorFactoryImpl() {
+}
+
+scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidator>
+TokenValidatorFactoryImpl::CreateTokenValidator(
+ const std::string& local_jid,
+ const std::string& remote_jid) {
+ return scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidator>(
+ new TokenValidatorImpl(token_url_, token_validation_url_, key_pair_,
+ local_jid, remote_jid,
+ request_context_getter_));
+}
+
+} // namespace remoting
diff --git a/remoting/host/token_validator_factory_impl.h b/remoting/host/token_validator_factory_impl.h
new file mode 100644
index 0000000..042f8e22
--- /dev/null
+++ b/remoting/host/token_validator_factory_impl.h
@@ -0,0 +1,50 @@
+// Copyright 2013 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_TOKEN_VALIDATOR_FACTORY_IMPL_H_
+#define REMOTING_HOST_TOKEN_VALIDATOR_FACTORY_IMPL_H_
+
+#include <set>
+#include <string>
+
+#include "base/basictypes.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "remoting/protocol/third_party_host_authenticator.h"
+
+namespace remoting {
+
+// This class dispenses |TokenValidator| implementations that use a UrlFetcher
+// to contact a |token_validation_url| and exchange the |token| for a
+// |shared_secret|.
+class TokenValidatorFactoryImpl
+ : public protocol::ThirdPartyHostAuthenticator::TokenValidatorFactory {
+ public:
+ // Creates a new factory. |token_url| and |token_validation_url| are the
+ // third party authentication service URLs, obtained via policy. |key_pair_|
+ // is used by the host to authenticate with the service by signing the token.
+ TokenValidatorFactoryImpl(
+ const GURL& token_url,
+ const GURL& token_validation_url,
+ scoped_refptr<RsaKeyPair> key_pair,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter);
+
+ virtual ~TokenValidatorFactoryImpl();
+
+ // TokenValidatorFactory interface.
+ virtual scoped_ptr<protocol::ThirdPartyHostAuthenticator::TokenValidator>
+ CreateTokenValidator(const std::string& local_jid,
+ const std::string& remote_jid) OVERRIDE;
+
+ private:
+ GURL token_url_;
+ GURL token_validation_url_;
+ scoped_refptr<RsaKeyPair> key_pair_;
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+
+ DISALLOW_COPY_AND_ASSIGN(TokenValidatorFactoryImpl);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_URL_FETCHER_TOKEN_VALIDATOR_FACTORY_H_
diff --git a/remoting/protocol/it2me_host_authenticator_factory.cc b/remoting/protocol/it2me_host_authenticator_factory.cc
index e9f6c09..e5e446a 100644
--- a/remoting/protocol/it2me_host_authenticator_factory.cc
+++ b/remoting/protocol/it2me_host_authenticator_factory.cc
@@ -27,8 +27,8 @@ scoped_ptr<Authenticator> It2MeHostAuthenticatorFactory::CreateAuthenticator(
const std::string& local_jid,
const std::string& remote_jid,
const buzz::XmlElement* first_message) {
- return scoped_ptr<Authenticator>(new NegotiatingHostAuthenticator(
- local_cert_, key_pair_, shared_secret_, AuthenticationMethod::NONE));
+ return NegotiatingHostAuthenticator::CreateWithSharedSecret(
+ local_cert_, key_pair_, shared_secret_, AuthenticationMethod::NONE);
}
} // namespace protocol
diff --git a/remoting/protocol/me2me_host_authenticator_factory.cc b/remoting/protocol/me2me_host_authenticator_factory.cc
index 4ee7b65..5d908e7 100644
--- a/remoting/protocol/me2me_host_authenticator_factory.cc
+++ b/remoting/protocol/me2me_host_authenticator_factory.cc
@@ -58,13 +58,43 @@ class RejectingAuthenticator : public Authenticator {
} // namespace
-Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory(
+// static
+scoped_ptr<AuthenticatorFactory>
+Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
const std::string& local_cert,
scoped_refptr<RsaKeyPair> key_pair,
- const SharedSecretHash& shared_secret_hash)
- : local_cert_(local_cert),
- key_pair_(key_pair),
- shared_secret_hash_(shared_secret_hash) {
+ const SharedSecretHash& shared_secret_hash) {
+ scoped_ptr<Me2MeHostAuthenticatorFactory> result(
+ new Me2MeHostAuthenticatorFactory());
+ result->local_cert_ = local_cert;
+ result->key_pair_ = key_pair;
+ result->shared_secret_hash_ = shared_secret_hash;
+ return scoped_ptr<AuthenticatorFactory>(result.Pass());
+}
+
+
+// static
+scoped_ptr<AuthenticatorFactory>
+Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
+ const std::string& local_cert,
+ scoped_refptr<RsaKeyPair> key_pair,
+ scoped_ptr<ThirdPartyHostAuthenticator::TokenValidatorFactory>
+ token_validator_factory) {
+ scoped_ptr<Me2MeHostAuthenticatorFactory> result(
+ new Me2MeHostAuthenticatorFactory());
+ result->local_cert_ = local_cert;
+ result->key_pair_ = key_pair;
+ result->token_validator_factory_ = token_validator_factory.Pass();
+ return scoped_ptr<AuthenticatorFactory>(result.Pass());
+}
+
+// static
+scoped_ptr<AuthenticatorFactory>
+ Me2MeHostAuthenticatorFactory::CreateRejecting() {
+ return scoped_ptr<AuthenticatorFactory>(new Me2MeHostAuthenticatorFactory());
+}
+
+Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory() {
}
Me2MeHostAuthenticatorFactory::~Me2MeHostAuthenticatorFactory() {
@@ -91,9 +121,20 @@ scoped_ptr<Authenticator> Me2MeHostAuthenticatorFactory::CreateAuthenticator(
return scoped_ptr<Authenticator>(new RejectingAuthenticator());
}
- return scoped_ptr<Authenticator>(new NegotiatingHostAuthenticator(
- local_cert_, key_pair_, shared_secret_hash_.value,
- shared_secret_hash_.hash_function));
+ if (!local_cert_.empty() && key_pair_) {
+ if (token_validator_factory_) {
+ return NegotiatingHostAuthenticator::CreateWithThirdPartyAuth(
+ local_cert_, key_pair_,
+ token_validator_factory_->CreateTokenValidator(
+ local_jid, remote_jid));
+ }
+
+ return NegotiatingHostAuthenticator::CreateWithSharedSecret(
+ local_cert_, key_pair_, shared_secret_hash_.value,
+ shared_secret_hash_.hash_function);
+ }
+
+ return scoped_ptr<Authenticator>(new RejectingAuthenticator());
}
} // namespace protocol
diff --git a/remoting/protocol/me2me_host_authenticator_factory.h b/remoting/protocol/me2me_host_authenticator_factory.h
index e6375a2..7d0eebe 100644
--- a/remoting/protocol/me2me_host_authenticator_factory.h
+++ b/remoting/protocol/me2me_host_authenticator_factory.h
@@ -13,6 +13,7 @@
#include "base/memory/scoped_ptr.h"
#include "remoting/protocol/authentication_method.h"
#include "remoting/protocol/authenticator.h"
+#include "remoting/protocol/third_party_host_authenticator.h"
namespace remoting {
@@ -22,10 +23,22 @@ namespace protocol {
class Me2MeHostAuthenticatorFactory : public AuthenticatorFactory {
public:
- Me2MeHostAuthenticatorFactory(
+ // Create a factory that dispenses shared secret authenticators.
+ static scoped_ptr<AuthenticatorFactory> CreateWithSharedSecret(
const std::string& local_cert,
scoped_refptr<RsaKeyPair> key_pair,
const SharedSecretHash& shared_secret_hash);
+ // Create a factory that dispenses third party authenticators.
+ static scoped_ptr<AuthenticatorFactory> CreateWithThirdPartyAuth(
+ const std::string& local_cert,
+ scoped_refptr<RsaKeyPair> key_pair,
+ scoped_ptr<ThirdPartyHostAuthenticator::TokenValidatorFactory>
+ token_validator_factory);
+ // Create a factory that dispenses rejecting authenticators (used when the
+ // host config/policy is inconsistent)
+ static scoped_ptr<AuthenticatorFactory> CreateRejecting();
+
+ Me2MeHostAuthenticatorFactory();
virtual ~Me2MeHostAuthenticatorFactory();
// AuthenticatorFactory interface.
@@ -35,11 +48,17 @@ class Me2MeHostAuthenticatorFactory : public AuthenticatorFactory {
const buzz::XmlElement* first_message) OVERRIDE;
private:
- std::string local_jid_prefix_;
+ // Used for all host authenticators.
std::string local_cert_;
scoped_refptr<RsaKeyPair> key_pair_;
+
+ // Used only for shared secret host authenticators.
SharedSecretHash shared_secret_hash_;
+ // Used only for third party host authenticators.
+ scoped_ptr<ThirdPartyHostAuthenticator::TokenValidatorFactory>
+ token_validator_factory_;
+
DISALLOW_COPY_AND_ASSIGN(Me2MeHostAuthenticatorFactory);
};
diff --git a/remoting/protocol/negotiating_authenticator_unittest.cc b/remoting/protocol/negotiating_authenticator_unittest.cc
index 1a6e93f..e33b7d6 100644
--- a/remoting/protocol/negotiating_authenticator_unittest.cc
+++ b/remoting/protocol/negotiating_authenticator_unittest.cc
@@ -49,8 +49,8 @@ class NegotiatingAuthenticatorTest : public AuthenticatorTestBase {
bool client_hmac_only) {
std::string host_secret_hash = AuthenticationMethod::ApplyHashFunction(
hash_function, kTestHostId, host_secret);
- host_.reset(new NegotiatingHostAuthenticator(
- host_cert_, key_pair_, host_secret_hash, hash_function));
+ host_ = NegotiatingHostAuthenticator::CreateWithSharedSecret(
+ host_cert_, key_pair_, host_secret_hash, hash_function);
std::vector<AuthenticationMethod> methods;
methods.push_back(AuthenticationMethod::Spake2(
diff --git a/remoting/protocol/negotiating_host_authenticator.cc b/remoting/protocol/negotiating_host_authenticator.cc
index c54b6af..f60a6d2 100644
--- a/remoting/protocol/negotiating_host_authenticator.cc
+++ b/remoting/protocol/negotiating_host_authenticator.cc
@@ -21,15 +21,36 @@ namespace protocol {
NegotiatingHostAuthenticator::NegotiatingHostAuthenticator(
const std::string& local_cert,
- scoped_refptr<RsaKeyPair> key_pair,
- const std::string& shared_secret_hash,
- AuthenticationMethod::HashFunction hash_function)
+ scoped_refptr<RsaKeyPair> key_pair)
: NegotiatingAuthenticatorBase(WAITING_MESSAGE),
local_cert_(local_cert),
- local_key_pair_(key_pair),
- shared_secret_hash_(shared_secret_hash) {
+ local_key_pair_(key_pair) {
+}
- AddMethod(AuthenticationMethod::Spake2(hash_function));
+// static
+scoped_ptr<Authenticator> NegotiatingHostAuthenticator::CreateWithSharedSecret(
+ const std::string& local_cert,
+ scoped_refptr<RsaKeyPair> key_pair,
+ const std::string& shared_secret_hash,
+ AuthenticationMethod::HashFunction hash_function) {
+ scoped_ptr<NegotiatingHostAuthenticator> result(
+ new NegotiatingHostAuthenticator(local_cert, key_pair));
+ result->shared_secret_hash_ = shared_secret_hash;
+ result->AddMethod(AuthenticationMethod::Spake2(hash_function));
+ return scoped_ptr<Authenticator>(result.Pass());
+}
+
+// static
+scoped_ptr<Authenticator>
+NegotiatingHostAuthenticator::CreateWithThirdPartyAuth(
+ const std::string& local_cert,
+ scoped_refptr<RsaKeyPair> key_pair,
+ scoped_ptr<ThirdPartyHostAuthenticator::TokenValidator> token_validator) {
+ scoped_ptr<NegotiatingHostAuthenticator> result(
+ new NegotiatingHostAuthenticator(local_cert, key_pair));
+ result->token_validator_ = token_validator.Pass();
+ result->AddMethod(AuthenticationMethod::ThirdParty());
+ return scoped_ptr<Authenticator>(result.Pass());
}
NegotiatingHostAuthenticator::~NegotiatingHostAuthenticator() {
@@ -55,7 +76,6 @@ void NegotiatingHostAuthenticator::ProcessMessage(
// then select the first known method from the supported-methods attribute.
if (!method.is_valid() ||
std::find(methods_.begin(), methods_.end(), method) == methods_.end()) {
-
method = AuthenticationMethod::Invalid();
std::string supported_methods_attr =
@@ -126,9 +146,21 @@ scoped_ptr<buzz::XmlElement> NegotiatingHostAuthenticator::GetNextMessage() {
void NegotiatingHostAuthenticator::CreateAuthenticator(
Authenticator::State preferred_initial_state,
const base::Closure& resume_callback) {
- current_authenticator_ = V2Authenticator::CreateForHost(
- local_cert_, local_key_pair_, shared_secret_hash_,
- preferred_initial_state);
+ DCHECK(current_method_.is_valid());
+
+ if (current_method_.type() == AuthenticationMethod::THIRD_PARTY) {
+ // |ThirdPartyHostAuthenticator| takes ownership of |token_validator_|.
+ // The authentication method negotiation logic should guarantee that only
+ // one |ThirdPartyHostAuthenticator| will need to be created per session.
+ DCHECK(token_validator_);
+ current_authenticator_.reset(new ThirdPartyHostAuthenticator(
+ local_cert_, local_key_pair_, token_validator_.Pass()));
+ } else {
+ current_authenticator_ = V2Authenticator::CreateForHost(
+ local_cert_, local_key_pair_, shared_secret_hash_,
+ preferred_initial_state);
+ }
+
resume_callback.Run();
}
diff --git a/remoting/protocol/negotiating_host_authenticator.h b/remoting/protocol/negotiating_host_authenticator.h
index 4ff53f6..588fee2 100644
--- a/remoting/protocol/negotiating_host_authenticator.h
+++ b/remoting/protocol/negotiating_host_authenticator.h
@@ -15,6 +15,7 @@
#include "remoting/protocol/authentication_method.h"
#include "remoting/protocol/authenticator.h"
#include "remoting/protocol/negotiating_authenticator_base.h"
+#include "remoting/protocol/third_party_host_authenticator.h"
namespace remoting {
@@ -26,14 +27,20 @@ namespace protocol {
// See comments in negotiating_authenticator_base.h for a general explanation.
class NegotiatingHostAuthenticator : public NegotiatingAuthenticatorBase {
public:
+ virtual ~NegotiatingHostAuthenticator();
+
// Creates a host authenticator, using a fixed shared secret/PIN hash.
- NegotiatingHostAuthenticator(
+ static scoped_ptr<Authenticator> CreateWithSharedSecret(
const std::string& local_cert,
scoped_refptr<RsaKeyPair> key_pair,
const std::string& shared_secret_hash,
AuthenticationMethod::HashFunction hash_function);
- virtual ~NegotiatingHostAuthenticator();
+ // Creates a host authenticator, using third party authentication.
+ static scoped_ptr<Authenticator> CreateWithThirdPartyAuth(
+ const std::string& local_cert,
+ scoped_refptr<RsaKeyPair> key_pair,
+ scoped_ptr<ThirdPartyHostAuthenticator::TokenValidator> token_validator);
// Overriden from Authenticator.
virtual void ProcessMessage(const buzz::XmlElement* message,
@@ -41,6 +48,10 @@ class NegotiatingHostAuthenticator : public NegotiatingAuthenticatorBase {
virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE;
private:
+ NegotiatingHostAuthenticator(
+ const std::string& local_cert,
+ scoped_refptr<RsaKeyPair> key_pair);
+
// (Asynchronously) creates an authenticator, and stores it in
// |current_authenticator_|. Authenticators that can be started in either
// state will be created in |preferred_initial_state|.
@@ -50,8 +61,13 @@ class NegotiatingHostAuthenticator : public NegotiatingAuthenticatorBase {
std::string local_cert_;
scoped_refptr<RsaKeyPair> local_key_pair_;
+
+ // Used only for shared secret host authenticators.
std::string shared_secret_hash_;
+ // Used only for third party host authenticators.
+ scoped_ptr<ThirdPartyHostAuthenticator::TokenValidator> token_validator_;
+
DISALLOW_COPY_AND_ASSIGN(NegotiatingHostAuthenticator);
};
diff --git a/remoting/protocol/third_party_host_authenticator.h b/remoting/protocol/third_party_host_authenticator.h
index b72ac05..60538b2 100644
--- a/remoting/protocol/third_party_host_authenticator.h
+++ b/remoting/protocol/third_party_host_authenticator.h
@@ -54,6 +54,17 @@ class ThirdPartyHostAuthenticator : public ThirdPartyAuthenticatorBase {
virtual const std::string& token_scope() const = 0;
};
+ class TokenValidatorFactory {
+ public:
+ virtual ~TokenValidatorFactory() {}
+
+ // Creates a TokenValidator. |local_jid| and |remote_jid| are used to create
+ // a token scope that is restricted to the current connection's JIDs.
+ virtual scoped_ptr<TokenValidator> CreateTokenValidator(
+ const std::string& local_jid,
+ const std::string& remote_jid) = 0;
+ };
+
// Creates a third-party host authenticator. |local_cert| and |key_pair| are
// used by the underlying V2Authenticator to create the SSL channels.
// |token_validator| contains the token parameters to be sent to the client
@@ -78,6 +89,8 @@ class ThirdPartyHostAuthenticator : public ThirdPartyAuthenticatorBase {
std::string local_cert_;
scoped_refptr<RsaKeyPair> key_pair_;
scoped_ptr<TokenValidator> token_validator_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThirdPartyHostAuthenticator);
};
} // namespace protocol
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index dd1670c..ce276ca 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -441,6 +441,8 @@
'host/session_manager_factory.h',
'host/signaling_connector.cc',
'host/signaling_connector.h',
+ 'host/token_validator_factory_impl.cc',
+ 'host/token_validator_factory_impl.h',
'host/ui_strings.cc',
'host/ui_strings.h',
'host/url_request_context.cc',