• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
created_timePairing60     base::Time created_time() const { return created_time_; }
client_idPairing61     std::string client_id() const { return client_id_; }
client_namePairing62     std::string client_name() const { return client_name_; }
shared_secretPairing63     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:
~Delegate()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