| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_authenticator.h" | 5 #include "remoting/protocol/negotiating_authenticator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 | 9 |
| 10 #include "base/bind.h" |
| 10 #include "base/logging.h" | 11 #include "base/logging.h" |
| 11 #include "base/string_split.h" | 12 #include "base/string_split.h" |
| 12 #include "crypto/rsa_private_key.h" | 13 #include "crypto/rsa_private_key.h" |
| 13 #include "remoting/protocol/channel_authenticator.h" | 14 #include "remoting/protocol/channel_authenticator.h" |
| 14 #include "remoting/protocol/v2_authenticator.h" | 15 #include "remoting/protocol/v2_authenticator.h" |
| 15 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" | 16 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" |
| 16 | 17 |
| 17 namespace remoting { | 18 namespace remoting { |
| 18 namespace protocol { | 19 namespace protocol { |
| 19 | 20 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 | 84 |
| 84 Authenticator::State NegotiatingAuthenticator::state() const { | 85 Authenticator::State NegotiatingAuthenticator::state() const { |
| 85 return state_; | 86 return state_; |
| 86 } | 87 } |
| 87 | 88 |
| 88 Authenticator::RejectionReason | 89 Authenticator::RejectionReason |
| 89 NegotiatingAuthenticator::rejection_reason() const { | 90 NegotiatingAuthenticator::rejection_reason() const { |
| 90 return rejection_reason_; | 91 return rejection_reason_; |
| 91 } | 92 } |
| 92 | 93 |
| 93 void NegotiatingAuthenticator::ProcessMessage(const buzz::XmlElement* message) { | 94 void NegotiatingAuthenticator::ProcessMessage( |
| 95 const buzz::XmlElement* message, |
| 96 const base::Closure& resume_callback) { |
| 94 DCHECK_EQ(state(), WAITING_MESSAGE); | 97 DCHECK_EQ(state(), WAITING_MESSAGE); |
| 95 | 98 |
| 96 std::string method_attr = message->Attr(kMethodAttributeQName); | 99 std::string method_attr = message->Attr(kMethodAttributeQName); |
| 97 AuthenticationMethod method = AuthenticationMethod::FromString(method_attr); | 100 AuthenticationMethod method = AuthenticationMethod::FromString(method_attr); |
| 98 | 101 |
| 99 // Check if the remote end specified a method that is not supported locally. | 102 // Check if the remote end specified a method that is not supported locally. |
| 100 if (method.is_valid() && | 103 if (method.is_valid() && |
| 101 std::find(methods_.begin(), methods_.end(), method) == methods_.end()) { | 104 std::find(methods_.begin(), methods_.end(), method) == methods_.end()) { |
| 102 method = AuthenticationMethod::Invalid(); | 105 method = AuthenticationMethod::Invalid(); |
| 103 } | 106 } |
| 104 | 107 |
| 105 // If the remote peer did not specify auth method or specified unknown | 108 // If the remote peer did not specify auth method or specified unknown |
| 106 // method then select the first known method from the supported-methods | 109 // method then select the first known method from the supported-methods |
| 107 // attribute. | 110 // attribute. |
| 108 if (!method.is_valid()) { | 111 if (!method.is_valid()) { |
| 109 std::string supported_methods_attr = | 112 std::string supported_methods_attr = |
| 110 message->Attr(kSupportedMethodsAttributeQName); | 113 message->Attr(kSupportedMethodsAttributeQName); |
| 111 if (supported_methods_attr.empty()) { | 114 if (supported_methods_attr.empty()) { |
| 112 // Message contains neither method nor supported-methods attributes. | 115 // Message contains neither method nor supported-methods attributes. |
| 113 state_ = REJECTED; | 116 state_ = REJECTED; |
| 114 rejection_reason_ = PROTOCOL_ERROR; | 117 rejection_reason_ = PROTOCOL_ERROR; |
| 118 resume_callback.Run(); |
| 115 return; | 119 return; |
| 116 } | 120 } |
| 117 | 121 |
| 118 // Find the first mutually-supported method in the peer's list of | 122 // Find the first mutually-supported method in the peer's list of |
| 119 // supported-methods. | 123 // supported-methods. |
| 120 std::vector<std::string> supported_methods_strs; | 124 std::vector<std::string> supported_methods_strs; |
| 121 base::SplitString(supported_methods_attr, kSupportedMethodsSeparator, | 125 base::SplitString(supported_methods_attr, kSupportedMethodsSeparator, |
| 122 &supported_methods_strs); | 126 &supported_methods_strs); |
| 123 for (std::vector<std::string>::iterator it = supported_methods_strs.begin(); | 127 for (std::vector<std::string>::iterator it = supported_methods_strs.begin(); |
| 124 it != supported_methods_strs.end(); ++it) { | 128 it != supported_methods_strs.end(); ++it) { |
| 125 AuthenticationMethod list_value = AuthenticationMethod::FromString(*it); | 129 AuthenticationMethod list_value = AuthenticationMethod::FromString(*it); |
| 126 if (list_value.is_valid() && | 130 if (list_value.is_valid() && |
| 127 std::find(methods_.begin(), | 131 std::find(methods_.begin(), |
| 128 methods_.end(), list_value) != methods_.end()) { | 132 methods_.end(), list_value) != methods_.end()) { |
| 129 // Found common method. | 133 // Found common method. |
| 130 method = list_value; | 134 method = list_value; |
| 131 break; | 135 break; |
| 132 } | 136 } |
| 133 } | 137 } |
| 134 | 138 |
| 135 if (!method.is_valid()) { | 139 if (!method.is_valid()) { |
| 136 // Failed to find a common auth method. | 140 // Failed to find a common auth method. |
| 137 state_ = REJECTED; | 141 state_ = REJECTED; |
| 138 rejection_reason_ = PROTOCOL_ERROR; | 142 rejection_reason_ = PROTOCOL_ERROR; |
| 143 resume_callback.Run(); |
| 139 return; | 144 return; |
| 140 } | 145 } |
| 141 | 146 |
| 142 // Drop the current message because we've chosen a different | 147 // Drop the current message because we've chosen a different |
| 143 // method. | 148 // method. |
| 144 state_ = MESSAGE_READY; | 149 state_ = MESSAGE_READY; |
| 145 } | 150 } |
| 146 | 151 |
| 147 DCHECK(method.is_valid()); | 152 DCHECK(method.is_valid()); |
| 148 | 153 |
| 149 // Replace current authenticator if the method has changed. | 154 // Replace current authenticator if the method has changed. |
| 150 if (method != current_method_) { | 155 if (method != current_method_) { |
| 151 current_method_ = method; | 156 current_method_ = method; |
| 152 CreateAuthenticator(state_); | 157 CreateAuthenticator(state_); |
| 153 } | 158 } |
| 159 if (state_ == WAITING_MESSAGE) { |
| 160 // |current_authenticator_| is owned, so Unretained() is safe here. |
| 161 current_authenticator_->ProcessMessage(message, base::Bind( |
| 162 &NegotiatingAuthenticator::UpdateState, |
| 163 base::Unretained(this), resume_callback)); |
| 164 } else { |
| 165 UpdateState(resume_callback); |
| 166 } |
| 167 } |
| 154 | 168 |
| 155 if (state_ == WAITING_MESSAGE) { | 169 void NegotiatingAuthenticator::UpdateState( |
| 156 current_authenticator_->ProcessMessage(message); | 170 const base::Closure& resume_callback) { |
| 157 state_ = current_authenticator_->state(); | 171 // After the underlying authenticator finishes processing the message, the |
| 158 if (state_ == REJECTED) | 172 // NegotiatingAuthenticator must update its own state before running the |
| 159 rejection_reason_ = current_authenticator_->rejection_reason(); | 173 // |resume_callback| to resume the session negotiation. |
| 160 } | 174 state_ = current_authenticator_->state(); |
| 175 if (state_ == REJECTED) |
| 176 rejection_reason_ = current_authenticator_->rejection_reason(); |
| 177 resume_callback.Run(); |
| 161 } | 178 } |
| 162 | 179 |
| 163 scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() { | 180 scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() { |
| 164 DCHECK_EQ(state(), MESSAGE_READY); | 181 DCHECK_EQ(state(), MESSAGE_READY); |
| 165 | 182 |
| 166 bool add_supported_methods_attr = false; | 183 bool add_supported_methods_attr = false; |
| 167 | 184 |
| 168 // Initialize current method in case it is not initialized | 185 // Initialize current method in case it is not initialized |
| 169 // yet. Normally happens only on client. | 186 // yet. Normally happens only on client. |
| 170 if (!current_method_.is_valid()) { | 187 if (!current_method_.is_valid()) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 current_authenticator_ = V2Authenticator::CreateForClient( | 238 current_authenticator_ = V2Authenticator::CreateForClient( |
| 222 AuthenticationMethod::ApplyHashFunction( | 239 AuthenticationMethod::ApplyHashFunction( |
| 223 current_method_.hash_function(), | 240 current_method_.hash_function(), |
| 224 authentication_tag_, shared_secret_), | 241 authentication_tag_, shared_secret_), |
| 225 initial_state); | 242 initial_state); |
| 226 } | 243 } |
| 227 } | 244 } |
| 228 | 245 |
| 229 } // namespace protocol | 246 } // namespace protocol |
| 230 } // namespace remoting | 247 } // namespace remoting |
| OLD | NEW |