Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Unified Diff: remoting/protocol/negotiating_authenticator.cc

Issue 12518027: Protocol / client plugin changes to support interactively asking for a PIN (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: remoting/protocol/negotiating_authenticator.cc
diff --git a/remoting/protocol/negotiating_authenticator.cc b/remoting/protocol/negotiating_authenticator.cc
index 7b794d2a05f69a1f8de26ea3dc64b6d80b4773fe..e2f639a0e2473f444075f253e2c02a86551ddb0b 100644
--- a/remoting/protocol/negotiating_authenticator.cc
+++ b/remoting/protocol/negotiating_authenticator.cc
@@ -14,6 +14,8 @@
#include "remoting/base/rsa_key_pair.h"
#include "remoting/protocol/channel_authenticator.h"
#include "remoting/protocol/v2_authenticator.h"
+#include "remoting/protocol/pin_client_authenticator.h"
+#include "remoting/protocol/pin_fetcher_factory.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
namespace remoting {
@@ -30,20 +32,16 @@ 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,
+ PinFetcherFactory* pin_fetcher_factory,
const std::vector<AuthenticationMethod>& methods) {
scoped_ptr<NegotiatingAuthenticator> result(
new NegotiatingAuthenticator(MESSAGE_READY));
result->authentication_tag_ = authentication_tag;
result->shared_secret_ = shared_secret;
+ result->pin_fetcher_factory_ = pin_fetcher_factory;
DCHECK(!methods.empty());
for (std::vector<AuthenticationMethod>::const_iterator it = methods.begin();
@@ -145,23 +143,36 @@ 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_);
+ state_ = PROCESSING_MESSAGE;
+ CreateAuthenticator(MESSAGE_READY, base::Bind(
+ &NegotiatingAuthenticator::UpdateState,
+ base::Unretained(this), resume_callback));
+ } else {
+ 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));
+ } else {
+ ProcessMessageInternal(message, resume_callback);
+ }
}
- if (state_ == WAITING_MESSAGE) {
+}
+
+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));
- } else {
- UpdateState(resume_callback);
}
}
@@ -179,27 +190,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 +204,17 @@ 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_NE(state_, REJECTED);
+ DCHECK_NE(state_, MESSAGE_READY);
+ result->AddAttr(kMethodAttributeQName, current_method_.ToString());
}
return result.Pass();
@@ -228,16 +235,31 @@ 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);
} else {
- current_authenticator_ = V2Authenticator::CreateForClient(
- AuthenticationMethod::ApplyHashFunction(
- current_method_.hash_function(),
- authentication_tag_, shared_secret_), initial_state);
+ if (pin_fetcher_factory_) {
Sergey Ulanov 2013/03/17 21:29:21 Do we really need to distinguish between these two
rmsousa 2013/03/18 21:07:26 I think that would get ugly in the upper layers, w
Sergey Ulanov 2013/03/19 02:44:53 I think this is just a question of whether we shou
rmsousa 2013/03/19 23:14:31 Done.
+ // No pre-entered secret, need to use the interactive authenticator.
+ current_authenticator_.reset(new PinClientAuthenticator(
+ current_method_.hash_function(), authentication_tag_,
+ pin_fetcher_factory_->CreatePinFetcher(), preferred_initial_state,
Sergey Ulanov 2013/03/17 21:29:21 Why do we need the factory interface? Is there any
rmsousa 2013/03/18 21:07:26 It's to manage the lifetime for the callback appro
Sergey Ulanov 2013/03/19 02:44:53 The issue with possible lifetime mismatch is easy
rmsousa 2013/03/19 23:14:31 Done.
+ resume_callback));
+ return;
+ } else {
+ // Pre-entered secret (legacy client), just proceed with V2 authenticator.
+ current_authenticator_ = V2Authenticator::CreateForClient(
+ AuthenticationMethod::ApplyHashFunction(
+ current_method_.hash_function(),
+ authentication_tag_, shared_secret_), preferred_initial_state);
Sergey Ulanov 2013/03/17 21:29:21 nit: move the last parameter to a separate line fo
rmsousa 2013/03/18 21:07:26 Done.
+ }
}
+ resume_callback.Run();
}
} // namespace protocol

Powered by Google App Engine
This is Rietveld 408576698