// Copyright 2015 The Weave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/privet/auth_manager.h"

#include <algorithm>

#include <base/guid.h>
#include <base/rand_util.h>
#include <base/strings/string_number_conversions.h>

#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"

extern "C" {
#include "third_party/libuweave/src/macaroon.h"
}

namespace weave {
namespace privet {

namespace {

const size_t kMaxMacaroonSize = 1024;
const size_t kMaxPendingClaims = 10;
const char kInvalidTokenError[] = "invalid_token";

template <class T>
void AppendToArray(T value, std::vector<uint8_t>* array) {
  auto begin = reinterpret_cast<const uint8_t*>(&value);
  array->insert(array->end(), begin, begin + sizeof(value));
}

class Caveat {
 public:
  // TODO(vitalybuka): Use _get_buffer_size_ when available.
  Caveat(UwMacaroonCaveatType type, uint32_t value) : buffer(8) {
    CHECK(uw_macaroon_caveat_create_with_uint_(type, value, buffer.data(),
                                               buffer.size(), &caveat));
  }

  // TODO(vitalybuka): Use _get_buffer_size_ when available.
  Caveat(UwMacaroonCaveatType type, const std::string& value)
      : buffer(std::max<size_t>(value.size(), 32u) * 2) {
    CHECK(uw_macaroon_caveat_create_with_str_(
        type, reinterpret_cast<const uint8_t*>(value.data()), value.size(),
        buffer.data(), buffer.size(), &caveat));
  }

  const UwMacaroonCaveat& GetCaveat() const { return caveat; }

 private:
  UwMacaroonCaveat caveat;
  std::vector<uint8_t> buffer;

