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>
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 @@
   return secret;
 }
 
+bool IsClaimAllowed(RootClientTokenOwner curret, RootClientTokenOwner claimer) {
+  return claimer > curret || claimer == RootClientTokenOwner::kCloud;
+}
+
 }  // namespace
 
 AuthManager::AuthManager(Config* config,
@@ -148,6 +153,17 @@
 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 @@
                    [&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();