File: pairing_registry.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (189 lines) | stat: -rw-r--r-- 6,889 bytes parent folder | download | duplicates (7)
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
// Copyright 2013 The Chromium Authors
// 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 <string>
#include <vector>

#include "base/containers/queue.h"
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "base/values.h"

namespace base {
class Location;
class SingleThreadTaskRunner;
}  // namespace base

namespace remoting::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::Value::Dict& pairing);

    base::Value::Dict 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::OnceCallback<void(bool success)> DoneCallback;
  typedef base::OnceCallback<void(base::Value::List pairings)>
      GetAllPairingsCallback;
  typedef base::OnceCallback<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 base::Value::List 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);

  PairingRegistry(const PairingRegistry&) = delete;
  PairingRegistry& operator=(const PairingRegistry&) = delete;

  // 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, GetPairingCallback callback);

  // Gets all pairings with the shared secrets removed as a base::Value::List.
  void GetAllPairings(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, DoneCallback callback);

  // Clear all pairings from the registry.
  void ClearAllPairings(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 base::Location& from_here,
      base::OnceClosure 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(GetAllPairingsCallback callback);
  void DoDeleteAll(DoneCallback callback);
  void DoLoad(const std::string& client_id, GetPairingCallback callback);
  void DoSave(const Pairing& pairing, DoneCallback callback);
  void DoDelete(const std::string& client_id, DoneCallback callback);

  // "Trampoline" callbacks that schedule the next pending request and then
  // invoke the original caller-supplied callback.
  void InvokeDoneCallbackAndScheduleNext(DoneCallback callback, bool success);
  void InvokeGetPairingCallbackAndScheduleNext(GetPairingCallback callback,
                                               Pairing pairing);
  void InvokeGetAllPairingsCallbackAndScheduleNext(
      GetAllPairingsCallback callback,
      base::Value::List pairings);

  // Sanitize |pairings| by parsing each entry and removing the secret from it.
  void SanitizePairings(GetAllPairingsCallback callback,
                        base::Value::List pairings);

  // Queue management methods.
  void ServiceOrQueueRequest(base::OnceClosure 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_;

  base::queue<base::OnceClosure> pending_requests_;
};

}  // namespace remoting::protocol

#endif  // REMOTING_PROTOCOL_PAIRING_REGISTRY_H_