// Copyright 2013 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/host/it2me/it2me_host.h"

#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/policy/policy_constants.h"
#include "net/url_request/url_request_context_getter.h"
#include "remoting/base/auto_thread.h"
#include "remoting/base/chromium_url_request.h"
#include "remoting/base/logging.h"
#include "remoting/base/rsa_key_pair.h"
#include "remoting/base/service_urls.h"
#include "remoting/host/chromoting_host.h"
#include "remoting/host/chromoting_host_context.h"
#include "remoting/host/host_event_logger.h"
#include "remoting/host/host_secret.h"
#include "remoting/host/host_status_logger.h"
#include "remoting/host/it2me/it2me_confirmation_dialog.h"
#include "remoting/host/it2me_desktop_environment.h"
#include "remoting/host/register_support_host_request.h"
#include "remoting/protocol/auth_util.h"
#include "remoting/protocol/chromium_port_allocator_factory.h"
#include "remoting/protocol/ice_transport.h"
#include "remoting/protocol/it2me_host_authenticator_factory.h"
#include "remoting/protocol/jingle_session_manager.h"
#include "remoting/protocol/network_settings.h"
#include "remoting/protocol/transport_context.h"
#include "remoting/protocol/validating_authenticator.h"
#include "remoting/signaling/jid_util.h"
#include "remoting/signaling/server_log_entry.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

namespace remoting {

using protocol::ErrorCode;

namespace {

// This is used for tagging system event logs.
const char kApplicationName[] = "chromoting";
const int kMaxLoginAttempts = 5;

using protocol::ValidatingAuthenticator;
typedef ValidatingAuthenticator::Result ValidationResult;
typedef ValidatingAuthenticator::ValidationCallback ValidationCallback;
typedef ValidatingAuthenticator::ResultCallback ValidationResultCallback;

}  // namespace

It2MeHost::It2MeHost() = default;

It2MeHost::~It2MeHost() {
  // Check that resources that need to be torn down on the UI thread are gone.
  DCHECK(!desktop_environment_factory_.get());
}

void It2MeHost::set_enable_dialogs(bool enable) {
#if defined(OS_CHROMEOS)
  enable_dialogs_ = enable;
#else
  NOTREACHED() << "It2MeHost::set_enable_dialogs is only supported on ChromeOS";
#endif
}

void It2MeHost::Connect(
    std::unique_ptr<ChromotingHostContext> host_context,
    std::unique_ptr<base::DictionaryValue> policies,
    std::unique_ptr<It2MeConfirmationDialogFactory> dialog_factory,
    base::WeakPtr<It2MeHost::Observer> observer,
    std::unique_ptr<SignalStrategy> signal_strategy,
    const std::string& username,
    const std::string& directory_bot_jid,
    const protocol::IceConfig& ice_config) {
  DCHECK(host_context->ui_task_runner()->BelongsToCurrentThread());

  host_context_ = std::move(host_context);
  observer_ = std::move(observer);
  confirmation_dialog_factory_ = std::move(dialog_factory);
  signal_strategy_ = std::move(signal_strategy);

  OnPolicyUpdate(std::move(policies));

  desktop_environment_factory_.reset(new It2MeDesktopEnvironmentFactory(
      host_context_->network_task_runner(),
      host_context_->video_capture_task_runner(),
      host_context_->input_task_runner(), host_context_->ui_task_runner(),
      host_context_->system_input_injector_factory()));

  // Switch to the network thread to start the actual connection.
  host_context_->network_task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&It2MeHost::ConnectOnNetworkThread, this,
                                username, directory_bot_jid, ice_config));
}

void It2MeHost::Disconnect() {
  DCHECK(host_context_->ui_task_runner()->BelongsToCurrentThread());
  host_context_->network_task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&It2MeHost::DisconnectOnNetworkThread, this));
}

