Provide RootClientTokenOwner into ClaimRootClientAuthToken ClaimRootClientAuthToken will check if token is already claimed and block claim if needed. BUG=25766815 Change-Id: I8d12578c99307830afccd280c322d2240234e435 Reviewed-on: https://weave-review.googlesource.com/1934 Reviewed-by: Alex Vakulenko <avakulenko@google.com>
diff --git a/src/device_registration_info.cc b/src/device_registration_info.cc index ac4ad4e..f52c292 100644 --- a/src/device_registration_info.cc +++ b/src/device_registration_info.cc
@@ -936,7 +936,8 @@ auth_info_update_inprogress_ = true; std::string id = GetSettings().device_id; - std::vector<uint8_t> token = auth_manager_->ClaimRootClientAuthToken(); + std::vector<uint8_t> token = + auth_manager_->ClaimRootClientAuthToken(RootClientTokenOwner::kCloud); std::string token_base64 = Base64Encode(token); std::string fingerprint = Base64Encode(auth_manager_->GetCertificateFingerprint());
diff --git a/src/privet/auth_manager.cc b/src/privet/auth_manager.cc index 3a2f5e0..fa1d685 100644 --- a/src/privet/auth_manager.cc +++ b/src/privet/auth_manager.cc
@@ -85,26 +85,41 @@ AuthManager::AuthManager(Config* config, const std::vector<uint8_t>& certificate_fingerprint) : config_{config}, certificate_fingerprint_{certificate_fingerprint} { - SetSecret(config_ ? config_->GetSettings().secret : std::vector<uint8_t>{}); + if (config_) { + SetSecret(config_->GetSettings().secret, + config_->GetSettings().root_client_token_owner); + } else { + SetSecret({}, RootClientTokenOwner::kNone); + } } AuthManager::AuthManager(const std::vector<uint8_t>& secret, const std::vector<uint8_t>& certificate_fingerprint, base::Clock* clock) : AuthManager(nullptr, certificate_fingerprint) { - SetSecret(secret); + SetSecret(secret, RootClientTokenOwner::kNone); if (clock) clock_ = clock; } -void AuthManager::SetSecret(const std::vector<uint8_t>& secret) { - secret_ = secret.size() == kSha256OutputSize ? secret : CreateSecret(); - if (config_ && config_->GetSettings().secret != secret_) { - Config::Transaction change{config_}; - change.set_secret(secret); - change.set_root_client_token_owner(RootClientTokenOwner::kNone); - change.Commit(); +void AuthManager::SetSecret(const std::vector<uint8_t>& secret, + RootClientTokenOwner owner) { + secret_ = secret; + + if (secret.size() != kSha256OutputSize) { + secret_ = CreateSecret(); + owner = RootClientTokenOwner::kNone; } + + if (!config_ || (config_->GetSettings().secret == secret_ && + config_->GetSettings().root_client_token_owner == owner)) { + return; + } + + Config::Transaction change{config_}; + change.set_secret(secret); + change.set_root_client_token_owner(owner); + change.Commit(); } AuthManager::~AuthManager() {} @@ -130,12 +145,13 @@ return SplitTokenData(std::string(data.begin(), data.end()), time); } -std::vector<uint8_t> AuthManager::ClaimRootClientAuthToken() { - pending_claims_.push_back( - std::unique_ptr<AuthManager>{new AuthManager{nullptr, {}}}); +std::vector<uint8_t> AuthManager::ClaimRootClientAuthToken( + RootClientTokenOwner owner) { + pending_claims_.push_back(std::make_pair( + std::unique_ptr<AuthManager>{new AuthManager{nullptr, {}}}, owner)); if (pending_claims_.size() > kMaxPendingClaims) pending_claims_.pop_front(); - return pending_claims_.back()->GetRootClientAuthToken(); + return pending_claims_.back().first->GetRootClientAuthToken(); } bool AuthManager::ConfirmAuthToken(const std::vector<uint8_t>& token) { @@ -143,14 +159,15 @@ if (pending_claims_.empty() && IsValidAuthToken(token)) return true; - auto claim = std::find_if(pending_claims_.begin(), pending_claims_.end(), - [&token](const std::unique_ptr<AuthManager>& auth) { - return auth->IsValidAuthToken(token); - }); + auto claim = + std::find_if(pending_claims_.begin(), pending_claims_.end(), + [&token](const decltype(pending_claims_)::value_type& auth) { + return auth.first->IsValidAuthToken(token); + }); if (claim == pending_claims_.end()) return false; - secret_ = (*claim)->GetSecret(); + SetSecret(claim->first->GetSecret(), claim->second); pending_claims_.clear(); return true; }
diff --git a/src/privet/auth_manager.h b/src/privet/auth_manager.h index dd4ad3d..62a1606 100644 --- a/src/privet/auth_manager.h +++ b/src/privet/auth_manager.h
@@ -18,6 +18,7 @@ namespace weave { class Config; +enum class RootClientTokenOwner; namespace privet { @@ -43,14 +44,15 @@ base::Time Now() const; - std::vector<uint8_t> ClaimRootClientAuthToken(); + std::vector<uint8_t> ClaimRootClientAuthToken(RootClientTokenOwner owner); bool ConfirmAuthToken(const std::vector<uint8_t>& token); std::vector<uint8_t> GetRootClientAuthToken() const; bool IsValidAuthToken(const std::vector<uint8_t>& token) const; private: - void SetSecret(const std::vector<uint8_t>& secret); + void SetSecret(const std::vector<uint8_t>& secret, + RootClientTokenOwner owner); Config* config_{nullptr}; base::DefaultClock default_clock_; @@ -59,7 +61,8 @@ std::vector<uint8_t> secret_; std::vector<uint8_t> certificate_fingerprint_; - std::deque<std::unique_ptr<AuthManager>> pending_claims_; + std::deque<std::pair<std::unique_ptr<AuthManager>, RootClientTokenOwner>> + pending_claims_; DISALLOW_COPY_AND_ASSIGN(AuthManager); };
diff --git a/src/privet/auth_manager_unittest.cc b/src/privet/auth_manager_unittest.cc index 4bef217..4dd753b 100644 --- a/src/privet/auth_manager_unittest.cc +++ b/src/privet/auth_manager_unittest.cc
@@ -8,6 +8,7 @@ #include <gtest/gtest.h> #include <weave/settings.h> +#include "src/config.h" #include "src/data_encoding.h" #include "src/test/mock_clock.h" @@ -147,7 +148,7 @@ } TEST_F(AuthManagerTest, ClaimRootClientAuthToken) { - auto token = auth_.ClaimRootClientAuthToken(); + auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud); EXPECT_FALSE(auth_.IsValidAuthToken(token)); EXPECT_TRUE(auth_.ConfirmAuthToken(token)); @@ -155,22 +156,22 @@ } TEST_F(AuthManagerTest, ClaimRootClientAuthTokenDoubleConfirm) { - auto token = auth_.ClaimRootClientAuthToken(); + auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud); EXPECT_TRUE(auth_.ConfirmAuthToken(token)); EXPECT_TRUE(auth_.ConfirmAuthToken(token)); } TEST_F(AuthManagerTest, DoubleClaimRootClientAuthToken) { - auto token1 = auth_.ClaimRootClientAuthToken(); - auto token2 = auth_.ClaimRootClientAuthToken(); + auto token1 = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud); + auto token2 = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud); EXPECT_TRUE(auth_.ConfirmAuthToken(token1)); EXPECT_FALSE(auth_.ConfirmAuthToken(token2)); } TEST_F(AuthManagerTest, ClaimRootClientAuthTokenOverflow) { - auto token = auth_.ClaimRootClientAuthToken(); + auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud); for (size_t i = 0; i < 100; ++i) - auth_.ClaimRootClientAuthToken(); + auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud); EXPECT_FALSE(auth_.ConfirmAuthToken(token)); }
diff --git a/src/privet/security_manager.cc b/src/privet/security_manager.cc index 34c65f0..cb0d73d 100644 --- a/src/privet/security_manager.cc +++ b/src/privet/security_manager.cc
@@ -18,6 +18,7 @@ #include <base/time/time.h> #include <weave/provider/task_runner.h> +#include "src/config.h" #include "src/data_encoding.h" #include "src/privet/auth_manager.h" #include "src/privet/constants.h" @@ -136,7 +137,8 @@ } std::string SecurityManager::ClaimRootClientAuthToken() { - return Base64Encode(auth_manager_->ClaimRootClientAuthToken()); + return Base64Encode( + auth_manager_->ClaimRootClientAuthToken(RootClientTokenOwner::kClient)); } bool SecurityManager::ConfirmAuthToken(const std::string& token) {