// 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/bind.h>
#include <base/guid.h>
#include <base/rand_util.h>
#include <base/strings/string_number_conversions.h>

#include "src/access_revocation_manager.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"
#include "src/utils.h"

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

namespace weave {
namespace privet {

namespace {

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

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:
  Caveat(UwMacaroonCaveatType type, size_t str_len)
      : buffer_(uw_macaroon_caveat_creation_get_buffsize_(type, str_len)) {
    CHECK(!buffer_.empty());
  }
  const UwMacaroonCaveat& GetCaveat() const { return caveat_; }

 protected:
  UwMacaroonCaveat caveat_{};
  std::vector<uint8_t> buffer_;

  DISALLOW_COPY_AND_ASSIGN(Caveat);
};

class ScopeCaveat : public Caveat {
 public:
  explicit ScopeCaveat(UwMacaroonCaveatScopeType scope)
      : Caveat(kUwMacaroonCaveatTypeScope, 0) {
    CHECK(uw_macaroon_caveat_create_scope_(scope, buffer_.data(),
                                           buffer_.size(), &caveat_));
  }

  DISALLOW_COPY_AND_ASSIGN(ScopeCaveat);
};

class TimestampCaveat : public Caveat {
 public:
  explicit TimestampCaveat(const base::Time& timestamp)
      : Caveat(kUwMacaroonCaveatTypeDelegationTimestamp, 0) {
    CHECK(uw_macaroon_caveat_create_delegation_timestamp_(
        ToJ2000Time(timestamp), buffer_.data(), buffer_.size(), &caveat_));
  }

  DISALLOW_COPY_AND_ASSIGN(TimestampCaveat);
};

class ExpirationCaveat : public Caveat {
 public:
  explicit ExpirationCaveat(const base::Time& timestamp)
      : Caveat(kUwMacaroonCaveatTypeExpirationAbsolute, 0) {
    CHECK(uw_macaroon_caveat_create_expiration_absolute_(
        ToJ2000Time(timestamp), buffer_.data(), buffer_.size(), &caveat_));
  }

  DISALLOW_COPY_AND_ASSIGN(ExpirationCaveat);
};

class UserIdCaveat : public Caveat {
 public:
  explicit UserIdCaveat(const std::vector<uint8_t>& id)
      : Caveat(kUwMacaroonCaveatTypeDelegateeUser, id.size()) {
    CHECK(uw_macaroon_caveat_create_delegatee_user_(
        id.data(), id.size(), buffer_.data(), buffer_.size(), &caveat_));
  }

  DISALLOW_COPY_AND_ASSIGN(UserIdCaveat);
};

class AppIdCaveat : public Caveat {
 public:
  explicit AppIdCaveat(const std::vector<uint8_t>& id)
      : Caveat(kUwMacaroonCaveatTypeDelegateeApp, id.size()) {
    CHECK(uw_macaroon_caveat_create_delegatee_app_(
        id.data(), id.size(), buffer_.data(), buffer_.size(), &caveat_));
  }

  DISALLOW_COPY_AND_ASSIGN(AppIdCaveat);
};

class ServiceCaveat : public Caveat {
 public:
  explicit ServiceCaveat(UwMacaroonCaveatCloudServiceId service_id)
      : Caveat(kUwMacaroonCaveatTypeDelegateeService, 0) {
    CHECK(uw_macaroon_caveat_create_delegatee_service_(
        service_id, buffer_.data(), buffer_.size(), &caveat_));
  }

  DISALLOW_COPY_AND_ASSIGN(ServiceCaveat);
};

class SessionIdCaveat : public Caveat {
 public:
  explicit SessionIdCaveat(const std::string& id)
      : Caveat(kUwMacaroonCaveatTypeLanSessionID, id.size()) {
    CHECK(uw_macaroon_caveat_create_lan_session_id_(
        reinterpret_cast<const uint8_t*>(id.data()), id.size(), buffer_.data(),
        buffer_.size(), &caveat_));
  }