void It2MeHost::ConnectOnNetworkThread(const std::string& username,
                                       const std::string& directory_bot_jid,
                                       const protocol::IceConfig& ice_config) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());
  DCHECK_EQ(kDisconnected, state_);

  SetState(kStarting, ErrorCode::OK);

  // Check the host domain policy.
  if (!required_host_domain_list_.empty()) {
    bool matched = false;
    for (const auto& domain : required_host_domain_list_) {
      if (base::EndsWith(username, std::string("@") + domain,
                         base::CompareCase::INSENSITIVE_ASCII)) {
        matched = true;
        break;
      }
    }
    if (!matched) {
      SetState(kInvalidDomainError, ErrorCode::OK);
      return;
    }
  }

  // Generate a key pair for the Host to use.
  // TODO(wez): Move this to the worker thread.
  host_key_pair_ = RsaKeyPair::Generate();

  // Request registration of the host for support.
  std::unique_ptr<RegisterSupportHostRequest> register_request(
      new RegisterSupportHostRequest(
          signal_strategy_.get(), host_key_pair_, directory_bot_jid,
          base::Bind(&It2MeHost::OnReceivedSupportID, base::Unretained(this))));

  // Beyond this point nothing can fail, so save the config and request.
  register_request_ = std::move(register_request);

  HOST_LOG << "NAT state: " << nat_traversal_enabled_;

  protocol::NetworkSettings network_settings(
     nat_traversal_enabled_ ?
     protocol::NetworkSettings::NAT_TRAVERSAL_FULL :
     protocol::NetworkSettings::NAT_TRAVERSAL_DISABLED);

  if (!udp_port_range_.is_null()) {
    network_settings.port_range = udp_port_range_;
  } else if (!nat_traversal_enabled_) {
    // For legacy reasons we have to restrict the port range to a set of default
    // values when nat traversal is disabled, even if the port range was not
    // set in policy.
    network_settings.port_range.min_port =
        protocol::NetworkSettings::kDefaultMinPort;
    network_settings.port_range.max_port =
        protocol::NetworkSettings::kDefaultMaxPort;
  }

  scoped_refptr<protocol::TransportContext> transport_context =
      new protocol::TransportContext(
          signal_strategy_.get(),
          base::WrapUnique(new protocol::ChromiumPortAllocatorFactory()),
          base::WrapUnique(new ChromiumUrlRequestFactory(
              host_context_->url_loader_factory())),
          network_settings, protocol::TransportRole::SERVER);
  transport_context->set_turn_ice_config(ice_config);

  std::unique_ptr<protocol::SessionManager> session_manager(
      new protocol::JingleSessionManager(signal_strategy_.get()));

  std::unique_ptr<protocol::CandidateSessionConfig> protocol_config =
      protocol::CandidateSessionConfig::CreateDefault();
  // Disable audio by default.
  // TODO(sergeyu): Add UI to enable it.
  protocol_config->DisableAudioChannel();
  protocol_config->set_webrtc_supported(true);
  session_manager->set_protocol_config(std::move(protocol_config));

  // Create the host.
  DesktopEnvironmentOptions options(DesktopEnvironmentOptions::CreateDefault());
  options.set_enable_user_interface(enable_dialogs_);
  host_.reset(new ChromotingHost(
      desktop_environment_factory_.get(), std::move(session_manager),
      transport_context, host_context_->audio_task_runner(),
      host_context_->video_encode_task_runner(), options));
  host_->status_monitor()->AddStatusObserver(this);
  host_status_logger_.reset(
      new HostStatusLogger(host_->status_monitor(), ServerLogEntry::IT2ME,
                           signal_strategy_.get(), directory_bot_jid));

  // Create event logger.
  host_event_logger_ =
      HostEventLogger::Create(host_->status_monitor(), kApplicationName);

  // Connect signaling and start the host.
  signal_strategy_->Connect();
  host_->Start(username);

  SetState(kRequestedAccessCode, ErrorCode::OK);
  return;
}

void It2MeHost::OnAccessDenied(const std::string& jid) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  ++failed_login_attempts_;
  if (failed_login_attempts_ == kMaxLoginAttempts) {
    DisconnectOnNetworkThread();
  } else if (connecting_jid_ == jid) {
    DCHECK_EQ(state_, kConnecting);
    connecting_jid_.clear();
    confirmation_dialog_proxy_.reset();
    SetState(kReceivedAccessCode, ErrorCode::OK);
  }
}

