This source file includes following definitions.
- weak_factory_
- ProcessMessage
- GetNextMessage
- CreateAuthenticatorForCurrentMethod
- CreatePreferredAuthenticator
- CreateV2AuthenticatorWithSecret
#include "remoting/protocol/negotiating_client_authenticator.h"
#include <algorithm>
#include <sstream>
#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "remoting/protocol/channel_authenticator.h"
#include "remoting/protocol/pairing_client_authenticator.h"
#include "remoting/protocol/v2_authenticator.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
namespace remoting {
namespace protocol {
NegotiatingClientAuthenticator::NegotiatingClientAuthenticator(
const std::string& client_pairing_id,
const std::string& shared_secret,
const std::string& authentication_tag,
const FetchSecretCallback& fetch_secret_callback,
scoped_ptr<ThirdPartyClientAuthenticator::TokenFetcher> token_fetcher,
const std::vector<AuthenticationMethod>& methods)
: NegotiatingAuthenticatorBase(MESSAGE_READY),
client_pairing_id_(client_pairing_id),
shared_secret_(shared_secret),
authentication_tag_(authentication_tag),
fetch_secret_callback_(fetch_secret_callback),
token_fetcher_(token_fetcher.Pass()),
method_set_by_host_(false),
weak_factory_(this) {
DCHECK(!methods.empty());
for (std::vector<AuthenticationMethod>::const_iterator it = methods.begin();
it != methods.end(); ++it) {
AddMethod(*it);
}
}
NegotiatingClientAuthenticator::~NegotiatingClientAuthenticator() {
}
void NegotiatingClientAuthenticator::ProcessMessage(
const buzz::XmlElement* message,
const base::Closure& resume_callback) {
DCHECK_EQ(state(), WAITING_MESSAGE);
std::string method_attr = message->Attr(kMethodAttributeQName);
AuthenticationMethod method = AuthenticationMethod::FromString(method_attr);
if (method != current_method_) {
if (method_set_by_host_ || !method.is_valid() ||
std::find(methods_.begin(), methods_.end(), method) == methods_.end()) {
state_ = REJECTED;
rejection_reason_ = PROTOCOL_ERROR;
resume_callback.Run();
return;
}
current_method_ = method;
method_set_by_host_ = true;
state_ = PROCESSING_MESSAGE;
base::Closure callback = base::Bind(
&NegotiatingAuthenticatorBase::ProcessMessageInternal,
base::Unretained(this), base::Owned(new buzz::XmlElement(*message)),
resume_callback);
CreateAuthenticatorForCurrentMethod(WAITING_MESSAGE, callback);
return;
}
ProcessMessageInternal(message, resume_callback);
}
scoped_ptr<buzz::XmlElement> NegotiatingClientAuthenticator::GetNextMessage() {
DCHECK_EQ(state(), MESSAGE_READY);
if (!current_method_.is_valid()) {
scoped_ptr<buzz::XmlElement> result;
CreatePreferredAuthenticator();
if (current_authenticator_) {
DCHECK(current_authenticator_->state() == MESSAGE_READY);
result = GetNextMessageInternal();
} else {
result = CreateEmptyAuthenticatorMessage();
}
std::stringstream supported_methods(std::stringstream::out);
for (std::vector<AuthenticationMethod>::iterator it = methods_.begin();
it != methods_.end(); ++it) {
if (it != methods_.begin())
supported_methods << kSupportedMethodsSeparator;
supported_methods << it->ToString();
}
result->AddAttr(kSupportedMethodsAttributeQName, supported_methods.str());
state_ = WAITING_MESSAGE;
return result.Pass();
}
return GetNextMessageInternal();
}
void NegotiatingClientAuthenticator::CreateAuthenticatorForCurrentMethod(
Authenticator::State preferred_initial_state,
const base::Closure& resume_callback) {
DCHECK(current_method_.is_valid());
if (current_method_.type() == AuthenticationMethod::THIRD_PARTY) {
DCHECK(token_fetcher_);
current_authenticator_.reset(new ThirdPartyClientAuthenticator(
token_fetcher_.Pass()));
resume_callback.Run();
} else {
DCHECK(current_method_.type() == AuthenticationMethod::SPAKE2 ||
current_method_.type() == AuthenticationMethod::SPAKE2_PAIR);
bool pairing_supported =
(current_method_.type() == AuthenticationMethod::SPAKE2_PAIR);
SecretFetchedCallback callback = base::Bind(
&NegotiatingClientAuthenticator::CreateV2AuthenticatorWithSecret,
weak_factory_.GetWeakPtr(), preferred_initial_state, resume_callback);
fetch_secret_callback_.Run(pairing_supported, callback);
}
}
void NegotiatingClientAuthenticator::CreatePreferredAuthenticator() {
if (!client_pairing_id_.empty() && !shared_secret_.empty() &&
std::find(methods_.begin(), methods_.end(),
AuthenticationMethod::Spake2Pair()) != methods_.end()) {
current_authenticator_.reset(new PairingClientAuthenticator(
client_pairing_id_, shared_secret_, fetch_secret_callback_,
authentication_tag_));
current_method_ = AuthenticationMethod::Spake2Pair();
}
}
void NegotiatingClientAuthenticator::CreateV2AuthenticatorWithSecret(
Authenticator::State initial_state,
const base::Closure& resume_callback,
const std::string& shared_secret) {
current_authenticator_ = V2Authenticator::CreateForClient(
AuthenticationMethod::ApplyHashFunction(
current_method_.hash_function(), authentication_tag_, shared_secret),
initial_state);
resume_callback.Run();
}
}
}