// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This is a fake 'smart door memory' component for security codelab.
// It CONTAINS vulnerability intentionally.
// DO NOT COPY ANY OF THE CODE IN THIS FILE!
#include "smart_door_memory_server_app.h"

#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/time.h>

#include <ctime>

#include "dirent.h"
#include "fcntl.h"
#include "stdint.h"
#include "sys/stat.h"

namespace smart_door_memory {

using fuchsia::security::codelabsmartdoor::Error;
using fuchsia::security::codelabsmartdoor::Memory_GenerateToken_Response;
using fuchsia::security::codelabsmartdoor::Memory_GenerateToken_Result;
using fuchsia::security::codelabsmartdoor::Memory_GetReader_Response;
using fuchsia::security::codelabsmartdoor::Memory_GetReader_Result;
using fuchsia::security::codelabsmartdoor::Memory_GetWriter_Response;
using fuchsia::security::codelabsmartdoor::Memory_GetWriter_Result;
using fuchsia::security::codelabsmartdoor::Reader;
using fuchsia::security::codelabsmartdoor::Reader_Read_Response;
using fuchsia::security::codelabsmartdoor::Reader_Read_Result;
using fuchsia::security::codelabsmartdoor::Token;
using fuchsia::security::codelabsmartdoor::TOKEN_ID_SIZE;
using fuchsia::security::codelabsmartdoor::Writer;
using fuchsia::security::codelabsmartdoor::Writer_Write_Response;
using fuchsia::security::codelabsmartdoor::Writer_Write_Result;

const char* STORAGE_FOLDER = "/data/storage/";
const char* LOG_FILE = "/data/log";

SmartDoorMemoryServer::SmartDoorMemoryServer() {
  // Create the storage folder.
  mkdir(STORAGE_FOLDER, 0700);
}

void SmartDoorMemoryServer::GenerateToken(GenerateTokenCallback callback) {
  FX_LOGS(INFO) << "Generating random token" << std::endl;
  Token token;
  uint8_t id[TOKEN_ID_SIZE / 2];
  zx_cprng_draw(id, TOKEN_ID_SIZE / 2);
  char id_hex[TOKEN_ID_SIZE + 1] = {};
  for (size_t i = 0; i < TOKEN_ID_SIZE / 2; i++) {
    snprintf(&id_hex[i * 2], sizeof(id_hex) - (i * 2), "%02X", id[i]);
  }
  token.set_id(std::string(id_hex));
  callback(
      Memory_GenerateToken_Result::WithResponse(Memory_GenerateToken_Response(std::move(token))));
}

bool SmartDoorMemoryServer::Log(std::string file_path, bool read_or_write) {
  std::timespec ts;
  if (!std::timespec_get(&ts, TIME_UTC)) {
    return false;
  }
  zx_time_t now = zx_time_from_timespec(ts);
  char time[256] = {};
  int written = snprintf(time, sizeof(time), "%" PRIi64, now);
  if (written < 0 || written > (int)sizeof(time)) {
    return false;
  }
  std::string log = std::string(time) + " " + file_path;
  if (read_or_write) {
    log += " read";
  } else {
    log += " write";
  }
  log += "\n";
  int fd = 0;
  FX_LOGS(INFO) << "logging to file " << LOG_FILE << std::endl;
  if (fdio_open_fd(
          LOG_FILE,
          static_cast<uint32_t>(fuchsia::io::OpenFlags::RIGHT_WRITABLE |
                                fuchsia::io::OpenFlags::CREATE | fuchsia::io::OpenFlags::APPEND),
          &fd) != ZX_OK) {
    return false;
  }
  const char* log_c = log.c_str();
  if (write(fd, log_c, strlen(log_c) + 1) != static_cast<ssize_t>(strlen(log_c) + 1)) {
    close(fd);
    return false;
  }
  close(fd);
  return true;
}

bool SmartDoorMemoryServer::tokenToFilePath(const Token* token, std::string* file_path) {
  if (!token->has_id() || token->id().size() != TOKEN_ID_SIZE) {
    return false;
  }
  *file_path = STORAGE_FOLDER + token->id();
  return true;
}

void SmartDoorMemoryServer::GetReader(Token token, ::fidl::InterfaceRequest<Reader> request,
                                      GetReaderCallback callback) {
  FX_LOGS(INFO) << "Getting reader" << std::endl;
  std::string file_path;
  if (!tokenToFilePath(&token, &file_path)) {
    callback(Memory_GetReader_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  int fd = open(file_path.c_str(), O_RDONLY);
  if (fd < 0) {
    callback(Memory_GetReader_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  reader_bindings_.AddBinding(std::make_unique<SmartDoorMemoryReader>(fd, std::move(file_path)),
                              std::move(request));
  callback(Memory_GetReader_Result::WithResponse(Memory_GetReader_Response()));
}

void SmartDoorMemoryServer::GetWriter(Token token, ::fidl::InterfaceRequest<Writer> request,
                                      GetWriterCallback callback) {
  FX_LOGS(INFO) << "Getting writer" << std::endl;
  std::string file_path;
  if (!tokenToFilePath(&token, &file_path)) {
    callback(Memory_GetWriter_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  int fd = open(file_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
  if (fd < 0) {
    callback(Memory_GetWriter_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  writer_bindings_.AddBinding(std::make_unique<SmartDoorMemoryWriter>(fd, std::move(file_path)),
                              std::move(request));
  callback(Memory_GetWriter_Result::WithResponse(Memory_GetWriter_Response()));
}

void SmartDoorMemoryServer::Reset(ResetCallback callback) {
  // Erase every files under the storage folder.
  DIR* dir = opendir(STORAGE_FOLDER);
  ZX_ASSERT(dir);
  struct dirent* de;
  while ((de = readdir(dir)) != NULL) {
    if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
      continue;

    char tmp[PATH_MAX];
    tmp[0] = 0;
    size_t bytes_left = PATH_MAX - 1;
    strncat(tmp, STORAGE_FOLDER, bytes_left);
    bytes_left -= strlen(STORAGE_FOLDER);
    strncat(tmp, "/", bytes_left);
    bytes_left--;
    strncat(tmp, de->d_name, bytes_left);
    unlink(tmp);
  }
  closedir(dir);

  // Erase log file.
  unlink(LOG_FILE);

  callback();
  return;
}

void SmartDoorMemoryWriter::Write(std::vector<uint8_t> data, WriteCallback callback) {
  if (lseek(fd_, 0, SEEK_SET) == -1) {
    callback(Writer_Write_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  if (ftruncate(fd_, 0) == -1) {
    callback(Writer_Write_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  if (data.size() > UINT32_MAX) {
    callback(Writer_Write_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  ssize_t written = write(fd_, data.data(), data.size());
  if (written != static_cast<ssize_t>(data.size())) {
    callback(Writer_Write_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  sync();

  if (!SmartDoorMemoryServer::Log(file_path_, false)) {
    callback(Writer_Write_Result::WithErr(Error::INTERNAL));
    return;
  }

  ZX_ASSERT(written <= UINT32_MAX);
  callback(
      Writer_Write_Result::WithResponse(Writer_Write_Response(static_cast<uint32_t>(written))));
  return;
}

void SmartDoorMemoryReader::Read(ReadCallback callback) {
  // Get file size.
  ssize_t size = lseek(fd_, 0, SEEK_END);
  std::vector<uint8_t> data;
  data.resize(size);
  if (lseek(fd_, 0, SEEK_SET) == -1) {
    callback(Reader_Read_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  ssize_t read_bytes = read(fd_, data.data(), data.size());
  if (read_bytes != static_cast<ssize_t>(data.size())) {
    callback(Reader_Read_Result::WithErr(Error::INVALID_INPUT));
    return;
  }
  if (!SmartDoorMemoryServer::Log(file_path_, true)) {
    callback(Reader_Read_Result::WithErr(Error::INTERNAL));
    return;
  }
  callback(Reader_Read_Result::WithResponse(Reader_Read_Response(std::move(data))));
  return;
}

SmartDoorMemoryServerApp::SmartDoorMemoryServerApp()
    : SmartDoorMemoryServerApp(sys::ComponentContext::CreateAndServeOutgoingDirectory()) {}

SmartDoorMemoryServerApp::SmartDoorMemoryServerApp(std::unique_ptr<sys::ComponentContext> context)
    : service_(new SmartDoorMemoryServer()), context_(std::move(context)) {
  context_->outgoing()->AddPublicService(bindings_.GetHandler(service_.get()));
  context_->outgoing()->AddPublicService(reset_bindings_.GetHandler(service_.get()));
}

}  // namespace smart_door_memory