void It2MeHost::OnClientConnected(const std::string& jid) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  // ChromotingHost doesn't allow multiple concurrent connection and the
  // host is destroyed in OnClientDisconnected() after the first connection.
  CHECK_NE(state_, kConnected);

  std::string client_username;
  if (!SplitJidResource(jid, &client_username, /*resource=*/nullptr)) {
    LOG(WARNING) << "Incorrectly formatted JID received: " << jid;
    client_username = jid;
  }

  HOST_LOG << "Client " << client_username << " connected.";

  // Pass the client user name to the script object before changing state.
  host_context_->ui_task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&It2MeHost::Observer::OnClientAuthenticated,
                                observer_, client_username));

  SetState(kConnected, ErrorCode::OK);
}

void It2MeHost::OnClientDisconnected(const std::string& jid) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  DisconnectOnNetworkThread();
}

ValidationCallback It2MeHost::GetValidationCallbackForTesting() {
  return base::Bind(&It2MeHost::ValidateConnectionDetails,
                    base::Unretained(this));
}

void It2MeHost::OnPolicyUpdate(
    std::unique_ptr<base::DictionaryValue> policies) {
  // The policy watcher runs on the |ui_task_runner|.
  if (!host_context_->network_task_runner()->BelongsToCurrentThread()) {
    host_context_->network_task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&It2MeHost::OnPolicyUpdate, this, std::move(policies)));
    return;
  }

  bool nat_policy;
  if (policies->GetBoolean(policy::key::kRemoteAccessHostFirewallTraversal,
                           &nat_policy)) {
    UpdateNatPolicy(nat_policy);
  }
  const base::ListValue* host_domain_list;
  if (policies->GetList(policy::key::kRemoteAccessHostDomainList,
                        &host_domain_list)) {
    std::vector<std::string> host_domain_list_vector;
    for (const auto& value : *host_domain_list) {
      host_domain_list_vector.push_back(value.GetString());
    }
    UpdateHostDomainListPolicy(std::move(host_domain_list_vector));
  }
  const base::ListValue* client_domain_list;
  if (policies->GetList(policy::key::kRemoteAccessHostClientDomainList,
                        &client_domain_list)) {
    std::vector<std::string> client_domain_list_vector;
    for (const auto& value : *client_domain_list) {
      client_domain_list_vector.push_back(value.GetString());
    }
    UpdateClientDomainListPolicy(std::move(client_domain_list_vector));
  }

  std::string port_range_string;
  if (policies->GetString(policy::key::kRemoteAccessHostUdpPortRange,
                          &port_range_string)) {
    UpdateHostUdpPortRangePolicy(port_range_string);
  }
}

void It2MeHost::UpdateNatPolicy(bool nat_traversal_enabled) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  VLOG(2) << "UpdateNatPolicy: " << nat_traversal_enabled;

  // When transitioning from enabled to disabled, force disconnect any
  // existing session.
  if (nat_traversal_enabled_ && !nat_traversal_enabled && IsRunning()) {
    DisconnectOnNetworkThread();
  }

  nat_traversal_enabled_ = nat_traversal_enabled;

  // Notify the web-app of the policy setting.
  host_context_->ui_task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&It2MeHost::Observer::OnNatPolicyChanged,
                                observer_, nat_traversal_enabled_));
}

void It2MeHost::UpdateHostDomainListPolicy(
    std::vector<std::string> host_domain_list) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  VLOG(2) << "UpdateHostDomainListPolicy: "
          << base::JoinString(host_domain_list, ", ");

  // When setting a host domain policy, force disconnect any existing session.
  if (!host_domain_list.empty() && IsRunning()) {
    DisconnectOnNetworkThread();
  }

  required_host_domain_list_ = std::move(host_domain_list);
}

