| 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/negotiating_host_authenticator.h" | 5 #include "remoting/protocol/negotiating_host_authenticator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 result->AddMethod(Method::THIRD_PARTY_SPAKE2_P224); | 87 result->AddMethod(Method::THIRD_PARTY_SPAKE2_P224); |
| 88 return std::move(result); | 88 return std::move(result); |
| 89 } | 89 } |
| 90 | 90 |
| 91 NegotiatingHostAuthenticator::~NegotiatingHostAuthenticator() {} | 91 NegotiatingHostAuthenticator::~NegotiatingHostAuthenticator() {} |
| 92 | 92 |
| 93 void NegotiatingHostAuthenticator::ProcessMessage( | 93 void NegotiatingHostAuthenticator::ProcessMessage( |
| 94 const buzz::XmlElement* message, | 94 const buzz::XmlElement* message, |
| 95 const base::Closure& resume_callback) { | 95 const base::Closure& resume_callback) { |
| 96 DCHECK_EQ(state(), WAITING_MESSAGE); | 96 DCHECK_EQ(state(), WAITING_MESSAGE); |
| 97 state_ = PROCESSING_MESSAGE; |
| 98 |
| 99 const buzz::XmlElement* pairing_tag = message->FirstNamed(kPairingInfoTag); |
| 100 if (pairing_tag) { |
| 101 client_id_ = pairing_tag->Attr(kClientIdAttribute); |
| 102 } |
| 97 | 103 |
| 98 std::string method_attr = message->Attr(kMethodAttributeQName); | 104 std::string method_attr = message->Attr(kMethodAttributeQName); |
| 99 Method method = ParseMethodString(method_attr); | 105 Method method = ParseMethodString(method_attr); |
| 100 | 106 |
| 101 // If the host has already chosen a method, it can't be changed by the client. | 107 // If the host has already chosen a method, it can't be changed by the client. |
| 102 if (current_method_ != Method::INVALID && method != current_method_) { | 108 if (current_method_ != Method::INVALID && method != current_method_) { |
| 103 state_ = REJECTED; | 109 state_ = REJECTED; |
| 104 rejection_reason_ = PROTOCOL_ERROR; | 110 rejection_reason_ = PROTOCOL_ERROR; |
| 105 resume_callback.Run(); | 111 resume_callback.Run(); |
| 106 return; | 112 return; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 if (method == Method::INVALID) { | 148 if (method == Method::INVALID) { |
| 143 // Failed to find a common auth method. | 149 // Failed to find a common auth method. |
| 144 state_ = REJECTED; | 150 state_ = REJECTED; |
| 145 rejection_reason_ = PROTOCOL_ERROR; | 151 rejection_reason_ = PROTOCOL_ERROR; |
| 146 resume_callback.Run(); | 152 resume_callback.Run(); |
| 147 return; | 153 return; |
| 148 } | 154 } |
| 149 | 155 |
| 150 // Drop the current message because we've chosen a different method. | 156 // Drop the current message because we've chosen a different method. |
| 151 current_method_ = method; | 157 current_method_ = method; |
| 152 state_ = PROCESSING_MESSAGE; | 158 CreateAuthenticator(MESSAGE_READY, |
| 153 CreateAuthenticator(MESSAGE_READY, base::Bind( | 159 base::Bind(&NegotiatingHostAuthenticator::UpdateState, |
| 154 &NegotiatingHostAuthenticator::UpdateState, | 160 base::Unretained(this), resume_callback)); |
| 155 base::Unretained(this), resume_callback)); | |
| 156 return; | 161 return; |
| 157 } | 162 } |
| 158 | 163 |
| 159 // If the client specified a supported method, and the host hasn't chosen a | 164 // If the client specified a supported method, and the host hasn't chosen a |
| 160 // method yet, use the client's preferred method and process the message. | 165 // method yet, use the client's preferred method and process the message. |
| 161 if (current_method_ == Method::INVALID) { | 166 if (current_method_ == Method::INVALID) { |
| 162 current_method_ = method; | 167 current_method_ = method; |
| 163 state_ = PROCESSING_MESSAGE; | |
| 164 // Copy the message since the authenticator may process it asynchronously. | 168 // Copy the message since the authenticator may process it asynchronously. |
| 165 CreateAuthenticator(WAITING_MESSAGE, base::Bind( | 169 CreateAuthenticator( |
| 166 &NegotiatingAuthenticatorBase::ProcessMessageInternal, | 170 WAITING_MESSAGE, |
| 167 base::Unretained(this), base::Owned(new buzz::XmlElement(*message)), | 171 base::Bind(&NegotiatingAuthenticatorBase::ProcessMessageInternal, |
| 168 resume_callback)); | 172 base::Unretained(this), |
| 173 base::Owned(new buzz::XmlElement(*message)), |
| 174 resume_callback)); |
| 169 return; | 175 return; |
| 170 } | 176 } |
| 171 | 177 |
| 172 // If the client is using the host's current method, just process the message. | 178 // If the client is using the host's current method, just process the message. |
| 173 ProcessMessageInternal(message, resume_callback); | 179 ProcessMessageInternal(message, resume_callback); |
| 174 } | 180 } |
| 175 | 181 |
| 176 scoped_ptr<buzz::XmlElement> NegotiatingHostAuthenticator::GetNextMessage() { | 182 scoped_ptr<buzz::XmlElement> NegotiatingHostAuthenticator::GetNextMessage() { |
| 177 return GetNextMessageInternal(); | 183 return GetNextMessageInternal(); |
| 178 } | 184 } |
| 179 | 185 |
| 180 void NegotiatingHostAuthenticator::CreateAuthenticator( | 186 void NegotiatingHostAuthenticator::CreateAuthenticator( |
| 181 Authenticator::State preferred_initial_state, | 187 Authenticator::State preferred_initial_state, |
| 182 const base::Closure& resume_callback) { | 188 const base::Closure& resume_callback) { |
| 183 DCHECK(current_method_ != Method::INVALID); | 189 DCHECK(current_method_ != Method::INVALID); |
| 184 | 190 |
| 185 if (current_method_ == Method::THIRD_PARTY_SPAKE2_P224) { | 191 if (current_method_ == Method::THIRD_PARTY_SPAKE2_P224) { |
| 186 current_authenticator_.reset(new ThirdPartyHostAuthenticator( | 192 current_authenticator_.reset(new ThirdPartyHostAuthenticator( |
| 187 base::Bind(&V2Authenticator::CreateForHost, local_cert_, | 193 base::Bind(&V2Authenticator::CreateForHost, local_cert_, |
| 188 local_key_pair_), | 194 local_key_pair_), |
| 189 token_validator_factory_->CreateTokenValidator(local_id_, remote_id_))); | 195 token_validator_factory_->CreateTokenValidator(local_id_, remote_id_))); |
| 190 } else if (current_method_ == Method::THIRD_PARTY_SPAKE2_CURVE25519) { | 196 } else if (current_method_ == Method::THIRD_PARTY_SPAKE2_CURVE25519) { |
| 191 current_authenticator_.reset(new ThirdPartyHostAuthenticator( | 197 current_authenticator_.reset(new ThirdPartyHostAuthenticator( |
| 192 base::Bind(&Spake2Authenticator::CreateForHost, local_id_, remote_id_, | 198 base::Bind(&Spake2Authenticator::CreateForHost, local_id_, remote_id_, |
| 193 local_cert_, local_key_pair_), | 199 local_cert_, local_key_pair_), |
| 194 token_validator_factory_->CreateTokenValidator(local_id_, remote_id_))); | 200 token_validator_factory_->CreateTokenValidator(local_id_, remote_id_))); |
| 201 } else if (current_method_ == Method::PAIRED_SPAKE2_P224) { |
| 202 PairingHostAuthenticator* pairing_authenticator = |
| 203 new PairingHostAuthenticator(pairing_registry_, |
| 204 base::Bind(&V2Authenticator::CreateForHost, |
| 205 local_cert_, local_key_pair_), |
| 206 shared_secret_hash_); |
| 207 current_authenticator_.reset(pairing_authenticator); |
| 208 pairing_authenticator->Initialize(client_id_, preferred_initial_state, |
| 209 resume_callback); |
| 210 return; |
| 195 } else if (current_method_ == Method::SHARED_SECRET_SPAKE2_CURVE25519) { | 211 } else if (current_method_ == Method::SHARED_SECRET_SPAKE2_CURVE25519) { |
| 196 current_authenticator_ = Spake2Authenticator::CreateForHost( | 212 current_authenticator_ = Spake2Authenticator::CreateForHost( |
| 197 local_id_, remote_id_, local_cert_, local_key_pair_, | 213 local_id_, remote_id_, local_cert_, local_key_pair_, |
| 198 shared_secret_hash_, preferred_initial_state); | 214 shared_secret_hash_, preferred_initial_state); |
| 199 } else if (current_method_ == Method::PAIRED_SPAKE2_P224 && | |
| 200 preferred_initial_state == WAITING_MESSAGE) { | |
| 201 // If the client requested Spake2Pair and sent an initial message, attempt | |
| 202 // the paired connection protocol. | |
| 203 current_authenticator_.reset(new PairingHostAuthenticator( | |
| 204 pairing_registry_, base::Bind(&V2Authenticator::CreateForHost, | |
| 205 local_cert_, local_key_pair_), | |
| 206 shared_secret_hash_)); | |
| 207 } else { | 215 } else { |
| 208 // In all other cases, use the V2 protocol. Note that this includes the | |
| 209 // case where the protocol is Spake2Pair but the client is not yet paired. | |
| 210 // In this case, the on-the-wire protocol is plain Spake2, advertised as | |
| 211 // Spake2Pair so that the client knows that the host supports pairing and | |
| 212 // that it can therefore present the option to the user when they enter | |
| 213 // the PIN. | |
| 214 DCHECK(current_method_ == Method::SHARED_SECRET_PLAIN_SPAKE2_P224 || | 216 DCHECK(current_method_ == Method::SHARED_SECRET_PLAIN_SPAKE2_P224 || |
| 215 current_method_ == Method::SHARED_SECRET_SPAKE2_P224 || | 217 current_method_ == Method::SHARED_SECRET_SPAKE2_P224); |
| 216 current_method_ == Method::PAIRED_SPAKE2_P224); | |
| 217 current_authenticator_ = V2Authenticator::CreateForHost( | 218 current_authenticator_ = V2Authenticator::CreateForHost( |
| 218 local_cert_, local_key_pair_, shared_secret_hash_, | 219 local_cert_, local_key_pair_, shared_secret_hash_, |
| 219 preferred_initial_state); | 220 preferred_initial_state); |
| 220 } | 221 } |
| 221 resume_callback.Run(); | 222 resume_callback.Run(); |
| 222 } | 223 } |
| 223 | 224 |
| 224 } // namespace protocol | 225 } // namespace protocol |
| 225 } // namespace remoting | 226 } // namespace remoting |
| OLD | NEW |