// 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/me2me_host_authenticator_factory.h"

#include "base/base64.h"
#include "base/strings/string_util.h"
#include "remoting/base/rsa_key_pair.h"
#include "remoting/protocol/channel_authenticator.h"
#include "remoting/protocol/negotiating_host_authenticator.h"
#include "remoting/protocol/token_validator.h"
#include "third_party/webrtc/libjingle/xmllite/xmlelement.h"

namespace remoting {
namespace protocol {

namespace {

// Authenticator that accepts one message and rejects connection after that.
class RejectingAuthenticator : public Authenticator {
 public:
  RejectingAuthenticator()
      : state_(WAITING_MESSAGE) {
  }
  ~RejectingAuthenticator() override {}

  State state() const override { return state_; }

  bool started() const override { return true; }

  RejectionReason rejection_reason() const override {
    DCHECK_EQ(state_, REJECTED);
    return INVALID_CREDENTIALS;
  }

  void ProcessMessage(const buzz::XmlElement* message,
                      const base::Closure& resume_callback) override {
    DCHECK_EQ(state_, WAITING_MESSAGE);
    state_ = REJECTED;
    resume_callback.Run();
  }

  scoped_ptr<buzz::XmlElement> GetNextMessage() override {
    NOTREACHED();
    return nullptr;
  }

  scoped_ptr<ChannelAuthenticator> CreateChannelAuthenticator() const override {
    NOTREACHED();
    return nullptr;
  }

 protected:
  State state_;
};

}  // namespace

// static
scoped_ptr<AuthenticatorFactory>
Me2MeHostAuthenticatorFactory::CreateWithSharedSecret(
    bool use_service_account,
    const std::string& host_owner,
    const std::string& local_cert,
    scoped_refptr<RsaKeyPair> key_pair,
    const SharedSecretHash& shared_secret_hash,
    scoped_refptr<PairingRegistry> pairing_registry) {
  scoped_ptr<Me2MeHostAuthenticatorFactory> result(
      new Me2MeHostAuthenticatorFactory());
  result->use_service_account_ = use_service_account;
  result->host_owner_ = host_owner;
  result->local_cert_ = local_cert;
  result->key_pair_ = key_pair;
  result->shared_secret_hash_ = shared_secret_hash;
  result->pairing_registry_ = pairing_registry;
  return result.Pass();
}


// static
scoped_ptr<AuthenticatorFactory>
Me2MeHostAuthenticatorFactory::CreateWithThirdPartyAuth(
    bool use_service_account,
    const std::string& host_owner,
    const std::string& local_cert,
    scoped_refptr<RsaKeyPair> key_pair,
    scoped_ptr<TokenValidatorFactory>
        token_validator_factory) {
  scoped_ptr<Me2MeHostAuthenticatorFactory> result(
      new Me2MeHostAuthenticatorFactory());
  result->use_service_account_ = use_service_account;
  result->host_owner_ = host_owner;
  result->local_cert_ = local_cert;
  result->key_pair_ = key_pair;
  result->token_validator_factory_ = token_validator_factory.Pass();
  return result.Pass();
}

// static
scoped_ptr<AuthenticatorFactory>
    Me2MeHostAuthenticatorFactory::CreateRejecting() {
  return make_scoped_ptr(new Me2MeHostAuthenticatorFactory());
}

Me2MeHostAuthenticatorFactory::Me2MeHostAuthenticatorFactory() {
}

Me2MeHostAuthenticatorFactory::~Me2MeHostAuthenticatorFactory() {
}

scoped_ptr<Authenticator> Me2MeHostAuthenticatorFactory::CreateAuthenticator(
    const std::string& local_jid,
    const std::string& remote_jid,
    const buzz::XmlElement* first_message) {

  std::string remote_jid_prefix;

  if (!use_service_account_) {
    // JID prefixes may not match the host owner email, for example, in cases
    // where the host owner account does not have an email associated with it.
    // In those cases, the only guarantee we have is that JIDs for the same
    // account will have the same prefix.
    size_t slash_pos = local_jid.find('/');
    if (slash_pos == std::string::npos) {
      LOG(DFATAL) << "Invalid local JID:" << local_jid;
      return make_scoped_ptr(new RejectingAuthenticator());
    }
    remote_jid_prefix = local_jid.substr(0, slash_pos);
  } else {
    // TODO(rmsousa): This only works for cases where the JID prefix matches
    // the host owner email. Figure out a way to verify the JID in other cases.
    remote_jid_prefix = host_owner_;
  }

  // Verify that the client's jid is an ASCII string, and then check that the
  // client JID has the expected prefix. Comparison is case insensitive.
  if (!base::IsStringASCII(remote_jid) ||
      !StartsWithASCII(remote_jid, remote_jid_prefix + '/', false)) {
    LOG(ERROR) << "Rejecting incoming connection from " << remote_jid;
    return make_scoped_ptr(new RejectingAuthenticator());
  }

  if (!local_cert_.empty() && key_pair_.get()) {
    if (token_validator_factory_) {
      return NegotiatingHostAuthenticator::CreateWithThirdPartyAuth(
          local_cert_, key_pair_,
          token_validator_factory_->CreateTokenValidator(
              local_jid, remote_jid));
    }

    return NegotiatingHostAuthenticator::CreateWithSharedSecret(
        local_cert_, key_pair_, shared_secret_hash_.value,
        shared_secret_hash_.hash_function, pairing_registry_);
  }

  return make_scoped_ptr(new RejectingAuthenticator());
}

}  // namespace protocol
}  // namespace remoting