  DISALLOW_COPY_AND_ASSIGN(Caveat);
};

bool CheckCaveatType(const UwMacaroonCaveat& caveat,
                     UwMacaroonCaveatType type,
                     ErrorPtr* error) {
  UwMacaroonCaveatType caveat_type{};
  if (!uw_macaroon_caveat_get_type_(&caveat, &caveat_type)) {
    Error::AddTo(error, FROM_HERE, kInvalidTokenError, "Unable to get type");
    return false;
  }

  if (caveat_type != type) {
    Error::AddTo(error, FROM_HERE, kInvalidTokenError,
                 "Unexpected caveat type");
    return false;
  }

  return true;
}

bool ReadCaveat(const UwMacaroonCaveat& caveat,
                UwMacaroonCaveatType type,
                uint32_t* value,
                ErrorPtr* error) {
  if (!CheckCaveatType(caveat, type, error))
    return false;

  if (!uw_macaroon_caveat_get_value_uint_(&caveat, value)) {
    Error::AddTo(error, FROM_HERE, kInvalidTokenError, "Unable to read caveat");
    return false;
  }

  return true;
}

bool ReadCaveat(const UwMacaroonCaveat& caveat,
                UwMacaroonCaveatType type,
                std::string* value,
                ErrorPtr* error) {
  if (!CheckCaveatType(caveat, type, error))
    return false;

  const uint8_t* start{nullptr};
  size_t size{0};
  if (!uw_macaroon_caveat_get_value_str_(&caveat, &start, &size)) {
    Error::AddTo(error, FROM_HERE, kInvalidTokenError, "Unable to read caveat");
    return false;
  }

  value->assign(reinterpret_cast<const char*>(start), size);
  return true;
}

std::vector<uint8_t> CreateSecret() {
  std::vector<uint8_t> secret(kSha256OutputSize);
  base::RandBytes(secret.data(), secret.size());
  return secret;
}

bool IsClaimAllowed(RootClientTokenOwner curret, RootClientTokenOwner claimer) {
  return claimer > curret || claimer == RootClientTokenOwner::kCloud;
}

std::vector<uint8_t> CreateMacaroonToken(
    const std::vector<uint8_t>& secret,
    const std::vector<UwMacaroonCaveat>& caveats) {
  CHECK_EQ(kSha256OutputSize, secret.size());
  UwMacaroon macaroon{};
  CHECK(uw_macaroon_new_from_root_key_(&macaroon, secret.data(), secret.size(),
                                       caveats.data(), caveats.size()));

  std::vector<uint8_t> token(kMaxMacaroonSize);
  size_t len = 0;
  CHECK(uw_macaroon_dump_(&macaroon, token.data(), token.size(), &len));
  token.resize(len);

  return token;
}

bool LoadMacaroon(const std::vector<uint8_t>& token,
                  std::vector<uint8_t>* buffer,
                  UwMacaroon* macaroon,
                  ErrorPtr* error) {
  buffer->resize(kMaxMacaroonSize);
  if (!uw_macaroon_load_(token.data(), token.size(), buffer->data(),
                         buffer->size(), macaroon)) {
    Error::AddTo(error, FROM_HERE, kInvalidTokenError, "Invalid token format");
    return false;
  }
  return true;
}

bool VerifyMacaroon(const std::vector<uint8_t>& secret,
                    const UwMacaroon& macaroon,
                    ErrorPtr* error) {
  CHECK_EQ(kSha256OutputSize, secret.size());
  if (!uw_macaroon_verify_(&macaroon, secret.data(), secret.size())) {
    Error::AddTo(error, FROM_HERE, "invalid_signature",
                 "Invalid token signature");
    return false;
  }
  return true;
}

UwMacaroonCaveatScopeType ToMacaroonScope(AuthScope scope) {
  switch (scope) {
    case AuthScope::kViewer:
      return kUwMacaroonCaveatScopeTypeViewer;
    case AuthScope::kUser:
      return kUwMacaroonCaveatScopeTypeUser;
    case AuthScope::kManager:
      return kUwMacaroonCaveatScopeTypeManager;
    case AuthScope::kOwner:
      return kUwMacaroonCaveatScopeTypeOwner;
    default:
      NOTREACHED() << EnumToString(scope);
  }
  return kUwMacaroonCaveatScopeTypeViewer;
}

AuthScope FromMacaroonScope(uint32_t scope) {
  if (scope <= kUwMacaroonCaveatScopeTypeOwner)
    return AuthScope::kOwner;
  if (scope <= kUwMacaroonCaveatScopeTypeManager)
    return AuthScope::kManager;
  if (scope <= kUwMacaroonCaveatScopeTypeUser)
    return AuthScope::kUser;
  if (scope <= kUwMacaroonCaveatScopeTypeViewer)
    return AuthScope::kViewer;
  return AuthScope::kNone;
}

}  // namespace

AuthManager::AuthManager(Config* config,
                         const std::vector<uint8_t>& certificate_fingerprint)
    : config_{config},
      certificate_fingerprint_{certificate_fingerprint},
      access_secret_{CreateSecret()} {
  if (config_) {
    SetAuthSecret(config_->GetSettings().secret,
                  config_->GetSettings().root_client_token_owner);
  } else {
    SetAuthSecret({}, RootClientTokenOwner::kNone);
  }
}

AuthManager::AuthManager(const std::vector<uint8_t>& auth_secret,
                         const std::vector<uint8_t>& certificate_fingerprint,
                         const std::vector<uint8_t>& access_secret,
                         base::Clock* clock)
    : AuthManager(nullptr, certificate_fingerprint) {
  access_secret_ = access_secret.size() == kSha256OutputSize ? access_secret
                                                             : CreateSecret();
  SetAuthSecret(auth_secret, RootClientTokenOwner::kNone);
  if (clock)
    clock_ = clock;
}

void AuthManager::SetAuthSecret(const std::vector<uint8_t>& secret,
                                RootClientTokenOwner owner) {
  auth_secret_ = secret;

  if (auth_secret_.size() != kSha256OutputSize) {
    auth_secret_ = CreateSecret();
    owner = RootClientTokenOwner::kNone;
  }

  if (!config_ || (config_->GetSettings().secret == auth_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() {}

std::vector<uint8_t> AuthManager::CreateAccessToken(const UserInfo& user_info,
                                                    base::TimeDelta ttl) const {
  Caveat scope{kUwMacaroonCaveatTypeScope, ToMacaroonScope(user_info.scope())};
  Caveat user{kUwMacaroonCaveatTypeIdentifier, user_info.user_id()};
  Caveat issued{kUwMacaroonCaveatTypeExpiration,
                static_cast<uint32_t>((Now() + ttl).ToTimeT())};
  return CreateMacaroonToken(
      access_secret_,
      {
          scope.GetCaveat(), user.GetCaveat(), issued.GetCaveat(),
      });
}

bool AuthManager::ParseAccessToken(const std::vector<uint8_t>& token,
                                   UserInfo* user_info,
                                   ErrorPtr* error) const {
  std::vector<uint8_t> buffer;
  UwMacaroon macaroon{};

  uint32_t scope{0};
  std::string user_id;
  uint32_t expiration{0};

  if (!LoadMacaroon(token, &buffer, &macaroon, error) ||
      !VerifyMacaroon(access_secret_, macaroon, error) ||
      macaroon.num_caveats != 3 ||
      !ReadCaveat(macaroon.caveats[0], kUwMacaroonCaveatTypeScope, &scope,
                  error) ||
      !ReadCaveat(macaroon.caveats[1], kUwMacaroonCaveatTypeIdentifier,
                  &user_id, error) ||
      !ReadCaveat(macaroon.caveats[2], kUwMacaroonCaveatTypeExpiration,
                  &expiration, error)) {
    Error::AddTo(error, FROM_HERE, errors::kInvalidAuthorization,
                 "Invalid token");
    return false;
  }

  AuthScope auth_scope{FromMacaroonScope(scope)};
  if (auth_scope == AuthScope::kNone) {
    Error::AddTo(error, FROM_HERE, errors::kInvalidAuthorization,
                 "Invalid token data");
    return false;
  }

  base::Time time{base::Time::FromTimeT(expiration)};
  if (time < clock_->Now()) {
    Error::AddTo(error, FROM_HERE, errors::kAuthorizationExpired,
                 "Token is expired");
    return false;
  }

  if (user_info)
    *user_info = UserInfo{auth_scope, user_id};

  return true;
}

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::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)
    pending_claims_.pop_front();
  return pending_claims_.back().first->GetRootClientAuthToken();
}

bool AuthManager::ConfirmClientAuthToken(const std::vector<uint8_t>& token,
                                         ErrorPtr* error) {
  // Cover case when caller sent confirm twice.
  if (pending_claims_.empty())
    return IsValidAuthToken(token, error);

  auto claim =
      std::find_if(pending_claims_.begin(), pending_claims_.end(),
                   [&token](const decltype(pending_claims_)::value_type& auth) {
                     return auth.first->IsValidAuthToken(token, nullptr);
                   });
  if (claim == pending_claims_.end()) {
    Error::AddTo(error, FROM_HERE, errors::kNotFound, "Unknown claim");
    return false;
  }

  SetAuthSecret(claim->first->GetAuthSecret(), claim->second);
  pending_claims_.clear();
  return true;
}

std::vector<uint8_t> AuthManager::GetRootClientAuthToken() const {
  Caveat scope{kUwMacaroonCaveatTypeScope, kUwMacaroonCaveatScopeTypeOwner};
  Caveat issued{kUwMacaroonCaveatTypeIssued,
                static_cast<uint32_t>(Now().ToTimeT())};
  return CreateMacaroonToken(auth_secret_,
                             {
                                 scope.GetCaveat(), issued.GetCaveat(),
                             });
}

base::Time AuthManager::Now() const {
  return clock_->Now();
}

bool AuthManager::IsValidAuthToken(const std::vector<uint8_t>& token,
                                   ErrorPtr* error) const {
  std::vector<uint8_t> buffer;
  UwMacaroon macaroon{};
  if (!LoadMacaroon(token, &buffer, &macaroon, error) ||
      !VerifyMacaroon(auth_secret_, macaroon, error)) {
    Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode, "Invalid token");
    return false;
  }
  return true;
}

bool AuthManager::CreateAccessTokenFromAuth(
    const std::vector<uint8_t>& auth_token,
    base::TimeDelta ttl,
    std::vector<uint8_t>* access_token,
    AuthScope* access_token_scope,
    base::TimeDelta* access_token_ttl,
    ErrorPtr* error) const {
  // TODO(vitalybuka): implement token validation.
  if (!IsValidAuthToken(auth_token, error))
    return false;

  if (!access_token)
    return true;

  // TODO(vitalybuka): User and scope must be parsed from auth_token.
  UserInfo info{config_ ? config_->GetSettings().local_anonymous_access_role
                        : AuthScope::kViewer,
                base::GenerateGUID()};

  // TODO(vitalybuka): TTL also should be reduced in accordance with auth_token.
  *access_token = CreateAccessToken(info, ttl);

  if (access_token_scope)
    *access_token_scope = info.scope();

  if (access_token_ttl)
    *access_token_ttl = ttl;
  return true;
}

std::vector<uint8_t> AuthManager::CreateSessionId() {
  std::vector<uint8_t> result;
  AppendToArray(Now().ToTimeT(), &result);
  AppendToArray(++session_counter_, &result);
  return result;
}

}  // namespace privet
}  // namespace weave
