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_REGISTRY_H_ 6 #define REMOTING_PROTOCOL_PAIRING_REGISTRY_H_ 7 8 #include <map> 9 #include <queue> 10 #include <string> 11 #include <vector> 12 13 #include "base/callback.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "base/time/time.h" 18 19 namespace base { 20 class DictionaryValue; 21 class ListValue; 22 class SingleThreadTaskRunner; 23 } // namespace base 24 25 namespace tracked_objects { 26 class Location; 27 } // namespace tracked_objects 28 29 namespace remoting { 30 namespace protocol { 31 32 // PairingRegistry holds information about paired clients to support 33 // PIN-less authentication. For each paired client, the registry holds 34 // the following information: 35 // * The name of the client. This is supplied by the client and is not 36 // guaranteed to be unique. 37 // * The unique id of the client. This is generated on-demand by this 38 // class and sent in plain-text by the client during authentication. 39 // * The shared secret for the client. This is generated on-demand by this 40 // class and used in the SPAKE2 exchange to mutually verify identity. 41 class PairingRegistry : public base::RefCountedThreadSafe<PairingRegistry> { 42 public: 43 struct Pairing { 44 Pairing(); 45 Pairing(const base::Time& created_time, 46 const std::string& client_name, 47 const std::string& client_id, 48 const std::string& shared_secret); 49 ~Pairing(); 50 51 static Pairing Create(const std::string& client_name); 52 static Pairing CreateFromValue(const base::DictionaryValue& pairing); 53 54 scoped_ptr<base::DictionaryValue> ToValue() const; 55 56 bool operator==(const Pairing& other) const; 57 58 bool is_valid() const; 59 60 base::Time created_time() const { return created_time_; } 61 std::string client_id() const { return client_id_; } 62 std::string client_name() const { return client_name_; } 63 std::string shared_secret() const { return shared_secret_; } 64 65 private: 66 base::Time created_time_; 67 std::string client_name_; 68 std::string client_id_; 69 std::string shared_secret_; 70 }; 71 72 // Mapping from client id to pairing information. 73 typedef std::map<std::string, Pairing> PairedClients; 74 75 // Delegate callbacks. 76 typedef base::Callback<void(bool success)> DoneCallback; 77 typedef base::Callback<void(scoped_ptr<base::ListValue> pairings)> 78 GetAllPairingsCallback; 79 typedef base::Callback<void(Pairing pairing)> GetPairingCallback; 80 81 static const char kCreatedTimeKey[]; 82 static const char kClientIdKey[]; 83 static const char kClientNameKey[]; 84 static const char kSharedSecretKey[]; 85 86 // Interface representing the persistent storage back-end. 87 class Delegate { 88 public: 89 virtual ~Delegate() {} 90 91 // Retrieves all JSON-encoded pairings from persistent storage. 92 virtual scoped_ptr<base::ListValue> LoadAll() = 0; 93 94 // Deletes all pairings in persistent storage. 95 virtual bool DeleteAll() = 0; 96 97 // Retrieves the pairing identified by |client_id|. 98 virtual Pairing Load(const std::string& client_id) = 0; 99 100 // Saves |pairing| to persistent storage. 101 virtual bool Save(const Pairing& pairing) = 0; 102 103 // Deletes the pairing identified by |client_id|. 104 virtual bool Delete(const std::string& client_id) = 0; 105 }; 106 107 PairingRegistry( 108 scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner, 109 scoped_ptr<Delegate> delegate); 110 111 // Creates a pairing for a new client and saves it to disk. 112 // 113 // TODO(jamiewalch): Plumb the Save callback into the RequestPairing flow 114 // so that the client isn't sent the pairing information until it has been 115 // saved. 116 Pairing CreatePairing(const std::string& client_name); 117 118 // Gets the pairing for the specified client id. See the corresponding 119 // Delegate method for details. If none is found, the callback is invoked 120 // with an invalid Pairing. 121 void GetPairing(const std::string& client_id, 122 const GetPairingCallback& callback); 123 124 // Gets all pairings with the shared secrets removed as a base::ListValue. 125 void GetAllPairings(const GetAllPairingsCallback& callback); 126 127 // Delete a pairing, identified by its client ID. |callback| is called with 128 // the result of saving the new config, which occurs even if the client ID 129 // did not match any pairing. 130 void DeletePairing(const std::string& client_id, 131 const DoneCallback& callback); 132 133 // Clear all pairings from the registry. 134 void ClearAllPairings(const DoneCallback& callback); 135 136 protected: 137 friend class base::RefCountedThreadSafe<PairingRegistry>; 138 virtual ~PairingRegistry(); 139 140 // Lets the tests override task posting to make all callbacks synchronous. 141 virtual void PostTask( 142 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 143 const tracked_objects::Location& from_here, 144 const base::Closure& task); 145 146 private: 147 FRIEND_TEST_ALL_PREFIXES(PairingRegistryTest, AddPairing); 148 friend class NegotiatingAuthenticatorTest; 149 150 // Helper method for unit tests. 151 void AddPairing(const Pairing& pairing); 152 153 // Blocking helper methods used to call the delegate. 154 void DoLoadAll( 155 const protocol::PairingRegistry::GetAllPairingsCallback& callback); 156 void DoDeleteAll( 157 const protocol::PairingRegistry::DoneCallback& callback); 158 void DoLoad( 159 const std::string& client_id, 160 const protocol::PairingRegistry::GetPairingCallback& callback); 161 void DoSave( 162 const protocol::PairingRegistry::Pairing& pairing, 163 const protocol::PairingRegistry::DoneCallback& callback); 164 void DoDelete( 165 const std::string& client_id, 166 const protocol::PairingRegistry::DoneCallback& callback); 167 168 // "Trampoline" callbacks that schedule the next pending request and then 169 // invoke the original caller-supplied callback. 170 void InvokeDoneCallbackAndScheduleNext( 171 const DoneCallback& callback, bool success); 172 void InvokeGetPairingCallbackAndScheduleNext( 173 const GetPairingCallback& callback, Pairing pairing); 174 void InvokeGetAllPairingsCallbackAndScheduleNext( 175 const GetAllPairingsCallback& callback, 176 scoped_ptr<base::ListValue> pairings); 177 178 // Sanitize |pairings| by parsing each entry and removing the secret from it. 179 void SanitizePairings(const GetAllPairingsCallback& callback, 180 scoped_ptr<base::ListValue> pairings); 181 182 // Queue management methods. 183 void ServiceOrQueueRequest(const base::Closure& request); 184 void ServiceNextRequest(); 185 186 // Task runner on which all public methods of this class should be called. 187 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; 188 189 // Task runner used to run blocking calls to the delegate. A single thread 190 // task runner is used to guarantee that one one method of the delegate is 191 // called at a time. 192 scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_; 193 194 scoped_ptr<Delegate> delegate_; 195 196 std::queue<base::Closure> pending_requests_; 197 198 DISALLOW_COPY_AND_ASSIGN(PairingRegistry); 199 }; 200 201 } // namespace protocol 202 } // namespace remoting 203 204 #endif // REMOTING_PROTOCOL_PAIRING_REGISTRY_H_ 205