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 #ifndef REMOTING_PROTOCOL_PAIRING_AUTHENTICATOR_BASE_H_ 6 #define REMOTING_PROTOCOL_PAIRING_AUTHENTICATOR_BASE_H_ 7 8 #include "base/memory/weak_ptr.h" 9 #include "remoting/protocol/authenticator.h" 10 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" 11 12 namespace remoting { 13 namespace protocol { 14 15 // The pairing authenticator builds on top of V2Authenticator to add 16 // support for PIN-less authentication via device pairing: 17 // 18 // * If a client device is already paired, it includes in the initial 19 // authentication message a Client Id and the first SPAKE message 20 // using the Paired Secret and HMAC_SHA256. 21 // * If the host recognizes the Client Id, it looks up the corresponding 22 // Paired Secret and continue the SPAKE exchange. 23 // * If it does not recognize the Client Id, it initiates a SPAKE exchange 24 // with HMAC_SHA256 using the PIN as the shared secret. The initial 25 // message of this exchange includes an an error message, which 26 // informs the client that the PIN-less connection failed and causes 27 // it to prompt the user for a PIN to use for authentication 28 // instead. 29 // * If, at any point, the SPAKE exchange fails with the Paired Secret, 30 // the endpoint that detects the failure initiates a new SPAKE exchange 31 // using the PIN, and includes an error message to instruct the peer 32 // to do likewise. 33 // 34 // If a client device is not already paired, but supports pairing, then 35 // the V2Authenticator is used instead of this class. Only the method name 36 // differs, which the client uses to determine that pairing should be offered 37 // to the user (see NegotiatingHostAuthenticator::CreateAuthenticator and 38 // NegotiatingClientAuthenticator::CreateAuthenticatorForCurrentMethod). 39 class PairingAuthenticatorBase : public Authenticator { 40 public: 41 PairingAuthenticatorBase(); 42 virtual ~PairingAuthenticatorBase(); 43 44 // Authenticator interface. 45 virtual State state() const OVERRIDE; 46 virtual bool started() const OVERRIDE; 47 virtual RejectionReason rejection_reason() const OVERRIDE; 48 virtual void ProcessMessage(const buzz::XmlElement* message, 49 const base::Closure& resume_callback) OVERRIDE; 50 virtual scoped_ptr<buzz::XmlElement> GetNextMessage() OVERRIDE; 51 virtual scoped_ptr<ChannelAuthenticator> 52 CreateChannelAuthenticator() const OVERRIDE; 53 54 protected: 55 typedef base::Callback<void(scoped_ptr<Authenticator> authenticator)> 56 SetAuthenticatorCallback; 57 58 static const buzz::StaticQName kPairingInfoTag; 59 static const buzz::StaticQName kClientIdAttribute; 60 61 // Create a V2 authenticator in the specified state, prompting the user for 62 // the PIN first if necessary. 63 virtual void CreateV2AuthenticatorWithPIN( 64 State initial_state, 65 const SetAuthenticatorCallback& callback) = 0; 66 67 // Amend an authenticator message, for example to add client- or host-specific 68 // elements to it. 69 virtual void AddPairingElements(buzz::XmlElement* message) = 0; 70 71 // A non-fatal error message that derived classes should set in order to 72 // cause the peer to be notified that pairing has failed and that it should 73 // fall back on PIN authentication. This string need not be human-readable, 74 // nor is it currently used other than being logged. 75 std::string error_message_; 76 77 // The underlying V2 authenticator, created with either the PIN or the 78 // Paired Secret by the derived class. 79 scoped_ptr<Authenticator> v2_authenticator_; 80 81 // Derived classes must set this to True if the underlying authenticator is 82 // using the Paired Secret. 83 bool using_paired_secret_; 84 85 private: 86 // Helper methods for ProcessMessage and GetNextMessage 87 void MaybeAddErrorMessage(buzz::XmlElement* message); 88 bool HasErrorMessage(const buzz::XmlElement* message) const; 89 void CheckForFailedSpakeExchange(const base::Closure& resume_callback); 90 void SetAuthenticatorAndProcessMessage( 91 const buzz::XmlElement* message, 92 const base::Closure& resume_callback, 93 scoped_ptr<Authenticator> authenticator); 94 95 // Set to true if a PIN-based authenticator has been requested but has not 96 // yet been set. 97 bool waiting_for_authenticator_; 98 99 base::WeakPtrFactory<PairingAuthenticatorBase> weak_factory_; 100 101 DISALLOW_COPY_AND_ASSIGN(PairingAuthenticatorBase); 102 }; 103 104 } // namespace protocol 105 } // namespace remoting 106 107 #endif // REMOTING_PROTOCOL_PAIRING_AUTHENTICATOR_H_ 108