// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/rand_util.h>

#include <brillo/http/http_request.h>
#include <brillo/mime_utils.h>

#include <firewalld/firewall.h>

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

#include "webservd/binder_request.h"
#include "webservd/binder_server.h"
#include "webservd/protocol_handler.h"
#include "webservd/request_handler_interface.h"
#include "webservd/utils.h"
#include "android/webservd/BnProtocolHandler.h"

using android::sp;
using android::String8;

using android::binder::Status;

using android::webservd::IProtocolHandler;
using android::webservd::IRequestHandler;
using android::webservd::IHttpRequest;
using android::webservd::HttpRequest;

using std::set;
using std::string;
using std::unique_ptr;
using std::vector;

namespace webservd {
namespace {

#ifdef __ANDROID__
const char kCertificateFile[] = "/data/misc/webservd/certificate";
const char kKeyFile[] = "/data/misc/webservd/key";
#else
const char kCertificateFile[] = "/var/lib/webservd-certificate";
const char kKeyFile[] = "/var/lib/webservd-key";
#endif

class BinderRequestHandler : public RequestHandlerInterface {
 public:
  explicit BinderRequestHandler(const sp<IRequestHandler>& handler)
      : handler_(handler) {}

  void HandleRequest(Request* request) override {
    sp<IHttpRequest> binder_request(new HttpRequest(request));
    if (!handler_->ProcessRequest(binder_request).isOk()) {
      request->Complete(brillo::http::status_code::InternalServerError, {},
                        brillo::mime::text::kPlain, "Internal server error");
    }
  }

 private:
  sp<IRequestHandler> handler_;

  DISALLOW_COPY_AND_ASSIGN(BinderRequestHandler);
};

class BinderProtocolHandler : public android::webservd::BnProtocolHandler {
 public:
  BinderProtocolHandler(string name, BinderServer* server,
                        android::BinderWrapper* binder_wrapper)
      : impl_(name, server),
        binder_wrapper_(binder_wrapper) {}

  bool Start(const Config::ProtocolHandler& config) {
    return impl_.Start(config);
  }

  Status AddRequestHandler(const string& url, const string& method,
                           const sp<IRequestHandler>& handler, string* ret)
        override {
    *ret = impl_.AddRequestHandler(url, method,
        unique_ptr<RequestHandlerInterface>(new BinderRequestHandler(handler)));

    binder_wrapper_->RegisterForDeathNotifications(
        IRequestHandler::asBinder(handler),
        base::Bind(&BinderProtocolHandler::HandlerDied,
                   base::Unretained(this), *ret));
    return Status::ok();
  }

  Status RemoveRequestHandler(const string& guid) override {
    if (impl_.RemoveRequestHandler(guid)) {
      return Status::ok();
    }

    return Status::fromExceptionCode(
        Status::EX_ILLEGAL_ARGUMENT,
        String8{"No such handler registered"});
  }

  Status GetName(string* name) override {
    *name = impl_.GetName();
    return Status::ok();
  }

  Status GetPort(int32_t* port) override {
    *port = impl_.GetPort();
    return Status::ok();
  }

  Status GetProtocol(string* protocol) override {
    *protocol = impl_.GetProtocol();
    return Status::ok();
  }

  Status GetCertificateFingerprint(vector<uint8_t>* fingerprint)
      override {
    // Note: ProtocolHandler::GetCertificateFingerprint returns a brillo::Blob,
    // which at time of writing is an alias to vector<uint8_t>. This will break
    // if that changes.
    *fingerprint = impl_.GetCertificateFingerprint();

    return Status::ok();
  }

 private:
  void HandlerDied(const string& guid) {
    impl_.RemoveRequestHandler(guid);
  }

  ProtocolHandler impl_;
  android::BinderWrapper* binder_wrapper_;

  DISALLOW_COPY_AND_ASSIGN(BinderProtocolHandler);
};

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;
}

}  // namespace

base::FilePath BinderServer::GetUploadDirectory() const {
  base::FilePath upload_dir;
#ifdef __ANDROID__
  upload_dir = base::FilePath{"/data/misc/webservd/uploads"};
#else
  CHECK(base::GetTempDir(&upload_dir));
#endif
  return upload_dir;
}

void BinderServer::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_;
    }
  }
}

BinderServer::BinderServer(const Config& config,
                           android::BinderWrapper* binder_wrapper)
    : config_(config),
      default_encryptor_{Encryptor::CreateDefaultEncryptor()},
      encryptor_(default_encryptor_.get()) {
  InitTlsData();

  unique_ptr<firewalld::Firewall> firewall =
      firewalld::Firewall::Connect(binder_wrapper);

  if (!firewall) {
    LOG(ERROR) << "Could not connect to firewall.";
  }

  for (const auto& handler_config : config_.protocol_handlers) {
    sp<BinderProtocolHandler> handler_ptr{
        new BinderProtocolHandler(handler_config.name, this, binder_wrapper)};

    if (handler_ptr->Start(handler_config)) {
      protocol_handlers_.push_back(handler_ptr);
      if (firewall &&
          !firewall->PunchTcpHole(handler_config.port,
                                  handler_config.interface_name)) {
          LOG(ERROR) << "Could not open port " << handler_config.port
                     << " for protocol handler.";
      }
    }
  }
}

Status BinderServer::Ping(string* result) {
  *result = "Web Server is running.";
  return Status::ok();
}

Status BinderServer::GetDefaultRequestTimeout(int32_t* timeout_seconds) {
  *timeout_seconds = config_.default_request_timeout_seconds;
  return Status::ok();
}

Status BinderServer::GetProtocolHandlers(
    const string& name,
    vector<sp<IBinder>>* result) {
  result->clear();

  for (auto handler : protocol_handlers_) {
    string handler_name;

    if (name.empty()) {
      result->push_back(IProtocolHandler::asBinder(handler));
      continue;
    }

    // No reason for this to fail on the server side
    CHECK(handler->GetName(&handler_name).isOk());

    if (handler_name == name) {
      result->push_back(IProtocolHandler::asBinder(handler));
    }
  }

  return Status::ok();
}

}  // namespace webservd
