Home | History | Annotate | Download | only in protocol
      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