  DISALLOW_COPY_AND_ASSIGN(SessionIdCaveat);
};

class ClientAuthTokenCaveat : public Caveat {
 public:
  ClientAuthTokenCaveat()
      : Caveat(kUwMacaroonCaveatTypeClientAuthorizationTokenV1, 0) {
    CHECK(uw_macaroon_caveat_create_client_authorization_token_(
        nullptr, 0, buffer_.data(), buffer_.size(), &caveat_));
  }

  DISALLOW_COPY_AND_ASSIGN(ClientAuthTokenCaveat);
};

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 base::Time& time,
    const std::vector<const UwMacaroonCaveat*>& caveats) {
  CHECK_EQ(kSha256OutputSize, secret.size());

  UwMacaroonContext context{};
  CHECK(uw_macaroon_context_create_(ToJ2000Time(time), nullptr, 0, nullptr, 0,
                                    &context));

  UwMacaroon macaroon{};
  CHECK(uw_macaroon_create_from_root_key_(&macaroon, secret.data(),
                                          secret.size(), &context,
                                          caveats.data(), caveats.size()));

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

  return serialized_token;
}

std::vector<uint8_t> ExtendMacaroonToken(
    const UwMacaroon& macaroon,
    const base::Time& time,
    const std::vector<const UwMacaroonCaveat*>& caveats) {
  UwMacaroonContext context{};
  CHECK(uw_macaroon_context_create_(ToJ2000Time(time), nullptr, 0, nullptr, 0,
                                    &context));

  UwMacaroon prev_macaroon = macaroon;
  std::vector<uint8_t> prev_buffer(kMaxMacaroonSize);
  std::vector<uint8_t> new_buffer(kMaxMacaroonSize);

  for (auto caveat : caveats) {
    UwMacaroon new_macaroon{};
    CHECK(uw_macaroon_extend_(&prev_macaroon, &new_macaroon, &context, caveat,
                              new_buffer.data(), new_buffer.size()));
    new_buffer.swap(prev_buffer);
    prev_macaroon = new_macaroon;
  }

  std::vector<uint8_t> serialized_token(kMaxMacaroonSize);
  size_t len = 0;
  CHECK(uw_macaroon_serialize_(&prev_macaroon, serialized_token.data(),
                               serialized_token.size(), &len));
  serialized_token.resize(len);

  return serialized_token;
}

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

bool VerifyMacaroon(const std::vector<uint8_t>& secret,
                    const UwMacaroon& macaroon,
                    const base::Time& time,
                    UwMacaroonValidationResult* result,
                    ErrorPtr* error) {
  CHECK_EQ(kSha256OutputSize, secret.size());
  UwMacaroonContext context = {};
  CHECK(uw_macaroon_context_create_(ToJ2000Time(time), nullptr, 0, nullptr, 0,
                                    &context));

  if (!uw_macaroon_validate_(&macaroon, secret.data(), secret.size(), &context,
                             result)) {
    return Error::AddTo(error, FROM_HERE, "invalid_token",
                        "Invalid token signature");
  }
  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,
                         AccessRevocationManager* black_list,
                         const std::vector<uint8_t>& certificate_fingerprint)
    : config_{config},
      black_list_{black_list},
      certificate_fingerprint_{certificate_fingerprint},
      access_secret_{CreateSecret()} {
  if (black_list_) {
    black_list_->AddEntryAddedCallback(base::Bind(
        &AuthManager::ResetAccessSecret, weak_ptr_factory_.GetWeakPtr()));
  }
  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,
                         AccessRevocationManager* black_list)
    : AuthManager(nullptr, black_list, 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 {
  const base::Time now = Now();
  TimestampCaveat issued{now};
  ScopeCaveat scope{ToMacaroonScope(user_info.scope())};
  // Macaroons have no caveats for auth type. So we just append the type to the
  // user ID.
  std::vector<uint8_t> id_with_type{user_info.id().user};
  id_with_type.push_back(static_cast<uint8_t>(user_info.id().type));
  UserIdCaveat user{id_with_type};
  AppIdCaveat app{user_info.id().app};
  ExpirationCaveat expiration{now + ttl};
  return CreateMacaroonToken(
      access_secret_, now,
      {

          &issued.GetCaveat(), &scope.GetCaveat(), &user.GetCaveat(),
          &app.GetCaveat(), &expiration.GetCaveat(),
      });
}

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

  UwMacaroonValidationResult result{};
  const base::Time now = Now();
  if (!LoadMacaroon(token, &buffer, &macaroon, error) ||
      macaroon.num_caveats != 5 ||
      !VerifyMacaroon(access_secret_, macaroon, now, &result, error)) {
    return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthorization,
                        "Invalid token");
  }

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

