Commit 4386f0a9 authored by rmsousa@chromium.org's avatar rmsousa@chromium.org

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
parent 46ad3392
......@@ -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.
......
......@@ -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[];
......
......@@ -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
......
......@@ -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_);
......
// 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
// 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_
......@@ -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
......
......@@ -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
......
......@@ -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);
};
......
......@@ -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(
......
......@@ -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();
}
......
......@@ -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();