// Copyright 2015 The Chromium OS 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 "webservd/server.h"

#include <openssl/evp.h>
#include <openssl/x509.h>

#include <limits>
#include <utility>

#include <base/files/file_util.h>
#include <base/rand_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/dbus/async_event_sequencer.h>

#include "webservd/dbus_protocol_handler.h"
#include "webservd/encryptor.h"
#include "webservd/protocol_handler.h"
#include "webservd/utils.h"

using brillo::dbus_utils::AsyncEventSequencer;
using brillo::dbus_utils::DBusObject;
using brillo::dbus_utils::ExportedObjectManager;

namespace {

const char kCertificateFile[] = "/var/lib/webservd-certificate";
const char kKeyFile[] = "/var/lib/webservd-key";

void OnFirewallSuccess(const std::string& itf_name,
                       uint16_t port,
                       bool allowed) {
  if (allowed) {
    LOG(INFO) << "Successfully opened up port " << port << " on interface "
              << itf_name;
  } else {
    LOG(ERROR) << "Failed to open up port " << port
               << ", interface: " << itf_name;
  }
}

void IgnoreFirewallDBusMethodError(brillo::Error* /* error */) {}

brillo::SecureBlob LoadAndValidatePrivateKey(const base::FilePath& key_file,
                                             webservd::Encryptor* encryptor) {
  std::string encrypted_key_data;
  if (!base::ReadFileToString(key_file, &encrypted_key_data))
    return {};
  std::string key_data;
  if (!encryptor->DecryptWithAuthentication(encrypted_key_data, &key_data))
    return {};
  brillo::SecureBlob key{key_data};
  if (!webservd::ValidateRSAPrivateKey(key))
    key.clear();
  return key;
}

}  // anonymous namespace

