From 40d33caad15e6c989f569a011f9803563d93c529 Mon Sep 17 00:00:00 2001 From: "hclam@chromium.org" Date: Thu, 23 Dec 2010 18:49:18 +0000 Subject: 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 --- remoting/protocol/jingle_session_manager.cc | 81 ++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 12 deletions(-) (limited to 'remoting/protocol/jingle_session_manager.cc') 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 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 JingleSessionManager::Connect( protocol::Session::StateChangeCallback* state_change_callback) { // Can be called from any thread. scoped_refptr 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 private_key( + base::RSAPrivateKey::Create(1024)); + std::string subject = "CN=chromoting"; + scoped_refptr 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 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( // //