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

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: Pin -> Secret, comment clarifications. 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 } else {
Sergey Ulanov 2013/03/20 05:49:05 nit: add return above and then you won't need "els
rmsousa 2013/03/20 20:17:16 Done.
149 if (method != current_method_) {
150 current_method_ = method;
151 state_ = PROCESSING_MESSAGE;
152 // Copy the message since the authenticator may process it asynchronously.
153 CreateAuthenticator(WAITING_MESSAGE, base::Bind(
154 &NegotiatingAuthenticator::ProcessMessageInternal,
155 base::Unretained(this), base::Owned(new buzz::XmlElement(*message)),
156 resume_callback));
157 } else {
158 ProcessMessageInternal(message, resume_callback);
159 }
149 } 160 }
161 }
150 162
151 DCHECK(method.is_valid()); 163 void NegotiatingAuthenticator::ProcessMessageInternal(
Sergey Ulanov 2013/03/20 05:49:05 Move this below so order of functions here matches
rmsousa 2013/03/20 20:17:16 Done.
152 164 const buzz::XmlElement* message,
153 // Replace current authenticator if the method has changed. 165 const base::Closure& resume_callback) {
154 if (method != current_method_) { 166 if (current_authenticator_->state() == WAITING_MESSAGE) {
155 current_method_ = method; 167 // If the message was not discarded and the authenticator is waiting for it,
156 CreateAuthenticator(state_); 168 // give it to the underlying authenticator to process.
157 }
158 if (state_ == WAITING_MESSAGE) {
159 // |current_authenticator_| is owned, so Unretained() is safe here. 169 // |current_authenticator_| is owned, so Unretained() is safe here.
160 current_authenticator_->ProcessMessage(message, base::Bind( 170 current_authenticator_->ProcessMessage(message, base::Bind(
161 &NegotiatingAuthenticator::UpdateState, 171 &NegotiatingAuthenticator::UpdateState,
162 base::Unretained(this), resume_callback)); 172 base::Unretained(this), resume_callback));
163 } else {
164 UpdateState(resume_callback);
165 } 173 }
166 } 174 }
167 175
168 void NegotiatingAuthenticator::UpdateState( 176 void NegotiatingAuthenticator::UpdateState(
169 const base::Closure& resume_callback) { 177 const base::Closure& resume_callback) {
170 // After the underlying authenticator finishes processing the message, the 178 // After the underlying authenticator finishes processing the message, the
171 // NegotiatingAuthenticator must update its own state before running the 179 // NegotiatingAuthenticator must update its own state before running the
172 // |resume_callback| to resume the session negotiation. 180 // |resume_callback| to resume the session negotiation.
173 state_ = current_authenticator_->state(); 181 state_ = current_authenticator_->state();
174 if (state_ == REJECTED) 182 if (state_ == REJECTED)
175 rejection_reason_ = current_authenticator_->rejection_reason(); 183 rejection_reason_ = current_authenticator_->rejection_reason();
176 resume_callback.Run(); 184 resume_callback.Run();
177 } 185 }
178 186
179 scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() { 187 scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() {
180 DCHECK_EQ(state(), MESSAGE_READY); 188 DCHECK_EQ(state(), MESSAGE_READY);
181 189
182 bool add_supported_methods_attr = false; 190 scoped_ptr<buzz::XmlElement> result;
183 191
184 // Initialize current method in case it is not initialized 192 // No method yet, just send a message with the list of supported methods.
185 // yet. Normally happens only on client. 193 // Normally happens only on client.
186 if (!current_method_.is_valid()) { 194 if (!current_method_.is_valid()) {
187 CHECK(!methods_.empty()); 195 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); 196 std::stringstream supported_methods(std::stringstream::out);
204 for (std::vector<AuthenticationMethod>::iterator it = methods_.begin(); 197 for (std::vector<AuthenticationMethod>::iterator it = methods_.begin();
205 it != methods_.end(); ++it) { 198 it != methods_.end(); ++it) {
206 if (it != methods_.begin()) 199 if (it != methods_.begin())
207 supported_methods << kSupportedMethodsSeparator; 200 supported_methods << kSupportedMethodsSeparator;
208 supported_methods << it->ToString(); 201 supported_methods << it->ToString();
209 } 202 }
210 result->AddAttr(kSupportedMethodsAttributeQName, supported_methods.str()); 203 result->AddAttr(kSupportedMethodsAttributeQName, supported_methods.str());
204 state_ = WAITING_MESSAGE;
205 } else {
206 if (current_authenticator_->state() == MESSAGE_READY) {
207 result = current_authenticator_->GetNextMessage();
208 } else {
209 result = CreateEmptyAuthenticatorMessage();
210 }
211 state_ = current_authenticator_->state();
212 DCHECK_NE(state_, REJECTED);
Sergey Ulanov 2013/03/20 05:49:05 here state can be either WAITING_MESSAGE or ACCEPT
rmsousa 2013/03/20 20:17:16 Done.
213 DCHECK_NE(state_, MESSAGE_READY);
214 result->AddAttr(kMethodAttributeQName, current_method_.ToString());
211 } 215 }
212 216
213 return result.Pass(); 217 return result.Pass();
214 } 218 }
215 219
216 void NegotiatingAuthenticator::AddMethod(const AuthenticationMethod& method) { 220 void NegotiatingAuthenticator::AddMethod(const AuthenticationMethod& method) {
217 DCHECK(method.is_valid()); 221 DCHECK(method.is_valid());
218 methods_.push_back(method); 222 methods_.push_back(method);
219 } 223 }
220 224
221 scoped_ptr<ChannelAuthenticator> 225 scoped_ptr<ChannelAuthenticator>
222 NegotiatingAuthenticator::CreateChannelAuthenticator() const { 226 NegotiatingAuthenticator::CreateChannelAuthenticator() const {
223 DCHECK_EQ(state(), ACCEPTED); 227 DCHECK_EQ(state(), ACCEPTED);
224 return current_authenticator_->CreateChannelAuthenticator(); 228 return current_authenticator_->CreateChannelAuthenticator();
225 } 229 }
226 230
227 bool NegotiatingAuthenticator::is_host_side() const { 231 bool NegotiatingAuthenticator::is_host_side() const {
228 return local_key_pair_.get() != NULL; 232 return local_key_pair_.get() != NULL;
229 } 233 }
230 234
231 void NegotiatingAuthenticator::CreateAuthenticator(State initial_state) { 235
Sergey Ulanov 2013/03/20 05:49:05 nit: remove empty line
rmsousa 2013/03/20 20:17:16 Done.
236 void NegotiatingAuthenticator::CreateAuthenticator(
237 Authenticator::State preferred_initial_state,
238 const base::Closure& resume_callback) {
232 if (is_host_side()) { 239 if (is_host_side()) {
233 current_authenticator_ = V2Authenticator::CreateForHost( 240 current_authenticator_ = V2Authenticator::CreateForHost(
234 local_cert_, local_key_pair_, shared_secret_hash_, initial_state); 241 local_cert_, local_key_pair_, shared_secret_hash_,
242 preferred_initial_state);
243 resume_callback.Run();
Sergey Ulanov 2013/03/20 05:49:05 Do you need to set state_ here to something other
rmsousa 2013/03/20 20:17:16 The callbacks passed in here all call UpdateState
235 } else { 244 } else {
236 current_authenticator_ = V2Authenticator::CreateForClient( 245 fetch_secret_callback_.Run(base::Bind(
237 AuthenticationMethod::ApplyHashFunction( 246 &NegotiatingAuthenticator::CreateV2AuthenticatorWithSecret,
238 current_method_.hash_function(), 247 weak_factory_.GetWeakPtr(), preferred_initial_state, resume_callback));
239 authentication_tag_, shared_secret_), initial_state);
240 } 248 }
241 } 249 }
242 250
251 void NegotiatingAuthenticator::CreateV2AuthenticatorWithSecret(
252 Authenticator::State initial_state,
253 const base::Closure& resume_callback,
254 const std::string& shared_secret) {
255 current_authenticator_ = V2Authenticator::CreateForClient(
256 AuthenticationMethod::ApplyHashFunction(
257 current_method_.hash_function(), authentication_tag_, shared_secret),
258 initial_state);
259 resume_callback.Run();
Sergey Ulanov 2013/03/20 05:49:05 Set state_ to MESSAGE_READY?
rmsousa 2013/03/20 20:17:16 Same applies, there's an UpdateState in the callba
260 }
261
243 } // namespace protocol 262 } // namespace protocol
244 } // namespace remoting 263 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698