// Copyright (c) 2012 The Chromium 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 "remoting/protocol/v2_authenticator.h"

#include <utility>

#include "base/base64.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "remoting/base/constants.h"
#include "remoting/base/rsa_key_pair.h"
#include "remoting/protocol/ssl_hmac_channel_authenticator.h"
#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"

using crypto::P224EncryptedKeyExchange;

namespace remoting {
namespace protocol {

namespace {

const buzz::StaticQName kEkeTag = { kChromotingXmlNamespace,
                                    "eke-message" };
const buzz::StaticQName kCertificateTag = { kChromotingXmlNamespace,
                                            "certificate" };

}  // namespace

// static
bool V2Authenticator::IsEkeMessage(const buzz::XmlElement* message) {
  return message->FirstNamed(kEkeTag) != nullptr;
}

// static
std::unique_ptr<Authenticator> V2Authenticator::CreateForClient(
    const std::string& shared_secret,
    Authenticator::State initial_state) {
  return base::WrapUnique(new V2Authenticator(
      P224EncryptedKeyExchange::kPeerTypeClient, shared_secret, initial_state));
}

// static
std::unique_ptr<Authenticator> V2Authenticator::CreateForHost(
    const std::string& local_cert,
    scoped_refptr<RsaKeyPair> key_pair,
    const std::string& shared_secret,
    Authenticator::State initial_state) {
  std::unique_ptr<V2Authenticator> result(new V2Authenticator(
      P224EncryptedKeyExchange::kPeerTypeServer, shared_secret, initial_state));
  result->local_cert_ = local_cert;
  result->local_key_pair_ = key_pair;
  return std::move(result);
}

V2Authenticator::V2Authenticator(
    crypto::P224EncryptedKeyExchange::PeerType type,
    const std::string& shared_secret,
    Authenticator::State initial_state)
    : certificate_sent_(false),
      key_exchange_impl_(type, shared_secret),
      state_(initial_state),
      started_(false),
      rejection_reason_(INVALID_CREDENTIALS) {
  pending_messages_.push(key_exchange_impl_.GetNextMessage());
}

V2Authenticator::~V2Authenticator() = default;

Authenticator::State V2Authenticator::state() const {
  if (state_ == ACCEPTED && !pending_messages_.empty())
    return MESSAGE_READY;
  return state_;
}

bool V2Authenticator::started() const {
  return started_;
}

Authenticator::RejectionReason V2Authenticator::rejection_reason() const {
  DCHECK_EQ(state(), REJECTED);
  return rejection_reason_;
}

void V2Authenticator::ProcessMessage(const buzz::XmlElement* message,
                                     const base::Closure& resume_callback) {
  ProcessMessageInternal(message);
  resume_callback.Run();
}

void V2Authenticator::ProcessMessageInternal(const buzz::XmlElement* message) {
  DCHECK_EQ(state(), WAITING_MESSAGE);

  // Parse the certificate.
  std::string base64_cert = message->TextNamed(kCertificateTag);
  if (!base64_cert.empty()) {
    if (!base::Base64Decode(base64_cert, &remote_cert_)) {
      LOG(WARNING) << "Failed to decode certificate received from the peer.";
      remote_cert_.clear();
    }
  }

  // Client always expect certificate in the first message.
  if (!is_host_side() && remote_cert_.empty()) {
    LOG(WARNING) << "No valid host certificate.";
    state_ = REJECTED;
    rejection_reason_ = PROTOCOL_ERROR;
    return;
  }

  const buzz::XmlElement* eke_element = message->FirstNamed(kEkeTag);
  if (!eke_element) {
    LOG(WARNING) << "No eke-message found.";
    state_ = REJECTED;
    rejection_reason_ = PROTOCOL_ERROR;
    return;
  }

  for (; eke_element; eke_element = eke_element->NextNamed(kEkeTag)) {
    std::string base64_message = eke_element->BodyText();
    std::string spake_message;
    if (base64_message.empty() ||
        !base::Base64Decode(base64_message, &spake_message)) {
      LOG(WARNING) << "Failed to decode auth message received from the peer.";
      state_ = REJECTED;
      rejection_reason_ = PROTOCOL_ERROR;
      return;
    }

    P224EncryptedKeyExchange::Result result =
        key_exchange_impl_.ProcessMessage(spake_message);
    started_ = true;
    switch (result) {
      case P224EncryptedKeyExchange::kResultPending:
        pending_messages_.push(key_exchange_impl_.GetNextMessage());
        break;

      case P224EncryptedKeyExchange::kResultFailed:
        state_ = REJECTED;
        rejection_reason_ = INVALID_CREDENTIALS;
        return;

      case P224EncryptedKeyExchange::kResultSuccess:
        auth_key_ = key_exchange_impl_.GetKey();
        state_ = ACCEPTED;
        return;
    }
  }
  state_ = MESSAGE_READY;
}

std::unique_ptr<buzz::XmlElement> V2Authenticator::GetNextMessage() {
  DCHECK_EQ(state(), MESSAGE_READY);

  std::unique_ptr<buzz::XmlElement> message = CreateEmptyAuthenticatorMessage();

  DCHECK(!pending_messages_.empty());
  while (!pending_messages_.empty()) {
    const std::string& spake_message = pending_messages_.front();
    std::string base64_message;
    base::Base64Encode(spake_message, &base64_message);

    buzz::XmlElement* eke_tag = new buzz::XmlElement(kEkeTag);
    eke_tag->SetBodyText(base64_message);
    message->AddElement(eke_tag);

    pending_messages_.pop();
  }

  if (!local_cert_.empty() && !certificate_sent_) {
    buzz::XmlElement* certificate_tag = new buzz::XmlElement(kCertificateTag);
    std::string base64_cert;
    base::Base64Encode(local_cert_, &base64_cert);
    certificate_tag->SetBodyText(base64_cert);
    message->AddElement(certificate_tag);
    certificate_sent_ = true;
  }

  if (state_ != ACCEPTED) {
    state_ = WAITING_MESSAGE;
  }
  return message;
}

const std::string& V2Authenticator::GetAuthKey() const {
  return auth_key_;
}

std::unique_ptr<ChannelAuthenticator>
V2Authenticator::CreateChannelAuthenticator() const {
  DCHECK_EQ(state(), ACCEPTED);
  CHECK(!auth_key_.empty());

  if (is_host_side()) {
    return SslHmacChannelAuthenticator::CreateForHost(
        local_cert_, local_key_pair_, auth_key_);
  } else {
    return SslHmacChannelAuthenticator::CreateForClient(
        remote_cert_, auth_key_);
  }
}

bool V2Authenticator::is_host_side() const {
  return local_key_pair_.get() != nullptr;
}

}  // namespace protocol
}  // namespace remoting
