| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/protocol/pairing_authenticator_base.h" | 5 #include "remoting/protocol/pairing_authenticator_base.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "remoting/base/constants.h" | 10 #include "remoting/base/constants.h" |
| 11 #include "remoting/protocol/channel_authenticator.h" | 11 #include "remoting/protocol/channel_authenticator.h" |
| 12 | 12 |
| 13 namespace remoting { | 13 namespace remoting { |
| 14 namespace protocol { | 14 namespace protocol { |
| 15 | 15 |
| 16 const buzz::StaticQName PairingAuthenticatorBase::kPairingInfoTag = | 16 const buzz::StaticQName PairingAuthenticatorBase::kPairingInfoTag = |
| 17 { kChromotingXmlNamespace, "pairing-info" }; | 17 { kChromotingXmlNamespace, "pairing-info" }; |
| 18 const buzz::StaticQName PairingAuthenticatorBase::kClientIdAttribute = | 18 const buzz::StaticQName PairingAuthenticatorBase::kClientIdAttribute = |
| 19 { "", "client-id" }; | 19 { "", "client-id" }; |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 const buzz::StaticQName kPairingFailedTag = | 22 const buzz::StaticQName kPairingFailedTag = |
| 23 { kChromotingXmlNamespace, "pairing-failed" }; | 23 { kChromotingXmlNamespace, "pairing-failed" }; |
| 24 const buzz::StaticQName kPairingErrorAttribute = { "", "error" }; | 24 const buzz::StaticQName kPairingErrorAttribute = { "", "error" }; |
| 25 } // namespace | 25 } // namespace |
| 26 | 26 |
| 27 PairingAuthenticatorBase::PairingAuthenticatorBase() | 27 PairingAuthenticatorBase::PairingAuthenticatorBase() : weak_factory_(this) {} |
| 28 : using_paired_secret_(false), | 28 PairingAuthenticatorBase::~PairingAuthenticatorBase() {} |
| 29 waiting_for_authenticator_(false), | |
| 30 weak_factory_(this) { | |
| 31 } | |
| 32 | |
| 33 PairingAuthenticatorBase::~PairingAuthenticatorBase() { | |
| 34 } | |
| 35 | 29 |
| 36 Authenticator::State PairingAuthenticatorBase::state() const { | 30 Authenticator::State PairingAuthenticatorBase::state() const { |
| 37 if (waiting_for_authenticator_) { | 31 DCHECK(spake2_authenticator_); |
| 38 return PROCESSING_MESSAGE; | 32 return spake2_authenticator_->state(); |
| 39 } | |
| 40 return v2_authenticator_->state(); | |
| 41 } | 33 } |
| 42 | 34 |
| 43 bool PairingAuthenticatorBase::started() const { | 35 bool PairingAuthenticatorBase::started() const { |
| 44 if (!v2_authenticator_) { | 36 if (!spake2_authenticator_) { |
| 45 return false; | 37 return false; |
| 46 } | 38 } |
| 47 return v2_authenticator_->started(); | 39 return spake2_authenticator_->started(); |
| 48 } | 40 } |
| 49 | 41 |
| 50 Authenticator::RejectionReason | 42 Authenticator::RejectionReason |
| 51 PairingAuthenticatorBase::rejection_reason() const { | 43 PairingAuthenticatorBase::rejection_reason() const { |
| 52 if (!v2_authenticator_) { | 44 if (!spake2_authenticator_) { |
| 53 return PROTOCOL_ERROR; | 45 return PROTOCOL_ERROR; |
| 54 } | 46 } |
| 55 return v2_authenticator_->rejection_reason(); | 47 return spake2_authenticator_->rejection_reason(); |
| 56 } | 48 } |
| 57 | 49 |
| 58 void PairingAuthenticatorBase::ProcessMessage( | 50 void PairingAuthenticatorBase::ProcessMessage( |
| 59 const buzz::XmlElement* message, | 51 const buzz::XmlElement* message, |
| 60 const base::Closure& resume_callback) { | 52 const base::Closure& resume_callback) { |
| 61 DCHECK_EQ(state(), WAITING_MESSAGE); | 53 DCHECK_EQ(state(), WAITING_MESSAGE); |
| 62 | 54 |
| 63 // The client authenticator creates the underlying authenticator in the ctor | 55 // The client authenticator creates the underlying authenticator in the ctor |
| 64 // and the host creates it in response to the first message before deferring | 56 // and the host creates it in response to the first message before deferring |
| 65 // to this class to process it. Either way, it should exist here. | 57 // to this class to process it. Either way, it should exist here. |
| 66 DCHECK(v2_authenticator_); | 58 DCHECK(spake2_authenticator_); |
| 67 | 59 |
| 68 // If pairing failed, and we haven't already done so, try again with the PIN. | 60 // If pairing failed, and we haven't already done so, try again with the PIN. |
| 69 if (using_paired_secret_ && HasErrorMessage(message)) { | 61 if (using_paired_secret_ && HasErrorMessage(message)) { |
| 70 using_paired_secret_ = false; | 62 using_paired_secret_ = false; |
| 71 waiting_for_authenticator_ = true; | 63 spake2_authenticator_.reset(); |
| 72 v2_authenticator_.reset(); | 64 CreateSpakeAuthenticatorWithPin( |
| 73 SetAuthenticatorCallback set_authenticator = base::Bind( | 65 WAITING_MESSAGE, base::Bind(&PairingAuthenticatorBase::ProcessMessage, |
| 74 &PairingAuthenticatorBase::SetAuthenticatorAndProcessMessage, | 66 weak_factory_.GetWeakPtr(), |
| 75 weak_factory_.GetWeakPtr(), base::Owned(new buzz::XmlElement(*message)), | 67 base::Owned(new buzz::XmlElement(*message)), |
| 76 resume_callback); | 68 resume_callback)); |
| 77 CreateV2AuthenticatorWithPIN(WAITING_MESSAGE, set_authenticator); | |
| 78 return; | 69 return; |
| 79 } | 70 } |
| 80 | 71 |
| 81 // Pass the message to the underlying authenticator for processing, but | 72 // Pass the message to the underlying authenticator for processing, but |
| 82 // check for a failed SPAKE exchange if we're using the paired secret. In | 73 // check for a failed SPAKE exchange if we're using the paired secret. In |
| 83 // this case the pairing protocol can continue by communicating the error | 74 // this case the pairing protocol can continue by communicating the error |
| 84 // to the peer and retrying with the PIN. | 75 // to the peer and retrying with the PIN. |
| 85 v2_authenticator_->ProcessMessage( | 76 spake2_authenticator_->ProcessMessage( |
| 86 message, | 77 message, |
| 87 base::Bind(&PairingAuthenticatorBase::CheckForFailedSpakeExchange, | 78 base::Bind(&PairingAuthenticatorBase::CheckForFailedSpakeExchange, |
| 88 weak_factory_.GetWeakPtr(), resume_callback)); | 79 weak_factory_.GetWeakPtr(), resume_callback)); |
| 89 } | 80 } |
| 90 | 81 |
| 91 scoped_ptr<buzz::XmlElement> PairingAuthenticatorBase::GetNextMessage() { | 82 scoped_ptr<buzz::XmlElement> PairingAuthenticatorBase::GetNextMessage() { |
| 92 DCHECK_EQ(state(), MESSAGE_READY); | 83 DCHECK_EQ(state(), MESSAGE_READY); |
| 93 scoped_ptr<buzz::XmlElement> result = v2_authenticator_->GetNextMessage(); | 84 scoped_ptr<buzz::XmlElement> result = spake2_authenticator_->GetNextMessage(); |
| 94 AddPairingElements(result.get()); | 85 AddPairingElements(result.get()); |
| 95 MaybeAddErrorMessage(result.get()); | 86 MaybeAddErrorMessage(result.get()); |
| 96 return result; | 87 return result; |
| 97 } | 88 } |
| 98 | 89 |
| 99 const std::string& PairingAuthenticatorBase::GetAuthKey() const { | 90 const std::string& PairingAuthenticatorBase::GetAuthKey() const { |
| 100 return v2_authenticator_->GetAuthKey(); | 91 return spake2_authenticator_->GetAuthKey(); |
| 101 } | 92 } |
| 102 | 93 |
| 103 scoped_ptr<ChannelAuthenticator> | 94 scoped_ptr<ChannelAuthenticator> |
| 104 PairingAuthenticatorBase::CreateChannelAuthenticator() const { | 95 PairingAuthenticatorBase::CreateChannelAuthenticator() const { |
| 105 return v2_authenticator_->CreateChannelAuthenticator(); | 96 return spake2_authenticator_->CreateChannelAuthenticator(); |
| 106 } | 97 } |
| 107 | 98 |
| 108 void PairingAuthenticatorBase::MaybeAddErrorMessage(buzz::XmlElement* message) { | 99 void PairingAuthenticatorBase::MaybeAddErrorMessage(buzz::XmlElement* message) { |
| 109 if (!error_message_.empty()) { | 100 if (!error_message_.empty()) { |
| 110 buzz::XmlElement* pairing_failed_tag = | 101 buzz::XmlElement* pairing_failed_tag = |
| 111 new buzz::XmlElement(kPairingFailedTag); | 102 new buzz::XmlElement(kPairingFailedTag); |
| 112 pairing_failed_tag->AddAttr(kPairingErrorAttribute, error_message_); | 103 pairing_failed_tag->AddAttr(kPairingErrorAttribute, error_message_); |
| 113 message->AddElement(pairing_failed_tag); | 104 message->AddElement(pairing_failed_tag); |
| 114 error_message_.clear(); | 105 error_message_.clear(); |
| 115 } | 106 } |
| 116 } | 107 } |
| 117 | 108 |
| 118 bool PairingAuthenticatorBase::HasErrorMessage( | 109 bool PairingAuthenticatorBase::HasErrorMessage( |
| 119 const buzz::XmlElement* message) const { | 110 const buzz::XmlElement* message) const { |
| 120 const buzz::XmlElement* pairing_failed_tag = | 111 const buzz::XmlElement* pairing_failed_tag = |
| 121 message->FirstNamed(kPairingFailedTag); | 112 message->FirstNamed(kPairingFailedTag); |
| 122 if (pairing_failed_tag) { | 113 if (pairing_failed_tag) { |
| 123 std::string error = pairing_failed_tag->Attr(kPairingErrorAttribute); | 114 std::string error = pairing_failed_tag->Attr(kPairingErrorAttribute); |
| 124 LOG(ERROR) << "Pairing failed: " << error; | 115 LOG(ERROR) << "Pairing failed: " << error; |
| 125 } | 116 } |
| 126 return pairing_failed_tag != nullptr; | 117 return pairing_failed_tag != nullptr; |
| 127 } | 118 } |
| 128 | 119 |
| 129 void PairingAuthenticatorBase::CheckForFailedSpakeExchange( | 120 void PairingAuthenticatorBase::CheckForFailedSpakeExchange( |
| 130 const base::Closure& resume_callback) { | 121 const base::Closure& resume_callback) { |
| 131 // If the SPAKE exchange failed due to invalid credentials, and those | 122 // If the SPAKE exchange failed due to invalid credentials, and those |
| 132 // credentials were the paired secret, then notify the peer that the | 123 // credentials were the paired secret, then notify the peer that the |
| 133 // PIN-less connection failed and retry using the PIN. | 124 // PIN-less connection failed and retry using the PIN. |
| 134 if (v2_authenticator_->state() == REJECTED && | 125 if (spake2_authenticator_->state() == REJECTED && |
| 135 v2_authenticator_->rejection_reason() == INVALID_CREDENTIALS && | 126 spake2_authenticator_->rejection_reason() == INVALID_CREDENTIALS && |
| 136 using_paired_secret_) { | 127 using_paired_secret_) { |
| 137 using_paired_secret_ = false; | 128 using_paired_secret_ = false; |
| 138 error_message_ = "invalid-shared-secret"; | 129 error_message_ = "invalid-shared-secret"; |
| 139 v2_authenticator_.reset(); | 130 spake2_authenticator_.reset(); |
| 140 buzz::XmlElement* no_message = nullptr; | 131 CreateSpakeAuthenticatorWithPin(MESSAGE_READY, resume_callback); |
| 141 SetAuthenticatorCallback set_authenticator = base::Bind( | |
| 142 &PairingAuthenticatorBase::SetAuthenticatorAndProcessMessage, | |
| 143 weak_factory_.GetWeakPtr(), no_message, resume_callback); | |
| 144 CreateV2AuthenticatorWithPIN(MESSAGE_READY, set_authenticator); | |
| 145 return; | 132 return; |
| 146 } | 133 } |
| 147 | 134 |
| 148 resume_callback.Run(); | 135 resume_callback.Run(); |
| 149 } | 136 } |
| 150 | 137 |
| 151 void PairingAuthenticatorBase::SetAuthenticatorAndProcessMessage( | |
| 152 const buzz::XmlElement* message, | |
| 153 const base::Closure& resume_callback, | |
| 154 scoped_ptr<Authenticator> authenticator) { | |
| 155 DCHECK(!v2_authenticator_); | |
| 156 DCHECK(authenticator); | |
| 157 waiting_for_authenticator_ = false; | |
| 158 v2_authenticator_ = std::move(authenticator); | |
| 159 if (message) { | |
| 160 ProcessMessage(message, resume_callback); | |
| 161 } else { | |
| 162 resume_callback.Run(); | |
| 163 } | |
| 164 } | |
| 165 | |
| 166 } // namespace protocol | 138 } // namespace protocol |
| 167 } // namespace remoting | 139 } // namespace remoting |
| OLD | NEW |