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