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 15 namespace remoting { 16 namespace protocol { 17 18 PairingHostAuthenticator::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 32 PairingHostAuthenticator::~PairingHostAuthenticator() { 33 } 34 35 Authenticator::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 46 Authenticator::RejectionReason 47 PairingHostAuthenticator::rejection_reason() const { 48 if (protocol_error_) { 49 return PROTOCOL_ERROR; 50 } 51 return PairingAuthenticatorBase::rejection_reason(); 52 } 53 54 void 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 61 void PairingHostAuthenticator::ProcessMessage( 62 const buzz::XmlElement* message, 63 const base::Closure& resume_callback) { 64 if (!v2_authenticator_) { 65 std::string client_id; 66 std::string paired_secret; 67 68 const buzz::XmlElement* pairing_tag = message->FirstNamed(kPairingInfoTag); 69 if (pairing_tag) { 70 client_id = pairing_tag->Attr(kClientIdAttribute); 71 } 72 73 if (client_id.empty()) { 74 LOG(ERROR) << "No client id specified."; 75 protocol_error_ = true; 76 } else { 77 waiting_for_paired_secret_ = true; 78 pairing_registry_->GetPairing( 79 client_id, 80 base::Bind(&PairingHostAuthenticator::ProcessMessageWithPairing, 81 weak_factory_.GetWeakPtr(), 82 base::Owned(new buzz::XmlElement(*message)), 83 resume_callback)); 84 return; 85 } 86 } 87 88 PairingAuthenticatorBase::ProcessMessage(message, resume_callback); 89 } 90 91 void PairingHostAuthenticator::AddPairingElements(buzz::XmlElement* message) { 92 // Nothing to do here 93 } 94 95 void PairingHostAuthenticator::ProcessMessageWithPairing( 96 const buzz::XmlElement* message, 97 const base::Closure& resume_callback, 98 PairingRegistry::Pairing pairing) { 99 waiting_for_paired_secret_ = false; 100 std::string paired_secret = pairing.shared_secret(); 101 if (paired_secret.empty()) { 102 LOG(INFO) << "Unknown client id"; 103 error_message_ = "unknown-client-id"; 104 } 105 106 using_paired_secret_ = !paired_secret.empty(); 107 if (using_paired_secret_) { 108 v2_authenticator_ = V2Authenticator::CreateForHost( 109 local_cert_, key_pair_, paired_secret, WAITING_MESSAGE); 110 PairingAuthenticatorBase::ProcessMessage(message, resume_callback); 111 } else { 112 v2_authenticator_ = V2Authenticator::CreateForHost( 113 local_cert_, key_pair_, pin_, MESSAGE_READY); 114 // The client's optimistic SPAKE message is using a Paired Secret to 115 // which the host doesn't have access, so don't bother processing it. 116 resume_callback.Run(); 117 } 118 } 119 120 } // namespace protocol 121 } // namespace remoting 122