summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 18:49:18 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 18:49:18 +0000
commit40d33caad15e6c989f569a011f9803563d93c529 (patch)
treeccea729b503749063ca5e003409689bc4edc0fb7 /remoting
parentf4ae0ed7eedbb35d59376c300a6147da2b41c2b7 (diff)
downloadchromium_src-40d33caad15e6c989f569a011f9803563d93c529.zip
chromium_src-40d33caad15e6c989f569a011f9803563d93c529.tar.gz
chromium_src-40d33caad15e6c989f569a011f9803563d93c529.tar.bz2
Send certificate in content description in jingle for Chromoting
Transmit the server certificate to the client via content description. This allow secure encryption between Chromoting host and client. BUG=None TEST=remoting_unittests Review URL: http://codereview.chromium.org/5804001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70075 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/protocol/jingle_session.cc12
-rw-r--r--remoting/protocol/jingle_session.h5
-rw-r--r--remoting/protocol/jingle_session_manager.cc81
-rw-r--r--remoting/protocol/jingle_session_manager.h24
-rw-r--r--remoting/protocol/jingle_session_unittest.cc35
5 files changed, 96 insertions, 61 deletions
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
index bf4b7d8..b151c1df 100644
--- a/remoting/protocol/jingle_session.cc
+++ b/remoting/protocol/jingle_session.cc
@@ -68,9 +68,8 @@ net::SSLClientSocket* CreateSSLClientSocket(
// static
JingleSession* JingleSession::CreateClientSession(
- JingleSessionManager* manager,
- scoped_refptr<net::X509Certificate> certificate) {
- return new JingleSession(manager, certificate, NULL);
+ JingleSessionManager* manager) {
+ return new JingleSession(manager, NULL, NULL);
}
// static
@@ -249,6 +248,10 @@ void JingleSession::set_candidate_config(
candidate_config_.reset(candidate_config);
}
+scoped_refptr<net::X509Certificate> JingleSession::server_certificate() const {
+ return server_cert_;
+}
+
const SessionConfig* JingleSession::config() {
DCHECK(config_.get());
return config_.get();
@@ -414,6 +417,9 @@ void JingleSession::OnAccept() {
const protocol::ContentDescription* content_description =
static_cast<const protocol::ContentDescription*>(content->description);
+ server_cert_ = content_description->certificate();
+ CHECK(server_cert_);
+
SessionConfig* config = content_description->config()->GetFinalConfig();
// Terminate the session if the config we received is invalid.
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h
index 284fb9c..f8689cc 100644
--- a/remoting/protocol/jingle_session.h
+++ b/remoting/protocol/jingle_session.h
@@ -44,9 +44,7 @@ class JingleSession : public protocol::Session,
// Create a JingleSession used in client mode. A server certificate is
// required.
- static JingleSession* CreateClientSession(
- JingleSessionManager* manager,
- scoped_refptr<net::X509Certificate> certificate);
+ static JingleSession* CreateClientSession(JingleSessionManager* manager);
// Create a JingleSession used in server mode. A server certificate and
// private key is provided. |key| is copied in the constructor.
@@ -91,6 +89,7 @@ class JingleSession : public protocol::Session,
// Called by JingleSessionManager.
void set_candidate_config(const CandidateSessionConfig* candidate_config);
+ scoped_refptr<net::X509Certificate> server_certificate() const;
void Init(cricket::Session* cricket_session);
// Close all the channels and terminate the session.
diff --git a/remoting/protocol/jingle_session_manager.cc b/remoting/protocol/jingle_session_manager.cc
index dbaed17..5a99a3f 100644
--- a/remoting/protocol/jingle_session_manager.cc
+++ b/remoting/protocol/jingle_session_manager.cc
@@ -4,6 +4,7 @@
#include "remoting/protocol/jingle_session_manager.h"
+#include "base/base64.h"
#include "base/message_loop.h"
#include "base/string_number_conversions.h"
#include "remoting/base/constants.h"
@@ -31,6 +32,8 @@ const char kControlTag[] = "control";
const char kEventTag[] = "event";
const char kVideoTag[] = "video";
const char kResolutionTag[] = "initial-resolution";
+const char kAuthenticationTag[] = "authentication";
+const char kCertificateTag[] = "certificate";
const char kTransportAttr[] = "transport";
const char kVersionAttr[] = "version";
@@ -150,9 +153,11 @@ bool ParseChannelConfig(const XmlElement* element, bool codec_required,
ContentDescription::ContentDescription(
const CandidateSessionConfig* candidate_config,
- const std::string& auth_token)
+ const std::string& auth_token,
+ scoped_refptr<net::X509Certificate> certificate)
: candidate_config_(candidate_config),
- auth_token_(auth_token) {
+ auth_token_(auth_token),
+ certificate_(certificate) {
}
ContentDescription::~ContentDescription() { }
@@ -210,7 +215,6 @@ void JingleSessionManager::Close(Task* closed_task) {
closed_ = true;
}
- key_.reset();
closed_task->Run();
delete closed_task;
}
@@ -226,7 +230,7 @@ scoped_refptr<protocol::Session> JingleSessionManager::Connect(
protocol::Session::StateChangeCallback* state_change_callback) {
// Can be called from any thread.
scoped_refptr<JingleSession> jingle_session(
- JingleSession::CreateClientSession(this, server_cert_));
+ JingleSession::CreateClientSession(this));
jingle_session->set_candidate_config(candidate_config);
jingle_session->set_receiver_token(receiver_token);
message_loop()->PostTask(
@@ -253,7 +257,7 @@ void JingleSessionManager::DoConnect(
cricket_session->Initiate(
host_jid,
CreateSessionDescription(jingle_session->candidate_config()->Clone(),
- receiver_token));
+ receiver_token, NULL));
}
JingleThread* JingleSessionManager::jingle_thread() {
@@ -271,11 +275,20 @@ void JingleSessionManager::OnSessionCreate(
// Allow local connections if neccessary.
cricket_session->set_allow_local_ips(allow_local_ips_);
- // If this is an outcoming session the connection object is already
- // created.
+ // If this is an outcoming session the session object is already created.
if (incoming) {
+ // Generate private key and certificate.
+ // TODO(hclam): Instead of generating we should restore them from the disk.
+ scoped_ptr<base::RSAPrivateKey> private_key(
+ base::RSAPrivateKey::Create(1024));
+ std::string subject = "CN=chromoting";
+ scoped_refptr<net::X509Certificate> x509_certificate =
+ net::X509Certificate::CreateSelfSigned(
+ private_key.get(), subject, 1, base::TimeDelta::FromDays(1));
+ CHECK(x509_certificate);
JingleSession* jingle_session =
- JingleSession::CreateServerSession(this, server_cert_, key_.get());
+ JingleSession::CreateServerSession(this, x509_certificate,
+ private_key.get());
sessions_.push_back(make_scoped_refptr(jingle_session));
jingle_session->Init(cricket_session);
}
@@ -318,6 +331,8 @@ void JingleSessionManager::AcceptConnection(
// Always reject connection if there is no callback.
IncomingSessionResponse response = protocol::SessionManager::DECLINE;
+
+ // Use the callback to generate a response.
if (incoming_session_callback_.get())
incoming_session_callback_->Run(jingle_session, &response);
@@ -329,7 +344,8 @@ void JingleSessionManager::AcceptConnection(
CandidateSessionConfig::CreateFrom(jingle_session->config());
cricket_session->Accept(
CreateSessionDescription(candidate_config,
- jingle_session->initiator_token()));
+ jingle_session->initiator_token(),
+ jingle_session->server_certificate()));
break;
}
@@ -415,7 +431,25 @@ bool JingleSessionManager::ParseContent(
std::string auth_token;
// TODO(ajwong): Parse this out.
- *content = new ContentDescription(config.release(), auth_token);
+ // Parse the certificate.
+ scoped_refptr<net::X509Certificate> certificate;
+ child = element->FirstNamed(QName(kChromotingXmlNamespace,
+ kAuthenticationTag));
+ if (child)
+ child = child->FirstNamed(QName(kChromotingXmlNamespace,
+ kCertificateTag));
+
+ if (child) {
+ std::string base64_cert = child->BodyText();
+ std::string der_cert;
+ bool ret = base::Base64Decode(base64_cert, &der_cert);
+ DCHECK(ret) << "Failed to decode certificate";
+ certificate = net::X509Certificate::CreateFromBytes(der_cert.data(),
+ der_cert.length());
+ }
+
+ *content = new ContentDescription(config.release(), auth_token,
+ certificate);
return true;
}
LOG(ERROR) << "Invalid description: " << element->Str();
@@ -429,6 +463,9 @@ bool JingleSessionManager::ParseContent(
// <event transport="datagram" version="1" />
// <video transport="srtp" codec="vp8" version="1" />
// <initial-resolution width="800" height="600" />
+// <authentication>
+// <certificate>[BASE64 Encoded Certificate]</certificate>
+// </authentication>" />
// </description>
//
bool JingleSessionManager::WriteContent(
@@ -470,17 +507,37 @@ bool JingleSessionManager::WriteContent(
config->initial_resolution().height));
root->AddElement(resolution_tag);
+ if (desc->certificate()) {
+ XmlElement* authentication_tag = new XmlElement(
+ QName(kChromotingXmlNamespace, kAuthenticationTag));
+ XmlElement* certificate_tag = new XmlElement(
+ QName(kChromotingXmlNamespace, kCertificateTag));
+
+ std::string der_cert;
+ bool ret = desc->certificate()->GetDEREncoded(&der_cert);
+ DCHECK(ret) << "Cannot obtain DER encoded certificate";
+
+ std::string base64_cert;
+ ret = base::Base64Encode(der_cert, &base64_cert);
+ DCHECK(ret) << "Cannot perform base64 encode on certificate";
+
+ certificate_tag->SetBodyText(base64_cert);
+ authentication_tag->AddElement(certificate_tag);
+ root->AddElement(authentication_tag);
+ }
+
*elem = root;
return true;
}
cricket::SessionDescription* JingleSessionManager::CreateSessionDescription(
const CandidateSessionConfig* config,
- const std::string& auth_token) {
+ const std::string& auth_token,
+ scoped_refptr<net::X509Certificate> certificate) {
cricket::SessionDescription* desc = new cricket::SessionDescription();
desc->AddContent(JingleSession::kChromotingContentName,
kChromotingXmlNamespace,
- new ContentDescription(config, auth_token));
+ new ContentDescription(config, auth_token, certificate));
return desc;
}
diff --git a/remoting/protocol/jingle_session_manager.h b/remoting/protocol/jingle_session_manager.h
index 2a86c5f..8dcce03 100644
--- a/remoting/protocol/jingle_session_manager.h
+++ b/remoting/protocol/jingle_session_manager.h
@@ -37,7 +37,8 @@ namespace protocol {
class ContentDescription : public cricket::ContentDescription {
public:
explicit ContentDescription(const CandidateSessionConfig* config,
- const std::string& auth_token);
+ const std::string& auth_token,
+ scoped_refptr<net::X509Certificate> certificate);
~ContentDescription();
const CandidateSessionConfig* config() const {
@@ -46,12 +47,18 @@ class ContentDescription : public cricket::ContentDescription {
const std::string& auth_token() const { return auth_token_; }
+ scoped_refptr<net::X509Certificate> certificate() const {
+ return certificate_;
+ }
+
private:
scoped_ptr<const CandidateSessionConfig> candidate_config_;
// This may contain the initiating, or the accepting token depending on
// context.
std::string auth_token_;
+
+ scoped_refptr<net::X509Certificate> certificate_;
};
// This class implements SessionClient for Chromoting sessions. It acts as a
@@ -94,15 +101,6 @@ 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,7 +126,8 @@ class JingleSessionManager
// Creates outgoing session description for an incoming session.
cricket::SessionDescription* CreateSessionDescription(
const CandidateSessionConfig* candidate_config,
- const std::string& auth_token);
+ const std::string& auth_token,
+ scoped_refptr<net::X509Certificate> certificate);
std::string local_jid_; // Full jid for the local side of the session.
JingleThread* jingle_thread_;
@@ -138,9 +137,6 @@ 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 148c19b..cdcd069 100644
--- a/remoting/protocol/jingle_session_unittest.cc
+++ b/remoting/protocol/jingle_session_unittest.cc
@@ -132,35 +132,6 @@ 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() {
@@ -547,6 +518,10 @@ class UDPChannelTester : public ChannelTesterBase {
int broken_packets_;
};
+// Mac needs to implement X509Certificate::CreateSelfSigned to enable these
+// tests.
+#if defined(USE_NSS) || defined(OS_WIN)
+
// Verify that we can create and destory server objects without a connection.
TEST_F(JingleSessionTest, CreateAndDestoy) {
if (!base::CheckNSSVersion("3.12.8"))
@@ -669,5 +644,7 @@ TEST_F(JingleSessionTest, TestVideoRtpChannel) {
CloseSessions();
}
+#endif
+
} // namespace protocol
} // namespace remoting