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

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: - 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
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 } 55 }
76 56
77 void JingleSession::Init(cricket::Session* cricket_session) { 57 void JingleSession::Initiate() {
78 DCHECK(CalledOnValidThread()); 58 DCHECK_EQ(authenticator_->state(), Authenticator::MESSAGE_READY);
79 59 cricket_session_->Initiate(
80 cricket_session_ = cricket_session; 60 jid_, CreateSessionDescription(candidate_config()->Clone(),
81 jid_ = cricket_session_->remote_name(); 61 authenticator_->GetNextMessage()));
82 cricket_session_->SignalState.connect(
83 this, &JingleSession::OnSessionState);
84 cricket_session_->SignalError.connect(
85 this, &JingleSession::OnSessionError);
86 } 62 }
87 63
88 void JingleSession::CloseInternal(int result, Error error) { 64 void JingleSession::CloseInternal(int result, Error error) {
89 DCHECK(CalledOnValidThread()); 65 DCHECK(CalledOnValidThread());
90 66
91 if (state_ != FAILED && state_ != CLOSED && !closing_) { 67 if (state_ != FAILED && state_ != CLOSED && !closing_) {
92 closing_ = true; 68 closing_ = true;
93 69
94 STLDeleteContainerPairSecondPointers(channel_connectors_.begin(), 70 STLDeleteContainerPairSecondPointers(channel_connectors_.begin(),
95 channel_connectors_.end()); 71 channel_connectors_.end());
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 } 170 }
195 171
196 void JingleSession::set_candidate_config( 172 void JingleSession::set_candidate_config(
197 const CandidateSessionConfig* candidate_config) { 173 const CandidateSessionConfig* candidate_config) {
198 DCHECK(CalledOnValidThread()); 174 DCHECK(CalledOnValidThread());
199 DCHECK(!candidate_config_.get()); 175 DCHECK(!candidate_config_.get());
200 DCHECK(candidate_config); 176 DCHECK(candidate_config);
201 candidate_config_.reset(candidate_config); 177 candidate_config_.reset(candidate_config);
202 } 178 }
203 179
204 const std::string& JingleSession::local_certificate() const {
205 DCHECK(CalledOnValidThread());
206 return local_cert_;
207 }
208
209 const SessionConfig& JingleSession::config() { 180 const SessionConfig& JingleSession::config() {
210 DCHECK(CalledOnValidThread()); 181 DCHECK(CalledOnValidThread());
211 DCHECK(config_set_); 182 DCHECK(config_set_);
212 return config_; 183 return config_;
213 } 184 }
214 185
215 void JingleSession::set_config(const SessionConfig& config) { 186 void JingleSession::set_config(const SessionConfig& config) {
216 DCHECK(CalledOnValidThread()); 187 DCHECK(CalledOnValidThread());
217 DCHECK(!config_set_); 188 DCHECK(!config_set_);
218 config_ = config; 189 config_ = config;
219 config_set_ = true; 190 config_set_ = true;
220 } 191 }
221 192
222 const std::string& JingleSession::initiator_token() {
223 DCHECK(CalledOnValidThread());
224 return initiator_token_;
225 }
226
227 void JingleSession::set_initiator_token(const std::string& initiator_token) {
228 DCHECK(CalledOnValidThread());
229 initiator_token_ = initiator_token;
230 }
231
232 const std::string& JingleSession::receiver_token() {
233 DCHECK(CalledOnValidThread());
234 return receiver_token_;
235 }
236
237 void JingleSession::set_receiver_token(const std::string& receiver_token) {
238 DCHECK(CalledOnValidThread());
239 receiver_token_ = receiver_token;
240 }
241
242 void JingleSession::set_shared_secret(const std::string& secret) {
243 DCHECK(CalledOnValidThread());
244 shared_secret_ = secret;
245 }
246
247 const std::string& JingleSession::shared_secret() {
248 DCHECK(CalledOnValidThread());
249 return shared_secret_;
250 }
251
252
253 void JingleSession::Close() { 193 void JingleSession::Close() {
254 DCHECK(CalledOnValidThread()); 194 DCHECK(CalledOnValidThread());
255 195
256 CloseInternal(net::ERR_CONNECTION_CLOSED, OK); 196 CloseInternal(net::ERR_CONNECTION_CLOSED, OK);
257 } 197 }
258 198
259 void JingleSession::OnSessionState( 199 void JingleSession::OnSessionState(
260 BaseSession* session, BaseSession::State state) { 200 BaseSession* session, BaseSession::State state) {
261 DCHECK(CalledOnValidThread()); 201 DCHECK(CalledOnValidThread());
262 DCHECK_EQ(cricket_session_, session); 202 DCHECK_EQ(cricket_session_, session);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 if (error != cricket::Session::ERROR_NONE) { 243 if (error != cricket::Session::ERROR_NONE) {
304 // TODO(sergeyu): Report different errors depending on |error|. 244 // TODO(sergeyu): Report different errors depending on |error|.
305 CloseInternal(net::ERR_CONNECTION_ABORTED, CHANNEL_CONNECTION_ERROR); 245 CloseInternal(net::ERR_CONNECTION_ABORTED, CHANNEL_CONNECTION_ERROR);
306 } 246 }
307 } 247 }
308 248
309 void JingleSession::OnInitiate() { 249 void JingleSession::OnInitiate() {
310 DCHECK(CalledOnValidThread()); 250 DCHECK(CalledOnValidThread());
311 jid_ = cricket_session_->remote_name(); 251 jid_ = cricket_session_->remote_name();
312 252
313 if (!cricket_session_->initiator()) {
314 const protocol::ContentDescription* content_description =
315 static_cast<const protocol::ContentDescription*>(
316 GetContentInfo()->description);
317 CHECK(content_description);
318 }
319
320 if (cricket_session_->initiator()) { 253 if (cricket_session_->initiator()) {
321 // Set state to CONNECTING if this is an outgoing message. We need 254 // Set state to CONNECTING if this is an outgoing message. We need
322 // to post this task because channel creation works only after we 255 // to post this task because channel creation works only after we
323 // return from this method. This is because 256 // return from this method. This is because
324 // JingleChannelConnector::Connect() needs to call 257 // JingleChannelConnector::Connect() needs to call
325 // set_incoming_only() on P2PTransportChannel, but 258 // set_incoming_only() on P2PTransportChannel, but
326 // P2PTransportChannel is created only after we return from this 259 // P2PTransportChannel is created only after we return from this
327 // method. 260 // method.
328 // TODO(sergeyu): Add set_incoming_only() in TransportChannelProxy. 261 // TODO(sergeyu): Add set_incoming_only() in TransportChannelProxy.
329 jingle_session_manager_->message_loop_->PostTask( 262 jingle_session_manager_->message_loop_->PostTask(
(...skipping 10 matching lines...) Expand all
340 const cricket::SessionDescription* description) { 273 const cricket::SessionDescription* description) {
341 // We should only be called after ParseContent has succeeded, in which 274 // We should only be called after ParseContent has succeeded, in which
342 // case there will always be a Chromoting session configuration. 275 // case there will always be a Chromoting session configuration.
343 const cricket::ContentInfo* content = 276 const cricket::ContentInfo* content =
344 description->FirstContentByType(kChromotingXmlNamespace); 277 description->FirstContentByType(kChromotingXmlNamespace);
345 CHECK(content); 278 CHECK(content);
346 const protocol::ContentDescription* content_description = 279 const protocol::ContentDescription* content_description =
347 static_cast<const protocol::ContentDescription*>(content->description); 280 static_cast<const protocol::ContentDescription*>(content->description);
348 CHECK(content_description); 281 CHECK(content_description);
349 282
350 remote_cert_ = content_description->certificate(); 283 // Process authenticator message.
351 if (remote_cert_.empty()) { 284 const buzz::XmlElement* auth_message =
352 LOG(ERROR) << "Connection response does not specify certificate"; 285 content_description->authenticator_message();
286 if (!auth_message) {
287 DLOG(WARNING) << "Received session-accept without authentication message "
288 << auth_message->Str();
353 return false; 289 return false;
354 } 290 }
355 291
292 DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
293 authenticator_->ProcessMessage(auth_message);
294 // Support for more than two auth message is not implemented yet.
295 DCHECK(authenticator_->state() != Authenticator::WAITING_MESSAGE &&
296 authenticator_->state() != Authenticator::MESSAGE_READY);
297
298 if (authenticator_->state() != Authenticator::ACCEPTED) {
299 return false;
300 }
301
356 SessionConfig config; 302 SessionConfig config;
357 if (!content_description->config()->GetFinalConfig(&config)) { 303 if (!content_description->config()->GetFinalConfig(&config)) {
358 LOG(ERROR) << "Connection response does not specify configuration"; 304 LOG(ERROR) << "Connection response does not specify configuration";
359 return false; 305 return false;
360 } 306 }
361 if (!candidate_config()->IsSupported(config)) { 307 if (!candidate_config()->IsSupported(config)) {
362 LOG(ERROR) << "Connection response specifies an invalid configuration"; 308 LOG(ERROR) << "Connection response specifies an invalid configuration";
363 return false; 309 return false;
364 } 310 }
365 311
(...skipping 18 matching lines...) Expand all
384 } 330 }
385 331
386 void JingleSession::OnTerminate() { 332 void JingleSession::OnTerminate() {
387 DCHECK(CalledOnValidThread()); 333 DCHECK(CalledOnValidThread());
388 CloseInternal(net::ERR_CONNECTION_ABORTED, OK); 334 CloseInternal(net::ERR_CONNECTION_ABORTED, OK);
389 } 335 }
390 336
391 void JingleSession::AcceptConnection() { 337 void JingleSession::AcceptConnection() {
392 SetState(CONNECTING); 338 SetState(CONNECTING);
393 339
394 if (!jingle_session_manager_->AcceptConnection(this, cricket_session_)) { 340 const cricket::SessionDescription* session_description =
341 cricket_session_->remote_description();
342 const cricket::ContentInfo* content =
343 session_description->FirstContentByType(kChromotingXmlNamespace);
344
345 CHECK(content);
346 const ContentDescription* content_description =
347 static_cast<const ContentDescription*>(content->description);
348 candidate_config_.reset(content_description->config()->Clone());
349
350 SessionManager::IncomingSessionResponse response =
351 jingle_session_manager_->AcceptConnection(this);
352 if (response != SessionManager::ACCEPT) {
353 if (response == SessionManager::INCOMPATIBLE) {
354 cricket_session_->TerminateWithReason(
355 cricket::STR_TERMINATE_INCOMPATIBLE_PARAMETERS);
356 } else {
357 cricket_session_->TerminateWithReason(cricket::STR_TERMINATE_DECLINE);
358 }
395 Close(); 359 Close();
396 // Release session so that JingleSessionManager::SessionDestroyed() 360 // Release session so that JingleSessionManager::SessionDestroyed()
397 // doesn't try to call cricket::SessionManager::DestroySession() for it. 361 // doesn't try to call cricket::SessionManager::DestroySession() for it.
398 ReleaseSession(); 362 ReleaseSession();
399 delete this; 363 delete this;
400 return; 364 return;
401 } 365 }
402 366
403 if (!VerifySupportAuthToken(jid_, shared_secret_, initiator_token())) 367 const buzz::XmlElement* auth_message =
368 content_description->authenticator_message();
369 if (!auth_message) {
370 DLOG(WARNING) << "Received session-initiate without authenticator message.";
371 CloseInternal(net::ERR_CONNECTION_FAILED, INCOMPATIBLE_PROTOCOL);
372 return;
373 }
374
375 authenticator_.reset(
376 jingle_session_manager_->CreateAuthenticator(jid(), auth_message));
377 if (!authenticator_.get()) {
378 CloseInternal(net::ERR_CONNECTION_FAILED, INCOMPATIBLE_PROTOCOL);
379 return;
380 }
381
382 DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
383 authenticator_->ProcessMessage(auth_message);
384 // Support for more than two auth message is not implemented yet.
385 DCHECK(authenticator_->state() != Authenticator::WAITING_MESSAGE);
386 if (authenticator_->state() == Authenticator::REJECTED) {
404 CloseInternal(net::ERR_CONNECTION_FAILED, AUTHENTICATION_FAILED); 387 CloseInternal(net::ERR_CONNECTION_FAILED, AUTHENTICATION_FAILED);
388 return;
389 }
390
391 // Connection must be configured by the AcceptConnection() callback.
392 CandidateSessionConfig* candidate_config =
393 CandidateSessionConfig::CreateFrom(config());
394
395 buzz::XmlElement* auth_reply = NULL;
396 if (authenticator_->state() == Authenticator::MESSAGE_READY)
397 auth_reply = authenticator_->GetNextMessage();
398 DCHECK_EQ(authenticator_->state(), Authenticator::ACCEPTED);
399 cricket_session_->Accept(
400 CreateSessionDescription(candidate_config, auth_reply));
405 } 401 }
406 402
407 void JingleSession::AddChannelConnector( 403 void JingleSession::AddChannelConnector(
408 const std::string& name, JingleChannelConnector* connector) { 404 const std::string& name, JingleChannelConnector* connector) {
409 DCHECK(channel_connectors_.find(name) == channel_connectors_.end()); 405 DCHECK(channel_connectors_.find(name) == channel_connectors_.end());
410 406
411 const std::string& content_name = GetContentInfo()->name; 407 const std::string& content_name = GetContentInfo()->name;
412 cricket::TransportChannel* raw_channel = 408 cricket::TransportChannel* raw_channel =
413 cricket_session_->CreateChannel(content_name, name); 409 cricket_session_->CreateChannel(content_name, name);
414 410
415 if (!jingle_session_manager_->allow_nat_traversal_ && 411 if (!jingle_session_manager_->allow_nat_traversal_ &&
416 !cricket_session_->initiator()) { 412 !cricket_session_->initiator()) {
417 // Don't make outgoing connections from the host to client when 413 // Don't make outgoing connections from the host to client when
418 // NAT traversal is disabled. 414 // NAT traversal is disabled.
419 raw_channel->GetP2PChannel()->set_incoming_only(true); 415 raw_channel->GetP2PChannel()->set_incoming_only(true);
420 } 416 }
421 417
422 channel_connectors_[name] = connector; 418 channel_connectors_[name] = connector;
423 ChannelAuthenticator* authenticator; 419 ChannelAuthenticator* authenticator =
424 if (cricket_session_->initiator()) { 420 authenticator_->CreateChannelAuthenticator();
425 authenticator = new V1ClientChannelAuthenticator(
426 remote_cert_, shared_secret_);
427 } else {
428 authenticator = new V1HostChannelAuthenticator(
429 local_cert_, local_private_key_.get(), shared_secret_);
430 }
431 connector->Connect(authenticator, raw_channel); 421 connector->Connect(authenticator, raw_channel);
432 422
433 // Workaround bug in libjingle - it doesn't connect channels if they 423 // Workaround bug in libjingle - it doesn't connect channels if they
434 // are created after the session is accepted. See crbug.com/89384. 424 // are created after the session is accepted. See crbug.com/89384.
435 // TODO(sergeyu): Fix the bug and remove this line. 425 // TODO(sergeyu): Fix the bug and remove this line.
436 cricket_session_->GetTransport(content_name)->ConnectChannels(); 426 cricket_session_->GetTransport(content_name)->ConnectChannels();
437 } 427 }
438 428
439 void JingleSession::OnChannelConnectorFinished( 429 void JingleSession::OnChannelConnectorFinished(
440 const std::string& name, JingleChannelConnector* connector) { 430 const std::string& name, JingleChannelConnector* connector) {
(...skipping 23 matching lines...) Expand all
464 if (new_state != state_) { 454 if (new_state != state_) {
465 DCHECK_NE(state_, CLOSED); 455 DCHECK_NE(state_, CLOSED);
466 DCHECK_NE(state_, FAILED); 456 DCHECK_NE(state_, FAILED);
467 457
468 state_ = new_state; 458 state_ = new_state;
469 if (!state_change_callback_.is_null()) 459 if (!state_change_callback_.is_null())
470 state_change_callback_.Run(new_state); 460 state_change_callback_.Run(new_state);
471 } 461 }
472 } 462 }
473 463
464 // static
465 cricket::SessionDescription* JingleSession::CreateSessionDescription(
466 const CandidateSessionConfig* config,
467 const buzz::XmlElement* authenticator_message) {
468 cricket::SessionDescription* desc = new cricket::SessionDescription();
469 desc->AddContent(
470 ContentDescription::kChromotingContentName, kChromotingXmlNamespace,
471 new ContentDescription(config, authenticator_message));
472 return desc;
473 }
474
474 } // namespace protocol 475 } // namespace protocol
475 } // namespace remoting 476 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698