| Index: remoting/protocol/pairing_host_authenticator.cc
|
| diff --git a/remoting/protocol/pairing_host_authenticator.cc b/remoting/protocol/pairing_host_authenticator.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f33ba8b23d796a5757821616694d7fc6bb38bf17
|
| --- /dev/null
|
| +++ b/remoting/protocol/pairing_host_authenticator.cc
|
| @@ -0,0 +1,136 @@
|
| +// Copyright 2013 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/pairing_host_authenticator.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "remoting/base/constants.h"
|
| +#include "remoting/base/rsa_key_pair.h"
|
| +#include "remoting/protocol/channel_authenticator.h"
|
| +#include "remoting/protocol/pairing_registry.h"
|
| +#include "remoting/protocol/v2_authenticator.h"
|
| +#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
|
| +
|
| +namespace remoting {
|
| +namespace protocol {
|
| +
|
| +namespace {
|
| +// These definitions must be kept in sync with pairing_client_authenticator.cc.
|
| +const buzz::StaticQName kPairingInfoTag =
|
| + { kChromotingXmlNamespace, "pairing-info" };
|
| +const buzz::StaticQName kClientIdAttribute =
|
| + { "", "client-id" };
|
| +const buzz::StaticQName kPairingFailedTag =
|
| + { kChromotingXmlNamespace, "pairing-failed" };
|
| +const buzz::StaticQName kPairingErrorAttribute =
|
| + { "", "error" };
|
| +}
|
| +
|
| +PairingHostAuthenticator::PairingHostAuthenticator(
|
| + scoped_refptr<PairingRegistry> pairing_registry,
|
| + const std::string& local_cert,
|
| + scoped_refptr<RsaKeyPair> key_pair,
|
| + const std::string& pin,
|
| + State initial_state)
|
| + : pairing_registry_(pairing_registry),
|
| + local_cert_(local_cert),
|
| + key_pair_(key_pair),
|
| + pin_(pin),
|
| + protocol_error_(false) {
|
| + // If the client didn't specify an initial message, use the PIN as the shared
|
| + // secret. If it did, the authenticator will be created in ProcessMessage with
|
| + // the appropriate paired secret from the pairing registry.
|
| + if (initial_state != WAITING_MESSAGE) {
|
| + DCHECK_EQ(initial_state, MESSAGE_READY);
|
| + CreateV2AuthenticatorWithPIN();
|
| + }
|
| +}
|
| +
|
| +Authenticator::State PairingHostAuthenticator::state() const {
|
| + if (protocol_error_) {
|
| + return REJECTED;
|
| + } else if (v2_authenticator_) {
|
| + return v2_authenticator_->state();
|
| + } else {
|
| + return WAITING_MESSAGE;
|
| + }
|
| +}
|
| +
|
| +Authenticator::RejectionReason
|
| +PairingHostAuthenticator::rejection_reason() const {
|
| + DCHECK(v2_authenticator_);
|
| + return v2_authenticator_->rejection_reason();
|
| +}
|
| +
|
| +void PairingHostAuthenticator::ProcessMessage(
|
| + const buzz::XmlElement* message,
|
| + const base::Closure& resume_callback) {
|
| + DCHECK_EQ(state(), WAITING_MESSAGE);
|
| +
|
| + // If there's already an underlying authenticator, defer to it.
|
| + if (v2_authenticator_) {
|
| + DCHECK_EQ(v2_authenticator_->state(), WAITING_MESSAGE);
|
| + v2_authenticator_->ProcessMessage(message, resume_callback);
|
| + return;
|
| + }
|
| +
|
| + // If not, then create one based on the contents of the first message.
|
| + std::string client_id;
|
| + const buzz::XmlElement* pairing_tag = message->FirstNamed(kPairingInfoTag);
|
| + if (pairing_tag) {
|
| + client_id = pairing_tag->Attr(kClientIdAttribute);
|
| + if (client_id.empty()) {
|
| + LOG(ERROR) << "No client id specified.";
|
| + protocol_error_ = true;
|
| + resume_callback.Run();
|
| + return;
|
| + }
|
| + }
|
| +
|
| + std::string paired_secret = pairing_registry_->GetSecret(client_id);
|
| +
|
| + if (paired_secret.empty()) {
|
| + LOG(INFO) << "Unknown client id";
|
| + error_message_ = "unknown-client-id";
|
| + CreateV2AuthenticatorWithPIN();
|
| + resume_callback.Run();
|
| + return;
|
| + }
|
| +
|
| + v2_authenticator_ = V2Authenticator::CreateForHost(
|
| + local_cert_, key_pair_, paired_secret, MESSAGE_READY);
|
| + resume_callback.Run();
|
| +}
|
| +
|
| +scoped_ptr<buzz::XmlElement> PairingHostAuthenticator::GetNextMessage() {
|
| + DCHECK_EQ(state(), MESSAGE_READY);
|
| +
|
| + DCHECK(v2_authenticator_);
|
| + scoped_ptr<buzz::XmlElement> result = v2_authenticator_->GetNextMessage();
|
| +
|
| + if (!error_message_.empty()) {
|
| + buzz::XmlElement* pairing_failed_tag =
|
| + new buzz::XmlElement(kPairingFailedTag);
|
| + pairing_failed_tag->AddAttr(kPairingErrorAttribute, error_message_);
|
| + result->AddElement(pairing_failed_tag);
|
| + error_message_.clear();
|
| + }
|
| +
|
| + return result.Pass();
|
| +}
|
| +
|
| +scoped_ptr<ChannelAuthenticator>
|
| +PairingHostAuthenticator::CreateChannelAuthenticator() const {
|
| + DCHECK(v2_authenticator_);
|
| + return v2_authenticator_->CreateChannelAuthenticator();
|
| +}
|
| +
|
| +void PairingHostAuthenticator::CreateV2AuthenticatorWithPIN() {
|
| + DCHECK(!v2_authenticator_);
|
| + v2_authenticator_ = V2Authenticator::CreateForHost(
|
| + local_cert_, key_pair_, pin_, MESSAGE_READY);
|
| +}
|
| +
|
| +} // namespace protocol
|
| +} // namespace remoting
|
|
|