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

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

Issue 8619011: Use Authenticator interface in Session and SessionManager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix unittests Created 9 years 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 | Annotate | Revision Log
« no previous file with comments | « remoting/protocol/jingle_session.h ('k') | remoting/protocol/jingle_session_manager.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/jingle_session.h" 5 #include "remoting/protocol/jingle_session.h"
6 6
7 #include "base/base64.h"
7 #include "base/bind.h" 8 #include "base/bind.h"
8 #include "base/location.h" 9 #include "base/location.h"
9 #include "base/message_loop_proxy.h" 10 #include "base/message_loop_proxy.h"
10 #include "base/rand_util.h" 11 #include "base/rand_util.h"
11 #include "base/stl_util.h" 12 #include "base/stl_util.h"
12 #include "crypto/hmac.h" 13 #include "crypto/hmac.h"
13 #include "crypto/rsa_private_key.h"
14 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
15 #include "net/socket/stream_socket.h" 15 #include "net/socket/stream_socket.h"
16 #include "remoting/base/constants.h" 16 #include "remoting/base/constants.h"
17 #include "remoting/protocol/auth_util.h" 17 #include "remoting/protocol/auth_util.h"
18 #include "remoting/protocol/authenticator.h"
19 #include "remoting/protocol/channel_authenticator.h"
18 #include "remoting/protocol/jingle_datagram_connector.h" 20 #include "remoting/protocol/jingle_datagram_connector.h"
19 #include "remoting/protocol/jingle_session_manager.h" 21 #include "remoting/protocol/jingle_session_manager.h"
20 #include "remoting/protocol/jingle_stream_connector.h" 22 #include "remoting/protocol/jingle_stream_connector.h"
21 #include "remoting/protocol/v1_client_channel_authenticator.h"
22 #include "remoting/protocol/v1_host_channel_authenticator.h"
23 #include "third_party/libjingle/source/talk/base/thread.h" 23 #include "third_party/libjingle/source/talk/base/thread.h"
24 #include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h" 24 #include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h"
25 #include "third_party/libjingle/source/talk/p2p/base/session.h" 25 #include "third_party/libjingle/source/talk/p2p/base/session.h"
26 #include "third_party/libjingle/source/talk/p2p/base/transport.h" 26 #include "third_party/libjingle/source/talk/p2p/base/transport.h"
27 27
28 using cricket::BaseSession; 28 using cricket::BaseSession;
29 29
30 namespace remoting { 30 namespace remoting {
31 namespace protocol { 31 namespace protocol {
32 32
33 // static
34 JingleSession* JingleSession::CreateClientSession(
35 JingleSessionManager* manager, const std::string& host_public_key) {
36 return new JingleSession(manager, "", NULL, host_public_key);
37 }
38
39 // static
40 JingleSession* JingleSession::CreateServerSession(
41 JingleSessionManager* manager,
42 const std::string& certificate,
43 crypto::RSAPrivateKey* key) {
44 return new JingleSession(manager, certificate, key, "");
45 }
46
47 JingleSession::JingleSession( 33 JingleSession::JingleSession(
48 JingleSessionManager* jingle_session_manager, 34 JingleSessionManager* jingle_session_manager,
49 const std::string& local_cert, 35 cricket::Session* cricket_session,
50 crypto::RSAPrivateKey* local_private_key, 36 Authenticator* authenticator)
51 const std::string& peer_public_key)
52 : jingle_session_manager_(jingle_session_manager), 37 : jingle_session_manager_(jingle_session_manager),
53 local_cert_(local_cert), 38 authenticator_(authenticator),
54 state_(INITIALIZING), 39 state_(INITIALIZING),
55 error_(OK), 40 error_(OK),
56 closing_(false), 41 closing_(false),
57 cricket_session_(NULL), 42 cricket_session_(cricket_session),
58 config_set_(false), 43 config_set_(false),
59 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { 44 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
60 // TODO(hclam): Need a better way to clone a key. 45 jid_ = cricket_session_->remote_name();
61 if (local_private_key) { 46 cricket_session_->SignalState.connect(this, &JingleSession::OnSessionState);
62 std::vector<uint8> key_bytes; 47 cricket_session_->SignalError.connect(this, &JingleSession::OnSessionError);
63 CHECK(local_private_key->ExportPrivateKey(&key_bytes));
64 local_private_key_.reset(
65 crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
66 CHECK(local_private_key_.get());
67 }
68 } 48 }
69 49
70 JingleSession::~JingleSession() { 50 JingleSession::~JingleSession() {
71 // Reset the callback so that it's not called from Close(). 51 // Reset the callback so that it's not called from Close().
72 state_change_callback_.Reset(); 52 state_change_callback_.Reset();
73 Close(); 53 Close();
74 jingle_session_manager_->SessionDestroyed(this); 54 jingle_session_manager_->SessionDestroyed(this);
75 DCHECK(channel_connectors_.empty()); 55 DCHECK(channel_connectors_.empty());
76 } 56 }
77 57
78 void JingleSession::Init(cricket::Session* cricket_session) { 58 void JingleSession::SendSessionInitiate() {
79 DCHECK(CalledOnValidThread()); 59 DCHECK_EQ(authenticator_->state(), Authenticator::MESSAGE_READY);
80 60 cricket_session_->Initiate(
81 cricket_session_ = cricket_session; 61 jid_, CreateSessionDescription(candidate_config()->Clone(),
82 jid_ = cricket_session_->remote_name(); 62 authenticator_->GetNextMessage()));
83 cricket_session_->SignalState.connect(
84 this, &JingleSession::OnSessionState);
85 cricket_session_->SignalError.connect(
86 this, &JingleSession::OnSessionError);
87 } 63 }
88 64
89 void JingleSession::CloseInternal(int result, Error error) { 65 void JingleSession::CloseInternal(int result, Error error) {
90 DCHECK(CalledOnValidThread()); 66 DCHECK(CalledOnValidThread());
91 67
92 if (state_ != FAILED && state_ != CLOSED && !closing_) { 68 if (state_ != FAILED && state_ != CLOSED && !closing_) {
93 closing_ = true; 69 closing_ = true;
94 70
95 // Tear down the cricket session, including the cricket transport channels. 71 // Tear down the cricket session, including the cricket transport channels.
96 if (cricket_session_) { 72 if (cricket_session_) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 } 168 }
193 169
194 void JingleSession::set_candidate_config( 170 void JingleSession::set_candidate_config(
195 const CandidateSessionConfig* candidate_config) { 171 const CandidateSessionConfig* candidate_config) {
196 DCHECK(CalledOnValidThread()); 172 DCHECK(CalledOnValidThread());
197 DCHECK(!candidate_config_.get()); 173 DCHECK(!candidate_config_.get());
198 DCHECK(candidate_config); 174 DCHECK(candidate_config);
199 candidate_config_.reset(candidate_config); 175 candidate_config_.reset(candidate_config);
200 } 176 }
201 177
202 const std::string& JingleSession::local_certificate() const {
203 DCHECK(CalledOnValidThread());
204 return local_cert_;
205 }
206
207 const SessionConfig& JingleSession::config() { 178 const SessionConfig& JingleSession::config() {
208 DCHECK(CalledOnValidThread()); 179 DCHECK(CalledOnValidThread());
209 DCHECK(config_set_); 180 DCHECK(config_set_);
210 return config_; 181 return config_;
211 } 182 }
212 183
213 void JingleSession::set_config(const SessionConfig& config) { 184 void JingleSession::set_config(const SessionConfig& config) {
214 DCHECK(CalledOnValidThread()); 185 DCHECK(CalledOnValidThread());
215 DCHECK(!config_set_); 186 DCHECK(!config_set_);
216 config_ = config; 187 config_ = config;
217 config_set_ = true; 188 config_set_ = true;
218 } 189 }
219 190
220 const std::string& JingleSession::initiator_token() {
221 DCHECK(CalledOnValidThread());
222 return initiator_token_;
223 }
224
225 void JingleSession::set_initiator_token(const std::string& initiator_token) {
226 DCHECK(CalledOnValidThread());
227 initiator_token_ = initiator_token;
228 }
229
230 const std::string& JingleSession::receiver_token() {
231 DCHECK(CalledOnValidThread());
232 return receiver_token_;
233 }
234
235 void JingleSession::set_receiver_token(const std::string& receiver_token) {
236 DCHECK(CalledOnValidThread());
237 receiver_token_ = receiver_token;
238 }
239
240 void JingleSession::set_shared_secret(const std::string& secret) {
241 DCHECK(CalledOnValidThread());
242 shared_secret_ = secret;
243 }
244
245 const std::string& JingleSession::shared_secret() {
246 DCHECK(CalledOnValidThread());
247 return shared_secret_;
248 }
249
250
251 void JingleSession::Close() { 191 void JingleSession::Close() {
252 DCHECK(CalledOnValidThread()); 192 DCHECK(CalledOnValidThread());
253 193
254 CloseInternal(net::ERR_CONNECTION_CLOSED, OK); 194 CloseInternal(net::ERR_CONNECTION_CLOSED, OK);
255 } 195 }
256 196
257 void JingleSession::OnSessionState( 197 void JingleSession::OnSessionState(
258 BaseSession* session, BaseSession::State state) { 198 BaseSession* session, BaseSession::State state) {
259 DCHECK(CalledOnValidThread()); 199 DCHECK(CalledOnValidThread());
260 DCHECK_EQ(cricket_session_, session); 200 DCHECK_EQ(cricket_session_, session);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 if (error != cricket::Session::ERROR_NONE) { 241 if (error != cricket::Session::ERROR_NONE) {
302 // TODO(sergeyu): Report different errors depending on |error|. 242 // TODO(sergeyu): Report different errors depending on |error|.
303 CloseInternal(net::ERR_CONNECTION_ABORTED, CHANNEL_CONNECTION_ERROR); 243 CloseInternal(net::ERR_CONNECTION_ABORTED, CHANNEL_CONNECTION_ERROR);
304 } 244 }
305 } 245 }
306 246
307 void JingleSession::OnInitiate() { 247 void JingleSession::OnInitiate() {
308 DCHECK(CalledOnValidThread()); 248 DCHECK(CalledOnValidThread());
309 jid_ = cricket_session_->remote_name(); 249 jid_ = cricket_session_->remote_name();
310 250
311 if (!cricket_session_->initiator()) {
312 const protocol::ContentDescription* content_description =
313 static_cast<const protocol::ContentDescription*>(
314 GetContentInfo()->description);
315 CHECK(content_description);
316 }
317
318 if (cricket_session_->initiator()) { 251 if (cricket_session_->initiator()) {
319 // Set state to CONNECTING if this is an outgoing message. We need 252 // Set state to CONNECTING if this is an outgoing message. We need
320 // to post this task because channel creation works only after we 253 // to post this task because channel creation works only after we
321 // return from this method. This is because 254 // return from this method. This is because
322 // JingleChannelConnector::Connect() needs to call 255 // JingleChannelConnector::Connect() needs to call
323 // set_incoming_only() on P2PTransportChannel, but 256 // set_incoming_only() on P2PTransportChannel, but
324 // P2PTransportChannel is created only after we return from this 257 // P2PTransportChannel is created only after we return from this
325 // method. 258 // method.
326 // TODO(sergeyu): Add set_incoming_only() in TransportChannelProxy. 259 // TODO(sergeyu): Add set_incoming_only() in TransportChannelProxy.
327 jingle_session_manager_->message_loop_->PostTask( 260 jingle_session_manager_->message_loop_->PostTask(
(...skipping 10 matching lines...) Expand all
338 const cricket::SessionDescription* description) { 271 const cricket::SessionDescription* description) {
339 // We should only be called after ParseContent has succeeded, in which 272 // We should only be called after ParseContent has succeeded, in which
340 // case there will always be a Chromoting session configuration. 273 // case there will always be a Chromoting session configuration.
341 const cricket::ContentInfo* content = 274 const cricket::ContentInfo* content =
342 description->FirstContentByType(kChromotingXmlNamespace); 275 description->FirstContentByType(kChromotingXmlNamespace);
343 CHECK(content); 276 CHECK(content);
344 const protocol::ContentDescription* content_description = 277 const protocol::ContentDescription* content_description =
345 static_cast<const protocol::ContentDescription*>(content->description); 278 static_cast<const protocol::ContentDescription*>(content->description);
346 CHECK(content_description); 279 CHECK(content_description);
347 280
348 remote_cert_ = content_description->certificate(); 281 // Process authenticator message.
349 if (remote_cert_.empty()) { 282 const buzz::XmlElement* auth_message =
350 LOG(ERROR) << "Connection response does not specify certificate"; 283 content_description->authenticator_message();
284 if (!auth_message) {
285 DLOG(WARNING) << "Received session-accept without authentication message "
286 << auth_message->Str();
351 return false; 287 return false;
352 } 288 }
353 289
290 DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
291 authenticator_->ProcessMessage(auth_message);
292 // Support for more than two auth message is not implemented yet.
293 DCHECK(authenticator_->state() != Authenticator::WAITING_MESSAGE &&
294 authenticator_->state() != Authenticator::MESSAGE_READY);
295
296 if (authenticator_->state() != Authenticator::ACCEPTED) {
297 return false;
298 }
299
354 SessionConfig config; 300 SessionConfig config;
355 if (!content_description->config()->GetFinalConfig(&config)) { 301 if (!content_description->config()->GetFinalConfig(&config)) {
356 LOG(ERROR) << "Connection response does not specify configuration"; 302 LOG(ERROR) << "Connection response does not specify configuration";
357 return false; 303 return false;
358 } 304 }
359 if (!candidate_config()->IsSupported(config)) { 305 if (!candidate_config()->IsSupported(config)) {
360 LOG(ERROR) << "Connection response specifies an invalid configuration"; 306 LOG(ERROR) << "Connection response specifies an invalid configuration";
361 return false; 307 return false;
362 } 308 }
363 309
(...skipping 18 matching lines...) Expand all
382 } 328 }
383 329
384 void JingleSession::OnTerminate() { 330 void JingleSession::OnTerminate() {
385 DCHECK(CalledOnValidThread()); 331 DCHECK(CalledOnValidThread());
386 CloseInternal(net::ERR_CONNECTION_ABORTED, OK); 332 CloseInternal(net::ERR_CONNECTION_ABORTED, OK);
387 } 333 }
388 334
389 void JingleSession::AcceptConnection() { 335 void JingleSession::AcceptConnection() {
390 SetState(CONNECTING); 336 SetState(CONNECTING);
391 337
392 if (!jingle_session_manager_->AcceptConnection(this, cricket_session_)) { 338 const cricket::SessionDescription* session_description =
339 cricket_session_->remote_description();
340 const cricket::ContentInfo* content =
341 session_description->FirstContentByType(kChromotingXmlNamespace);
342
343 CHECK(content);
344 const ContentDescription* content_description =
345 static_cast<const ContentDescription*>(content->description);
346 candidate_config_.reset(content_description->config()->Clone());
347
348 SessionManager::IncomingSessionResponse response =
349 jingle_session_manager_->AcceptConnection(this);
350 if (response != SessionManager::ACCEPT) {
351 if (response == SessionManager::INCOMPATIBLE) {
352 cricket_session_->TerminateWithReason(
353 cricket::STR_TERMINATE_INCOMPATIBLE_PARAMETERS);
354 } else {
355 cricket_session_->TerminateWithReason(cricket::STR_TERMINATE_DECLINE);
356 }
393 Close(); 357 Close();
394 // Release session so that JingleSessionManager::SessionDestroyed() 358 // Release session so that JingleSessionManager::SessionDestroyed()
395 // doesn't try to call cricket::SessionManager::DestroySession() for it. 359 // doesn't try to call cricket::SessionManager::DestroySession() for it.
396 ReleaseSession(); 360 ReleaseSession();
397 delete this; 361 delete this;
398 return; 362 return;
399 } 363 }
400 364
401 if (!VerifySupportAuthToken(jid_, shared_secret_, initiator_token())) 365 const buzz::XmlElement* auth_message =
366 content_description->authenticator_message();
367 if (!auth_message) {
368 DLOG(WARNING) << "Received session-initiate without authenticator message.";
369 CloseInternal(net::ERR_CONNECTION_FAILED, INCOMPATIBLE_PROTOCOL);
370 return;
371 }
372
373 authenticator_.reset(
374 jingle_session_manager_->CreateAuthenticator(jid(), auth_message));
375 if (!authenticator_.get()) {
376 CloseInternal(net::ERR_CONNECTION_FAILED, INCOMPATIBLE_PROTOCOL);
377 return;
378 }
379
380 DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
381 authenticator_->ProcessMessage(auth_message);
382 // Support for more than two auth message is not implemented yet.
383 DCHECK(authenticator_->state() != Authenticator::WAITING_MESSAGE);
384 if (authenticator_->state() == Authenticator::REJECTED) {
402 CloseInternal(net::ERR_CONNECTION_FAILED, AUTHENTICATION_FAILED); 385 CloseInternal(net::ERR_CONNECTION_FAILED, AUTHENTICATION_FAILED);
386 return;
387 }
388
389 // Connection must be configured by the AcceptConnection() callback.
390 CandidateSessionConfig* candidate_config =
391 CandidateSessionConfig::CreateFrom(config());
392
393 buzz::XmlElement* auth_reply = NULL;
394 if (authenticator_->state() == Authenticator::MESSAGE_READY)
395 auth_reply = authenticator_->GetNextMessage();
396 DCHECK_EQ(authenticator_->state(), Authenticator::ACCEPTED);
397 cricket_session_->Accept(
398 CreateSessionDescription(candidate_config, auth_reply));
403 } 399 }
404 400
405 void JingleSession::AddChannelConnector( 401 void JingleSession::AddChannelConnector(
406 const std::string& name, JingleChannelConnector* connector) { 402 const std::string& name, JingleChannelConnector* connector) {
407 DCHECK(channel_connectors_.find(name) == channel_connectors_.end()); 403 DCHECK(channel_connectors_.find(name) == channel_connectors_.end());
408 404
409 const std::string& content_name = GetContentInfo()->name; 405 const std::string& content_name = GetContentInfo()->name;
410 cricket::TransportChannel* raw_channel = 406 cricket::TransportChannel* raw_channel =
411 cricket_session_->CreateChannel(content_name, name); 407 cricket_session_->CreateChannel(content_name, name);
412 408
413 if (!jingle_session_manager_->allow_nat_traversal_ && 409 if (!jingle_session_manager_->allow_nat_traversal_ &&
414 !cricket_session_->initiator()) { 410 !cricket_session_->initiator()) {
415 // Don't make outgoing connections from the host to client when 411 // Don't make outgoing connections from the host to client when
416 // NAT traversal is disabled. 412 // NAT traversal is disabled.
417 raw_channel->GetP2PChannel()->set_incoming_only(true); 413 raw_channel->GetP2PChannel()->set_incoming_only(true);
418 } 414 }
419 415
420 channel_connectors_[name] = connector; 416 channel_connectors_[name] = connector;
421 ChannelAuthenticator* authenticator; 417 ChannelAuthenticator* authenticator =
422 if (cricket_session_->initiator()) { 418 authenticator_->CreateChannelAuthenticator();
423 authenticator = new V1ClientChannelAuthenticator(
424 remote_cert_, shared_secret_);
425 } else {
426 authenticator = new V1HostChannelAuthenticator(
427 local_cert_, local_private_key_.get(), shared_secret_);
428 }
429 connector->Connect(authenticator, raw_channel); 419 connector->Connect(authenticator, raw_channel);
430 420
431 // Workaround bug in libjingle - it doesn't connect channels if they 421 // Workaround bug in libjingle - it doesn't connect channels if they
432 // are created after the session is accepted. See crbug.com/89384. 422 // are created after the session is accepted. See crbug.com/89384.
433 // TODO(sergeyu): Fix the bug and remove this line. 423 // TODO(sergeyu): Fix the bug and remove this line.
434 cricket_session_->GetTransport(content_name)->ConnectChannels(); 424 cricket_session_->GetTransport(content_name)->ConnectChannels();
435 } 425 }
436 426
437 void JingleSession::OnChannelConnectorFinished( 427 void JingleSession::OnChannelConnectorFinished(
438 const std::string& name, JingleChannelConnector* connector) { 428 const std::string& name, JingleChannelConnector* connector) {
(...skipping 23 matching lines...) Expand all
462 if (new_state != state_) { 452 if (new_state != state_) {
463 DCHECK_NE(state_, CLOSED); 453 DCHECK_NE(state_, CLOSED);
464 DCHECK_NE(state_, FAILED); 454 DCHECK_NE(state_, FAILED);
465 455
466 state_ = new_state; 456 state_ = new_state;
467 if (!state_change_callback_.is_null()) 457 if (!state_change_callback_.is_null())
468 state_change_callback_.Run(new_state); 458 state_change_callback_.Run(new_state);
469 } 459 }
470 } 460 }
471 461
462 // static
463 cricket::SessionDescription* JingleSession::CreateSessionDescription(
464 const CandidateSessionConfig* config,
465 const buzz::XmlElement* authenticator_message) {
466 cricket::SessionDescription* desc = new cricket::SessionDescription();
467 desc->AddContent(
468 ContentDescription::kChromotingContentName, kChromotingXmlNamespace,
469 new ContentDescription(config, authenticator_message));
470 return desc;
471 }
472
472 } // namespace protocol 473 } // namespace protocol
473 } // namespace remoting 474 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/protocol/jingle_session.h ('k') | remoting/protocol/jingle_session_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698