void It2MeHost::UpdateClientDomainListPolicy(
    std::vector<std::string> client_domain_list) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  VLOG(2) << "UpdateClientDomainPolicy: "
          << base::JoinString(client_domain_list, ", ");

  // When setting a client  domain policy, disconnect any existing session.
  if (!client_domain_list.empty() && IsRunning()) {
    DisconnectOnNetworkThread();
  }

  required_client_domain_list_ = std::move(client_domain_list);
}

void It2MeHost::UpdateHostUdpPortRangePolicy(
    const std::string& port_range_string) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  VLOG(2) << "UpdateHostUdpPortRangePolicy: " << port_range_string;

  if (IsRunning()) {
    DisconnectOnNetworkThread();
  }

  if (!PortRange::Parse(port_range_string, &udp_port_range_)) {
    // PolicyWatcher verifies that the value is formatted correctly.
    LOG(FATAL) << "Invalid port range: " << port_range_string;
  }
}

void It2MeHost::SetState(It2MeHostState state, ErrorCode error_code) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  switch (state_) {
    case kDisconnected:
      DCHECK(state == kStarting ||
             state == kError) << state;
      break;
    case kStarting:
      DCHECK(state == kRequestedAccessCode ||
             state == kDisconnected ||
             state == kError ||
             state == kInvalidDomainError) << state;
      break;
    case kRequestedAccessCode:
      DCHECK(state == kReceivedAccessCode ||
             state == kDisconnected ||
             state == kError) << state;
      break;
    case kReceivedAccessCode:
      DCHECK(state == kConnecting ||
             state == kDisconnected ||
             state == kError) << state;
      break;
    case kConnecting:
      DCHECK(state == kConnected ||
             state == kDisconnected ||
             state == kError) << state;
      break;
    case kConnected:
      DCHECK(state == kDisconnected ||
             state == kError) << state;
      break;
    case kError:
      DCHECK(state == kDisconnected) << state;
      break;
    case kInvalidDomainError:
      DCHECK(state == kDisconnected) << state;
      break;
  };

  state_ = state;

  // Post a state-change notification to the web-app.
  host_context_->ui_task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&It2MeHost::Observer::OnStateChanged, observer_,
                                state, error_code));
}

bool It2MeHost::IsRunning() const {
  return state_ == kRequestedAccessCode || state_ == kReceivedAccessCode ||
         state_ == kConnected || state_ == kConnecting;
}

void It2MeHost::OnReceivedSupportID(const std::string& support_id,
                                    const base::TimeDelta& lifetime,
                                    const ErrorCode error_code) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  if (error_code != ErrorCode::OK) {
    SetState(kError, error_code);
    DisconnectOnNetworkThread();
    return;
  }

  std::string host_secret = GenerateSupportHostSecret();
  std::string access_code = support_id + host_secret;
  std::string access_code_hash =
      protocol::GetSharedSecretHash(support_id, access_code);

  std::string local_certificate = host_key_pair_->GenerateCertificate();
  if (local_certificate.empty()) {
    LOG(ERROR) << "Failed to generate host certificate.";
    SetState(kError, ErrorCode::HOST_CERTIFICATE_ERROR);
    DisconnectOnNetworkThread();
    return;
  }

  std::unique_ptr<protocol::AuthenticatorFactory> factory(
      new protocol::It2MeHostAuthenticatorFactory(
          local_certificate, host_key_pair_, access_code_hash,
          base::Bind(&It2MeHost::ValidateConnectionDetails,
                     base::Unretained(this))));
  host_->SetAuthenticatorFactory(std::move(factory));

  // Pass the Access Code to the script object before changing state.
  host_context_->ui_task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&It2MeHost::Observer::OnStoreAccessCode,
                                observer_, access_code, lifetime));

  SetState(kReceivedAccessCode, ErrorCode::OK);
}

