| Index: remoting/protocol/negotiating_authenticator.cc
|
| diff --git a/remoting/protocol/negotiating_authenticator.cc b/remoting/protocol/negotiating_authenticator.cc
|
| index 7b794d2a05f69a1f8de26ea3dc64b6d80b4773fe..c6ecacb6a327dceae945ace9116139f3a77b0e60 100644
|
| --- a/remoting/protocol/negotiating_authenticator.cc
|
| +++ b/remoting/protocol/negotiating_authenticator.cc
|
| @@ -30,20 +30,14 @@ const char kSupportedMethodsSeparator = ',';
|
| } // namespace
|
|
|
| // static
|
| -bool NegotiatingAuthenticator::IsNegotiableMessage(
|
| - const buzz::XmlElement* message) {
|
| - return message->HasAttr(kSupportedMethodsAttributeQName);
|
| -}
|
| -
|
| -// static
|
| scoped_ptr<Authenticator> NegotiatingAuthenticator::CreateForClient(
|
| const std::string& authentication_tag,
|
| - const std::string& shared_secret,
|
| + const FetchSecretCallback& fetch_secret_callback,
|
| const std::vector<AuthenticationMethod>& methods) {
|
| scoped_ptr<NegotiatingAuthenticator> result(
|
| new NegotiatingAuthenticator(MESSAGE_READY));
|
| result->authentication_tag_ = authentication_tag;
|
| - result->shared_secret_ = shared_secret;
|
| + result->fetch_secret_callback_ = fetch_secret_callback;
|
|
|
| DCHECK(!methods.empty());
|
| for (std::vector<AuthenticationMethod>::const_iterator it = methods.begin();
|
| @@ -75,7 +69,8 @@ NegotiatingAuthenticator::NegotiatingAuthenticator(
|
| Authenticator::State initial_state)
|
| : current_method_(AuthenticationMethod::Invalid()),
|
| state_(initial_state),
|
| - rejection_reason_(INVALID_CREDENTIALS) {
|
| + rejection_reason_(INVALID_CREDENTIALS),
|
| + weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
|
| }
|
|
|
| NegotiatingAuthenticator::~NegotiatingAuthenticator() {
|
| @@ -145,24 +140,24 @@ void NegotiatingAuthenticator::ProcessMessage(
|
|
|
| // Drop the current message because we've chosen a different
|
| // method.
|
| - state_ = MESSAGE_READY;
|
| - }
|
| -
|
| - DCHECK(method.is_valid());
|
| -
|
| - // Replace current authenticator if the method has changed.
|
| - if (method != current_method_) {
|
| current_method_ = method;
|
| - CreateAuthenticator(state_);
|
| - }
|
| - if (state_ == WAITING_MESSAGE) {
|
| - // |current_authenticator_| is owned, so Unretained() is safe here.
|
| - current_authenticator_->ProcessMessage(message, base::Bind(
|
| + state_ = PROCESSING_MESSAGE;
|
| + CreateAuthenticator(MESSAGE_READY, base::Bind(
|
| &NegotiatingAuthenticator::UpdateState,
|
| base::Unretained(this), resume_callback));
|
| - } else {
|
| - UpdateState(resume_callback);
|
| + return;
|
| }
|
| + if (method != current_method_) {
|
| + current_method_ = method;
|
| + state_ = PROCESSING_MESSAGE;
|
| + // Copy the message since the authenticator may process it asynchronously.
|
| + CreateAuthenticator(WAITING_MESSAGE, base::Bind(
|
| + &NegotiatingAuthenticator::ProcessMessageInternal,
|
| + base::Unretained(this), base::Owned(new buzz::XmlElement(*message)),
|
| + resume_callback));
|
| + return;
|
| + }
|
| + ProcessMessageInternal(message, resume_callback);
|
| }
|
|
|
| void NegotiatingAuthenticator::UpdateState(
|
| @@ -179,27 +174,12 @@ void NegotiatingAuthenticator::UpdateState(
|
| scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() {
|
| DCHECK_EQ(state(), MESSAGE_READY);
|
|
|
| - bool add_supported_methods_attr = false;
|
| + scoped_ptr<buzz::XmlElement> result;
|
|
|
| - // Initialize current method in case it is not initialized
|
| - // yet. Normally happens only on client.
|
| + // No method yet, just send a message with the list of supported methods.
|
| + // Normally happens only on client.
|
| if (!current_method_.is_valid()) {
|
| - CHECK(!methods_.empty());
|
| -
|
| - // Initially try the first method.
|
| - current_method_ = methods_[0];
|
| - CreateAuthenticator(MESSAGE_READY);
|
| - add_supported_methods_attr = true;
|
| - }
|
| -
|
| - scoped_ptr<buzz::XmlElement> result =
|
| - current_authenticator_->GetNextMessage();
|
| - state_ = current_authenticator_->state();
|
| - DCHECK_NE(state_, REJECTED);
|
| -
|
| - result->AddAttr(kMethodAttributeQName, current_method_.ToString());
|
| -
|
| - if (add_supported_methods_attr) {
|
| + result = CreateEmptyAuthenticatorMessage();
|
| std::stringstream supported_methods(std::stringstream::out);
|
| for (std::vector<AuthenticationMethod>::iterator it = methods_.begin();
|
| it != methods_.end(); ++it) {
|
| @@ -208,6 +188,16 @@ scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() {
|
| supported_methods << it->ToString();
|
| }
|
| result->AddAttr(kSupportedMethodsAttributeQName, supported_methods.str());
|
| + state_ = WAITING_MESSAGE;
|
| + } else {
|
| + if (current_authenticator_->state() == MESSAGE_READY) {
|
| + result = current_authenticator_->GetNextMessage();
|
| + } else {
|
| + result = CreateEmptyAuthenticatorMessage();
|
| + }
|
| + state_ = current_authenticator_->state();
|
| + DCHECK(state_ == ACCEPTED || state_ == WAITING_MESSAGE);
|
| + result->AddAttr(kMethodAttributeQName, current_method_.ToString());
|
| }
|
|
|
| return result.Pass();
|
| @@ -228,17 +218,44 @@ bool NegotiatingAuthenticator::is_host_side() const {
|
| return local_key_pair_.get() != NULL;
|
| }
|
|
|
| -void NegotiatingAuthenticator::CreateAuthenticator(State initial_state) {
|
| +void NegotiatingAuthenticator::CreateAuthenticator(
|
| + Authenticator::State preferred_initial_state,
|
| + const base::Closure& resume_callback) {
|
| if (is_host_side()) {
|
| current_authenticator_ = V2Authenticator::CreateForHost(
|
| - local_cert_, local_key_pair_, shared_secret_hash_, initial_state);
|
| + local_cert_, local_key_pair_, shared_secret_hash_,
|
| + preferred_initial_state);
|
| + resume_callback.Run();
|
| } else {
|
| - current_authenticator_ = V2Authenticator::CreateForClient(
|
| - AuthenticationMethod::ApplyHashFunction(
|
| - current_method_.hash_function(),
|
| - authentication_tag_, shared_secret_), initial_state);
|
| + fetch_secret_callback_.Run(base::Bind(
|
| + &NegotiatingAuthenticator::CreateV2AuthenticatorWithSecret,
|
| + weak_factory_.GetWeakPtr(), preferred_initial_state, resume_callback));
|
| + }
|
| +}
|
| +
|
| +void NegotiatingAuthenticator::ProcessMessageInternal(
|
| + const buzz::XmlElement* message,
|
| + const base::Closure& resume_callback) {
|
| + if (current_authenticator_->state() == WAITING_MESSAGE) {
|
| + // If the message was not discarded and the authenticator is waiting for it,
|
| + // give it to the underlying authenticator to process.
|
| + // |current_authenticator_| is owned, so Unretained() is safe here.
|
| + current_authenticator_->ProcessMessage(message, base::Bind(
|
| + &NegotiatingAuthenticator::UpdateState,
|
| + base::Unretained(this), resume_callback));
|
| }
|
| }
|
|
|
| +void NegotiatingAuthenticator::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();
|
| +}
|
| +
|
| } // namespace protocol
|
| } // namespace remoting
|
|
|