// 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/bind.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/v2_authenticator.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" namespace remoting { namespace protocol { PairingHostAuthenticator::PairingHostAuthenticator( scoped_refptr<PairingRegistry> pairing_registry, const std::string& local_cert, scoped_refptr<RsaKeyPair> key_pair, const std::string& pin) : pairing_registry_(pairing_registry), local_cert_(local_cert), key_pair_(key_pair), pin_(pin), protocol_error_(false), waiting_for_paired_secret_(false), weak_factory_(this) { } PairingHostAuthenticator::~PairingHostAuthenticator() { } Authenticator::State PairingHostAuthenticator::state() const { if (protocol_error_) { return REJECTED; } else if (waiting_for_paired_secret_) { return PROCESSING_MESSAGE; } else if (!v2_authenticator_) { return WAITING_MESSAGE; } return PairingAuthenticatorBase::state(); } Authenticator::RejectionReason PairingHostAuthenticator::rejection_reason() const { if (protocol_error_) { return PROTOCOL_ERROR; } return PairingAuthenticatorBase::rejection_reason(); } void PairingHostAuthenticator::CreateV2AuthenticatorWithPIN( State initial_state, const SetAuthenticatorCallback& callback) { callback.Run(V2Authenticator::CreateForHost( local_cert_, key_pair_, pin_, initial_state)); } void PairingHostAuthenticator::ProcessMessage( const buzz::XmlElement* message, const base::Closure& resume_callback) { if (!v2_authenticator_) { 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; } else { waiting_for_paired_secret_ = true; pairing_registry_->GetPairing( client_id, base::Bind(&PairingHostAuthenticator::ProcessMessageWithPairing, weak_factory_.GetWeakPtr(), base::Owned(new buzz::XmlElement(*message)), resume_callback)); return; } } PairingAuthenticatorBase::ProcessMessage(message, resume_callback); } void PairingHostAuthenticator::AddPairingElements(buzz::XmlElement* message) { // Nothing to do here } void PairingHostAuthenticator::ProcessMessageWithPairing( const buzz::XmlElement* message, const base::Closure& resume_callback, PairingRegistry::Pairing pairing) { waiting_for_paired_secret_ = false; std::string paired_secret = pairing.shared_secret(); if (paired_secret.empty()) { VLOG(0) << "Unknown client id"; error_message_ = "unknown-client-id"; } using_paired_secret_ = !paired_secret.empty(); if (using_paired_secret_) { v2_authenticator_ = V2Authenticator::CreateForHost( local_cert_, key_pair_, paired_secret, WAITING_MESSAGE); PairingAuthenticatorBase::ProcessMessage(message, resume_callback); } else { v2_authenticator_ = V2Authenticator::CreateForHost( local_cert_, key_pair_, pin_, MESSAGE_READY); // The client's optimistic SPAKE message is using a Paired Secret to // which the host doesn't have access, so don't bother processing it. resume_callback.Run(); } } } // namespace protocol } // namespace remoting