summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 18:48:36 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 18:48:36 +0000
commitf4ae0ed7eedbb35d59376c300a6147da2b41c2b7 (patch)
tree71142f08e29e7d4c1799ff6af4f74c3e799446a5 /remoting
parent59ba0142d4219a4ac6c5e3b463a1d5f923e0b568 (diff)
downloadchromium_src-f4ae0ed7eedbb35d59376c300a6147da2b41c2b7.zip
chromium_src-f4ae0ed7eedbb35d59376c300a6147da2b41c2b7.tar.gz
chromium_src-f4ae0ed7eedbb35d59376c300a6147da2b41c2b7.tar.bz2
Add an extra SSL layer in JingleSession for Chromoting
Wrap the existing StreamSocketAdpaters in JingleSession with an extra of SSLClientSocket and SSLServerSocket. Since the server certificate is self-signed, SSLClientSocket will refuse to connect. An additional patch is needed to transmit the certificate via other channels so client sSL socket can accept this untrusted certificate. BUG=None TEST=remoting_unittests Review URL: http://codereview.chromium.org/5675003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70074 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/jingle_glue/stream_socket_adapter.cc42
-rw-r--r--remoting/jingle_glue/stream_socket_adapter.h19
-rw-r--r--remoting/protocol/jingle_session.cc268
-rw-r--r--remoting/protocol/jingle_session.h64
-rw-r--r--remoting/protocol/jingle_session_manager.cc7
-rw-r--r--remoting/protocol/jingle_session_manager.h13
-rw-r--r--remoting/protocol/jingle_session_unittest.cc55
7 files changed, 400 insertions, 68 deletions
diff --git a/remoting/jingle_glue/stream_socket_adapter.cc b/remoting/jingle_glue/stream_socket_adapter.cc
index 3155328..4c5e6cf 100644
--- a/remoting/jingle_glue/stream_socket_adapter.cc
+++ b/remoting/jingle_glue/stream_socket_adapter.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/message_loop.h"
+#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "remoting/jingle_glue/utils.h"
@@ -26,6 +27,47 @@ StreamSocketAdapter::StreamSocketAdapter(talk_base::StreamInterface* stream)
StreamSocketAdapter::~StreamSocketAdapter() {
}
+int StreamSocketAdapter::Connect(net::CompletionCallback* callback) {
+ return net::OK;
+}
+
+void StreamSocketAdapter::Disconnect() {
+}
+
+bool StreamSocketAdapter::IsConnected() const {
+ return true;
+}
+
+bool StreamSocketAdapter::IsConnectedAndIdle() const {
+ return true;
+}
+
+int StreamSocketAdapter::GetPeerAddress(net::AddressList* address) const {
+ // We actually don't know the peer address. Returning so the upper layers
+ // won't complain.
+ net::IPAddressNumber ip_address(4);
+ *address = net::AddressList(ip_address, 0, false);
+ return net::OK;
+}
+
+const net::BoundNetLog& StreamSocketAdapter::NetLog() const {
+ return net_log_;
+}
+
+void StreamSocketAdapter::SetSubresourceSpeculation() {
+}
+
+void StreamSocketAdapter::SetOmniboxSpeculation() {
+}
+
+bool StreamSocketAdapter::WasEverUsed() const {
+ return true;
+}
+
+bool StreamSocketAdapter::UsingTCPFastOpen() const {
+ return false;
+}
+
int StreamSocketAdapter::Read(
net::IOBuffer* buffer, int buffer_size, net::CompletionCallback* callback) {
DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
diff --git a/remoting/jingle_glue/stream_socket_adapter.h b/remoting/jingle_glue/stream_socket_adapter.h
index 2387bdd..942aa45 100644
--- a/remoting/jingle_glue/stream_socket_adapter.h
+++ b/remoting/jingle_glue/stream_socket_adapter.h
@@ -6,7 +6,8 @@
#define REMOTING_JINGLE_GLUE_STREAM_SOCKET_ADAPTER_H_
#include "base/scoped_ptr.h"
-#include "net/socket/socket.h"
+#include "net/base/net_log.h"
+#include "net/socket/client_socket.h"
#include "third_party/libjingle/source/talk/base/sigslot.h"
namespace talk_base {
@@ -18,13 +19,25 @@ namespace remoting {
// StreamSocketAdapter implements net::Socket interface on top of
// libjingle's StreamInterface. It is used by JingleChromotocolConnection
// to provide net::Socket interface for channels.
-class StreamSocketAdapter : public net::Socket,
+class StreamSocketAdapter : public net::ClientSocket,
public sigslot::has_slots<> {
public:
// Ownership of the stream is passed to the adapter.
explicit StreamSocketAdapter(talk_base::StreamInterface* stream);
virtual ~StreamSocketAdapter();
+ // ClientSocket interface.
+ virtual int Connect(net::CompletionCallback* callback);
+ virtual void Disconnect();
+ virtual bool IsConnected() const;
+ virtual bool IsConnectedAndIdle() const;
+ virtual int GetPeerAddress(net::AddressList* address) const;
+ virtual const net::BoundNetLog& NetLog() const;
+ virtual void SetSubresourceSpeculation();
+ virtual void SetOmniboxSpeculation();
+ virtual bool WasEverUsed() const;
+ virtual bool UsingTCPFastOpen() const;
+
// Closes the stream. |error_code| specifies error code that will
// be returned by Read() and Write() after the stream is closed.
void Close(int error_code);
@@ -62,6 +75,8 @@ class StreamSocketAdapter : public net::Socket,
int closed_error_code_;
+ net::BoundNetLog net_log_;
+
DISALLOW_COPY_AND_ASSIGN(StreamSocketAdapter);
};
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
index f4acf8e..bf4b7d8 100644
--- a/remoting/protocol/jingle_session.cc
+++ b/remoting/protocol/jingle_session.cc
@@ -4,8 +4,16 @@
#include "remoting/protocol/jingle_session.h"
+#include "base/crypto/rsa_private_key.h"
#include "base/message_loop.h"
+#include "net/base/cert_verifier.h"
+#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
+#include "net/base/ssl_config_service.h"
+#include "net/base/x509_certificate.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/ssl_client_socket.h"
+#include "net/socket/ssl_server_socket.h"
#include "remoting/base/constants.h"
#include "remoting/jingle_glue/channel_socket_adapter.h"
#include "remoting/jingle_glue/jingle_thread.h"
@@ -22,24 +30,77 @@ namespace remoting {
namespace protocol {
+const char JingleSession::kChromotingContentName[] = "chromoting";
+
namespace {
const char kControlChannelName[] = "control";
const char kEventChannelName[] = "event";
const char kVideoChannelName[] = "video";
const char kVideoRtpChannelName[] = "videortp";
const char kVideoRtcpChannelName[] = "videortcp";
+
+// Helper method to create a SSL client socket.
+net::SSLClientSocket* CreateSSLClientSocket(
+ net::ClientSocket* socket, scoped_refptr<net::X509Certificate> cert,
+ net::CertVerifier* cert_verifier) {
+ net::SSLConfig ssl_config;
+ ssl_config.false_start_enabled = false;
+ ssl_config.snap_start_enabled = false;
+ ssl_config.ssl3_enabled = true;
+ ssl_config.tls1_enabled = true;
+ ssl_config.session_resume_disabled = true;
+
+ // Certificate provided by the host doesn't need authority.
+ net::SSLConfig::CertAndStatus cert_and_status;
+ cert_and_status.cert_status = net::ERR_CERT_AUTHORITY_INVALID;
+ cert_and_status.cert = cert;
+ ssl_config.allowed_bad_certs.push_back(cert_and_status);
+
+ // SSLClientSocket takes ownership of the adapter.
+ net::HostPortPair host_and_pair(JingleSession::kChromotingContentName, 0);
+ net::SSLClientSocket* ssl_socket =
+ net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
+ socket, host_and_pair, ssl_config, NULL, cert_verifier);
+ return ssl_socket;
+}
+
} // namespace
-const char JingleSession::kChromotingContentName[] = "chromoting";
+// static
+JingleSession* JingleSession::CreateClientSession(
+ JingleSessionManager* manager,
+ scoped_refptr<net::X509Certificate> certificate) {
+ return new JingleSession(manager, certificate, NULL);
+}
+
+// static
+JingleSession* JingleSession::CreateServerSession(
+ JingleSessionManager* manager,
+ scoped_refptr<net::X509Certificate> certificate,
+ base::RSAPrivateKey* key) {
+ return new JingleSession(manager, certificate, key);
+}
JingleSession::JingleSession(
- JingleSessionManager* jingle_session_manager)
+ JingleSessionManager* jingle_session_manager,
+ scoped_refptr<net::X509Certificate> server_cert, base::RSAPrivateKey* key)
: jingle_session_manager_(jingle_session_manager),
+ server_cert_(server_cert),
state_(INITIALIZING),
closed_(false),
cricket_session_(NULL),
event_channel_(NULL),
- video_channel_(NULL) {
+ video_channel_(NULL),
+ ssl_connections_(0),
+ ALLOW_THIS_IN_INITIALIZER_LIST(connect_callback_(
+ NewCallback(this, &JingleSession::OnSSLConnect))) {
+ // TODO(hclam): Need a better way to clone a key.
+ if (key) {
+ std::vector<uint8> key_bytes;
+ CHECK(key->ExportPrivateKey(&key_bytes));
+ key_.reset(base::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
+ CHECK(key_.get());
+ }
}
JingleSession::~JingleSession() {
@@ -51,10 +112,73 @@ void JingleSession::Init(cricket::Session* cricket_session) {
cricket_session_ = cricket_session;
jid_ = cricket_session_->remote_name();
+ cert_verifier_.reset(new net::CertVerifier());
cricket_session_->SignalState.connect(
this, &JingleSession::OnSessionState);
}
+void JingleSession::CloseInternal(Task* closed_task, int result) {
+ if (MessageLoop::current() != jingle_session_manager_->message_loop()) {
+ jingle_session_manager_->message_loop()->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &JingleSession::CloseInternal,
+ closed_task, result));
+ return;
+ }
+
+ if (!closed_) {
+ if (control_ssl_socket_.get())
+ control_ssl_socket_.reset();
+
+ if (control_channel_adapter_.get())
+ control_channel_adapter_->Close(result);
+
+ if (control_channel_) {
+ control_channel_->OnSessionTerminate(cricket_session_);
+ control_channel_ = NULL;
+ }
+
+ if (event_ssl_socket_.get())
+ event_ssl_socket_.reset();
+
+ if (event_channel_adapter_.get())
+ event_channel_adapter_->Close(result);
+
+ if (event_channel_) {
+ event_channel_->OnSessionTerminate(cricket_session_);
+ event_channel_ = NULL;
+ }
+
+ if (video_ssl_socket_.get())
+ video_ssl_socket_.reset();
+
+ if (video_channel_adapter_.get())
+ video_channel_adapter_->Close(result);
+
+ if (video_channel_) {
+ video_channel_->OnSessionTerminate(cricket_session_);
+ video_channel_ = NULL;
+ }
+
+ if (video_rtp_channel_.get())
+ video_rtp_channel_->Close(result);
+ if (video_rtcp_channel_.get())
+ video_rtcp_channel_->Close(result);
+
+ if (cricket_session_)
+ cricket_session_->Terminate();
+
+ SetState(CLOSED);
+
+ closed_ = true;
+ }
+ cert_verifier_.reset();
+
+ if (closed_task) {
+ closed_task->Run();
+ delete closed_task;
+ }
+}
+
bool JingleSession::HasSession(cricket::Session* cricket_session) {
return cricket_session_ == cricket_session;
}
@@ -71,8 +195,7 @@ cricket::Session* JingleSession::ReleaseSession() {
return session;
}
-void JingleSession::SetStateChangeCallback(
- StateChangeCallback* callback) {
+void JingleSession::SetStateChangeCallback(StateChangeCallback* callback) {
DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
DCHECK(callback);
state_change_callback_.reset(callback);
@@ -80,18 +203,18 @@ void JingleSession::SetStateChangeCallback(
net::Socket* JingleSession::control_channel() {
DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
- return control_channel_adapter_.get();
+ return control_ssl_socket_.get();
}
net::Socket* JingleSession::event_channel() {
DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
- return event_channel_adapter_.get();
+ return event_ssl_socket_.get();
}
// TODO(sergeyu): Remove this method after we switch to RTP.
net::Socket* JingleSession::video_channel() {
DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
- return video_channel_adapter_.get();
+ return video_ssl_socket_.get();
}
net::Socket* JingleSession::video_rtp_channel() {
@@ -114,8 +237,7 @@ MessageLoop* JingleSession::message_loop() {
return jingle_session_manager_->message_loop();
}
-const CandidateSessionConfig*
-JingleSession::candidate_config() {
+const CandidateSessionConfig* JingleSession::candidate_config() {
DCHECK(candidate_config_.get());
return candidate_config_.get();
}
@@ -155,53 +277,7 @@ void JingleSession::set_receiver_token(const std::string& receiver_token) {
}
void JingleSession::Close(Task* closed_task) {
- if (MessageLoop::current() != jingle_session_manager_->message_loop()) {
- jingle_session_manager_->message_loop()->PostTask(
- FROM_HERE, NewRunnableMethod(this, &JingleSession::Close,
- closed_task));
- return;
- }
-
- if (!closed_) {
- if (control_channel_adapter_.get())
- control_channel_adapter_->Close(net::ERR_CONNECTION_CLOSED);
-
- if (control_channel_) {
- control_channel_->OnSessionTerminate(cricket_session_);
- control_channel_ = NULL;
- }
-
- if (event_channel_adapter_.get())
- event_channel_adapter_->Close(net::ERR_CONNECTION_CLOSED);
-
- if (event_channel_) {
- event_channel_->OnSessionTerminate(cricket_session_);
- event_channel_ = NULL;
- }
-
- if (video_channel_adapter_.get())
- video_channel_adapter_->Close(net::ERR_CONNECTION_CLOSED);
-
- if (video_channel_) {
- video_channel_->OnSessionTerminate(cricket_session_);
- video_channel_ = NULL;
- }
-
- if (video_rtp_channel_.get())
- video_rtp_channel_->Close(net::ERR_CONNECTION_CLOSED);
- if (video_rtcp_channel_.get())
- video_rtcp_channel_->Close(net::ERR_CONNECTION_CLOSED);
-
- if (cricket_session_)
- cricket_session_->Terminate();
-
- SetState(CLOSED);
-
- closed_ = true;
- }
-
- closed_task->Run();
- delete closed_task;
+ CloseInternal(closed_task, net::ERR_CONNECTION_CLOSED);
}
void JingleSession::OnSessionState(
@@ -287,7 +363,48 @@ void JingleSession::OnInitiate() {
SetState(CONNECTING);
}
+bool JingleSession::EstablishSSLConnection(
+ net::ClientSocket* adapter, scoped_ptr<net::Socket>* ssl_socket) {
+ if (cricket_session_->initiator()) {
+ // Create client SSL socket.
+ net::SSLClientSocket* socket = CreateSSLClientSocket(adapter,
+ server_cert_,
+ cert_verifier_.get());
+ ssl_socket->reset(socket);
+
+ int ret = socket->Connect(connect_callback_.get());
+ if (ret == net::ERR_IO_PENDING) {
+ return true;
+ } else if (ret != net::OK) {
+ LOG(ERROR) << "Failed to establish SSL connection";
+ cricket_session_->Terminate();
+ return false;
+ }
+ } else {
+ // Create server SSL socket.
+ net::SSLConfig ssl_config;
+ net::SSLServerSocket* socket = net::CreateSSLServerSocket(
+ adapter, server_cert_, key_.get(), ssl_config);
+ ssl_socket->reset(socket);
+
+ int ret = socket->Accept(connect_callback_.get());
+ if (ret == net::ERR_IO_PENDING) {
+ return true;
+ } else if (ret != net::OK) {
+ LOG(ERROR) << "Failed to establish SSL connection";
+ cricket_session_->Terminate();
+ return true;
+ }
+ }
+ // Reach here if net::OK is received.
+ connect_callback_->Run(net::OK);
+ return true;
+}
+
void JingleSession::OnAccept() {
+ // TODO(hclam): Need to close the adapters on failuire otherwise it will
+ // crash in the destructor.
+
// Set the config if we are the one who initiated the session.
if (cricket_session_->initiator()) {
const cricket::ContentInfo* content =
@@ -307,11 +424,24 @@ void JingleSession::OnAccept() {
cricket_session_->Terminate();
return;
}
-
set_config(config);
}
- SetState(CONNECTED);
+ bool ret = EstablishSSLConnection(control_channel_adapter_.release(),
+ &control_ssl_socket_);
+ if (ret) {
+ ret = EstablishSSLConnection(event_channel_adapter_.release(),
+ &event_ssl_socket_);
+ }
+ if (ret) {
+ ret = EstablishSSLConnection(video_channel_adapter_.release(),
+ &video_ssl_socket_);
+ }
+
+ if (!ret) {
+ LOG(ERROR) << "Failed to establish SSL connections";
+ cricket_session_->Terminate();
+ }
}
void JingleSession::OnTerminate() {
@@ -346,6 +476,26 @@ void JingleSession::OnTerminate() {
closed_ = true;
}
+void JingleSession::OnSSLConnect(int result) {
+ DCHECK(!closed_);
+ if (result != net::OK) {
+ LOG(ERROR) << "Error during SSL connection: " << result;
+ // TODO(hclam): Just setting the state is not enough. Need to invoke a
+ // callback to report failure.
+ CloseInternal(NULL, result);
+ return;
+ }
+
+ // Number of channels for a jingle session.
+ const int kChannels = 3;
+
+ // Set the state to connected only of all SSL sockets are connected.
+ if (++ssl_connections_ == kChannels) {
+ SetState(CONNECTED);
+ }
+ CHECK(ssl_connections_ <= kChannels) << "Unexpected SSL connect callback";
+}
+
void JingleSession::SetState(State new_state) {
if (new_state != state_) {
state_ = new_state;
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h
index cd5a602..284fb9c 100644
--- a/remoting/protocol/jingle_session.h
+++ b/remoting/protocol/jingle_session.h
@@ -5,8 +5,10 @@
#ifndef REMOTING_PROTOCOL_JINGLE_SESSION_H_
#define REMOTING_PROTOCOL_JINGLE_SESSION_H_
+#include "base/crypto/rsa_private_key.h"
#include "base/lock.h"
#include "base/ref_counted.h"
+#include "net/base/completion_callback.h"
#include "remoting/protocol/session.h"
#include "third_party/libjingle/source/talk/base/sigslot.h"
#include "third_party/libjingle/source/talk/p2p/base/session.h"
@@ -16,7 +18,11 @@ class PseudoTcpChannel;
} // namespace cricket
namespace net {
+class CertVerifier;
+class ClientSocket;
+class ClientSocketFactory;
class Socket;
+class X509Certificate;
} // namespace net
namespace remoting {
@@ -36,7 +42,18 @@ class JingleSession : public protocol::Session,
public:
static const char kChromotingContentName[];
- explicit JingleSession(JingleSessionManager* client);
+ // Create a JingleSession used in client mode. A server certificate is
+ // required.
+ static JingleSession* CreateClientSession(
+ JingleSessionManager* manager,
+ scoped_refptr<net::X509Certificate> certificate);
+
+ // Create a JingleSession used in server mode. A server certificate and
+ // private key is provided. |key| is copied in the constructor.
+ static JingleSession* CreateServerSession(
+ JingleSessionManager* manager,
+ scoped_refptr<net::X509Certificate> certificate,
+ base::RSAPrivateKey* key);
// Chromotocol Session interface.
virtual void SetStateChangeCallback(StateChangeCallback* callback);
@@ -64,18 +81,30 @@ class JingleSession : public protocol::Session,
virtual void Close(Task* closed_task);
- protected:
- virtual ~JingleSession();
-
private:
friend class JingleSessionManager;
+ JingleSession(JingleSessionManager* client,
+ scoped_refptr<net::X509Certificate> server_cert,
+ base::RSAPrivateKey* key);
+ virtual ~JingleSession();
+
// Called by JingleSessionManager.
void set_candidate_config(const CandidateSessionConfig* candidate_config);
void Init(cricket::Session* cricket_session);
+
+ // Close all the channels and terminate the session.
+ void CloseInternal(Task* closed_task, int result);
+
bool HasSession(cricket::Session* cricket_session);
cricket::Session* ReleaseSession();
+ // Helper method to create and initialize SSL socket using the adapter
+ // provided. The resultant SSL socket is written to |ssl_socket|.
+ // Return true if successful.
+ bool EstablishSSLConnection(net::ClientSocket* adapter,
+ scoped_ptr<net::Socket>* ssl_socket);
+
// Used for Session.SignalState sigslot.
void OnSessionState(cricket::BaseSession* session,
cricket::BaseSession::State state);
@@ -84,11 +113,20 @@ class JingleSession : public protocol::Session,
void OnAccept();
void OnTerminate();
+ // Called by SSL socket to notify connect event.
+ void OnSSLConnect(int result);
+
void SetState(State new_state);
// JingleSessionManager that created this session.
scoped_refptr<JingleSessionManager> jingle_session_manager_;
+ // Server certificate used in SSL connections.
+ scoped_refptr<net::X509Certificate> server_cert_;
+
+ // Private key used in SSL server sockets.
+ scoped_ptr<base::RSAPrivateKey> key_;
+
State state_;
scoped_ptr<StateChangeCallback> state_change_callback_;
@@ -109,15 +147,33 @@ class JingleSession : public protocol::Session,
// These data members are only set on the receiving side.
scoped_ptr<const CandidateSessionConfig> candidate_config_;
+ // A channel is the the base channel created by libjingle.
+ // A channel adapter is used to convert a jingle channel to net::Socket.
+ // A SSL socket is a wrapper over a net::Socket to provide SSL functionality.
cricket::PseudoTcpChannel* control_channel_;
scoped_ptr<StreamSocketAdapter> control_channel_adapter_;
+ scoped_ptr<net::Socket> control_ssl_socket_;
+
cricket::PseudoTcpChannel* event_channel_;
scoped_ptr<StreamSocketAdapter> event_channel_adapter_;
+ scoped_ptr<net::Socket> event_ssl_socket_;
+
cricket::PseudoTcpChannel* video_channel_;
scoped_ptr<StreamSocketAdapter> video_channel_adapter_;
+ scoped_ptr<net::Socket> video_ssl_socket_;
+
+ // Count the number of SSL connections esblished.
+ int ssl_connections_;
+
+ // Used to verify the certificate received in SSLClientSocket.
+ scoped_ptr<net::CertVerifier> cert_verifier_;
+
scoped_ptr<TransportChannelSocketAdapter> video_rtp_channel_;
scoped_ptr<TransportChannelSocketAdapter> video_rtcp_channel_;
+ // Callback called by the SSL layer.
+ scoped_ptr<net::CompletionCallback> connect_callback_;
+
DISALLOW_COPY_AND_ASSIGN(JingleSession);
};
diff --git a/remoting/protocol/jingle_session_manager.cc b/remoting/protocol/jingle_session_manager.cc
index 12f9298..dbaed17 100644
--- a/remoting/protocol/jingle_session_manager.cc
+++ b/remoting/protocol/jingle_session_manager.cc
@@ -210,6 +210,7 @@ void JingleSessionManager::Close(Task* closed_task) {
closed_ = true;
}
+ key_.reset();
closed_task->Run();
delete closed_task;
}
@@ -224,7 +225,8 @@ scoped_refptr<protocol::Session> JingleSessionManager::Connect(
CandidateSessionConfig* candidate_config,
protocol::Session::StateChangeCallback* state_change_callback) {
// Can be called from any thread.
- scoped_refptr<JingleSession> jingle_session(new JingleSession(this));
+ scoped_refptr<JingleSession> jingle_session(
+ JingleSession::CreateClientSession(this, server_cert_));
jingle_session->set_candidate_config(candidate_config);
jingle_session->set_receiver_token(receiver_token);
message_loop()->PostTask(
@@ -272,7 +274,8 @@ void JingleSessionManager::OnSessionCreate(
// If this is an outcoming session the connection object is already
// created.
if (incoming) {
- JingleSession* jingle_session = new JingleSession(this);
+ JingleSession* jingle_session =
+ JingleSession::CreateServerSession(this, server_cert_, key_.get());
sessions_.push_back(make_scoped_refptr(jingle_session));
jingle_session->Init(cricket_session);
}
diff --git a/remoting/protocol/jingle_session_manager.h b/remoting/protocol/jingle_session_manager.h
index 7bb0424..2a86c5f 100644
--- a/remoting/protocol/jingle_session_manager.h
+++ b/remoting/protocol/jingle_session_manager.h
@@ -10,6 +10,7 @@
#include "base/lock.h"
#include "base/ref_counted.h"
+#include "net/base/x509_certificate.h"
#include "remoting/protocol/jingle_session.h"
#include "remoting/protocol/session_manager.h"
#include "third_party/libjingle/source/talk/p2p/base/session.h"
@@ -93,6 +94,15 @@ class JingleSessionManager
buzz::XmlElement** elem,
cricket::WriteError* error);
+ // The following two methods are used in unit tests only.
+ void set_server_cert(scoped_refptr<net::X509Certificate> server_cert) {
+ server_cert_ = server_cert;
+ }
+
+ void set_key(base::RSAPrivateKey* key) {
+ key_.reset(key);
+ }
+
protected:
virtual ~JingleSessionManager();
@@ -128,6 +138,9 @@ class JingleSessionManager
bool closed_;
+ scoped_refptr<net::X509Certificate> server_cert_;
+ scoped_ptr<base::RSAPrivateKey> key_;
+
std::list<scoped_refptr<JingleSession> > sessions_;
DISALLOW_COPY_AND_ASSIGN(JingleSessionManager);
diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc
index 6b5a99d..148c19b 100644
--- a/remoting/protocol/jingle_session_unittest.cc
+++ b/remoting/protocol/jingle_session_unittest.cc
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/nss_util.h"
+#include "base/path_service.h"
#include "base/time.h"
#include "base/waitable_event.h"
#include "base/test/test_timeouts.h"
@@ -128,6 +132,35 @@ class JingleSessionTest : public testing::Test {
session_manager_pair_->client_session_manager(),
NewCallback(&client_server_callback_,
&MockSessionManagerCallback::OnIncomingSession));
+
+ FilePath certs_dir;
+ PathService::Get(base::DIR_SOURCE_ROOT, &certs_dir);
+ certs_dir = certs_dir.AppendASCII("net");
+ certs_dir = certs_dir.AppendASCII("data");
+ certs_dir = certs_dir.AppendASCII("ssl");
+ certs_dir = certs_dir.AppendASCII("certificates");
+
+ FilePath cert_path = certs_dir.AppendASCII("unittest.selfsigned.der");
+ std::string cert_der;
+ ASSERT_TRUE(file_util::ReadFileToString(cert_path, &cert_der));
+
+ scoped_refptr<net::X509Certificate> cert =
+ net::X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
+
+ FilePath key_path = certs_dir.AppendASCII("unittest.key.bin");
+ std::string key_string;
+ ASSERT_TRUE(file_util::ReadFileToString(key_path, &key_string));
+ std::vector<uint8> key_vector(
+ reinterpret_cast<const uint8*>(key_string.data()),
+ reinterpret_cast<const uint8*>(key_string.data() +
+ key_string.length()));
+
+ scoped_ptr<base::RSAPrivateKey> private_key(
+ base::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector));
+
+ host_server_->set_server_cert(cert);
+ host_server_->set_key(private_key.release());
+ client_server_->set_server_cert(cert);
}
bool InitiateConnection() {
@@ -516,12 +549,18 @@ class UDPChannelTester : public ChannelTesterBase {
// Verify that we can create and destory server objects without a connection.
TEST_F(JingleSessionTest, CreateAndDestoy) {
+ if (!base::CheckNSSVersion("3.12.8"))
+ return;
+
CreateServerPair();
}
// Verify that incoming session can be rejected, and that the status
// of the connection is set to CLOSED in this case.
TEST_F(JingleSessionTest, RejectConnection) {
+ if (!base::CheckNSSVersion("3.12.8"))
+ return;
+
CreateServerPair();
// Reject incoming session.
@@ -551,12 +590,18 @@ TEST_F(JingleSessionTest, RejectConnection) {
// Verify that we can connect two endpoints.
TEST_F(JingleSessionTest, Connect) {
+ if (!base::CheckNSSVersion("3.12.8"))
+ return;
+
CreateServerPair();
ASSERT_TRUE(InitiateConnection());
}
// Verify that data can be transmitted over the event channel.
TEST_F(JingleSessionTest, TestControlChannel) {
+ if (!base::CheckNSSVersion("3.12.8"))
+ return;
+
CreateServerPair();
ASSERT_TRUE(InitiateConnection());
scoped_refptr<TCPChannelTester> tester(
@@ -570,9 +615,11 @@ TEST_F(JingleSessionTest, TestControlChannel) {
CloseSessions();
}
-
// Verify that data can be transmitted over the video channel.
TEST_F(JingleSessionTest, TestVideoChannel) {
+ if (!base::CheckNSSVersion("3.12.8"))
+ return;
+
CreateServerPair();
ASSERT_TRUE(InitiateConnection());
scoped_refptr<TCPChannelTester> tester(
@@ -588,6 +635,9 @@ TEST_F(JingleSessionTest, TestVideoChannel) {
// Verify that data can be transmitted over the event channel.
TEST_F(JingleSessionTest, TestEventChannel) {
+ if (!base::CheckNSSVersion("3.12.8"))
+ return;
+
CreateServerPair();
ASSERT_TRUE(InitiateConnection());
scoped_refptr<TCPChannelTester> tester(
@@ -603,6 +653,9 @@ TEST_F(JingleSessionTest, TestEventChannel) {
// Verify that data can be transmitted over the video RTP channel.
TEST_F(JingleSessionTest, TestVideoRtpChannel) {
+ if (!base::CheckNSSVersion("3.12.8"))
+ return;
+
CreateServerPair();
ASSERT_TRUE(InitiateConnection());
scoped_refptr<UDPChannelTester> tester(