1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "remoting/protocol/pairing_host_authenticator.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "remoting/base/constants.h" 10#include "remoting/base/rsa_key_pair.h" 11#include "remoting/protocol/channel_authenticator.h" 12#include "remoting/protocol/v2_authenticator.h" 13#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" 14 15namespace remoting { 16namespace protocol { 17 18PairingHostAuthenticator::PairingHostAuthenticator( 19 scoped_refptr<PairingRegistry> pairing_registry, 20 const std::string& local_cert, 21 scoped_refptr<RsaKeyPair> key_pair, 22 const std::string& pin) 23 : pairing_registry_(pairing_registry), 24 local_cert_(local_cert), 25 key_pair_(key_pair), 26 pin_(pin), 27 protocol_error_(false), 28 waiting_for_paired_secret_(false), 29 weak_factory_(this) { 30} 31 32PairingHostAuthenticator::~PairingHostAuthenticator() { 33} 34 35Authenticator::State PairingHostAuthenticator::state() const { 36 if (protocol_error_) { 37 return REJECTED; 38 } else if (waiting_for_paired_secret_) { 39 return PROCESSING_MESSAGE; 40 } else if (!v2_authenticator_) { 41 return WAITING_MESSAGE; 42 } 43 return PairingAuthenticatorBase::state(); 44} 45 46Authenticator::RejectionReason 47PairingHostAuthenticator::rejection_reason() const { 48 if (protocol_error_) { 49 return PROTOCOL_ERROR; 50 } 51 return PairingAuthenticatorBase::rejection_reason(); 52} 53 54void PairingHostAuthenticator::CreateV2AuthenticatorWithPIN( 55 State initial_state, 56 const SetAuthenticatorCallback& callback) { 57 callback.Run(V2Authenticator::CreateForHost( 58 local_cert_, key_pair_, pin_, initial_state)); 59} 60 61void PairingHostAuthenticator::ProcessMessage( 62 const buzz::XmlElement* message, 63 const base::Closure& resume_callback) { 64 if (!v2_authenticator_) { 65 std::string client_id; 66 67 const buzz::XmlElement* pairing_tag = message->FirstNamed(kPairingInfoTag); 68 if (pairing_tag) { 69 client_id = pairing_tag->Attr(kClientIdAttribute); 70 } 71 72 if (client_id.empty()) { 73 LOG(ERROR) << "No client id specified."; 74 protocol_error_ = true; 75 } else { 76 waiting_for_paired_secret_ = true; 77 pairing_registry_->GetPairing( 78 client_id, 79 base::Bind(&PairingHostAuthenticator::ProcessMessageWithPairing, 80 weak_factory_.GetWeakPtr(), 81 base::Owned(new buzz::XmlElement(*message)), 82 resume_callback)); 83 return; 84 } 85 } 86 87 PairingAuthenticatorBase::ProcessMessage(message, resume_callback); 88} 89 90void PairingHostAuthenticator::AddPairingElements(buzz::XmlElement* message) { 91 // Nothing to do here 92} 93 94void PairingHostAuthenticator::ProcessMessageWithPairing( 95 const buzz::XmlElement* message, 96 const base::Closure& resume_callback, 97 PairingRegistry::Pairing pairing) { 98 waiting_for_paired_secret_ = false; 99 std::string paired_secret = pairing.shared_secret(); 100 if (paired_secret.empty()) { 101 VLOG(0) << "Unknown client id"; 102 error_message_ = "unknown-client-id"; 103 } 104 105 using_paired_secret_ = !paired_secret.empty(); 106 if (using_paired_secret_) { 107 v2_authenticator_ = V2Authenticator::CreateForHost( 108 local_cert_, key_pair_, paired_secret, WAITING_MESSAGE); 109 PairingAuthenticatorBase::ProcessMessage(message, resume_callback); 110 } else { 111 v2_authenticator_ = V2Authenticator::CreateForHost( 112 local_cert_, key_pair_, pin_, MESSAGE_READY); 113 // The client's optimistic SPAKE message is using a Paired Secret to 114 // which the host doesn't have access, so don't bother processing it. 115 resume_callback.Run(); 116 } 117} 118 119} // namespace protocol 120} // namespace remoting 121