Index: remoting/protocol/pairing_client_authenticator.cc |
diff --git a/remoting/protocol/pairing_client_authenticator.cc b/remoting/protocol/pairing_client_authenticator.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ed6d65a0d895d414954207a006bbdb93791d1fea |
--- /dev/null |
+++ b/remoting/protocol/pairing_client_authenticator.cc |
@@ -0,0 +1,111 @@ |
+// 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/protocol/pairing_client_authenticator.h" |
+ |
+#include "base/bind.h" |
+#include "base/logging.h" |
+#include "remoting/base/constants.h" |
+#include "remoting/base/rsa_key_pair.h" |
+#include "remoting/protocol/authentication_method.h" |
+#include "remoting/protocol/channel_authenticator.h" |
+#include "remoting/protocol/v2_authenticator.h" |
+#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" |
+ |
+namespace remoting { |
+namespace protocol { |
+ |
+namespace { |
+const buzz::StaticQName kPairingQName = |
rmsousa
2013/05/15 01:25:16
Nit: We use kPairingTag for tags inside an authent
rmsousa
2013/05/15 01:25:16
Nit: I'd prefer if these were in a shared place, a
Jamie
2013/05/15 23:41:08
Done.
Jamie
2013/05/15 23:41:08
Done.
|
+ { kChromotingXmlNamespace, "pairing-info" }; |
+const buzz::StaticQName kClientIdAttributeQName = |
+ { "", "client-id" }; |
+const buzz::StaticQName kPairingFailedQName = |
+ { kChromotingXmlNamespace, "pairing-failed" }; |
+const buzz::StaticQName kPairingErrorQName = |
+ { "", "error" }; |
+} |
+ |
+PairingClientAuthenticator::PairingClientAuthenticator( |
+ const std::string& client_id, |
+ const std::string& shared_secret, |
+ const FetchSecretCallback& fetch_secret_callback, |
+ const std::string& authentication_tag) |
+ : initial_message_sent_(false), |
+ client_id_(client_id), |
+ shared_secret_(shared_secret), |
+ fetch_secret_callback_(fetch_secret_callback), |
+ authentication_tag_(authentication_tag), |
+ pairing_failed_(false), |
+ weak_factory_(this) { |
+ v2_authenticator_ = V2Authenticator::CreateForClient( |
rmsousa
2013/05/15 01:25:16
There is no need to create this underlying authent
Jamie
2013/05/15 23:41:08
Done.
|
+ shared_secret_, WAITING_MESSAGE); |
+} |
+ |
+Authenticator::State PairingClientAuthenticator::state() const { |
+ if (!initial_message_sent_) { |
+ return MESSAGE_READY; |
+ } else if (!v2_authenticator_) { |
+ return PROCESSING_MESSAGE; |
+ } |
+ return v2_authenticator_->state(); |
+} |
+ |
+Authenticator::RejectionReason |
+PairingClientAuthenticator::rejection_reason() const { |
+ DCHECK(v2_authenticator_); |
+ return v2_authenticator_->rejection_reason(); |
+} |
+ |
+void PairingClientAuthenticator::ProcessMessage( |
+ const buzz::XmlElement* message, |
+ const base::Closure& resume_callback) { |
+ const buzz::XmlElement* pairing_failed_tag = |
+ message->FirstNamed(kPairingFailedQName); |
+ if (pairing_failed_tag) { |
+ // If pairing failed, prompt the user for the PIN and try again. |
+ std::string error = pairing_failed_tag->Attr(kPairingErrorQName); |
+ LOG(INFO) << "Pairing failed: " << error; |
+ v2_authenticator_.reset(); |
+ SecretFetchedCallback callback = base::Bind( |
+ &PairingClientAuthenticator::CreateV2AuthenticatorWithSecret, |
+ weak_factory_.GetWeakPtr(), resume_callback); |
rmsousa
2013/05/16 22:16:37
(Comment for a future CL, when you implement the U
Jamie
2013/05/16 22:57:46
Good point.
|
+ fetch_secret_callback_.Run(callback); |
+ return; |
+ } |
+ v2_authenticator_->ProcessMessage(message, resume_callback); |
+} |
+ |
+scoped_ptr<buzz::XmlElement> PairingClientAuthenticator::GetNextMessage() { |
+ // If the initial message has not yet been sent, return it now. |
+ if (!initial_message_sent_) { |
rmsousa
2013/05/15 01:25:16
This is wrong when the host sends the first messag
Jamie
2013/05/15 23:41:08
My understanding is that the client always sends t
rmsousa
2013/05/16 00:46:25
No. If the client does not have a client ID, the c
Jamie
2013/05/16 19:30:16
Okay, I think we're talking at cross-purposes here
rmsousa
2013/05/16 20:12:59
Oh. I just realized that - CreateAuthenticator wil
Jamie
2013/05/16 21:09:09
I don't think that's true. The PairingSupportedBut
rmsousa
2013/05/16 22:16:37
Oh, I think I misunderstood your design. I was ass
Jamie
2013/05/16 22:57:46
That's correct.
rmsousa
2013/05/16 23:22:24
Oh, OK, we're in the same page, then.
Jamie
2013/05/17 17:55:45
I tried using the pairing authenticator for the ex
|
+ scoped_ptr<buzz::XmlElement> result = CreateEmptyAuthenticatorMessage(); |
+ buzz::XmlElement* pairing_tag = new buzz::XmlElement(kPairingQName); |
+ pairing_tag->AddAttr(kClientIdAttributeQName, client_id_); |
+ result->AddElement(pairing_tag); |
+ initial_message_sent_ = true; |
+ return result.Pass(); |
+ } |
+ // In all other cases, defer to the underlying authenticator. |
+ return v2_authenticator_->GetNextMessage(); |
+} |
+ |
+scoped_ptr<ChannelAuthenticator> |
+PairingClientAuthenticator::CreateChannelAuthenticator() const { |
+ return v2_authenticator_->CreateChannelAuthenticator(); |
+} |
+ |
+void PairingClientAuthenticator::CreateV2AuthenticatorWithSecret( |
+ const base::Closure& resume_callback, |
+ const std::string& shared_secret) { |
+ v2_authenticator_ = V2Authenticator::CreateForClient( |
+ AuthenticationMethod::ApplyHashFunction( |
+ AuthenticationMethod::HMAC_SHA256, |
+ authentication_tag_, shared_secret), |
+ MESSAGE_READY); |
+ resume_callback.Run(); |
+} |
+ |
+} // namespace protocol |
+} // namespace remoting |