  // If token is valid and token was not extended, it should has precisely this
  // values.
  CHECK_GE(FromJ2000Time(result.expiration_time), now);
  CHECK_EQ(2u, result.num_delegatees);
  CHECK_EQ(kUwMacaroonDelegateeTypeUser, result.delegatees[0].type);
  CHECK_EQ(kUwMacaroonDelegateeTypeApp, result.delegatees[1].type);
  CHECK_GT(result.delegatees[0].id_len, 1u);
  std::vector<uint8_t> user_id{
      result.delegatees[0].id,
      result.delegatees[0].id + result.delegatees[0].id_len};
  // Last byte is used for type. See |CreateAccessToken|.
  AuthType type = static_cast<AuthType>(user_id.back());
  user_id.pop_back();

  std::vector<uint8_t> app_id{
      result.delegatees[1].id,
      result.delegatees[1].id + result.delegatees[1].id_len};
  if (user_info)
    *user_info = UserInfo{auth_scope, UserAppId{type, user_id, app_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, nullptr, {}}},
      owner));
  if (pending_claims_.size() > kMaxPendingClaims)
    pending_claims_.pop_front();
  return pending_claims_.back().first->GetRootClientAuthToken(owner);
}

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()) {
    return Error::AddTo(error, FROM_HERE, errors::kNotFound, "Unknown claim");
  }

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

std::vector<uint8_t> AuthManager::GetRootClientAuthToken(
    RootClientTokenOwner owner) const {
  CHECK(RootClientTokenOwner::kNone != owner);
  ClientAuthTokenCaveat auth_token;
  const base::Time now = Now();
  TimestampCaveat issued{now};

  ServiceCaveat client{owner == RootClientTokenOwner::kCloud
                           ? kUwMacaroonCaveatCloudServiceIdGoogleWeave
                           : kUwMacaroonCaveatCloudServiceIdNotCloudRegistered};
  return CreateMacaroonToken(
      auth_secret_, now,
      {
          &auth_token.GetCaveat(), &issued.GetCaveat(), &client.GetCaveat(),
      });
}

base::Time AuthManager::Now() const {
  base::Time now = clock_->Now();
  static const base::Time k2010 = base::Time::FromTimeT(1262304000);
  if (now >= k2010)
    return now;
  // Slowdown time before 1 Jan 2010. This will increase expiration time of
  // access tokens but allow to handle dates which can not be handled by
  // macaroon library.
  return k2010 - base::TimeDelta::FromSeconds((k2010 - now).InSeconds() / 10);
}

