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