diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-30 04:43:17 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-30 04:43:17 +0000 |
commit | f4453851934ac99908286f195ac0a4379c2b9852 (patch) | |
tree | ebf7aff9bfa148994ca1cfc2cce325c0d599514f /remoting/protocol | |
parent | dc51d1ccc18135493f01464e38ed462825ae8e35 (diff) | |
download | chromium_src-f4453851934ac99908286f195ac0a4379c2b9852.zip chromium_src-f4453851934ac99908286f195ac0a4379c2b9852.tar.gz chromium_src-f4453851934ac99908286f195ac0a4379c2b9852.tar.bz2 |
Use Authenticator interface in Session and SessionManager.
BUG=105214
Review URL: http://codereview.chromium.org/8619011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112127 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/protocol')
-rw-r--r-- | remoting/protocol/connection_to_host.cc | 12 | ||||
-rw-r--r-- | remoting/protocol/content_description.cc | 72 | ||||
-rw-r--r-- | remoting/protocol/content_description.h | 16 | ||||
-rw-r--r-- | remoting/protocol/fake_session.cc | 24 | ||||
-rw-r--r-- | remoting/protocol/fake_session.h | 13 | ||||
-rw-r--r-- | remoting/protocol/jingle_session.cc | 191 | ||||
-rw-r--r-- | remoting/protocol/jingle_session.h | 57 | ||||
-rw-r--r-- | remoting/protocol/jingle_session_manager.cc | 125 | ||||
-rw-r--r-- | remoting/protocol/jingle_session_manager.h | 33 | ||||
-rw-r--r-- | remoting/protocol/jingle_session_unittest.cc | 192 | ||||
-rw-r--r-- | remoting/protocol/pepper_session.cc | 77 | ||||
-rw-r--r-- | remoting/protocol/pepper_session.h | 16 | ||||
-rw-r--r-- | remoting/protocol/pepper_session_manager.cc | 18 | ||||
-rw-r--r-- | remoting/protocol/pepper_session_manager.h | 10 | ||||
-rw-r--r-- | remoting/protocol/session.h | 10 | ||||
-rw-r--r-- | remoting/protocol/session_manager.h | 20 |
16 files changed, 399 insertions, 487 deletions
diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc index 84c2a3f..c1145a7 100644 --- a/remoting/protocol/connection_to_host.cc +++ b/remoting/protocol/connection_to_host.cc @@ -17,6 +17,7 @@ #include "remoting/protocol/client_stub.h" #include "remoting/protocol/jingle_session_manager.h" #include "remoting/protocol/pepper_session_manager.h" +#include "remoting/protocol/v1_authenticator.h" #include "remoting/protocol/video_reader.h" #include "remoting/protocol/video_stub.h" #include "remoting/protocol/util.h" @@ -100,7 +101,7 @@ void ConnectionToHost::InitSession() { session_manager_.reset(new PepperSessionManager(pp_instance_)); session_manager_->Init( - local_jid_, signal_strategy_.get(), this, NULL, "", allow_nat_traversal_); + local_jid_, signal_strategy_.get(), this, allow_nat_traversal_); } const SessionConfig& ConnectionToHost::config() { @@ -132,15 +133,12 @@ void ConnectionToHost::OnSessionManagerInitialized() { // After SessionManager is initialized we can try to connect to the host. CandidateSessionConfig* candidate_config = CandidateSessionConfig::CreateDefault(); - std::string client_token = - protocol::GenerateSupportAuthToken(local_jid_, access_code_); + V1ClientAuthenticator* authenticator = + new V1ClientAuthenticator(local_jid_, access_code_); session_.reset(session_manager_->Connect( - host_jid_, host_public_key_, client_token, candidate_config, + host_jid_, authenticator, candidate_config, base::Bind(&ConnectionToHost::OnSessionStateChange, base::Unretained(this)))); - - // Set the shared-secret for securing SSL channels. - session_->set_shared_secret(access_code_); } void ConnectionToHost::OnIncomingSession( diff --git a/remoting/protocol/content_description.cc b/remoting/protocol/content_description.cc index 7cfeac5..d6947d7 100644 --- a/remoting/protocol/content_description.cc +++ b/remoting/protocol/content_description.cc @@ -4,7 +4,6 @@ #include "remoting/protocol/content_description.h" -#include "base/base64.h" #include "base/logging.h" #include "base/string_number_conversions.h" #include "remoting/base/constants.h" @@ -29,8 +28,6 @@ const char kEventTag[] = "event"; const char kVideoTag[] = "video"; const char kResolutionTag[] = "initial-resolution"; const char kAuthenticationTag[] = "authentication"; -const char kCertificateTag[] = "certificate"; -const char kAuthTokenTag[] = "auth-token"; const char kTransportAttr[] = "transport"; const char kVersionAttr[] = "version"; @@ -150,11 +147,9 @@ bool ParseChannelConfig(const XmlElement* element, bool codec_required, ContentDescription::ContentDescription( const CandidateSessionConfig* candidate_config, - const std::string& auth_token, - const std::string& certificate) + const buzz::XmlElement* authenticator_message) : candidate_config_(candidate_config), - auth_token_(auth_token), - certificate_(certificate) { + authenticator_message_(authenticator_message) { } ContentDescription::~ContentDescription() { } @@ -167,8 +162,7 @@ ContentDescription::~ContentDescription() { } // <video transport="srtp" codec="vp8" version="1" /> // <initial-resolution width="800" height="600" /> // <authentication> -// <certificate>[BASE64 Encoded Certificate]</certificate> -// <auth-token>...</auth-token> // IT2Me only. +// Message created by Authenticator implementation. // </authentication> // </description> // @@ -203,31 +197,10 @@ XmlElement* ContentDescription::ToXml() const { config()->initial_resolution().height)); root->AddElement(resolution_tag); - if (!certificate().empty() || !auth_token().empty()) { - XmlElement* authentication_tag = new XmlElement( - QName(kChromotingXmlNamespace, kAuthenticationTag)); - - if (!certificate().empty()) { - XmlElement* certificate_tag = new XmlElement( - QName(kChromotingXmlNamespace, kCertificateTag)); - - std::string base64_cert; - if (!base::Base64Encode(certificate(), &base64_cert)) { - LOG(DFATAL) << "Cannot perform base64 encode on certificate"; - } - - certificate_tag->SetBodyText(base64_cert); - authentication_tag->AddElement(certificate_tag); - } - - if (!auth_token().empty()) { - XmlElement* auth_token_tag = new XmlElement( - QName(kChromotingXmlNamespace, kAuthTokenTag)); - auth_token_tag->SetBodyText(auth_token()); - authentication_tag->AddElement(auth_token_tag); - } - - root->AddElement(authentication_tag); + if (authenticator_message_.get()) { + DCHECK(authenticator_message_->Name() == + QName(kChromotingXmlNamespace, kAuthenticationTag)); + root->AddElement(new XmlElement(*authenticator_message_)); } return root; @@ -287,38 +260,19 @@ ContentDescription* ContentDescription::ParseXml( return NULL; } ScreenResolution resolution(width, height); - if (!resolution.IsValid()) { + if (!resolution.IsValid()) return NULL; - } *config->mutable_initial_resolution() = resolution; - // Parse authentication information. - std::string certificate; - std::string auth_token; + scoped_ptr<XmlElement> authenticator_message; child = element->FirstNamed(QName(kChromotingXmlNamespace, kAuthenticationTag)); - if (child) { - // Parse the certificate. - const XmlElement* cert_tag = - child->FirstNamed(QName(kChromotingXmlNamespace, kCertificateTag)); - if (cert_tag) { - std::string base64_cert = cert_tag->BodyText(); - if (!base::Base64Decode(base64_cert, &certificate)) { - LOG(ERROR) << "Failed to decode certificate received from the peer."; - return NULL; - } - } - - // Parse auth-token. - const XmlElement* auth_token_tag = - child->FirstNamed(QName(kChromotingXmlNamespace, kAuthTokenTag)); - if (auth_token_tag) { - auth_token = auth_token_tag->BodyText(); - } - } + if (child) + authenticator_message.reset(new XmlElement(*child)); - return new ContentDescription(config.release(), auth_token, certificate); + return new ContentDescription( + config.release(), authenticator_message.release()); } LOG(ERROR) << "Invalid description: " << element->Str(); return NULL; diff --git a/remoting/protocol/content_description.h b/remoting/protocol/content_description.h index 5e4053f..95ccf60 100644 --- a/remoting/protocol/content_description.h +++ b/remoting/protocol/content_description.h @@ -28,17 +28,18 @@ class ContentDescription : public cricket::ContentDescription { public: static const char kChromotingContentName[]; + // Takes ownership of |config| and |authenticator_message|. ContentDescription(const CandidateSessionConfig* config, - const std::string& auth_token, - const std::string& certificate); + const buzz::XmlElement* authenticator_message); virtual ~ContentDescription(); const CandidateSessionConfig* config() const { return candidate_config_.get(); } - const std::string& auth_token() const { return auth_token_; } - const std::string& certificate() const { return certificate_; } + const buzz::XmlElement* authenticator_message() const { + return authenticator_message_.get(); + } buzz::XmlElement* ToXml() const; @@ -46,12 +47,7 @@ class ContentDescription : public cricket::ContentDescription { private: scoped_ptr<const CandidateSessionConfig> candidate_config_; - - // This may contain the initiating, or the accepting token depending on - // context. - std::string auth_token_; - - std::string certificate_; + scoped_ptr<const buzz::XmlElement> authenticator_message_; }; } // namespace protocol diff --git a/remoting/protocol/fake_session.cc b/remoting/protocol/fake_session.cc index f8f1e97..c09a62a5 100644 --- a/remoting/protocol/fake_session.cc +++ b/remoting/protocol/fake_session.cc @@ -261,30 +261,6 @@ void FakeSession::set_config(const SessionConfig& config) { config_ = config; } -const std::string& FakeSession::initiator_token() { - return initiator_token_; -} - -void FakeSession::set_initiator_token(const std::string& initiator_token) { - initiator_token_ = initiator_token; -} - -const std::string& FakeSession::receiver_token() { - return receiver_token_; -} - -void FakeSession::set_receiver_token(const std::string& receiver_token) { - receiver_token_ = receiver_token; -} - -void FakeSession::set_shared_secret(const std::string& shared_secret) { - shared_secret_ = shared_secret; -} - -const std::string& FakeSession::shared_secret() { - return shared_secret_; -} - void FakeSession::Close() { closed_ = true; } diff --git a/remoting/protocol/fake_session.h b/remoting/protocol/fake_session.h index 2516a78..7eaab6b 100644 --- a/remoting/protocol/fake_session.h +++ b/remoting/protocol/fake_session.h @@ -156,14 +156,6 @@ class FakeSession : public Session { virtual const SessionConfig& config() OVERRIDE; virtual void set_config(const SessionConfig& config) OVERRIDE; - virtual const std::string& initiator_token() OVERRIDE; - virtual void set_initiator_token(const std::string& initiator_token) OVERRIDE; - virtual const std::string& receiver_token() OVERRIDE; - virtual void set_receiver_token(const std::string& receiver_token) OVERRIDE; - - virtual void set_shared_secret(const std::string& secret) OVERRIDE; - virtual const std::string& shared_secret() OVERRIDE; - virtual void Close() OVERRIDE; public: @@ -175,11 +167,6 @@ class FakeSession : public Session { std::map<std::string, FakeSocket*> stream_channels_; std::map<std::string, FakeUdpSocket*> datagram_channels_; - std::string initiator_token_; - std::string receiver_token_; - - std::string shared_secret_; - std::string jid_; Session::Error error_; diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc index b008bb4a..dd66e04 100644 --- a/remoting/protocol/jingle_session.cc +++ b/remoting/protocol/jingle_session.cc @@ -4,22 +4,22 @@ #include "remoting/protocol/jingle_session.h" +#include "base/base64.h" #include "base/bind.h" #include "base/location.h" #include "base/message_loop_proxy.h" #include "base/rand_util.h" #include "base/stl_util.h" #include "crypto/hmac.h" -#include "crypto/rsa_private_key.h" #include "net/base/net_errors.h" #include "net/socket/stream_socket.h" #include "remoting/base/constants.h" #include "remoting/protocol/auth_util.h" +#include "remoting/protocol/authenticator.h" +#include "remoting/protocol/channel_authenticator.h" #include "remoting/protocol/jingle_datagram_connector.h" #include "remoting/protocol/jingle_session_manager.h" #include "remoting/protocol/jingle_stream_connector.h" -#include "remoting/protocol/v1_client_channel_authenticator.h" -#include "remoting/protocol/v1_host_channel_authenticator.h" #include "third_party/libjingle/source/talk/base/thread.h" #include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h" #include "third_party/libjingle/source/talk/p2p/base/session.h" @@ -30,41 +30,21 @@ using cricket::BaseSession; namespace remoting { namespace protocol { -// static -JingleSession* JingleSession::CreateClientSession( - JingleSessionManager* manager, const std::string& host_public_key) { - return new JingleSession(manager, "", NULL, host_public_key); -} - -// static -JingleSession* JingleSession::CreateServerSession( - JingleSessionManager* manager, - const std::string& certificate, - crypto::RSAPrivateKey* key) { - return new JingleSession(manager, certificate, key, ""); -} - JingleSession::JingleSession( JingleSessionManager* jingle_session_manager, - const std::string& local_cert, - crypto::RSAPrivateKey* local_private_key, - const std::string& peer_public_key) + cricket::Session* cricket_session, + Authenticator* authenticator) : jingle_session_manager_(jingle_session_manager), - local_cert_(local_cert), + authenticator_(authenticator), state_(INITIALIZING), error_(OK), closing_(false), - cricket_session_(NULL), + cricket_session_(cricket_session), config_set_(false), ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { - // TODO(hclam): Need a better way to clone a key. - if (local_private_key) { - std::vector<uint8> key_bytes; - CHECK(local_private_key->ExportPrivateKey(&key_bytes)); - local_private_key_.reset( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes)); - CHECK(local_private_key_.get()); - } + jid_ = cricket_session_->remote_name(); + cricket_session_->SignalState.connect(this, &JingleSession::OnSessionState); + cricket_session_->SignalError.connect(this, &JingleSession::OnSessionError); } JingleSession::~JingleSession() { @@ -75,15 +55,11 @@ JingleSession::~JingleSession() { DCHECK(channel_connectors_.empty()); } -void JingleSession::Init(cricket::Session* cricket_session) { - DCHECK(CalledOnValidThread()); - - cricket_session_ = cricket_session; - jid_ = cricket_session_->remote_name(); - cricket_session_->SignalState.connect( - this, &JingleSession::OnSessionState); - cricket_session_->SignalError.connect( - this, &JingleSession::OnSessionError); +void JingleSession::SendSessionInitiate() { + DCHECK_EQ(authenticator_->state(), Authenticator::MESSAGE_READY); + cricket_session_->Initiate( + jid_, CreateSessionDescription(candidate_config()->Clone(), + authenticator_->GetNextMessage())); } void JingleSession::CloseInternal(int result, Error error) { @@ -199,11 +175,6 @@ void JingleSession::set_candidate_config( candidate_config_.reset(candidate_config); } -const std::string& JingleSession::local_certificate() const { - DCHECK(CalledOnValidThread()); - return local_cert_; -} - const SessionConfig& JingleSession::config() { DCHECK(CalledOnValidThread()); DCHECK(config_set_); @@ -217,37 +188,6 @@ void JingleSession::set_config(const SessionConfig& config) { config_set_ = true; } -const std::string& JingleSession::initiator_token() { - DCHECK(CalledOnValidThread()); - return initiator_token_; -} - -void JingleSession::set_initiator_token(const std::string& initiator_token) { - DCHECK(CalledOnValidThread()); - initiator_token_ = initiator_token; -} - -const std::string& JingleSession::receiver_token() { - DCHECK(CalledOnValidThread()); - return receiver_token_; -} - -void JingleSession::set_receiver_token(const std::string& receiver_token) { - DCHECK(CalledOnValidThread()); - receiver_token_ = receiver_token; -} - -void JingleSession::set_shared_secret(const std::string& secret) { - DCHECK(CalledOnValidThread()); - shared_secret_ = secret; -} - -const std::string& JingleSession::shared_secret() { - DCHECK(CalledOnValidThread()); - return shared_secret_; -} - - void JingleSession::Close() { DCHECK(CalledOnValidThread()); @@ -308,13 +248,6 @@ void JingleSession::OnInitiate() { DCHECK(CalledOnValidThread()); jid_ = cricket_session_->remote_name(); - if (!cricket_session_->initiator()) { - const protocol::ContentDescription* content_description = - static_cast<const protocol::ContentDescription*>( - GetContentInfo()->description); - CHECK(content_description); - } - if (cricket_session_->initiator()) { // Set state to CONNECTING if this is an outgoing message. We need // to post this task because channel creation works only after we @@ -345,9 +278,22 @@ bool JingleSession::InitializeConfigFromDescription( static_cast<const protocol::ContentDescription*>(content->description); CHECK(content_description); - remote_cert_ = content_description->certificate(); - if (remote_cert_.empty()) { - LOG(ERROR) << "Connection response does not specify certificate"; + // Process authenticator message. + const buzz::XmlElement* auth_message = + content_description->authenticator_message(); + if (!auth_message) { + DLOG(WARNING) << "Received session-accept without authentication message " + << auth_message->Str(); + return false; + } + + DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE); + authenticator_->ProcessMessage(auth_message); + // Support for more than two auth message is not implemented yet. + DCHECK(authenticator_->state() != Authenticator::WAITING_MESSAGE && + authenticator_->state() != Authenticator::MESSAGE_READY); + + if (authenticator_->state() != Authenticator::ACCEPTED) { return false; } @@ -389,7 +335,25 @@ void JingleSession::OnTerminate() { void JingleSession::AcceptConnection() { SetState(CONNECTING); - if (!jingle_session_manager_->AcceptConnection(this, cricket_session_)) { + const cricket::SessionDescription* session_description = + cricket_session_->remote_description(); + const cricket::ContentInfo* content = + session_description->FirstContentByType(kChromotingXmlNamespace); + + CHECK(content); + const ContentDescription* content_description = + static_cast<const ContentDescription*>(content->description); + candidate_config_.reset(content_description->config()->Clone()); + + SessionManager::IncomingSessionResponse response = + jingle_session_manager_->AcceptConnection(this); + if (response != SessionManager::ACCEPT) { + if (response == SessionManager::INCOMPATIBLE) { + cricket_session_->TerminateWithReason( + cricket::STR_TERMINATE_INCOMPATIBLE_PARAMETERS); + } else { + cricket_session_->TerminateWithReason(cricket::STR_TERMINATE_DECLINE); + } Close(); // Release session so that JingleSessionManager::SessionDestroyed() // doesn't try to call cricket::SessionManager::DestroySession() for it. @@ -398,8 +362,40 @@ void JingleSession::AcceptConnection() { return; } - if (!VerifySupportAuthToken(jid_, shared_secret_, initiator_token())) + const buzz::XmlElement* auth_message = + content_description->authenticator_message(); + if (!auth_message) { + DLOG(WARNING) << "Received session-initiate without authenticator message."; + CloseInternal(net::ERR_CONNECTION_FAILED, INCOMPATIBLE_PROTOCOL); + return; + } + + authenticator_.reset( + jingle_session_manager_->CreateAuthenticator(jid(), auth_message)); + if (!authenticator_.get()) { + CloseInternal(net::ERR_CONNECTION_FAILED, INCOMPATIBLE_PROTOCOL); + return; + } + + DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE); + authenticator_->ProcessMessage(auth_message); + // Support for more than two auth message is not implemented yet. + DCHECK(authenticator_->state() != Authenticator::WAITING_MESSAGE); + if (authenticator_->state() == Authenticator::REJECTED) { CloseInternal(net::ERR_CONNECTION_FAILED, AUTHENTICATION_FAILED); + return; + } + + // Connection must be configured by the AcceptConnection() callback. + CandidateSessionConfig* candidate_config = + CandidateSessionConfig::CreateFrom(config()); + + buzz::XmlElement* auth_reply = NULL; + if (authenticator_->state() == Authenticator::MESSAGE_READY) + auth_reply = authenticator_->GetNextMessage(); + DCHECK_EQ(authenticator_->state(), Authenticator::ACCEPTED); + cricket_session_->Accept( + CreateSessionDescription(candidate_config, auth_reply)); } void JingleSession::AddChannelConnector( @@ -418,14 +414,8 @@ void JingleSession::AddChannelConnector( } channel_connectors_[name] = connector; - ChannelAuthenticator* authenticator; - if (cricket_session_->initiator()) { - authenticator = new V1ClientChannelAuthenticator( - remote_cert_, shared_secret_); - } else { - authenticator = new V1HostChannelAuthenticator( - local_cert_, local_private_key_.get(), shared_secret_); - } + ChannelAuthenticator* authenticator = + authenticator_->CreateChannelAuthenticator(); connector->Connect(authenticator, raw_channel); // Workaround bug in libjingle - it doesn't connect channels if they @@ -469,5 +459,16 @@ void JingleSession::SetState(State new_state) { } } +// static +cricket::SessionDescription* JingleSession::CreateSessionDescription( + const CandidateSessionConfig* config, + const buzz::XmlElement* authenticator_message) { + cricket::SessionDescription* desc = new cricket::SessionDescription(); + desc->AddContent( + ContentDescription::kChromotingContentName, kChromotingXmlNamespace, + new ContentDescription(config, authenticator_message)); + return desc; +} + } // namespace protocol } // namespace remoting diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h index b2f831b..75f061f 100644 --- a/remoting/protocol/jingle_session.h +++ b/remoting/protocol/jingle_session.h @@ -7,16 +7,15 @@ #include "base/memory/ref_counted.h" #include "base/task.h" -#include "crypto/rsa_private_key.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" namespace remoting { - namespace protocol { +class Authenticator; class JingleChannelConnector; class JingleSessionManager; @@ -41,12 +40,6 @@ class JingleSession : public protocol::Session, virtual const CandidateSessionConfig* candidate_config() OVERRIDE; virtual const SessionConfig& config() OVERRIDE; virtual void set_config(const SessionConfig& config) OVERRIDE; - virtual const std::string& initiator_token() OVERRIDE; - virtual void set_initiator_token(const std::string& initiator_token) OVERRIDE; - virtual const std::string& receiver_token() OVERRIDE; - virtual void set_receiver_token(const std::string& receiver_token) OVERRIDE; - virtual void set_shared_secret(const std::string& secret) OVERRIDE; - virtual const std::string& shared_secret() OVERRIDE; virtual void Close() OVERRIDE; private: @@ -56,31 +49,17 @@ class JingleSession : public protocol::Session, typedef std::map<std::string, JingleChannelConnector*> ChannelConnectorsMap; - // Create a JingleSession used in client mode. A server certificate is - // required. - static JingleSession* CreateClientSession(JingleSessionManager* manager, - const std::string& host_public_key); - - // Create a JingleSession used in server mode. A server certificate and - // private key is provided. |key| is copied in the constructor. - // - // TODO(sergeyu): Remove |certificate| and |key| when we stop using TLS. - static JingleSession* CreateServerSession( - JingleSessionManager* manager, - const std::string& certificate, - crypto::RSAPrivateKey* key); - - // TODO(sergeyu): Change type of |peer_public_key| to RSAPublicKey. + // Takes ownership of |authenticator|. JingleSession(JingleSessionManager* jingle_session_manager, - const std::string& local_cert, - crypto::RSAPrivateKey* local_private_key, - const std::string& peer_public_key); + cricket::Session* cricket_session, + Authenticator* authenticator); virtual ~JingleSession(); // Called by JingleSessionManager. void set_candidate_config(const CandidateSessionConfig* candidate_config); - const std::string& local_certificate() const; - void Init(cricket::Session* cricket_session); + + // Sends session-initiate for new session. + void SendSessionInitiate(); // Close all the channels and terminate the session. |result| // defines error code that should returned to currently opened @@ -123,24 +102,15 @@ class JingleSession : public protocol::Session, void SetState(State new_state); + static cricket::SessionDescription* CreateSessionDescription( + const CandidateSessionConfig* candidate_config, + const buzz::XmlElement* authenticator_message); + // JingleSessionManager that created this session. Guaranteed to // exist throughout the lifetime of the session. JingleSessionManager* jingle_session_manager_; - // Certificates used for connection. Currently only receiving side - // has a certificate. - std::string local_cert_; - std::string remote_cert_; - - // Private key used in SSL server sockets. - scoped_ptr<crypto::RSAPrivateKey> local_private_key_; - - // Public key of the peer. - std::string peer_public_key_; - - // Shared secret to use in channel authentication. This is currently only - // used in IT2Me. - std::string shared_secret_; + scoped_ptr<Authenticator> authenticator_; State state_; StateChangeCallback state_change_callback_; @@ -159,9 +129,6 @@ class JingleSession : public protocol::Session, SessionConfig config_; bool config_set_; - std::string initiator_token_; - std::string receiver_token_; - // These data members are only set on the receiving side. scoped_ptr<const CandidateSessionConfig> candidate_config_; diff --git a/remoting/protocol/jingle_session_manager.cc b/remoting/protocol/jingle_session_manager.cc index 8408f94..2a24441 100644 --- a/remoting/protocol/jingle_session_manager.cc +++ b/remoting/protocol/jingle_session_manager.cc @@ -6,6 +6,7 @@ #include <limits> +#include "base/base64.h" #include "base/bind.h" #include "base/message_loop_proxy.h" #include "base/string_util.h" @@ -14,6 +15,7 @@ #include "remoting/jingle_glue/jingle_info_request.h" #include "remoting/jingle_glue/jingle_signaling_connector.h" #include "remoting/jingle_glue/signal_strategy.h" +#include "remoting/protocol/authenticator.h" #include "third_party/libjingle/source/talk/base/basicpacketsocketfactory.h" #include "third_party/libjingle/source/talk/p2p/base/constants.h" #include "third_party/libjingle/source/talk/p2p/base/sessionmanager.h" @@ -46,8 +48,6 @@ void JingleSessionManager::Init( const std::string& local_jid, SignalStrategy* signal_strategy, Listener* listener, - crypto::RSAPrivateKey* private_key, - const std::string& certificate, bool allow_nat_traversal) { DCHECK(CalledOnValidThread()); @@ -57,8 +57,6 @@ void JingleSessionManager::Init( local_jid_ = local_jid; signal_strategy_ = signal_strategy; listener_ = listener; - private_key_.reset(private_key); - certificate_ = certificate; allow_nat_traversal_ = allow_nat_traversal; if (!network_manager_.get()) { @@ -119,30 +117,30 @@ void JingleSessionManager::Close() { } } +void JingleSessionManager::set_authenticator_factory( + AuthenticatorFactory* authenticator_factory) { + DCHECK(CalledOnValidThread()); + authenticator_factory_.reset(authenticator_factory); +} + Session* JingleSessionManager::Connect( const std::string& host_jid, - const std::string& host_public_key, - const std::string& receiver_token, + Authenticator* authenticator, CandidateSessionConfig* candidate_config, const Session::StateChangeCallback& state_change_callback) { DCHECK(CalledOnValidThread()); - // Can be called from any thread. - JingleSession* jingle_session = - JingleSession::CreateClientSession(this, host_public_key); - jingle_session->set_candidate_config(candidate_config); - jingle_session->set_receiver_token(receiver_token); - cricket::Session* cricket_session = cricket_session_manager_->CreateSession( local_jid_, kChromotingXmlNamespace); + cricket_session->set_remote_name(host_jid); - // Initialize connection object before we send initiate stanza. + JingleSession* jingle_session = + new JingleSession(this, cricket_session, authenticator); + jingle_session->set_candidate_config(candidate_config); jingle_session->SetStateChangeCallback(state_change_callback); - jingle_session->Init(cricket_session); sessions_.push_back(jingle_session); - cricket_session->Initiate(host_jid, CreateClientSessionDescription( - jingle_session->candidate_config()->Clone(), receiver_token)); + jingle_session->SendSessionInitiate(); return jingle_session; } @@ -154,15 +152,10 @@ void JingleSessionManager::OnSessionCreate( // Allow local connections. cricket_session->set_allow_local_ips(true); - // If this is an incoming session, create a JingleSession on top of it. if (incoming) { - DCHECK(!certificate_.empty()); - DCHECK(private_key_.get()); - - JingleSession* jingle_session = JingleSession::CreateServerSession( - this, certificate_, private_key_.get()); + JingleSession* jingle_session = + new JingleSession(this, cricket_session, NULL); sessions_.push_back(jingle_session); - jingle_session->Init(cricket_session); } } @@ -178,63 +171,26 @@ void JingleSessionManager::OnSessionDestroy(cricket::Session* cricket_session) { } } -bool JingleSessionManager::AcceptConnection( - JingleSession* jingle_session, - cricket::Session* cricket_session) { +SessionManager::IncomingSessionResponse JingleSessionManager::AcceptConnection( + JingleSession* jingle_session) { DCHECK(CalledOnValidThread()); // Reject connection if we are closed. - if (closed_) { - cricket_session->Reject(cricket::STR_TERMINATE_DECLINE); - return false; - } - - const cricket::SessionDescription* session_description = - cricket_session->remote_description(); - const cricket::ContentInfo* content = - session_description->FirstContentByType(kChromotingXmlNamespace); - - CHECK(content); + if (closed_) + return SessionManager::DECLINE; - const ContentDescription* content_description = - static_cast<const ContentDescription*>(content->description); - jingle_session->set_candidate_config(content_description->config()->Clone()); - jingle_session->set_initiator_token(content_description->auth_token()); - - // Always reject connection if there is no callback. - IncomingSessionResponse response = protocol::SessionManager::DECLINE; - - // Use the callback to generate a response. + IncomingSessionResponse response = SessionManager::DECLINE; listener_->OnIncomingSession(jingle_session, &response); + return response; +} - switch (response) { - case SessionManager::ACCEPT: { - // Connection must be configured by the callback. - CandidateSessionConfig* candidate_config = - CandidateSessionConfig::CreateFrom(jingle_session->config()); - cricket_session->Accept( - CreateHostSessionDescription(candidate_config, - jingle_session->local_certificate())); - break; - } - - case SessionManager::INCOMPATIBLE: { - cricket_session->TerminateWithReason( - cricket::STR_TERMINATE_INCOMPATIBLE_PARAMETERS); - return false; - } - - case SessionManager::DECLINE: { - cricket_session->TerminateWithReason(cricket::STR_TERMINATE_DECLINE); - return false; - } - - default: { - NOTREACHED(); - } - } +Authenticator* JingleSessionManager::CreateAuthenticator( + const std::string& jid, const buzz::XmlElement* auth_message) { + DCHECK(CalledOnValidThread()); - return true; + if (!authenticator_factory_.get()) + return NULL; + return authenticator_factory_->CreateAuthenticator(jid, auth_message); } void JingleSessionManager::SessionDestroyed(JingleSession* jingle_session) { @@ -293,28 +249,5 @@ bool JingleSessionManager::WriteContent( return true; } -// static -cricket::SessionDescription* -JingleSessionManager::CreateClientSessionDescription( - const CandidateSessionConfig* config, - const std::string& auth_token) { - cricket::SessionDescription* desc = new cricket::SessionDescription(); - desc->AddContent( - ContentDescription::kChromotingContentName, kChromotingXmlNamespace, - new ContentDescription(config, auth_token, "")); - return desc; -} - -// static -cricket::SessionDescription* JingleSessionManager::CreateHostSessionDescription( - const CandidateSessionConfig* config, - const std::string& certificate) { - cricket::SessionDescription* desc = new cricket::SessionDescription(); - desc->AddContent( - ContentDescription::kChromotingContentName, kChromotingXmlNamespace, - new ContentDescription(config, "", certificate)); - return desc; -} - } // namespace protocol } // namespace remoting diff --git a/remoting/protocol/jingle_session_manager.h b/remoting/protocol/jingle_session_manager.h index 2f2125e..a72d9a3 100644 --- a/remoting/protocol/jingle_session_manager.h +++ b/remoting/protocol/jingle_session_manager.h @@ -43,16 +43,15 @@ class JingleSessionManager virtual void Init(const std::string& local_jid, SignalStrategy* signal_strategy, Listener* listener, - crypto::RSAPrivateKey* private_key, - const std::string& certificate, bool allow_nat_traversal) OVERRIDE; virtual Session* Connect( const std::string& host_jid, - const std::string& host_public_key, - const std::string& client_token, + Authenticator* authenticator, CandidateSessionConfig* config, const Session::StateChangeCallback& state_change_callback) OVERRIDE; virtual void Close() OVERRIDE; + virtual void set_authenticator_factory( + AuthenticatorFactory* authenticator_factory) OVERRIDE; // cricket::SessionClient interface. virtual void OnSessionCreate(cricket::Session* cricket_session, @@ -71,10 +70,16 @@ class JingleSessionManager private: friend class JingleSession; - // Called by JingleSession when a new connection is - // initiated. Returns true if session is accepted. - bool AcceptConnection(JingleSession* jingle_session, - cricket::Session* cricket_session); + // Called by JingleSession when a new connection is initiated. + SessionManager::IncomingSessionResponse AcceptConnection( + JingleSession* jingle_session); + + // Creates authenticator for incoming session. Returns NULL if + // authenticator cannot be created, e.g. if |auth_message| is + // invalid. Caller reatins ownership of |auth_message| and must + // accept ownership of the result. + Authenticator* CreateAuthenticator(const std::string& jid, + const buzz::XmlElement* auth_message); // Called by JingleSession when it is being destroyed. void SessionDestroyed(JingleSession* jingle_session); @@ -85,15 +90,6 @@ class JingleSessionManager const std::vector<std::string>& relay_hosts, const std::vector<talk_base::SocketAddress>& stun_hosts); - // Creates session description for outgoing session. - static cricket::SessionDescription* CreateClientSessionDescription( - const CandidateSessionConfig* candidate_config, - const std::string& auth_token); - // Creates session description for incoming session. - static cricket::SessionDescription* CreateHostSessionDescription( - const CandidateSessionConfig* candidate_config, - const std::string& certificate); - scoped_refptr<base::MessageLoopProxy> message_loop_; scoped_ptr<talk_base::NetworkManager> network_manager_; @@ -101,9 +97,8 @@ class JingleSessionManager std::string local_jid_; // Full jid for the local side of the session. SignalStrategy* signal_strategy_; + scoped_ptr<AuthenticatorFactory> authenticator_factory_; Listener* listener_; - std::string certificate_; - scoped_ptr<crypto::RSAPrivateKey> private_key_; bool allow_nat_traversal_; scoped_ptr<cricket::PortAllocator> port_allocator_; diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc index 4b91b13..9dd5143 100644 --- a/remoting/protocol/jingle_session_unittest.cc +++ b/remoting/protocol/jingle_session_unittest.cc @@ -10,14 +10,19 @@ #include "base/time.h" #include "base/test/test_timeouts.h" #include "crypto/nss_util.h" +#include "crypto/rsa_private_key.h" #include "net/base/completion_callback.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/socket/socket.h" #include "net/socket/stream_socket.h" +#include "remoting/base/constants.h" #include "remoting/protocol/auth_util.h" +#include "remoting/protocol/authenticator.h" +#include "remoting/protocol/channel_authenticator.h" #include "remoting/protocol/jingle_session.h" #include "remoting/protocol/jingle_session_manager.h" +#include "remoting/protocol/v1_authenticator.h" #include "remoting/jingle_glue/jingle_thread.h" #include "remoting/jingle_glue/fake_signal_strategy.h" #include "testing/gmock/include/gmock/gmock.h" @@ -108,6 +113,124 @@ class MockSessionCallback { MOCK_METHOD1(OnStateChange, void(Session::State)); }; +class FakeChannelAuthenticator : public ChannelAuthenticator { + public: + FakeChannelAuthenticator(bool accept) + : accept_(accept) { + } + virtual ~FakeChannelAuthenticator() {} + + virtual void SecureAndAuthenticate( + net::StreamSocket* socket, const DoneCallback& done_callback) OVERRIDE { + if (accept_) { + done_callback.Run(net::OK, socket); + } else { + delete socket; + done_callback.Run(net::ERR_FAILED, NULL); + } + } + + private: + bool accept_; + + DISALLOW_COPY_AND_ASSIGN(FakeChannelAuthenticator); +}; + +class FakeClientAuthenticator : public Authenticator { + public: + FakeClientAuthenticator(bool accept, bool accept_channel) + : accept_(accept), + accept_channel_(accept_channel), + state_(MESSAGE_READY) { + } + virtual ~FakeClientAuthenticator() {} + + virtual State state() const OVERRIDE { + return state_; + } + + virtual void ProcessMessage(const buzz::XmlElement* message) OVERRIDE { + EXPECT_EQ(WAITING_MESSAGE, state_); + state_ = accept_ ? ACCEPTED : REJECTED; + } + + virtual buzz::XmlElement* GetNextMessage() OVERRIDE { + EXPECT_EQ(MESSAGE_READY, state_); + state_ = WAITING_MESSAGE; + return new buzz::XmlElement( + buzz::QName(kChromotingXmlNamespace, "authentication")); + } + + virtual ChannelAuthenticator* CreateChannelAuthenticator() const OVERRIDE { + return new FakeChannelAuthenticator(accept_channel_); + } + + protected: + bool accept_; + bool accept_channel_; + State state_; + + DISALLOW_COPY_AND_ASSIGN(FakeClientAuthenticator); +}; + +class FakeHostAuthenticator : public Authenticator { + public: + FakeHostAuthenticator(bool accept, bool accept_channel) + : accept_(accept), + accept_channel_(accept_channel), + state_(WAITING_MESSAGE) { + } + virtual ~FakeHostAuthenticator() {} + + virtual State state() const OVERRIDE { + return state_; + } + + virtual void ProcessMessage(const buzz::XmlElement* message) OVERRIDE { + EXPECT_EQ(WAITING_MESSAGE, state_); + state_ = MESSAGE_READY; + } + + virtual buzz::XmlElement* GetNextMessage() OVERRIDE { + EXPECT_EQ(MESSAGE_READY, state_); + state_ = accept_ ? ACCEPTED : REJECTED; + return new buzz::XmlElement( + buzz::QName(kChromotingXmlNamespace, "authentication")); + } + + virtual ChannelAuthenticator* CreateChannelAuthenticator() const OVERRIDE { + return new FakeChannelAuthenticator(accept_channel_); + } + + protected: + bool accept_; + bool accept_channel_; + State state_; + + DISALLOW_COPY_AND_ASSIGN(FakeHostAuthenticator); +}; + +class FakeHostAuthenticatorFactory : public AuthenticatorFactory { + public: + FakeHostAuthenticatorFactory(bool accept, bool accept_channel) + : accept_(accept), + accept_channel_(accept_channel) { + } + virtual ~FakeHostAuthenticatorFactory() {} + + virtual Authenticator* CreateAuthenticator( + const std::string& remote_jid, + const buzz::XmlElement* first_message) OVERRIDE { + return new FakeHostAuthenticator(accept_, accept_channel_); + } + + private: + bool accept_; + bool accept_channel_; + + DISALLOW_COPY_AND_ASSIGN(FakeHostAuthenticatorFactory); +}; + } // namespace class JingleSessionTest : public testing::Test { @@ -125,7 +248,6 @@ class JingleSessionTest : public testing::Test { base::Unretained(&host_connection_callback_))); session->set_config(SessionConfig::GetDefault()); - session->set_shared_secret(kTestSharedSecret); } protected: @@ -148,7 +270,7 @@ class JingleSessionTest : public testing::Test { } } - void CreateServerPair() { + void CreateServerPair(bool use_fake_auth) { FilePath certs_dir; PathService::Get(base::DIR_SOURCE_ROOT, &certs_dir); certs_dir = certs_dir.AppendASCII("net"); @@ -180,16 +302,24 @@ class JingleSessionTest : public testing::Test { host_server_.reset(new JingleSessionManager( base::MessageLoopProxy::current())); host_server_->Init( - kHostJid, host_signal_strategy_.get(), &host_server_listener_, - private_key.release(), cert_der, false); + kHostJid, host_signal_strategy_.get(), &host_server_listener_, false); + + if (use_fake_auth) { + host_server_->set_authenticator_factory( + new FakeHostAuthenticatorFactory(true, false)); + } else { + host_server_->set_authenticator_factory( + new V1HostAuthenticatorFactory( + cert_der, private_key.release(), kTestSharedSecret)); + } EXPECT_CALL(client_server_listener_, OnSessionManagerInitialized()) .Times(1); client_server_.reset(new JingleSessionManager( base::MessageLoopProxy::current())); client_server_->Init( - kClientJid, client_signal_strategy_.get(), &client_server_listener_, - NULL, "", false); + kClientJid, client_signal_strategy_.get(), + &client_server_listener_, false); } void CloseSessionManager() { @@ -205,7 +335,7 @@ class JingleSessionTest : public testing::Test { client_signal_strategy_.reset(); } - bool InitiateConnection(const char* shared_secret) { + bool InitiateConnection(bool use_fake_auth) { int not_connected_peers = 2; EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) @@ -243,15 +373,18 @@ class JingleSessionTest : public testing::Test { .Times(AtMost(1)); } + Authenticator* authenticator; + if (use_fake_auth) { + authenticator = new FakeClientAuthenticator(true, true); + } else { + authenticator = new V1ClientAuthenticator(kClientJid, kTestSharedSecret); + } client_session_.reset(client_server_->Connect( - kHostJid, kTestHostPublicKey, - GenerateSupportAuthToken(kClientJid, kTestSharedSecret), + kHostJid, authenticator, CandidateSessionConfig::CreateDefault(), base::Bind(&MockSessionCallback::OnStateChange, base::Unretained(&client_connection_callback_)))); - client_session_->set_shared_secret(shared_secret); - return RunMessageLoopWithTimeout(TestTimeouts::action_max_timeout_ms()); } @@ -370,6 +503,8 @@ class TCPChannelTester : public ChannelTesterBase { void OnChannelReady(int id, net::StreamSocket* socket) { if (!socket) { + host_session_->CancelChannelCreation(kChannelName); + client_session_->CancelChannelCreation(kChannelName); Done(); return; } @@ -645,13 +780,13 @@ class UDPChannelTester : public ChannelTesterBase { // Verify that we can create and destory server objects without a connection. TEST_F(JingleSessionTest, CreateAndDestoy) { - CreateServerPair(); + CreateServerPair(false); } // 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) { - CreateServerPair(); + CreateServerPair(false); // Reject incoming session. EXPECT_CALL(host_server_listener_, OnIncomingSession(_, _)) @@ -669,9 +804,10 @@ TEST_F(JingleSessionTest, RejectConnection) { .WillOnce(InvokeWithoutArgs(&QuitCurrentThread)); } + Authenticator* authenticator = + new V1ClientAuthenticator(kClientJid, kTestSharedSecretBad); client_session_.reset(client_server_->Connect( - kHostJid, kTestHostPublicKey, - GenerateSupportAuthToken(kClientJid, kTestSharedSecret), + kHostJid, authenticator, CandidateSessionConfig::CreateDefault(), base::Bind(&MockSessionCallback::OnStateChange, base::Unretained(&client_connection_callback_)))); @@ -681,14 +817,14 @@ TEST_F(JingleSessionTest, RejectConnection) { // Verify that we can connect two endpoints. TEST_F(JingleSessionTest, Connect) { - CreateServerPair(); - ASSERT_TRUE(InitiateConnection(kTestSharedSecret)); + CreateServerPair(false); + ASSERT_TRUE(InitiateConnection(false)); } // Verify that we can't connect two endpoints with mismatched secrets. TEST_F(JingleSessionTest, ConnectBadChannelAuth) { - CreateServerPair(); - ASSERT_TRUE(InitiateConnection(kTestSharedSecretBad)); + CreateServerPair(true); + ASSERT_TRUE(InitiateConnection(true)); scoped_refptr<TCPChannelTester> tester( new TCPChannelTester(host_session_.get(), client_session_.get(), kMessageSize, kMessages)); @@ -701,8 +837,8 @@ TEST_F(JingleSessionTest, ConnectBadChannelAuth) { // Verify that data can be transmitted over the event channel. TEST_F(JingleSessionTest, TestTcpChannel) { - CreateServerPair(); - ASSERT_TRUE(InitiateConnection(kTestSharedSecret)); + CreateServerPair(false); + ASSERT_TRUE(InitiateConnection(false)); scoped_refptr<TCPChannelTester> tester( new TCPChannelTester(host_session_.get(), client_session_.get(), kMessageSize, kMessages)); @@ -716,8 +852,8 @@ TEST_F(JingleSessionTest, TestTcpChannel) { // Verify that data can be transmitted over the video RTP channel. TEST_F(JingleSessionTest, TestUdpChannel) { - CreateServerPair(); - ASSERT_TRUE(InitiateConnection(kTestSharedSecret)); + CreateServerPair(false); + ASSERT_TRUE(InitiateConnection(false)); scoped_refptr<UDPChannelTester> tester( new UDPChannelTester(host_session_.get(), client_session_.get())); tester->Start(); @@ -731,8 +867,8 @@ TEST_F(JingleSessionTest, TestUdpChannel) { // Send packets of different size to get the latency for sending data // using sockets from JingleSession. TEST_F(JingleSessionTest, FLAKY_TestSpeed) { - CreateServerPair(); - ASSERT_TRUE(InitiateConnection(kTestSharedSecret)); + CreateServerPair(false); + ASSERT_TRUE(InitiateConnection(false)); scoped_refptr<ChannelSpeedTester> tester; tester = new ChannelSpeedTester(host_session_.get(), @@ -743,7 +879,7 @@ TEST_F(JingleSessionTest, FLAKY_TestSpeed) { << tester->GetElapsedTime().InMilliseconds() << " ms."; CloseSessions(); - ASSERT_TRUE(InitiateConnection(kTestSharedSecret)); + ASSERT_TRUE(InitiateConnection(false)); tester = new ChannelSpeedTester(host_session_.get(), client_session_.get(), 1024); @@ -753,7 +889,7 @@ TEST_F(JingleSessionTest, FLAKY_TestSpeed) { << tester->GetElapsedTime().InMilliseconds() << " ms."; CloseSessions(); - ASSERT_TRUE(InitiateConnection(kTestSharedSecret)); + ASSERT_TRUE(InitiateConnection(false)); tester = new ChannelSpeedTester(host_session_.get(), client_session_.get(), 51200); @@ -763,7 +899,7 @@ TEST_F(JingleSessionTest, FLAKY_TestSpeed) { << tester->GetElapsedTime().InMilliseconds() << " ms."; CloseSessions(); - ASSERT_TRUE(InitiateConnection(kTestSharedSecret)); + ASSERT_TRUE(InitiateConnection(false)); tester = new ChannelSpeedTester(host_session_.get(), client_session_.get(), 512000); diff --git a/remoting/protocol/pepper_session.cc b/remoting/protocol/pepper_session.cc index 138993b..735d7ad 100644 --- a/remoting/protocol/pepper_session.cc +++ b/remoting/protocol/pepper_session.cc @@ -10,6 +10,7 @@ #include "base/string_number_conversions.h" #include "remoting/base/constants.h" #include "remoting/jingle_glue/iq_sender.h" +#include "remoting/protocol/authenticator.h" #include "remoting/protocol/content_description.h" #include "remoting/protocol/jingle_messages.h" #include "remoting/protocol/pepper_session_manager.h" @@ -56,15 +57,15 @@ Session::Error PepperSession::error() { void PepperSession::StartConnection( const std::string& peer_jid, - const std::string& peer_public_key, - const std::string& client_token, + Authenticator* authenticator, CandidateSessionConfig* config, const StateChangeCallback& state_change_callback) { DCHECK(CalledOnValidThread()); + DCHECK(authenticator); + DCHECK_EQ(authenticator->state(), Authenticator::MESSAGE_READY); peer_jid_ = peer_jid; - peer_public_key_ = peer_public_key; - initiator_token_ = client_token; + authenticator_.reset(authenticator); candidate_config_.reset(config); state_change_callback_ = state_change_callback; @@ -79,7 +80,8 @@ void PepperSession::StartConnection( session_id_); message.from = session_manager_->local_jid_; message.description.reset( - new ContentDescription(candidate_config_->Clone(), initiator_token_, "")); + new ContentDescription(candidate_config_->Clone(), + authenticator_->GetNextMessage())); initiate_request_.reset(session_manager_->iq_sender()->SendIq( message.ToXml(), base::Bind(&PepperSession::OnSessionInitiateResponse, @@ -112,12 +114,14 @@ void PepperSession::CreateStreamChannel( const StreamChannelCallback& callback) { DCHECK(!channels_[name]); - PepperStreamChannel* channel = new PepperStreamChannel(this, name, callback); + ChannelAuthenticator* channel_authenticator = + authenticator_->CreateChannelAuthenticator(); + PepperStreamChannel* channel = new PepperStreamChannel( + this, name, callback); channels_[name] = channel; channel->Connect(session_manager_->pp_instance_, session_manager_->transport_config_, - new V1ClientChannelAuthenticator( - remote_cert_, shared_secret_)); + channel_authenticator); } void PepperSession::CreateDatagramChannel( @@ -156,37 +160,6 @@ void PepperSession::set_config(const SessionConfig& config) { NOTREACHED(); } -const std::string& PepperSession::initiator_token() { - DCHECK(CalledOnValidThread()); - return initiator_token_; -} - -void PepperSession::set_initiator_token(const std::string& initiator_token) { - DCHECK(CalledOnValidThread()); - initiator_token_ = initiator_token; -} - -const std::string& PepperSession::receiver_token() { - DCHECK(CalledOnValidThread()); - return receiver_token_; -} - -void PepperSession::set_receiver_token(const std::string& receiver_token) { - DCHECK(CalledOnValidThread()); - // set_receiver_token() should not be called on the client side. - NOTREACHED(); -} - -void PepperSession::set_shared_secret(const std::string& secret) { - DCHECK(CalledOnValidThread()); - shared_secret_ = secret; -} - -const std::string& PepperSession::shared_secret() { - DCHECK(CalledOnValidThread()); - return shared_secret_; -} - void PepperSession::Close() { DCHECK(CalledOnValidThread()); @@ -237,6 +210,26 @@ void PepperSession::OnAccept(const JingleMessage& message, return; } + const buzz::XmlElement* auth_message = + message.description->authenticator_message(); + if (!auth_message) { + DLOG(WARNING) << "Received session-accept without authentication message " + << auth_message->Str(); + OnError(INCOMPATIBLE_PROTOCOL); + return; + } + + DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE); + authenticator_->ProcessMessage(auth_message); + // Support for more than two auth message is not implemented yet. + DCHECK(authenticator_->state() != Authenticator::WAITING_MESSAGE && + authenticator_->state() != Authenticator::MESSAGE_READY); + + if (authenticator_->state() == Authenticator::REJECTED) { + OnError(AUTHENTICATION_FAILED); + return; + } + if (!InitializeConfigFromDescription(message.description.get())) { OnError(INCOMPATIBLE_PROTOCOL); return; @@ -297,12 +290,6 @@ bool PepperSession::InitializeConfigFromDescription( const ContentDescription* description) { DCHECK(description); - remote_cert_ = description->certificate(); - if (remote_cert_.empty()) { - LOG(ERROR) << "session-accept does not specify certificate"; - return false; - } - if (!description->config()->GetFinalConfig(&config_)) { LOG(ERROR) << "session-accept does not specify configuration"; return false; diff --git a/remoting/protocol/pepper_session.h b/remoting/protocol/pepper_session.h index 7e06687..e13b875 100644 --- a/remoting/protocol/pepper_session.h +++ b/remoting/protocol/pepper_session.h @@ -28,6 +28,7 @@ class IqRequest; namespace protocol { +class Authenticator; class PepperChannel; class PepperSessionManager; @@ -53,12 +54,6 @@ class PepperSession : public Session { virtual const CandidateSessionConfig* candidate_config() OVERRIDE; virtual const SessionConfig& config() OVERRIDE; virtual void set_config(const SessionConfig& config) OVERRIDE; - virtual const std::string& initiator_token() OVERRIDE; - virtual void set_initiator_token(const std::string& initiator_token) OVERRIDE; - virtual const std::string& receiver_token() OVERRIDE; - virtual void set_receiver_token(const std::string& receiver_token) OVERRIDE; - virtual void set_shared_secret(const std::string& secret) OVERRIDE; - virtual const std::string& shared_secret() OVERRIDE; virtual void Close() OVERRIDE; private: @@ -71,8 +66,7 @@ class PepperSession : public Session { // Start cs connection by sending session-initiate message. void StartConnection(const std::string& peer_jid, - const std::string& peer_public_key, - const std::string& client_token, + Authenticator* authenticator, CandidateSessionConfig* config, const StateChangeCallback& state_change_callback); @@ -110,7 +104,6 @@ class PepperSession : public Session { PepperSessionManager* session_manager_; std::string peer_jid_; - std::string peer_public_key_; scoped_ptr<CandidateSessionConfig> candidate_config_; StateChangeCallback state_change_callback_; @@ -118,12 +111,9 @@ class PepperSession : public Session { State state_; Error error_; - std::string remote_cert_; SessionConfig config_; - std::string shared_secret_; - std::string initiator_token_; - std::string receiver_token_; + scoped_ptr<Authenticator> authenticator_; scoped_ptr<IqRequest> initiate_request_; scoped_ptr<IqRequest> transport_info_request_; diff --git a/remoting/protocol/pepper_session_manager.cc b/remoting/protocol/pepper_session_manager.cc index ea095c3..2e558a7 100644 --- a/remoting/protocol/pepper_session_manager.cc +++ b/remoting/protocol/pepper_session_manager.cc @@ -8,6 +8,7 @@ #include "remoting/jingle_glue/iq_sender.h" #include "remoting/jingle_glue/jingle_info_request.h" #include "remoting/jingle_glue/signal_strategy.h" +#include "remoting/protocol/authenticator.h" #include "remoting/protocol/jingle_messages.h" #include "remoting/protocol/pepper_session.h" #include "third_party/libjingle/source/talk/base/socketaddress.h" @@ -33,15 +34,11 @@ void PepperSessionManager::Init( const std::string& local_jid, SignalStrategy* signal_strategy, SessionManager::Listener* listener, - crypto::RSAPrivateKey* private_key, - const std::string& certificate, bool allow_nat_traversal) { listener_ = listener; local_jid_ = local_jid; signal_strategy_ = signal_strategy; iq_sender_.reset(new IqSender(signal_strategy_)); - private_key_.reset(private_key); - certificate_ = certificate; allow_nat_traversal_ = allow_nat_traversal; signal_strategy_->AddListener(this); @@ -76,13 +73,12 @@ void PepperSessionManager::OnJingleInfo( Session* PepperSessionManager::Connect( const std::string& host_jid, - const std::string& host_public_key, - const std::string& client_token, + Authenticator* authenticator, CandidateSessionConfig* config, const Session::StateChangeCallback& state_change_callback) { PepperSession* session = new PepperSession(this); - session->StartConnection(host_jid, host_public_key, client_token, - config, state_change_callback); + session->StartConnection(host_jid, authenticator, config, + state_change_callback); sessions_[session->session_id_] = session; return session; } @@ -99,6 +95,12 @@ void PepperSessionManager::Close() { signal_strategy_->RemoveListener(this); } +void PepperSessionManager::set_authenticator_factory( + AuthenticatorFactory* authenticator_factory) { + DCHECK(CalledOnValidThread()); + authenticator_factory_.reset(authenticator_factory); +} + bool PepperSessionManager::OnIncomingStanza(const buzz::XmlElement* stanza) { if (!JingleMessage::IsJingleMessage(stanza)) return false; diff --git a/remoting/protocol/pepper_session_manager.h b/remoting/protocol/pepper_session_manager.h index 41c06f6..3ae1823 100644 --- a/remoting/protocol/pepper_session_manager.h +++ b/remoting/protocol/pepper_session_manager.h @@ -51,16 +51,15 @@ class PepperSessionManager : public SessionManager, virtual void Init(const std::string& local_jid, SignalStrategy* signal_strategy, SessionManager::Listener* listener, - crypto::RSAPrivateKey* private_key, - const std::string& certificate, bool allow_nat_traversal) OVERRIDE; virtual Session* Connect( const std::string& host_jid, - const std::string& host_public_key, - const std::string& client_token, + Authenticator* authenticator, CandidateSessionConfig* config, const Session::StateChangeCallback& state_change_callback) OVERRIDE; virtual void Close() OVERRIDE; + virtual void set_authenticator_factory( + AuthenticatorFactory* authenticator_factory) OVERRIDE; // SignalStrategy::Listener interface. virtual bool OnIncomingStanza(const buzz::XmlElement* stanza) OVERRIDE; @@ -86,10 +85,9 @@ class PepperSessionManager : public SessionManager, std::string local_jid_; SignalStrategy* signal_strategy_; + scoped_ptr<AuthenticatorFactory> authenticator_factory_; scoped_ptr<IqSender> iq_sender_; SessionManager::Listener* listener_; - scoped_ptr<crypto::RSAPrivateKey> private_key_; - std::string certificate_; bool allow_nat_traversal_; TransportConfig transport_config_; diff --git a/remoting/protocol/session.h b/remoting/protocol/session.h index de85666..4640fad 100644 --- a/remoting/protocol/session.h +++ b/remoting/protocol/session.h @@ -110,16 +110,6 @@ class Session : public base::NonThreadSafe { // ChromotocolServer::IncomingConnectionCallback. virtual void set_config(const SessionConfig& config) = 0; - // The raw auth tokens from the session-initiate, or session-accept stanzas. - virtual const std::string& initiator_token() = 0; - virtual void set_initiator_token(const std::string& initiator_token) = 0; - virtual const std::string& receiver_token() = 0; - virtual void set_receiver_token(const std::string& receiver_token) = 0; - - // A shared secret to use to mutually-authenticate the SSL channels. - virtual void set_shared_secret(const std::string& secret) = 0; - virtual const std::string& shared_secret() = 0; - // Closes connection. Callbacks are guaranteed not to be called // after this method returns. Must be called before the object is // destroyed, unless the state is set to FAILED or CLOSED. diff --git a/remoting/protocol/session_manager.h b/remoting/protocol/session_manager.h index f36abd2..7a02c3d 100644 --- a/remoting/protocol/session_manager.h +++ b/remoting/protocol/session_manager.h @@ -52,16 +52,15 @@ #include "base/threading/non_thread_safe.h" #include "remoting/protocol/session.h" -namespace crypto { -class RSAPrivateKey; -} // namespace base - namespace remoting { class SignalStrategy; namespace protocol { +class Authenticator; +class AuthenticatorFactory; + // Generic interface for Chromoting session manager. // // TODO(sergeyu): Split this into two separate interfaces: one for the @@ -113,8 +112,6 @@ class SessionManager : public base::NonThreadSafe { virtual void Init(const std::string& local_jid, SignalStrategy* signal_strategy, Listener* listener, - crypto::RSAPrivateKey* private_key, - const std::string& certificate, bool allow_nat_traversal) = 0; // Tries to create a session to the host |jid|. Must be called only @@ -123,15 +120,14 @@ class SessionManager : public base::NonThreadSafe { // // |host_jid| is the full jid of the host to connect to. // |host_public_key| is used to for authentication. - // |client_oauth_token| is a short-lived OAuth token identify the client. + // |authenticator| is a client authenticator for the session. // |config| contains the session configurations that the client supports. // |state_change_callback| is called when the connection state changes. // // Ownership of the |config| is passed to the new session. virtual Session* Connect( const std::string& host_jid, - const std::string& host_public_key, - const std::string& client_token, + Authenticator* authenticator, CandidateSessionConfig* config, const Session::StateChangeCallback& state_change_callback) = 0; @@ -140,6 +136,12 @@ class SessionManager : public base::NonThreadSafe { // returns. virtual void Close() = 0; + // Set authenticator factory that should be used to authenticate + // incoming connection. No connections will be accepted if + // authenticator factory isn't set. + virtual void set_authenticator_factory( + AuthenticatorFactory* authenticator_factory) = 0; + private: DISALLOW_COPY_AND_ASSIGN(SessionManager); }; |