Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: remoting/protocol/negotiating_authenticator.cc

Issue 12518027: Protocol / client plugin changes to support interactively asking for a PIN (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Reviewer comments Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 12 matching lines...) Expand all
23 23
24 const buzz::StaticQName kMethodAttributeQName = { "", "method" }; 24 const buzz::StaticQName kMethodAttributeQName = { "", "method" };
25 const buzz::StaticQName kSupportedMethodsAttributeQName = 25 const buzz::StaticQName kSupportedMethodsAttributeQName =
26 { "", "supported-methods" }; 26 { "", "supported-methods" };
27 27
28 const char kSupportedMethodsSeparator = ','; 28 const char kSupportedMethodsSeparator = ',';
29 29
30 } // namespace 30 } // namespace
31 31
32 // static 32 // static
33 bool NegotiatingAuthenticator::IsNegotiableMessage(
34 const buzz::XmlElement* message) {
35 return message->HasAttr(kSupportedMethodsAttributeQName);
36 }
37
38 // static
39 scoped_ptr<Authenticator> NegotiatingAuthenticator::CreateForClient( 33 scoped_ptr<Authenticator> NegotiatingAuthenticator::CreateForClient(
40 const std::string& authentication_tag, 34 const std::string& authentication_tag,
41 const std::string& shared_secret, 35 const FetchSecretCallback& fetch_secret_callback,
42 const std::vector<AuthenticationMethod>& methods) { 36 const std::vector<AuthenticationMethod>& methods) {
43 scoped_ptr<NegotiatingAuthenticator> result( 37 scoped_ptr<NegotiatingAuthenticator> result(
44 new NegotiatingAuthenticator(MESSAGE_READY)); 38 new NegotiatingAuthenticator(MESSAGE_READY));
45 result->authentication_tag_ = authentication_tag; 39 result->authentication_tag_ = authentication_tag;
46 result->shared_secret_ = shared_secret; 40 result->fetch_secret_callback_ = fetch_secret_callback;
47 41
48 DCHECK(!methods.empty()); 42 DCHECK(!methods.empty());
49 for (std::vector<AuthenticationMethod>::const_iterator it = methods.begin(); 43 for (std::vector<AuthenticationMethod>::const_iterator it = methods.begin();
50 it != methods.end(); ++it) { 44 it != methods.end(); ++it) {
51 result->AddMethod(*it); 45 result->AddMethod(*it);
52 } 46 }
53 47
54 return scoped_ptr<Authenticator>(result.Pass()); 48 return scoped_ptr<Authenticator>(result.Pass());
55 } 49 }
56 50
(...skipping 11 matching lines...) Expand all
68 62
69 result->AddMethod(AuthenticationMethod::Spake2(hash_function)); 63 result->AddMethod(AuthenticationMethod::Spake2(hash_function));
70 64
71 return scoped_ptr<Authenticator>(result.Pass()); 65 return scoped_ptr<Authenticator>(result.Pass());
72 } 66 }
73 67
74 NegotiatingAuthenticator::NegotiatingAuthenticator( 68 NegotiatingAuthenticator::NegotiatingAuthenticator(
75 Authenticator::State initial_state) 69 Authenticator::State initial_state)
76 : current_method_(AuthenticationMethod::Invalid()), 70 : current_method_(AuthenticationMethod::Invalid()),
77 state_(initial_state), 71 state_(initial_state),
78 rejection_reason_(INVALID_CREDENTIALS) { 72 rejection_reason_(INVALID_CREDENTIALS),
73 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
79 } 74 }
80 75
81 NegotiatingAuthenticator::~NegotiatingAuthenticator() { 76 NegotiatingAuthenticator::~NegotiatingAuthenticator() {
82 } 77 }
83 78
84 Authenticator::State NegotiatingAuthenticator::state() const { 79 Authenticator::State NegotiatingAuthenticator::state() const {
85 return state_; 80 return state_;
86 } 81 }
87 82
88 Authenticator::RejectionReason 83 Authenticator::RejectionReason
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 if (!method.is_valid()) { 133 if (!method.is_valid()) {
139 // Failed to find a common auth method. 134 // Failed to find a common auth method.
140 state_ = REJECTED; 135 state_ = REJECTED;
141 rejection_reason_ = PROTOCOL_ERROR; 136 rejection_reason_ = PROTOCOL_ERROR;
142 resume_callback.Run(); 137 resume_callback.Run();
143 return; 138 return;
144 } 139 }
145 140
146 // Drop the current message because we've chosen a different 141 // Drop the current message because we've chosen a different
147 // method. 142 // method.
148 state_ = MESSAGE_READY; 143 current_method_ = method;
144 state_ = PROCESSING_MESSAGE;
145 CreateAuthenticator(MESSAGE_READY, base::Bind(
146 &NegotiatingAuthenticator::UpdateState,
147 base::Unretained(this), resume_callback));
148 return;
149 } 149 }
150
151 DCHECK(method.is_valid());
152
153 // Replace current authenticator if the method has changed.
154 if (method != current_method_) { 150 if (method != current_method_) {
155 current_method_ = method; 151 current_method_ = method;
156 CreateAuthenticator(state_); 152 state_ = PROCESSING_MESSAGE;
153 // Copy the message since the authenticator may process it asynchronously.
154 CreateAuthenticator(WAITING_MESSAGE, base::Bind(
155 &NegotiatingAuthenticator::ProcessMessageInternal,
156 base::Unretained(this), base::Owned(new buzz::XmlElement(*message)),
157 resume_callback));
158 return;
157 } 159 }
158 if (state_ == WAITING_MESSAGE) { 160 ProcessMessageInternal(message, resume_callback);
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 } 161 }
167 162
168 void NegotiatingAuthenticator::UpdateState( 163 void NegotiatingAuthenticator::UpdateState(
169 const base::Closure& resume_callback) { 164 const base::Closure& resume_callback) {
170 // After the underlying authenticator finishes processing the message, the 165 // After the underlying authenticator finishes processing the message, the
171 // NegotiatingAuthenticator must update its own state before running the 166 // NegotiatingAuthenticator must update its own state before running the
172 // |resume_callback| to resume the session negotiation. 167 // |resume_callback| to resume the session negotiation.
173 state_ = current_authenticator_->state(); 168 state_ = current_authenticator_->state();
174 if (state_ == REJECTED) 169 if (state_ == REJECTED)
175 rejection_reason_ = current_authenticator_->rejection_reason(); 170 rejection_reason_ = current_authenticator_->rejection_reason();
176 resume_callback.Run(); 171 resume_callback.Run();
177 } 172 }
178 173
179 scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() { 174 scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() {
180 DCHECK_EQ(state(), MESSAGE_READY); 175 DCHECK_EQ(state(), MESSAGE_READY);
181 176
182 bool add_supported_methods_attr = false; 177 scoped_ptr<buzz::XmlElement> result;
183 178
184 // Initialize current method in case it is not initialized 179 // No method yet, just send a message with the list of supported methods.
185 // yet. Normally happens only on client. 180 // Normally happens only on client.
186 if (!current_method_.is_valid()) { 181 if (!current_method_.is_valid()) {
187 CHECK(!methods_.empty()); 182 result = CreateEmptyAuthenticatorMessage();
188
189 // Initially try the first method.
190 current_method_ = methods_[0];
191 CreateAuthenticator(MESSAGE_READY);
192 add_supported_methods_attr = true;
193 }
194
195 scoped_ptr<buzz::XmlElement> result =
196 current_authenticator_->GetNextMessage();
197 state_ = current_authenticator_->state();
198 DCHECK_NE(state_, REJECTED);
199
200 result->AddAttr(kMethodAttributeQName, current_method_.ToString());
201
202 if (add_supported_methods_attr) {
203 std::stringstream supported_methods(std::stringstream::out); 183 std::stringstream supported_methods(std::stringstream::out);
204 for (std::vector<AuthenticationMethod>::iterator it = methods_.begin(); 184 for (std::vector<AuthenticationMethod>::iterator it = methods_.begin();
205 it != methods_.end(); ++it) { 185 it != methods_.end(); ++it) {
206 if (it != methods_.begin()) 186 if (it != methods_.begin())
207 supported_methods << kSupportedMethodsSeparator; 187 supported_methods << kSupportedMethodsSeparator;
208 supported_methods << it->ToString(); 188 supported_methods << it->ToString();
209 } 189 }
210 result->AddAttr(kSupportedMethodsAttributeQName, supported_methods.str()); 190 result->AddAttr(kSupportedMethodsAttributeQName, supported_methods.str());
191 state_ = WAITING_MESSAGE;
192 } else {
193 if (current_authenticator_->state() == MESSAGE_READY) {
194 result = current_authenticator_->GetNextMessage();
195 } else {
196 result = CreateEmptyAuthenticatorMessage();
197 }
198 state_ = current_authenticator_->state();
199 DCHECK(state_ == ACCEPTED || state_ == WAITING_MESSAGE);
200 result->AddAttr(kMethodAttributeQName, current_method_.ToString());
211 } 201 }
212 202
213 return result.Pass(); 203 return result.Pass();
214 } 204 }
215 205
216 void NegotiatingAuthenticator::AddMethod(const AuthenticationMethod& method) { 206 void NegotiatingAuthenticator::AddMethod(const AuthenticationMethod& method) {
217 DCHECK(method.is_valid()); 207 DCHECK(method.is_valid());
218 methods_.push_back(method); 208 methods_.push_back(method);
219 } 209 }
220 210
221 scoped_ptr<ChannelAuthenticator> 211 scoped_ptr<ChannelAuthenticator>
222 NegotiatingAuthenticator::CreateChannelAuthenticator() const { 212 NegotiatingAuthenticator::CreateChannelAuthenticator() const {
223 DCHECK_EQ(state(), ACCEPTED); 213 DCHECK_EQ(state(), ACCEPTED);
224 return current_authenticator_->CreateChannelAuthenticator(); 214 return current_authenticator_->CreateChannelAuthenticator();
225 } 215 }
226 216
227 bool NegotiatingAuthenticator::is_host_side() const { 217 bool NegotiatingAuthenticator::is_host_side() const {
228 return local_key_pair_.get() != NULL; 218 return local_key_pair_.get() != NULL;
229 } 219 }
230 220
231 void NegotiatingAuthenticator::CreateAuthenticator(State initial_state) { 221 void NegotiatingAuthenticator::CreateAuthenticator(
222 Authenticator::State preferred_initial_state,
223 const base::Closure& resume_callback) {
232 if (is_host_side()) { 224 if (is_host_side()) {
233 current_authenticator_ = V2Authenticator::CreateForHost( 225 current_authenticator_ = V2Authenticator::CreateForHost(
234 local_cert_, local_key_pair_, shared_secret_hash_, initial_state); 226 local_cert_, local_key_pair_, shared_secret_hash_,
227 preferred_initial_state);
228 resume_callback.Run();
235 } else { 229 } else {
236 current_authenticator_ = V2Authenticator::CreateForClient( 230 fetch_secret_callback_.Run(base::Bind(
237 AuthenticationMethod::ApplyHashFunction( 231 &NegotiatingAuthenticator::CreateV2AuthenticatorWithSecret,
238 current_method_.hash_function(), 232 weak_factory_.GetWeakPtr(), preferred_initial_state, resume_callback));
239 authentication_tag_, shared_secret_), initial_state);
240 } 233 }
241 } 234 }
242 235
236 void NegotiatingAuthenticator::ProcessMessageInternal(
237 const buzz::XmlElement* message,
238 const base::Closure& resume_callback) {
239 if (current_authenticator_->state() == WAITING_MESSAGE) {
240 // If the message was not discarded and the authenticator is waiting for it,
241 // give it to the underlying authenticator to process.
242 // |current_authenticator_| is owned, so Unretained() is safe here.
243 current_authenticator_->ProcessMessage(message, base::Bind(
244 &NegotiatingAuthenticator::UpdateState,
245 base::Unretained(this), resume_callback));
246 }
247 }
248
249 void NegotiatingAuthenticator::CreateV2AuthenticatorWithSecret(
250 Authenticator::State initial_state,
251 const base::Closure& resume_callback,
252 const std::string& shared_secret) {
253 current_authenticator_ = V2Authenticator::CreateForClient(
254 AuthenticationMethod::ApplyHashFunction(
255 current_method_.hash_function(), authentication_tag_, shared_secret),
256 initial_state);
257 resume_callback.Run();
258 }
259
243 } // namespace protocol 260 } // namespace protocol
244 } // namespace remoting 261 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698