summaryrefslogtreecommitdiffstats
path: root/remoting/protocol
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-13 06:28:49 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-12-13 06:28:49 +0000
commitbc407e962efd421576e6dad7cefde22ef0439f38 (patch)
tree267bea43b45377b65f4128a73c1488f8165b8de7 /remoting/protocol
parent76e68448d44901e32e2166cb53677f132b7f2bd6 (diff)
downloadchromium_src-bc407e962efd421576e6dad7cefde22ef0439f38.zip
chromium_src-bc407e962efd421576e6dad7cefde22ef0439f38.tar.gz
chromium_src-bc407e962efd421576e6dad7cefde22ef0439f38.tar.bz2
Multi-step authentication support in JingleSession.
BUG=105214 Review URL: http://codereview.chromium.org/8774031 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114187 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/protocol')
-rw-r--r--remoting/protocol/authenticator.cc35
-rw-r--r--remoting/protocol/authenticator.h11
-rw-r--r--remoting/protocol/content_description.cc8
-rw-r--r--remoting/protocol/jingle_session.cc59
-rw-r--r--remoting/protocol/jingle_session.h11
-rw-r--r--remoting/protocol/jingle_session_unittest.cc41
-rw-r--r--remoting/protocol/v1_authenticator.cc14
7 files changed, 141 insertions, 38 deletions
diff --git a/remoting/protocol/authenticator.cc b/remoting/protocol/authenticator.cc
new file mode 100644
index 0000000..23f77e1
--- /dev/null
+++ b/remoting/protocol/authenticator.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/protocol/authenticator.h"
+
+#include "remoting/base/constants.h"
+#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
+
+namespace remoting {
+namespace protocol {
+
+namespace {
+const buzz::StaticQName kAuthenticationQName = { kChromotingXmlNamespace,
+ "authentication" };
+} // namespace
+
+// static
+bool Authenticator::IsAuthenticatorMessage(const buzz::XmlElement* message) {
+ return message->Name() == kAuthenticationQName;
+}
+
+// static
+buzz::XmlElement* Authenticator::CreateEmptyAuthenticatorMessage() {
+ return new buzz::XmlElement(kAuthenticationQName);
+}
+
+// static
+const buzz::XmlElement* Authenticator::FindAuthenticatorMessage(
+ const buzz::XmlElement* message) {
+ return message->FirstNamed(kAuthenticationQName);
+}
+
+} // namespace protocol
+} // namespace remoting
diff --git a/remoting/protocol/authenticator.h b/remoting/protocol/authenticator.h
index 0f382ed..b79fe78 100644
--- a/remoting/protocol/authenticator.h
+++ b/remoting/protocol/authenticator.h
@@ -53,6 +53,17 @@ class Authenticator {
REJECTED,
};
+ // Returns true if |message| is an Authenticator message.
+ static bool IsAuthenticatorMessage(const buzz::XmlElement* message);
+
+ // Creates an empty Authenticator message, owned by the caller.
+ static buzz::XmlElement* CreateEmptyAuthenticatorMessage();
+
+ // Finds Authenticator message among child elements of |message|, or
+ // returns NULL otherwise.
+ static const buzz::XmlElement* FindAuthenticatorMessage(
+ const buzz::XmlElement* message);
+
Authenticator() {}
virtual ~Authenticator() {}
diff --git a/remoting/protocol/content_description.cc b/remoting/protocol/content_description.cc
index d6947d7..86aefb4 100644
--- a/remoting/protocol/content_description.cc
+++ b/remoting/protocol/content_description.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "remoting/base/constants.h"
+#include "remoting/protocol/authenticator.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
using buzz::QName;
@@ -27,7 +28,6 @@ const char kControlTag[] = "control";
const char kEventTag[] = "event";
const char kVideoTag[] = "video";
const char kResolutionTag[] = "initial-resolution";
-const char kAuthenticationTag[] = "authentication";
const char kTransportAttr[] = "transport";
const char kVersionAttr[] = "version";
@@ -198,8 +198,7 @@ XmlElement* ContentDescription::ToXml() const {
root->AddElement(resolution_tag);
if (authenticator_message_.get()) {
- DCHECK(authenticator_message_->Name() ==
- QName(kChromotingXmlNamespace, kAuthenticationTag));
+ DCHECK(Authenticator::IsAuthenticatorMessage(authenticator_message_.get()));
root->AddElement(new XmlElement(*authenticator_message_));
}
@@ -266,8 +265,7 @@ ContentDescription* ContentDescription::ParseXml(
*config->mutable_initial_resolution() = resolution;
scoped_ptr<XmlElement> authenticator_message;
- child = element->FirstNamed(QName(kChromotingXmlNamespace,
- kAuthenticationTag));
+ child = Authenticator::FindAuthenticatorMessage(element);
if (child)
authenticator_message.reset(new XmlElement(*child));
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
index 0d6dc4f..8abada2 100644
--- a/remoting/protocol/jingle_session.cc
+++ b/remoting/protocol/jingle_session.cc
@@ -45,6 +45,8 @@ JingleSession::JingleSession(
jid_ = cricket_session_->remote_name();
cricket_session_->SignalState.connect(this, &JingleSession::OnSessionState);
cricket_session_->SignalError.connect(this, &JingleSession::OnSessionError);
+ cricket_session_->SignalInfoMessage.connect(
+ this, &JingleSession::OnSessionInfoMessage);
cricket_session_->SignalReceivedTerminateReason.connect(
this, &JingleSession::OnTerminateReason);
}
@@ -246,6 +248,25 @@ void JingleSession::OnSessionError(
}
}
+void JingleSession::OnSessionInfoMessage(cricket::Session* session,
+ const buzz::XmlElement* message) {
+ DCHECK_EQ(cricket_session_,session);
+
+ const buzz::XmlElement* auth_message =
+ Authenticator::FindAuthenticatorMessage(message);
+ if (auth_message) {
+ if (state_ != CONNECTED ||
+ authenticator_->state() != Authenticator::WAITING_MESSAGE) {
+ LOG(WARNING) << "Received unexpected authenticator message "
+ << auth_message->Str();
+ return;
+ }
+
+ authenticator_->ProcessMessage(auth_message);
+ ProcessAuthenticationStep();
+ }
+}
+
void JingleSession::OnTerminateReason(cricket::Session* session,
const std::string& reason) {
terminate_reason_ = reason;
@@ -294,16 +315,10 @@ bool JingleSession::InitializeConfigFromDescription(
return false;
}
- DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
+ DCHECK_EQ(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;
- }
+ // Initialize session configuration.
SessionConfig config;
if (!content_description->config()->GetFinalConfig(&config)) {
LOG(ERROR) << "Connection response does not specify configuration";
@@ -333,8 +348,12 @@ void JingleSession::OnAccept() {
SetState(CONNECTED);
- if (authenticator_->state() == Authenticator::ACCEPTED)
+ // Process authentication.
+ if (authenticator_->state() == Authenticator::ACCEPTED) {
SetState(AUTHENTICATED);
+ } else {
+ ProcessAuthenticationStep();
+ }
}
void JingleSession::OnTerminate() {
@@ -398,8 +417,6 @@ void JingleSession::AcceptConnection() {
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;
@@ -412,11 +429,29 @@ void JingleSession::AcceptConnection() {
buzz::XmlElement* auth_reply = NULL;
if (authenticator_->state() == Authenticator::MESSAGE_READY)
auth_reply = authenticator_->GetNextMessage();
- DCHECK_EQ(authenticator_->state(), Authenticator::ACCEPTED);
+ DCHECK_NE(authenticator_->state(), Authenticator::MESSAGE_READY);
cricket_session_->Accept(
CreateSessionDescription(candidate_config, auth_reply));
}
+void JingleSession::ProcessAuthenticationStep() {
+ DCHECK_EQ(state_, CONNECTED);
+
+ if (authenticator_->state() == Authenticator::MESSAGE_READY) {
+ buzz::XmlElement* auth_message = authenticator_->GetNextMessage();
+ cricket::XmlElements message;
+ message.push_back(auth_message);
+ cricket_session_->SendInfoMessage(message);
+ }
+ DCHECK_NE(authenticator_->state(), Authenticator::MESSAGE_READY);
+
+ if (authenticator_->state() == Authenticator::ACCEPTED) {
+ SetState(AUTHENTICATED);
+ } else if (authenticator_->state() == Authenticator::REJECTED) {
+ CloseInternal(net::ERR_CONNECTION_ABORTED, AUTHENTICATION_FAILED);
+ }
+}
+
void JingleSession::AddChannelConnector(
const std::string& name, JingleChannelConnector* connector) {
DCHECK(channel_connectors_.find(name) == channel_connectors_.end());
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h
index 4894216..1c8b2cb 100644
--- a/remoting/protocol/jingle_session.h
+++ b/remoting/protocol/jingle_session.h
@@ -74,14 +74,15 @@ class JingleSession : public protocol::Session,
bool InitializeConfigFromDescription(
const cricket::SessionDescription* description);
- // Used for Session.SignalState sigslot.
+ // Handlers for |cricket_session_| signals.
void OnSessionState(cricket::BaseSession* session,
cricket::BaseSession::State state);
- // Used for Session.SignalError sigslot.
void OnSessionError(cricket::BaseSession* session,
cricket::BaseSession::Error error);
- // Used for Session.SignalReceivedTerminateReason sigslot.
- void OnTerminateReason(cricket::Session* session, const std::string& reason);
+ void OnSessionInfoMessage(cricket::Session* session,
+ const buzz::XmlElement* message);
+ void OnTerminateReason(cricket::Session* session,
+ const std::string& reason);
void OnInitiate();
void OnAccept();
@@ -91,6 +92,8 @@ class JingleSession : public protocol::Session,
// accepts/rejects connection.
void AcceptConnection();
+ void ProcessAuthenticationStep();
+
void AddChannelConnector(const std::string& name,
JingleChannelConnector* connector);
diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc
index 8ca7dcf..6c1fdfb 100644
--- a/remoting/protocol/jingle_session_unittest.cc
+++ b/remoting/protocol/jingle_session_unittest.cc
@@ -171,15 +171,15 @@ class JingleSessionTest : public testing::Test {
{
InSequence dummy;
+ EXPECT_CALL(host_connection_callback_,
+ OnStateChange(Session::CONNECTED))
+ .Times(AtMost(1));
if (expect_fail) {
EXPECT_CALL(host_connection_callback_,
OnStateChange(Session::FAILED))
.Times(1);
} else {
EXPECT_CALL(host_connection_callback_,
- OnStateChange(Session::CONNECTED))
- .Times(1);
- EXPECT_CALL(host_connection_callback_,
OnStateChange(Session::AUTHENTICATED))
.Times(1);
}
@@ -191,15 +191,15 @@ class JingleSessionTest : public testing::Test {
EXPECT_CALL(client_connection_callback_,
OnStateChange(Session::CONNECTING))
.Times(1);
+ EXPECT_CALL(client_connection_callback_,
+ OnStateChange(Session::CONNECTED))
+ .Times(AtMost(1));
if (expect_fail) {
EXPECT_CALL(client_connection_callback_,
OnStateChange(Session::FAILED))
.Times(1);
} else {
EXPECT_CALL(client_connection_callback_,
- OnStateChange(Session::CONNECTED))
- .Times(1);
- EXPECT_CALL(client_connection_callback_,
OnStateChange(Session::AUTHENTICATED))
.Times(1);
}
@@ -326,12 +326,24 @@ TEST_F(JingleSessionTest, Connect) {
InitiateConnection(1, FakeAuthenticator::ACCEPT, false);
}
-// Verify that we can't connect two endpoints with mismatched secrets.
+// Verify that we can connect two endpoints with multi-step authentication.
+TEST_F(JingleSessionTest, ConnectMultistep) {
+ CreateServerPair(3, FakeAuthenticator::ACCEPT);
+ InitiateConnection(3, FakeAuthenticator::ACCEPT, false);
+}
+
+// Verify that connection is terminated when auth fails.
TEST_F(JingleSessionTest, ConnectBadAuth) {
CreateServerPair(1, FakeAuthenticator::REJECT);
InitiateConnection(1, FakeAuthenticator::ACCEPT, true);
}
+// Verify that connection is terminted when multi-step auth fails.
+TEST_F(JingleSessionTest, ConnectBadMultistepAuth) {
+ CreateServerPair(3, FakeAuthenticator::REJECT);
+ InitiateConnection(3, FakeAuthenticator::ACCEPT, true);
+}
+
TEST_F(JingleSessionTest, ConnectBadChannelAuth) {
CreateServerPair(1, FakeAuthenticator::REJECT_CHANNEL);
ASSERT_NO_FATAL_FAILURE(
@@ -374,6 +386,21 @@ TEST_F(JingleSessionTest, TestTcpChannel) {
tester.CheckResults();
}
+// Verify that we can connect channels with multistep auth.
+TEST_F(JingleSessionTest, TestMultistepAuthTcpChannel) {
+ CreateServerPair(3, FakeAuthenticator::ACCEPT);
+ ASSERT_NO_FATAL_FAILURE(
+ InitiateConnection(3, FakeAuthenticator::ACCEPT, false));
+
+ ASSERT_NO_FATAL_FAILURE(CreateChannel());
+
+ StreamConnectionTester tester(host_socket_.get(), client_socket_.get(),
+ kMessageSize, kMessages);
+ tester.Start();
+ message_loop_.Run();
+ tester.CheckResults();
+}
+
// Verify that data can be transmitted over the video RTP channel.
TEST_F(JingleSessionTest, TestUdpChannel) {
CreateServerPair(1, FakeAuthenticator::ACCEPT);
diff --git a/remoting/protocol/v1_authenticator.cc b/remoting/protocol/v1_authenticator.cc
index 26eb3c7..afeb2d6 100644
--- a/remoting/protocol/v1_authenticator.cc
+++ b/remoting/protocol/v1_authenticator.cc
@@ -20,7 +20,6 @@ namespace remoting {
namespace protocol {
namespace {
-const char kAuthenticationTag[] = "authentication";
const char kAuthTokenTag[] = "auth-token";
const char kCertificateTag[] = "certificate";
} // namespace
@@ -64,19 +63,16 @@ void V1ClientAuthenticator::ProcessMessage(const XmlElement* message) {
XmlElement* V1ClientAuthenticator::GetNextMessage() {
DCHECK_EQ(state_, MESSAGE_READY);
- XmlElement* authentication_tag = new XmlElement(
- QName(kChromotingXmlNamespace, kAuthenticationTag));
-
+ XmlElement* message = CreateEmptyAuthenticatorMessage();
std::string token =
protocol::GenerateSupportAuthToken(local_jid_, shared_secret_);
-
XmlElement* auth_token_tag = new XmlElement(
QName(kChromotingXmlNamespace, kAuthTokenTag));
auth_token_tag->SetBodyText(token);
- authentication_tag->AddElement(auth_token_tag);
+ message->AddElement(auth_token_tag);
state_ = WAITING_MESSAGE;
- return authentication_tag;
+ return message;
}
ChannelAuthenticator*
@@ -121,9 +117,7 @@ void V1HostAuthenticator::ProcessMessage(const XmlElement* message) {
XmlElement* V1HostAuthenticator::GetNextMessage() {
DCHECK_EQ(state_, MESSAGE_READY);
- XmlElement* message = new XmlElement(
- QName(kChromotingXmlNamespace, kAuthenticationTag));
-
+ XmlElement* message = CreateEmptyAuthenticatorMessage();
buzz::XmlElement* certificate_tag = new XmlElement(
buzz::QName(kChromotingXmlNamespace, kCertificateTag));
std::string base64_cert;