diff options
author | Vitaly Buka <vitalybuka@google.com> | 2015-12-14 23:24:13 -0800 |
---|---|---|
committer | Vitaly Buka <vitalybuka@google.com> | 2015-12-15 19:58:21 +0000 |
commit | c3bc82a29cdff05d67d3b583ca0bc25df96ab382 (patch) | |
tree | 125f744f314a568b00b9bb4081f0ecd42d2a5e96 /src/privet | |
parent | 4ab500249f346a9fcfe084ee1619a39259f7471c (diff) | |
download | libweave-c3bc82a29cdff05d67d3b583ca0bc25df96ab382.tar.gz |
Check if device already claimed
Client can claim only unclaimed device.
Cloud can claim any device.
Claim with kNone is not allowed.
BUG=25766815, 26143922
Change-Id: Id92168b7f7c290509e672a659f09b7d06af37b76
Reviewed-on: https://weave-review.googlesource.com/1960
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
Diffstat (limited to 'src/privet')
-rw-r--r-- | src/privet/auth_manager.cc | 21 | ||||
-rw-r--r-- | src/privet/auth_manager_unittest.cc | 50 | ||||
-rw-r--r-- | src/privet/constants.cc | 1 | ||||
-rw-r--r-- | src/privet/constants.h | 1 | ||||
-rw-r--r-- | src/privet/privet_handler.cc | 1 |
5 files changed, 69 insertions, 5 deletions
diff --git a/src/privet/auth_manager.cc b/src/privet/auth_manager.cc index f38b854..f9f6777 100644 --- a/src/privet/auth_manager.cc +++ b/src/privet/auth_manager.cc @@ -9,6 +9,7 @@ #include "src/config.h" #include "src/data_encoding.h" +#include "src/privet/constants.h" #include "src/privet/openssl_utils.h" #include "src/string_utils.h" @@ -80,6 +81,10 @@ std::vector<uint8_t> CreateSecret() { return secret; } +bool IsClaimAllowed(RootClientTokenOwner curret, RootClientTokenOwner claimer) { + return claimer > curret || claimer == RootClientTokenOwner::kCloud; +} + } // namespace AuthManager::AuthManager(Config* config, @@ -148,6 +153,17 @@ UserInfo AuthManager::ParseAccessToken(const std::vector<uint8_t>& token, std::vector<uint8_t> AuthManager::ClaimRootClientAuthToken( RootClientTokenOwner owner, ErrorPtr* error) { + CHECK(RootClientTokenOwner::kNone != owner); + if (config_) { + auto current = config_->GetSettings().root_client_token_owner; + if (!IsClaimAllowed(current, owner)) { + Error::AddToPrintf( + error, FROM_HERE, errors::kDomain, errors::kAlreadyClaimed, + "Device already claimed by '%s'", EnumToString(current).c_str()); + return {}; + } + }; + pending_claims_.push_back(std::make_pair( std::unique_ptr<AuthManager>{new AuthManager{nullptr, {}}}, owner)); if (pending_claims_.size() > kMaxPendingClaims) @@ -166,8 +182,11 @@ bool AuthManager::ConfirmAuthToken(const std::vector<uint8_t>& token, [&token](const decltype(pending_claims_)::value_type& auth) { return auth.first->IsValidAuthToken(token); }); - if (claim == pending_claims_.end()) + if (claim == pending_claims_.end()) { + Error::AddTo(error, FROM_HERE, errors::kDomain, errors::kNotFound, + "Unknown claim"); return false; + } SetSecret(claim->first->GetSecret(), claim->second); pending_claims_.clear(); diff --git a/src/privet/auth_manager_unittest.cc b/src/privet/auth_manager_unittest.cc index 7b4aae4..aa124e1 100644 --- a/src/privet/auth_manager_unittest.cc +++ b/src/privet/auth_manager_unittest.cc @@ -147,23 +147,65 @@ TEST_F(AuthManagerTest, IsValidAuthToken) { } } -TEST_F(AuthManagerTest, ClaimRootClientAuthToken) { +class AuthManagerClaimTest : public testing::Test { + public: + void SetUp() override { EXPECT_GE(auth_.GetSecret().size(), 32u); } + + bool TestClaim(RootClientTokenOwner owner, RootClientTokenOwner claimer) { + Config::Transaction change{&config_}; + change.set_root_client_token_owner(owner); + change.Commit(); + return !auth_.ClaimRootClientAuthToken(claimer, nullptr).empty(); + } + + protected: + Config config_{nullptr}; + AuthManager auth_{&config_, {}}; +}; + +TEST_F(AuthManagerClaimTest, WithPreviosOwner) { + EXPECT_DEATH( + TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kNone), ""); + EXPECT_DEATH( + TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kNone), + ""); + EXPECT_DEATH( + TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kNone), ""); + EXPECT_TRUE( + TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kClient)); + EXPECT_FALSE( + TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kClient)); + EXPECT_FALSE( + TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kClient)); + EXPECT_TRUE( + TestClaim(RootClientTokenOwner::kNone, RootClientTokenOwner::kCloud)); + EXPECT_TRUE( + TestClaim(RootClientTokenOwner::kClient, RootClientTokenOwner::kCloud)); + EXPECT_TRUE( + TestClaim(RootClientTokenOwner::kCloud, RootClientTokenOwner::kCloud)); +} + +TEST_F(AuthManagerClaimTest, NormalClaim) { auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); EXPECT_FALSE(auth_.IsValidAuthToken(token)); + EXPECT_EQ(RootClientTokenOwner::kNone, + config_.GetSettings().root_client_token_owner); EXPECT_TRUE(auth_.ConfirmAuthToken(token, nullptr)); EXPECT_TRUE(auth_.IsValidAuthToken(token)); + EXPECT_EQ(RootClientTokenOwner::kCloud, + config_.GetSettings().root_client_token_owner); } -TEST_F(AuthManagerTest, ClaimRootClientAuthTokenDoubleConfirm) { +TEST_F(AuthManagerClaimTest, DoubleConfirm) { auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); EXPECT_TRUE(auth_.ConfirmAuthToken(token, nullptr)); EXPECT_TRUE(auth_.ConfirmAuthToken(token, nullptr)); } -TEST_F(AuthManagerTest, DoubleClaimRootClientAuthToken) { +TEST_F(AuthManagerClaimTest, DoubleClaim) { auto token1 = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); auto token2 = @@ -172,7 +214,7 @@ TEST_F(AuthManagerTest, DoubleClaimRootClientAuthToken) { EXPECT_FALSE(auth_.ConfirmAuthToken(token2, nullptr)); } -TEST_F(AuthManagerTest, ClaimRootClientAuthTokenOverflow) { +TEST_F(AuthManagerClaimTest, TokenOverflow) { auto token = auth_.ClaimRootClientAuthToken(RootClientTokenOwner::kCloud, nullptr); for (size_t i = 0; i < 100; ++i) diff --git a/src/privet/constants.cc b/src/privet/constants.cc index 3cc3e4a..e1962bd 100644 --- a/src/privet/constants.cc +++ b/src/privet/constants.cc @@ -30,6 +30,7 @@ const char kInvalidSsid[] = "invalidSsid"; const char kInvalidPassphrase[] = "invalidPassphrase"; const char kNotFound[] = "notFound"; const char kNotImplemented[] = "notImplemented"; +const char kAlreadyClaimed[] = "alreadyClaimed"; } // namespace errors } // namespace privet diff --git a/src/privet/constants.h b/src/privet/constants.h index 0668879..2b001aa 100644 --- a/src/privet/constants.h +++ b/src/privet/constants.h @@ -32,6 +32,7 @@ extern const char kInvalidSsid[]; extern const char kInvalidPassphrase[]; extern const char kNotFound[]; extern const char kNotImplemented[]; +extern const char kAlreadyClaimed[]; } // namespace errors } // namespace privet } // namespace weave diff --git a/src/privet/privet_handler.cc b/src/privet/privet_handler.cc index 86a2a85..b435435 100644 --- a/src/privet/privet_handler.cc +++ b/src/privet/privet_handler.cc @@ -153,6 +153,7 @@ struct { {errors::kInvalidState, http::kInternalServerError}, {errors::kNotFound, http::kNotFound}, {errors::kNotImplemented, http::kNotSupported}, + {errors::kAlreadyClaimed, http::kDenied}, }; AuthScope AuthScopeFromString(const std::string& scope, AuthScope auto_scope) { |