void It2MeHost::DisconnectOnNetworkThread() {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  // Disconnect() may be called even when after the host been already stopped.
  // Ignore repeated calls.
  if (state_ == kDisconnected) {
    return;
  }

  confirmation_dialog_proxy_.reset();

  if (host_) {
    host_->status_monitor()->RemoveStatusObserver(this);
    host_ = nullptr;
  }

  register_request_ = nullptr;
  host_status_logger_ = nullptr;
  signal_strategy_ = nullptr;
  host_event_logger_ = nullptr;

  // Post tasks to delete UI objects on the UI thread.
  host_context_->ui_task_runner()->DeleteSoon(
      FROM_HERE, desktop_environment_factory_.release());

  SetState(kDisconnected, ErrorCode::OK);
}

void It2MeHost::ValidateConnectionDetails(
    const std::string& remote_jid,
    const ValidationResultCallback& result_callback) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  // First ensure the JID we received is valid.
  std::string client_username;
  if (!SplitJidResource(remote_jid, &client_username, /*resource=*/nullptr)) {
    LOG(ERROR) << "Rejecting incoming connection from " << remote_jid
               << ": Invalid JID.";
    result_callback.Run(
        protocol::ValidatingAuthenticator::Result::ERROR_INVALID_ACCOUNT);
    DisconnectOnNetworkThread();
    return;
  }

  if (client_username.empty()) {
    LOG(ERROR) << "Invalid user name passed in: " << remote_jid;
    result_callback.Run(
        protocol::ValidatingAuthenticator::Result::ERROR_INVALID_ACCOUNT);
    DisconnectOnNetworkThread();
    return;
  }

  // Check the client domain policy.
  if (!required_client_domain_list_.empty()) {
    bool matched = false;
    for (const auto& domain : required_client_domain_list_) {
      if (base::EndsWith(client_username, std::string("@") + domain,
                         base::CompareCase::INSENSITIVE_ASCII)) {
        matched = true;
        break;
      }
    }
    if (!matched) {
      LOG(ERROR) << "Rejecting incoming connection from " << remote_jid
                 << ": Domain not allowed.";
      result_callback.Run(ValidationResult::ERROR_INVALID_ACCOUNT);
      DisconnectOnNetworkThread();
      return;
    }
  }

  // If we receive valid connection details multiple times, then we don't know
  // which remote user (if either) is valid so disconnect everyone.
  if (state_ != kReceivedAccessCode) {
    DCHECK_EQ(kConnecting, state_);
    LOG(ERROR) << "Received too many connection requests.";
    result_callback.Run(ValidationResult::ERROR_TOO_MANY_CONNECTIONS);
    DisconnectOnNetworkThread();
    return;
  }

  HOST_LOG << "Client " << client_username << " connecting.";
  connecting_jid_ = remote_jid;
  SetState(kConnecting, ErrorCode::OK);

  // Show a confirmation dialog to the user to allow them to confirm/reject it.
  // If dialogs are suppressed, just call the callback directly.
  if (enable_dialogs_) {
    confirmation_dialog_proxy_.reset(new It2MeConfirmationDialogProxy(
        host_context_->ui_task_runner(),
        confirmation_dialog_factory_->Create()));
    confirmation_dialog_proxy_->Show(
        client_username, base::Bind(&It2MeHost::OnConfirmationResult,
                                    base::Unretained(this), result_callback));
  } else {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(result_callback, ValidationResult::SUCCESS));
  }
}

void It2MeHost::OnConfirmationResult(
    const ValidationResultCallback& result_callback,
    It2MeConfirmationDialog::Result result) {
  DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread());

  connecting_jid_.clear();
  switch (result) {
    case It2MeConfirmationDialog::Result::OK:
      result_callback.Run(ValidationResult::SUCCESS);
      break;

    case It2MeConfirmationDialog::Result::CANCEL:
      result_callback.Run(ValidationResult::ERROR_REJECTED_BY_USER);
      DisconnectOnNetworkThread();
      break;
  }
}

It2MeHostFactory::It2MeHostFactory() = default;
It2MeHostFactory::~It2MeHostFactory() = default;

scoped_refptr<It2MeHost> It2MeHostFactory::CreateIt2MeHost() {
  return new It2MeHost();
}

}  // namespace remoting
