blob: 3b086135463ade020ca9193610036cb1cb8be13d [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Vitaly Buka7ce499f2015-06-09 08:04:11 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02005#include "src/privet/security_manager.h"
Vitaly Buka7ce499f2015-06-09 08:04:11 -07006
7#include <algorithm>
8#include <limits>
9#include <memory>
10#include <set>
11
12#include <base/bind.h>
13#include <base/guid.h>
14#include <base/logging.h>
Vitaly Buka7ce499f2015-06-09 08:04:11 -070015#include <base/rand_util.h>
Vitaly Buka7ce499f2015-06-09 08:04:11 -070016#include <base/strings/string_number_conversions.h>
17#include <base/strings/stringprintf.h>
18#include <base/time/time.h>
Vitaly Buka1e363672015-09-25 14:01:16 -070019#include <weave/provider/task_runner.h>
Vitaly Buka7ce499f2015-06-09 08:04:11 -070020
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020021#include "src/data_encoding.h"
Vitaly Bukaf08caeb2015-12-02 13:47:48 -080022#include "src/privet/auth_manager.h"
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020023#include "src/privet/constants.h"
24#include "src/privet/openssl_utils.h"
25#include "src/string_utils.h"
Vitaly Buka9e5b6832015-10-14 15:57:14 -070026#include "third_party/chromium/crypto/p224_spake.h"
Vitaly Buka7ce499f2015-06-09 08:04:11 -070027
Vitaly Bukab6f015a2015-07-09 14:59:23 -070028namespace weave {
29namespace privet {
Vitaly Buka7ce499f2015-06-09 08:04:11 -070030
31namespace {
32
Vitaly Buka7ce499f2015-06-09 08:04:11 -070033const int kSessionExpirationTimeMinutes = 5;
34const int kPairingExpirationTimeMinutes = 5;
35const int kMaxAllowedPairingAttemts = 3;
36const int kPairingBlockingTimeMinutes = 1;
37
Vitaly Bukafd2ef682015-12-17 20:57:01 -080038const int kAccessTokenExpirationSeconds = 3600;
39
Vitaly Buka7ce499f2015-06-09 08:04:11 -070040class Spakep224Exchanger : public SecurityManager::KeyExchanger {
41 public:
42 explicit Spakep224Exchanger(const std::string& password)
43 : spake_(crypto::P224EncryptedKeyExchange::kPeerTypeServer, password) {}
44 ~Spakep224Exchanger() override = default;
45
46 // SecurityManager::KeyExchanger methods.
47 const std::string& GetMessage() override { return spake_.GetNextMessage(); }
48
Vitaly Buka0801a1f2015-08-14 10:03:46 -070049 bool ProcessMessage(const std::string& message, ErrorPtr* error) override {
Vitaly Buka7ce499f2015-06-09 08:04:11 -070050 switch (spake_.ProcessMessage(message)) {
51 case crypto::P224EncryptedKeyExchange::kResultPending:
52 return true;
53 case crypto::P224EncryptedKeyExchange::kResultFailed:
Vitaly Buka0dbbf602016-01-22 11:38:37 -080054 return Error::AddTo(error, FROM_HERE, errors::kInvalidClientCommitment,
55 spake_.error());
Vitaly Buka7ce499f2015-06-09 08:04:11 -070056 default:
57 LOG(FATAL) << "SecurityManager uses only one round trip";
58 }
59 return false;
60 }
61
62 const std::string& GetKey() const override {
63 return spake_.GetUnverifiedKey();
64 }
65
66 private:
67 crypto::P224EncryptedKeyExchange spake_;
68};
69
Vitaly Buka7ce499f2015-06-09 08:04:11 -070070} // namespace
71
Vitaly Buka20896ab2015-12-22 15:06:10 -080072SecurityManager::SecurityManager(const Config* config,
73 AuthManager* auth_manager,
Vitaly Buka1e363672015-09-25 14:01:16 -070074 provider::TaskRunner* task_runner)
Vitaly Buka20896ab2015-12-22 15:06:10 -080075 : config_{config}, auth_manager_{auth_manager}, task_runner_{task_runner} {
Vitaly Bukaf08caeb2015-12-02 13:47:48 -080076 CHECK(auth_manager_);
Vitaly Buka20896ab2015-12-22 15:06:10 -080077 CHECK_EQ(GetSettings().embedded_code.empty(),
78 std::find(GetSettings().pairing_modes.begin(),
79 GetSettings().pairing_modes.end(),
80 PairingType::kEmbeddedCode) ==
81 GetSettings().pairing_modes.end());
Vitaly Buka7ce499f2015-06-09 08:04:11 -070082}
83
84SecurityManager::~SecurityManager() {
85 while (!pending_sessions_.empty())
86 ClosePendingSession(pending_sessions_.begin()->first);
87}
88
Vitaly Buka66a01e02015-12-20 18:37:14 -080089bool SecurityManager::CreateAccessTokenImpl(AuthType auth_type,
90 AuthScope desired_scope,
91 std::vector<uint8_t>* access_token,
92 AuthScope* access_token_scope,
93 base::TimeDelta* access_token_ttl) {
Vitaly Buka4fe71e32016-01-29 11:50:53 -080094 auto user_id = std::to_string(++last_user_id_);
95 UserInfo user_info{
96 desired_scope,
97 UserAppId{auth_type, {user_id.begin(), user_id.end()}, {}}};
Vitaly Buka66a01e02015-12-20 18:37:14 -080098
99 const base::TimeDelta kTtl =
100 base::TimeDelta::FromSeconds(kAccessTokenExpirationSeconds);
101
102 if (access_token)
103 *access_token = auth_manager_->CreateAccessToken(user_info, kTtl);
104
105 if (access_token_scope)
106 *access_token_scope = user_info.scope();
107
108 if (access_token_ttl)
109 *access_token_ttl = kTtl;
110
111 return true;
112}
113
114bool SecurityManager::CreateAccessTokenImpl(
115 AuthType auth_type,
116 const std::vector<uint8_t>& auth_code,
117 AuthScope desired_scope,
118 std::vector<uint8_t>* access_token,
119 AuthScope* access_token_scope,
120 base::TimeDelta* access_token_ttl,
121 ErrorPtr* error) {
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800122 auto disabled_mode = [](ErrorPtr* error) {
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800123 return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthMode,
124 "Mode is not available");
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800125 };
Vitaly Buka66a01e02015-12-20 18:37:14 -0800126
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800127 switch (auth_type) {
128 case AuthType::kAnonymous:
Vitaly Buka20896ab2015-12-22 15:06:10 -0800129 if (!IsAnonymousAuthSupported())
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800130 return disabled_mode(error);
Vitaly Buka66a01e02015-12-20 18:37:14 -0800131 return CreateAccessTokenImpl(auth_type, desired_scope, access_token,
132 access_token_scope, access_token_ttl);
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800133 case AuthType::kPairing:
Vitaly Buka20896ab2015-12-22 15:06:10 -0800134 if (!IsPairingAuthSupported())
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800135 return disabled_mode(error);
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800136 if (!IsValidPairingCode(auth_code)) {
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800137 return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode,
138 "Invalid authCode");
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800139 }
Vitaly Buka66a01e02015-12-20 18:37:14 -0800140 return CreateAccessTokenImpl(auth_type, desired_scope, access_token,
141 access_token_scope, access_token_ttl);
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800142 case AuthType::kLocal:
Vitaly Buka20896ab2015-12-22 15:06:10 -0800143 if (!IsLocalAuthSupported())
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800144 return disabled_mode(error);
Vitaly Buka66a01e02015-12-20 18:37:14 -0800145 const base::TimeDelta kTtl =
146 base::TimeDelta::FromSeconds(kAccessTokenExpirationSeconds);
147 return auth_manager_->CreateAccessTokenFromAuth(
148 auth_code, kTtl, access_token, access_token_scope, access_token_ttl,
149 error);
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800150 }
151
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800152 return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthMode,
153 "Unsupported auth mode");
Vitaly Buka66a01e02015-12-20 18:37:14 -0800154}
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800155
Vitaly Buka66a01e02015-12-20 18:37:14 -0800156bool SecurityManager::CreateAccessToken(AuthType auth_type,
157 const std::string& auth_code,
158 AuthScope desired_scope,
159 std::string* access_token,
160 AuthScope* access_token_scope,
161 base::TimeDelta* access_token_ttl,
162 ErrorPtr* error) {
163 std::vector<uint8_t> auth_decoded;
164 if (auth_type != AuthType::kAnonymous &&
165 !Base64Decode(auth_code, &auth_decoded)) {
Vitaly Buka48a86692016-01-21 17:15:58 -0800166 Error::AddToPrintf(error, FROM_HERE, errors::kInvalidAuthorization,
Vitaly Buka36fd44f2016-01-18 15:06:19 -0800167 "Invalid auth_code encoding: %s", auth_code.c_str());
Vitaly Buka66a01e02015-12-20 18:37:14 -0800168 return false;
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800169 }
170
Vitaly Buka66a01e02015-12-20 18:37:14 -0800171 std::vector<uint8_t> access_token_decoded;
172 if (!CreateAccessTokenImpl(auth_type, auth_decoded, desired_scope,
173 &access_token_decoded, access_token_scope,
174 access_token_ttl, error)) {
175 return false;
176 }
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800177
Vitaly Buka66a01e02015-12-20 18:37:14 -0800178 if (access_token)
179 *access_token = Base64Encode(access_token_decoded);
Vitaly Bukafd2ef682015-12-17 20:57:01 -0800180
181 return true;
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700182}
183
Vitaly Bukaa0a81342015-12-17 13:42:13 -0800184bool SecurityManager::ParseAccessToken(const std::string& token,
185 UserInfo* user_info,
186 ErrorPtr* error) const {
Vitaly Bukaa04405e2015-08-13 18:28:14 -0700187 std::vector<uint8_t> decoded;
Vitaly Bukaa0a81342015-12-17 13:42:13 -0800188 if (!Base64Decode(token, &decoded)) {
Vitaly Buka48a86692016-01-21 17:15:58 -0800189 Error::AddToPrintf(error, FROM_HERE, errors::kInvalidAuthorization,
Vitaly Bukaa0a81342015-12-17 13:42:13 -0800190 "Invalid token encoding: %s", token.c_str());
191 return false;
192 }
Vitaly Bukaf08caeb2015-12-02 13:47:48 -0800193
Vitaly Bukaa0a81342015-12-17 13:42:13 -0800194 return auth_manager_->ParseAccessToken(decoded, user_info, error);
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700195}
196
197std::set<PairingType> SecurityManager::GetPairingTypes() const {
Vitaly Buka20896ab2015-12-22 15:06:10 -0800198 return GetSettings().pairing_modes;
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700199}
200
201std::set<CryptoType> SecurityManager::GetCryptoTypes() const {
202 std::set<CryptoType> result{CryptoType::kSpake_p224};
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700203 return result;
204}
205
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800206std::set<AuthType> SecurityManager::GetAuthTypes() const {
207 std::set<AuthType> result;
Vitaly Buka20896ab2015-12-22 15:06:10 -0800208 if (IsAnonymousAuthSupported())
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800209 result.insert(AuthType::kAnonymous);
210
Vitaly Buka20896ab2015-12-22 15:06:10 -0800211 if (IsPairingAuthSupported())
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800212 result.insert(AuthType::kPairing);
213
Vitaly Buka20896ab2015-12-22 15:06:10 -0800214 if (IsLocalAuthSupported())
Vitaly Bukaee7322f2015-12-18 16:54:05 -0800215 result.insert(AuthType::kLocal);
216
217 return result;
218}
219
Vitaly Buka4ab50022015-12-14 22:32:24 -0800220std::string SecurityManager::ClaimRootClientAuthToken(ErrorPtr* error) {
221 return Base64Encode(auth_manager_->ClaimRootClientAuthToken(
222 RootClientTokenOwner::kClient, error));
Vitaly Buka29bc5932015-12-13 22:56:52 -0800223}
224
Vitaly Buka305ab612015-12-15 12:02:59 -0800225bool SecurityManager::ConfirmClientAuthToken(const std::string& token,
226 ErrorPtr* error) {
Vitaly Buka29bc5932015-12-13 22:56:52 -0800227 std::vector<uint8_t> token_decoded;
Vitaly Buka4ab50022015-12-14 22:32:24 -0800228 if (!Base64Decode(token, &token_decoded)) {
Vitaly Buka48a86692016-01-21 17:15:58 -0800229 Error::AddToPrintf(error, FROM_HERE, errors::kInvalidFormat,
Vitaly Buka4ab50022015-12-14 22:32:24 -0800230 "Invalid auth token string: '%s'", token.c_str());
Vitaly Buka29bc5932015-12-13 22:56:52 -0800231 return false;
Vitaly Buka4ab50022015-12-14 22:32:24 -0800232 }
Vitaly Buka305ab612015-12-15 12:02:59 -0800233 return auth_manager_->ConfirmClientAuthToken(token_decoded, error);
Vitaly Buka29bc5932015-12-13 22:56:52 -0800234}
235
Vitaly Buka20896ab2015-12-22 15:06:10 -0800236const Config::Settings& SecurityManager::GetSettings() const {
237 return config_->GetSettings();
238}
239
Vitaly Buka66a01e02015-12-20 18:37:14 -0800240bool SecurityManager::IsValidPairingCode(
241 const std::vector<uint8_t>& auth_code) const {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700242 for (const auto& session : confirmed_sessions_) {
Vitaly Bukaa04405e2015-08-13 18:28:14 -0700243 const std::string& key = session.second->GetKey();
244 const std::string& id = session.first;
Vitaly Buka66a01e02015-12-20 18:37:14 -0800245 if (auth_code == HmacSha256(std::vector<uint8_t>(key.begin(), key.end()),
246 std::vector<uint8_t>(id.begin(), id.end()))) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700247 pairing_attemts_ = 0;
248 block_pairing_until_ = base::Time{};
249 return true;
250 }
251 }
252 LOG(ERROR) << "Attempt to authenticate with invalide code.";
253 return false;
254}
255
256bool SecurityManager::StartPairing(PairingType mode,
257 CryptoType crypto,
258 std::string* session_id,
259 std::string* device_commitment,
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700260 ErrorPtr* error) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700261 if (!CheckIfPairingAllowed(error))
262 return false;
263
Vitaly Buka20896ab2015-12-22 15:06:10 -0800264 const auto& pairing_modes = GetSettings().pairing_modes;
265 if (std::find(pairing_modes.begin(), pairing_modes.end(), mode) ==
266 pairing_modes.end()) {
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800267 return Error::AddTo(error, FROM_HERE, errors::kInvalidParams,
268 "Pairing mode is not enabled");
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700269 }
270
271 std::string code;
272 switch (mode) {
273 case PairingType::kEmbeddedCode:
Vitaly Buka20896ab2015-12-22 15:06:10 -0800274 CHECK(!GetSettings().embedded_code.empty());
275 code = GetSettings().embedded_code;
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700276 break;
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700277 case PairingType::kPinCode:
278 code = base::StringPrintf("%04i", base::RandInt(0, 9999));
279 break;
280 default:
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800281 return Error::AddTo(error, FROM_HERE, errors::kInvalidParams,
282 "Unsupported pairing mode");
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700283 }
284
285 std::unique_ptr<KeyExchanger> spake;
286 switch (crypto) {
287 case CryptoType::kSpake_p224:
288 spake.reset(new Spakep224Exchanger(code));
289 break;
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700290 // Fall through...
291 default:
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800292 return Error::AddTo(error, FROM_HERE, errors::kInvalidParams,
293 "Unsupported crypto");
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700294 }
295
296 // Allow only a single session at a time for now.
297 while (!pending_sessions_.empty())
298 ClosePendingSession(pending_sessions_.begin()->first);
299
300 std::string session;
301 do {
302 session = base::GenerateGUID();
303 } while (confirmed_sessions_.find(session) != confirmed_sessions_.end() ||
304 pending_sessions_.find(session) != pending_sessions_.end());
305 std::string commitment = spake->GetMessage();
Vitaly Buka52d006a2015-11-21 17:14:51 -0800306 pending_sessions_.insert(std::make_pair(session, std::move(spake)));
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700307
Vitaly Bukaf9630fb2015-08-12 21:15:40 -0700308 task_runner_->PostDelayedTask(
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700309 FROM_HERE,
310 base::Bind(base::IgnoreResult(&SecurityManager::ClosePendingSession),
311 weak_ptr_factory_.GetWeakPtr(), session),
312 base::TimeDelta::FromMinutes(kPairingExpirationTimeMinutes));
313
314 *session_id = session;
Vitaly Buka7d556392015-08-13 20:06:48 -0700315 *device_commitment = Base64Encode(commitment);
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700316 LOG(INFO) << "Pairing code for session " << *session_id << " is " << code;
317 // TODO(vitalybuka): Handle case when device can't start multiple pairing
318 // simultaneously and implement throttling to avoid brute force attack.
319 if (!on_start_.is_null()) {
320 on_start_.Run(session, mode,
Vitaly Buka24d6fd52015-08-13 23:22:48 -0700321 std::vector<uint8_t>{code.begin(), code.end()});
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700322 }
323
324 return true;
325}
326
327bool SecurityManager::ConfirmPairing(const std::string& session_id,
328 const std::string& client_commitment,
329 std::string* fingerprint,
330 std::string* signature,
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700331 ErrorPtr* error) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700332 auto session = pending_sessions_.find(session_id);
333 if (session == pending_sessions_.end()) {
Vitaly Buka48a86692016-01-21 17:15:58 -0800334 Error::AddToPrintf(error, FROM_HERE, errors::kUnknownSession,
335 "Unknown session id: '%s'", session_id.c_str());
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700336 return false;
337 }
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700338
Vitaly Bukaa04405e2015-08-13 18:28:14 -0700339 std::vector<uint8_t> commitment;
Vitaly Buka7d556392015-08-13 20:06:48 -0700340 if (!Base64Decode(client_commitment, &commitment)) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700341 ClosePendingSession(session_id);
Vitaly Buka48a86692016-01-21 17:15:58 -0800342 Error::AddToPrintf(error, FROM_HERE, errors::kInvalidFormat,
343 "Invalid commitment string: '%s'",
344 client_commitment.c_str());
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700345 return false;
346 }
347
348 if (!session->second->ProcessMessage(
349 std::string(commitment.begin(), commitment.end()), error)) {
350 ClosePendingSession(session_id);
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800351 return Error::AddTo(error, FROM_HERE, errors::kCommitmentMismatch,
352 "Pairing code or crypto implementation mismatch");
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700353 }
354
Vitaly Bukaa04405e2015-08-13 18:28:14 -0700355 const std::string& key = session->second->GetKey();
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700356 VLOG(3) << "KEY " << base::HexEncode(key.data(), key.size());
357
Vitaly Bukaf08caeb2015-12-02 13:47:48 -0800358 const auto& certificate_fingerprint =
359 auth_manager_->GetCertificateFingerprint();
360 *fingerprint = Base64Encode(certificate_fingerprint);
Vitaly Bukaa04405e2015-08-13 18:28:14 -0700361 std::vector<uint8_t> cert_hmac = HmacSha256(
Vitaly Bukaf08caeb2015-12-02 13:47:48 -0800362 std::vector<uint8_t>(key.begin(), key.end()), certificate_fingerprint);
Vitaly Buka7d556392015-08-13 20:06:48 -0700363 *signature = Base64Encode(cert_hmac);
Vitaly Buka52d006a2015-11-21 17:14:51 -0800364 confirmed_sessions_.insert(
365 std::make_pair(session->first, std::move(session->second)));
Vitaly Bukaf9630fb2015-08-12 21:15:40 -0700366 task_runner_->PostDelayedTask(
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700367 FROM_HERE,
368 base::Bind(base::IgnoreResult(&SecurityManager::CloseConfirmedSession),
369 weak_ptr_factory_.GetWeakPtr(), session_id),
370 base::TimeDelta::FromMinutes(kSessionExpirationTimeMinutes));
371 ClosePendingSession(session_id);
372 return true;
373}
374
375bool SecurityManager::CancelPairing(const std::string& session_id,
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700376 ErrorPtr* error) {
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700377 bool confirmed = CloseConfirmedSession(session_id);
378 bool pending = ClosePendingSession(session_id);
379 if (pending) {
380 CHECK_GE(pairing_attemts_, 1);
381 --pairing_attemts_;
382 }
383 CHECK(!confirmed || !pending);
384 if (confirmed || pending)
385 return true;
Vitaly Buka48a86692016-01-21 17:15:58 -0800386 Error::AddToPrintf(error, FROM_HERE, errors::kUnknownSession,
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700387 "Unknown session id: '%s'", session_id.c_str());
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700388 return false;
389}
390
Vitaly Buka483d5972015-12-16 13:45:35 -0800391std::string SecurityManager::CreateSessionId() {
Vitaly Bukad5f7aab2016-01-27 18:25:14 -0800392 return auth_manager_->CreateSessionId();
Vitaly Buka483d5972015-12-16 13:45:35 -0800393}
394
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700395void SecurityManager::RegisterPairingListeners(
396 const PairingStartListener& on_start,
397 const PairingEndListener& on_end) {
398 CHECK(on_start_.is_null() && on_end_.is_null());
399 on_start_ = on_start;
Vitaly Buka075b3d42015-06-09 08:34:25 -0700400 on_end_ = on_end;
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700401}
402
Vitaly Buka0801a1f2015-08-14 10:03:46 -0700403bool SecurityManager::CheckIfPairingAllowed(ErrorPtr* error) {
Vitaly Buka41aa8092015-12-09 20:04:34 -0800404 if (block_pairing_until_ > auth_manager_->Now()) {
Vitaly Buka0dbbf602016-01-22 11:38:37 -0800405 return Error::AddTo(error, FROM_HERE, errors::kDeviceBusy,
406 "Too many pairing attempts");
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700407 }
408
409 if (++pairing_attemts_ >= kMaxAllowedPairingAttemts) {
410 LOG(INFO) << "Pairing blocked for" << kPairingBlockingTimeMinutes
411 << "minutes.";
Vitaly Buka41aa8092015-12-09 20:04:34 -0800412 block_pairing_until_ = auth_manager_->Now();
Vitaly Buka7ce499f2015-06-09 08:04:11 -0700413 block_pairing_until_ +=
414 base::TimeDelta::FromMinutes(kPairingBlockingTimeMinutes);
415 }
416
417 return true;
418}
419
420bool SecurityManager::ClosePendingSession(const std::string& session_id) {
421 // The most common source of these session_id values is the map containing
422 // the sessions, which we're about to clear out. Make a local copy.
423 const std::string safe_session_id{session_id};
424 const size_t num_erased = pending_sessions_.erase(safe_session_id);
425 if (num_erased > 0 && !on_end_.is_null())
426 on_end_.Run(safe_session_id);
427 return num_erased != 0;
428}
429
430bool SecurityManager::CloseConfirmedSession(const std::string& session_id) {
431 return confirmed_sessions_.erase(session_id) != 0;
432}
433
Vitaly Buka20896ab2015-12-22 15:06:10 -0800434bool SecurityManager::IsAnonymousAuthSupported() const {
435 return GetSettings().local_anonymous_access_role != AuthScope::kNone;
436}
437
438bool SecurityManager::IsPairingAuthSupported() const {
439 return GetSettings().local_pairing_enabled;
440}
441
442bool SecurityManager::IsLocalAuthSupported() const {
443 return GetSettings().root_client_token_owner != RootClientTokenOwner::kNone;
444}
445
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700446} // namespace privet
447} // namespace weave