Skip to content

Commit

Permalink
Add implementation for current IT2Me auth.
Browse files Browse the repository at this point in the history
The new SimpleClientAuthenticator and SimpleHostAuthenticator implement
the current IT2Me authentication mechanism.


Review URL: http://codereview.chromium.org/8647001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111321 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
sergeyu@chromium.org committed Nov 23, 2011
1 parent 34a43db commit 4aa41f2
Show file tree
Hide file tree
Showing 5 changed files with 399 additions and 5 deletions.
17 changes: 12 additions & 5 deletions remoting/protocol/authenticator.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class XmlElement;
namespace remoting {
namespace protocol {

class ChannelAuthenticator;

// Authenticator is an abstract interface for authentication protocol
// implementations. Different implementations of this interface may be
// used on each side of the connection depending of type of the auth
Expand All @@ -37,7 +39,6 @@ class Authenticator {
// When GetNextMessage() is called:
// MESSAGE_READY -> WAITING_MESSAGE
// MESSAGE_READY -> ACCEPTED
// MESSAGE_READY -> REJECTED
enum State {
// Waiting for the next message from the peer.
WAITING_MESSAGE,
Expand All @@ -59,12 +60,13 @@ class Authenticator {
virtual State state() const = 0;

// Called in response to incoming message received from the peer.
// Should only be called when in WAITING_MESSAGE state.
virtual void ProcessMessage(talk_base::XmlElement* message) = 0;
// Should only be called when in WAITING_MESSAGE state. Caller
// retains ownership of |message|.
virtual void ProcessMessage(const buzz::XmlElement* message) = 0;

// Must be called when in MESSAGE_READY state. Returns next
// authentication message that needs to be sent to the peer.
virtual talk_base::XmlElement* GetNextMessage() = 0;
virtual buzz::XmlElement* GetNextMessage() = 0;

// Creates new authenticator for a channel. Caller must take
// ownership of the result. Can be called only in the ACCEPTED
Expand All @@ -74,6 +76,10 @@ class Authenticator {

// Factory for Authenticator instances.
class AuthenticatorFactory {
public:
AuthenticatorFactory() {}
virtual ~AuthenticatorFactory() {}

// Called when session-initiate stanza is received to create
// authenticator for the new session. |first_message| specifies
// authentication part of the session-initiate stanza so that
Expand All @@ -83,7 +89,8 @@ class AuthenticatorFactory {
// rejected. ProcessMessage() should be called with |first_message|
// for the result of this method.
virtual Authenticator* CreateAuthenticator(
const talk_base::XmlElement* first_message) = 0;
const std::string& remote_jid,
const buzz::XmlElement* first_message) = 0;
};

} // namespace protocol
Expand Down
174 changes: 174 additions & 0 deletions remoting/protocol/v1_authenticator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// 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/v1_authenticator.h"

#include "base/base64.h"
#include "base/logging.h"
#include "crypto/rsa_private_key.h"
#include "remoting/base/constants.h"
#include "remoting/protocol/auth_util.h"
#include "remoting/protocol/v1_client_channel_authenticator.h"
#include "remoting/protocol/v1_host_channel_authenticator.h"
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"

using buzz::QName;
using buzz::XmlElement;

namespace remoting {
namespace protocol {

namespace {
const char kAuthenticationTag[] = "authentication";
const char kAuthTokenTag[] = "auth-token";
const char kCertificateTag[] = "certificate";
} // namespace

V1ClientAuthenticator::V1ClientAuthenticator(
const std::string& local_jid,
const std::string& shared_secret)
: local_jid_(local_jid),
shared_secret_(shared_secret),
state_(MESSAGE_READY) {
}

V1ClientAuthenticator::~V1ClientAuthenticator() {
}

Authenticator::State V1ClientAuthenticator::state() const {
return state_;
}

void V1ClientAuthenticator::ProcessMessage(const XmlElement* message) {
DCHECK_EQ(state_, WAITING_MESSAGE);

// Parse the certificate.
const XmlElement* cert_tag =
message->FirstNamed(QName(kChromotingXmlNamespace, kCertificateTag));
if (cert_tag) {
std::string base64_cert = cert_tag->BodyText();
if (!base::Base64Decode(base64_cert, &remote_cert_)) {
LOG(ERROR) << "Failed to decode certificate received from the peer.";
remote_cert_.clear();
}
}

if (remote_cert_.empty()) {
state_ = REJECTED;
} else {
state_ = ACCEPTED;
}
}

XmlElement* V1ClientAuthenticator::GetNextMessage() {
DCHECK_EQ(state_, MESSAGE_READY);

XmlElement* authentication_tag = new XmlElement(
QName(kChromotingXmlNamespace, kAuthenticationTag));

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);

state_ = WAITING_MESSAGE;
return authentication_tag;
}

ChannelAuthenticator*
V1ClientAuthenticator::CreateChannelAuthenticator() const {
DCHECK_EQ(state_, ACCEPTED);
return new V1ClientChannelAuthenticator(remote_cert_, shared_secret_);
};

V1HostAuthenticator::V1HostAuthenticator(
const std::string& local_cert,
crypto::RSAPrivateKey* local_private_key,
const std::string& shared_secret,
const std::string& remote_jid)
: local_cert_(local_cert),
local_private_key_(local_private_key),
shared_secret_(shared_secret),
remote_jid_(remote_jid),
state_(WAITING_MESSAGE) {
}

V1HostAuthenticator::~V1HostAuthenticator() {
}

Authenticator::State V1HostAuthenticator::state() const {
return state_;
}

void V1HostAuthenticator::ProcessMessage(const XmlElement* message) {
DCHECK_EQ(state_, WAITING_MESSAGE);

std::string auth_token =
message->TextNamed(buzz::QName(kChromotingXmlNamespace, kAuthTokenTag));

if (!protocol::VerifySupportAuthToken(
remote_jid_, shared_secret_, auth_token)) {
state_ = REJECTED;
} else {
state_ = MESSAGE_READY;
}
}

XmlElement* V1HostAuthenticator::GetNextMessage() {
DCHECK_EQ(state_, MESSAGE_READY);

XmlElement* message = new XmlElement(
QName(kChromotingXmlNamespace, kAuthenticationTag));

buzz::XmlElement* certificate_tag = new XmlElement(
buzz::QName(kChromotingXmlNamespace, kCertificateTag));
std::string base64_cert;
if (!base::Base64Encode(local_cert_, &base64_cert)) {
LOG(DFATAL) << "Cannot perform base64 encode on certificate";
}
certificate_tag->SetBodyText(base64_cert);
message->AddElement(certificate_tag);

state_ = ACCEPTED;
return message;
}

ChannelAuthenticator*
V1HostAuthenticator::CreateChannelAuthenticator() const {
DCHECK_EQ(state_, ACCEPTED);
return new V1HostChannelAuthenticator(
local_cert_, local_private_key_, shared_secret_);
};

V1HostAuthenticatorFactory::V1HostAuthenticatorFactory(
const std::string& local_cert,
crypto::RSAPrivateKey* local_private_key,
const std::string& shared_secret)
: local_cert_(local_cert),
shared_secret_(shared_secret) {
DCHECK(local_private_key);

// TODO(hclam): Need a better way to clone a key. See crbug.com/105220 .
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());
}

V1HostAuthenticatorFactory::~V1HostAuthenticatorFactory() {
}

Authenticator* V1HostAuthenticatorFactory::CreateAuthenticator(
const std::string& remote_jid,
const buzz::XmlElement* first_message) {
return new V1HostAuthenticator(local_cert_, local_private_key_.get(),
shared_secret_, remote_jid);
}

} // namespace remoting
} // namespace protocol
89 changes: 89 additions & 0 deletions remoting/protocol/v1_authenticator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// 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.

#ifndef REMOTING_PROTOCOL_V1_AUTHENTICATOR_H_
#define REMOTING_PROTOCOL_V1_AUTHENTICATOR_H_

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "remoting/protocol/authenticator.h"

namespace crypto {
class RSAPrivateKey;
} // namespace base

namespace remoting {
namespace protocol {

class V1ClientAuthenticator : public Authenticator {
public:
explicit V1ClientAuthenticator(const std::string& local_jid,
const std::string& shared_secret);
virtual ~V1ClientAuthenticator();

// Authenticator interface.
virtual State state() const OVERRIDE;
virtual void ProcessMessage(const buzz::XmlElement* message) OVERRIDE;
virtual buzz::XmlElement* GetNextMessage() OVERRIDE;
virtual ChannelAuthenticator* CreateChannelAuthenticator() const OVERRIDE;

private:
std::string local_jid_;
std::string shared_secret_;
std::string remote_cert_;
State state_;

DISALLOW_COPY_AND_ASSIGN(V1ClientAuthenticator);
};

class V1HostAuthenticator : public Authenticator {
public:
explicit V1HostAuthenticator(const std::string& local_cert,
crypto::RSAPrivateKey* local_private_key,
const std::string& shared_secret,
const std::string& remote_jid);
virtual ~V1HostAuthenticator();

// Authenticator interface.
virtual State state() const OVERRIDE;
virtual void ProcessMessage(const buzz::XmlElement* message) OVERRIDE;
virtual buzz::XmlElement* GetNextMessage() OVERRIDE;
virtual ChannelAuthenticator* CreateChannelAuthenticator() const OVERRIDE;

private:
std::string local_cert_;
crypto::RSAPrivateKey* local_private_key_;
std::string shared_secret_;
std::string remote_jid_;
State state_;

DISALLOW_COPY_AND_ASSIGN(V1HostAuthenticator);
};

class V1HostAuthenticatorFactory : public AuthenticatorFactory {
public:
// Doesn't take ownership of |local_private_key|.
V1HostAuthenticatorFactory(const std::string& local_cert,
crypto::RSAPrivateKey* local_private_key,
const std::string& shared_secret);
virtual ~V1HostAuthenticatorFactory();

// AuthenticatorFactory interface.
virtual Authenticator* CreateAuthenticator(
const std::string& remote_jid,
const buzz::XmlElement* first_message) OVERRIDE;

private:
std::string local_cert_;
scoped_ptr<crypto::RSAPrivateKey> local_private_key_;
std::string shared_secret_;

DISALLOW_COPY_AND_ASSIGN(V1HostAuthenticatorFactory);
};

} // namespace protocol
} // namespace remoting

#endif // REMOTING_PROTOCOL_V1_AUTHENTICATOR_H_
Loading

0 comments on commit 4aa41f2

Please sign in to comment.