| Index: remoting/protocol/v1_authenticator.cc
|
| diff --git a/remoting/protocol/v1_authenticator.cc b/remoting/protocol/v1_authenticator.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2daf246f26705b523319a42d58a1cf96e2c7cc4a
|
| --- /dev/null
|
| +++ b/remoting/protocol/v1_authenticator.cc
|
| @@ -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
|
|
|