namespace webservd {

Server::Server(ExportedObjectManager* object_manager,
               const Config& config,
               std::unique_ptr<FirewallInterface> firewall)
    : dbus_object_{new DBusObject{
          object_manager, object_manager->GetBus(),
          org::chromium::WebServer::ServerAdaptor::GetObjectPath()}},
      default_encryptor_{Encryptor::CreateDefaultEncryptor()},
      encryptor_{default_encryptor_.get()},
      config_{config},
      firewall_{std::move(firewall)} {
  dbus_adaptor_.SetDefaultRequestTimeout(
      config_.default_request_timeout_seconds);
}

Server::~Server() {}

void Server::RegisterAsync(
    const AsyncEventSequencer::CompletionAction& completion_callback) {
  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
  dbus_adaptor_.RegisterWithDBusObject(dbus_object_.get());

  InitTlsData();

  for (auto& handler_config : config_.protocol_handlers)
    CreateProtocolHandler(&handler_config);

  firewall_->WaitForServiceAsync(dbus_object_->GetBus(),
                                 base::Bind(&Server::OnFirewallServiceOnline,
                                            weak_ptr_factory_.GetWeakPtr()));

  dbus_object_->RegisterAsync(
      sequencer->GetHandler("Failed exporting Server.", true));

  for (const auto& pair : protocol_handler_map_) {
    pair.second->RegisterAsync(
        sequencer->GetHandler("Failed exporting ProtocolHandler.", false));
  }
  sequencer->OnAllTasksCompletedCall({completion_callback});
}

void Server::OnFirewallServiceOnline() {
  LOG(INFO) << "Firewall service is on-line. "
            << "Opening firewall for protocol handlers";
  for (auto& handler_config : config_.protocol_handlers) {
    VLOG(1) << "Firewall request: Protocol Handler = " << handler_config.name
            << ", Port = " << handler_config.port
            << ", Interface = " << handler_config.interface_name;
    firewall_->PunchTcpHoleAsync(
        handler_config.port, handler_config.interface_name,
        base::Bind(&OnFirewallSuccess, handler_config.interface_name,
                   handler_config.port),
        base::Bind(&IgnoreFirewallDBusMethodError));
  }
}

std::string Server::Ping() {
  return "Web Server is running";
}

void Server::ProtocolHandlerStarted(ProtocolHandler* handler) {
  CHECK(protocol_handler_map_.find(handler) == protocol_handler_map_.end())
      << "Protocol handler already registered";
  std::string path = base::StringPrintf("/org/chromium/WebServer/Servers/%d",
                                        ++last_protocol_handler_index_);
  dbus::ObjectPath object_path{path};
  std::unique_ptr<DBusProtocolHandler> dbus_protocol_handler{
      new DBusProtocolHandler{dbus_object_->GetObjectManager().get(),
                              object_path, handler, this}};
  protocol_handler_map_.emplace(handler, std::move(dbus_protocol_handler));
}

void Server::ProtocolHandlerStopped(ProtocolHandler* handler) {
  CHECK_EQ(1u, protocol_handler_map_.erase(handler))
      << "Unknown protocol handler";
}

void Server::CreateProtocolHandler(Config::ProtocolHandler* handler_config) {
  std::unique_ptr<ProtocolHandler> protocol_handler{
      new ProtocolHandler{handler_config->name, this}};
  if (protocol_handler->Start(*handler_config))
    protocol_handlers_.push_back(std::move(protocol_handler));
}

void Server::InitTlsData() {
  if (!TLS_certificate_.empty())
    return;  // Already initialized.

  // TODO(avakulenko): verify these constants and provide sensible values
  // for the long-term. See brbug.com/227
  const int kKeyLengthBits = 1024;
  const int64_t kOneYearInSeconds = 31556952;  // 365.2425 days
  const base::TimeDelta kCertExpiration =
      base::TimeDelta::FromSeconds(5 * kOneYearInSeconds);
  const char kCommonName[] = "Brillo device";

  const base::FilePath certificate_file{kCertificateFile};
  const base::FilePath key_file{kKeyFile};

  auto cert = LoadAndValidateCertificate(certificate_file);
  brillo::SecureBlob private_key =
      LoadAndValidatePrivateKey(key_file, encryptor_);
  if (!cert || private_key.empty()) {
    // Create the X509 certificate.
    LOG(INFO) << "Generating new certificate...";
    int cert_serial_number = base::RandInt(0, std::numeric_limits<int>::max());
    cert = CreateCertificate(cert_serial_number, kCertExpiration, kCommonName);

    // Create RSA key pair.
    auto rsa_key_pair = GenerateRSAKeyPair(kKeyLengthBits);

    // Store the private key to a temp buffer.
    // Do not assign it to |TLS_private_key_| yet until the end when we are sure
    // everything else has worked out.
    private_key = StoreRSAPrivateKey(rsa_key_pair.get());

    // Create EVP key and set it to the certificate.
    auto key = std::unique_ptr<EVP_PKEY, void (*)(EVP_PKEY*)>{EVP_PKEY_new(),
                                                              EVP_PKEY_free};
    CHECK(key.get());
    // Transfer ownership of |rsa_key_pair| to |key|.
    CHECK(EVP_PKEY_assign_RSA(key.get(), rsa_key_pair.release()));
    CHECK(X509_set_pubkey(cert.get(), key.get()));

    // Sign the certificate.
    CHECK(X509_sign(cert.get(), key.get(), EVP_sha256()));

    // Save the certificate and private key to disk.
    StoreCertificate(cert.get(), certificate_file);
    std::string encrypted_key;
    encryptor_->EncryptWithAuthentication(private_key.to_string(),
                                          &encrypted_key);
    base::WriteFile(key_file, encrypted_key.data(), encrypted_key.size());
  }

  TLS_certificate_ = StoreCertificate(cert.get());
  TLS_certificate_fingerprint_ = GetSha256Fingerprint(cert.get());
  TLS_private_key_ = std::move(private_key);

  // Update the TLS data in protocol handler config.
  for (auto& handler_config : config_.protocol_handlers) {
    if (handler_config.use_tls) {
      handler_config.certificate = TLS_certificate_;
      handler_config.certificate_fingerprint = TLS_certificate_fingerprint_;
      handler_config.private_key = TLS_private_key_;
    }
  }
}

base::FilePath Server::GetUploadDirectory() const {
  base::FilePath upload_dir;
  CHECK(base::GetTempDir(&upload_dir));
  return upload_dir;
}

}  // namespace webservd