bool AuthManager::IsValidAuthToken(const std::vector<uint8_t>& token,
                                   ErrorPtr* error) const {
  std::vector<uint8_t> buffer;
  UwMacaroon macaroon{};
  UwMacaroonValidationResult result{};
  if (!LoadMacaroon(token, &buffer, &macaroon, error) ||
      !VerifyMacaroon(auth_secret_, macaroon, Now(), &result, error)) {
    return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode,
                        "Invalid token");
  }
  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 {
  std::vector<uint8_t> buffer;
  UwMacaroon macaroon{};
  UwMacaroonValidationResult result{};
  const base::Time now = Now();
  if (!LoadMacaroon(auth_token, &buffer, &macaroon, error) ||
      !VerifyMacaroon(auth_secret_, macaroon, now, &result, error)) {
    return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode,
                        "Invalid token");
  }

  AuthScope auth_scope{FromMacaroonScope(result.granted_scope)};
  if (auth_scope == AuthScope::kNone) {
    return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode,
                        "Invalid token data");
  }

  // TODO: Integrate black list checks.
  auto delegates_rbegin = std::reverse_iterator<const UwMacaroonDelegateeInfo*>(
      result.delegatees + result.num_delegatees);
  auto delegates_rend =
      std::reverse_iterator<const UwMacaroonDelegateeInfo*>(result.delegatees);
  auto last_user_id =
      std::find_if(delegates_rbegin, delegates_rend,
                   [](const UwMacaroonDelegateeInfo& delegatee) {
                     return delegatee.type == kUwMacaroonDelegateeTypeUser;
                   });
  auto last_app_id =
      std::find_if(delegates_rbegin, delegates_rend,
                   [](const UwMacaroonDelegateeInfo& delegatee) {
                     return delegatee.type == kUwMacaroonDelegateeTypeApp;
                   });

  if (last_user_id == delegates_rend || !last_user_id->id_len) {
    return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode,
                        "User ID is missing");
  }

  const char* session_id = reinterpret_cast<const char*>(result.lan_session_id);
  if (!IsValidSessionId({session_id, session_id + result.lan_session_id_len})) {
    return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode,
                        "Invalid session id");
  }

  if (black_list_) {
    std::vector<uint8_t> user_id;
    std::vector<uint8_t> app_id;
    for (size_t i = 0; i < result.num_delegatees; ++i) {
      if (result.delegatees[i].type == kUwMacaroonDelegateeTypeUser) {
        user_id.assign(result.delegatees[i].id,
                       result.delegatees[i].id + result.delegatees[i].id_len);
      } else if (result.delegatees[i].type == kUwMacaroonDelegateeTypeApp) {
        app_id.assign(result.delegatees[i].id,
                      result.delegatees[i].id + result.delegatees[i].id_len);
      } else {
        // Do not block by other types of delegatees.
        continue;
      }
      if (black_list_->IsBlocked(
              user_id, app_id, FromJ2000Time(result.delegatees[i].timestamp))) {
        return Error::AddTo(error, FROM_HERE, errors::kInvalidAuthCode,
                            "Auth token is revoked");
      }
    }
  }

  CHECK_GE(FromJ2000Time(result.expiration_time), now);

  if (!access_token)
    return true;

  std::vector<uint8_t> user_id{last_user_id->id,
                               last_user_id->id + last_user_id->id_len};
  std::vector<uint8_t> app_id;
  if (last_app_id != delegates_rend)
    app_id.assign(last_app_id->id, last_app_id->id + last_app_id->id_len);

  UserInfo info{auth_scope, {AuthType::kLocal, user_id, app_id}};

  ttl = std::min(ttl, FromJ2000Time(result.expiration_time) - now);
  *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::string AuthManager::CreateSessionId() const {
  return std::to_string(ToJ2000Time(Now())) + ":" +
         std::to_string(++session_counter_);
}

bool AuthManager::IsValidSessionId(const std::string& session_id) const {
  base::Time ssid_time = FromJ2000Time(std::atoi(session_id.c_str()));
  return Now() - base::TimeDelta::FromMinutes(kSessionIdTtlMinutes) <=
             ssid_time &&
         ssid_time <= Now();
}

void AuthManager::ResetAccessSecret() {
  auto new_secret = CreateSecret();
  CHECK(new_secret != access_secret_);
  access_secret_.swap(new_secret);
}

std::vector<uint8_t> AuthManager::DelegateToUser(
    const std::vector<uint8_t>& token,
    base::TimeDelta ttl,
    const UserInfo& user_info) const {
  std::vector<uint8_t> buffer;
  UwMacaroon macaroon{};
  CHECK(LoadMacaroon(token, &buffer, &macaroon, nullptr));

  const base::Time now = Now();
  TimestampCaveat issued{now};
  ExpirationCaveat expiration{now + ttl};
  ScopeCaveat scope{ToMacaroonScope(user_info.scope())};
  UserIdCaveat user{user_info.id().user};
  AppIdCaveat app{user_info.id().app};
  SessionIdCaveat session{CreateSessionId()};

  std::vector<const UwMacaroonCaveat*> caveats{
      &issued.GetCaveat(), &expiration.GetCaveat(), &scope.GetCaveat(),
      &user.GetCaveat(),
  };

  if (!user_info.id().app.empty())
    caveats.push_back(&app.GetCaveat());

  caveats.push_back(&session.GetCaveat());

  return ExtendMacaroonToken(macaroon, now, caveats);
}

}  // namespace privet
}  // namespace weave
