// Copyright 2020 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 "smbfs/smbfs_bootstrap_impl.h"

#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/logging.h>
#include <base/files/file.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/strings/strcat.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/secure_blob.h>
#include <crypto/hmac.h>
#include <libpasswordprovider/password.h>
#include <mojo/public/cpp/bindings/remote.h>
#include <mojo/public/cpp/system/platform_handle.h>

#include "smbfs/smb_credential.h"
#include "smbfs/smb_filesystem.h"

namespace smbfs {
namespace {

mojom::MountError ConnectErrorToMountError(SmbFilesystem::ConnectError error) {
  switch (error) {
    case SmbFilesystem::ConnectError::kNotFound:
      return mojom::MountError::kNotFound;
    case SmbFilesystem::ConnectError::kAccessDenied:
      return mojom::MountError::kAccessDenied;
    case SmbFilesystem::ConnectError::kSmb1Unsupported:
      return mojom::MountError::kInvalidProtocol;
    default:
      return mojom::MountError::kUnknown;
  }
}

base::FilePath MakePasswordFileName(const std::string& share_path,
                                    const std::string& username,
                                    const std::string& workgroup,
                                    const std::vector<uint8_t>& salt) {
  // Normally, this could produce overlapping strings. eg. with
  // username/workgroup: "abc"/"def" and "a"/"bcdef". However, the salt ensures
  // the final filename is unique even if two mounts produce the same
  // |raw_name|.
  const std::string raw_name = base::StrCat({share_path, username, workgroup});
  crypto::HMAC hmac(crypto::HMAC::SHA256);
  CHECK(hmac.Init(salt.data(), salt.size()));

  const size_t hash_len = hmac.DigestLength();
  std::unique_ptr<unsigned char[]> raw_hash =
      std::make_unique<unsigned char[]>(hash_len);
  CHECK(hmac.Sign(raw_name, raw_hash.get(), hash_len));
  return base::FilePath(base::HexEncode(raw_hash.get(), hash_len));
}

brillo::SecureVector ObfuscatePassword(
    const password_provider::Password& password,
    const std::vector<uint8_t>& salt) {
  brillo::SecureVector obfuscated(password.GetRaw(),
                                  password.GetRaw() + password.size());
  // Obfuscate the password using the salt.
  for (size_t i = 0; i < obfuscated.size(); i++) {
    obfuscated[i] ^= salt[i % salt.size()];
  }
  return obfuscated;
}

bool SavePasswordToFile(const base::FilePath& file_path,
                        const brillo::SecureVector& obfuscated_password) {
  base::File password_file(
      file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
  if (!password_file.IsValid()) {
    LOG(ERROR) << "Unable to open password file for write with error: "
               << password_file.error_details();
    return false;
  }

  int written = password_file.WriteAtCurrentPos(
      reinterpret_cast<const char*>(obfuscated_password.data()),
      obfuscated_password.size());
  return written == obfuscated_password.size();
}

std::unique_ptr<password_provider::Password> ReadPasswordFromFile(
    const base::FilePath& file_path, const std::vector<uint8_t>& salt) {
  base::File password_file(file_path,
                           base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!password_file.IsValid()) {
    LOG(ERROR) << "Unable to open password file with error: "
               << password_file.error_details();
    return nullptr;
  }

  brillo::SecureVector tmp_password(password_file.GetLength());
  int read = password_file.ReadAtCurrentPos(
      reinterpret_cast<char*>(tmp_password.data()), password_file.GetLength());
  if (read != password_file.GetLength()) {
    LOG(ERROR) << "Unexpected password file read length: " << read;
    return nullptr;
  }

  if (!salt.empty()) {
    for (size_t i = 0; i < tmp_password.size(); i++) {
      tmp_password[i] ^= salt[i % salt.size()];
    }
  }

  int fds[2];
  CHECK(base::CreateLocalNonBlockingPipe(fds));
  base::ScopedFD read_fd(fds[0]);
  base::ScopedFD write_fd(fds[1]);
  CHECK(base::WriteFileDescriptor(
      write_fd.get(), reinterpret_cast<const char*>(tmp_password.data()),
      tmp_password.size()));
  return password_provider::Password::CreateFromFileDescriptor(
      read_fd.get(), tmp_password.size());
}

}  // namespace

SmbFsBootstrapImpl::SmbFsBootstrapImpl(
    mojo::PendingReceiver<mojom::SmbFsBootstrap> receiver,
    SmbFilesystemFactory smb_filesystem_factory,
    Delegate* delegate,
    const base::FilePath& daemon_store_root)
    : receiver_(this, std::move(receiver)),
      smb_filesystem_factory_(smb_filesystem_factory),
      delegate_(delegate),
      daemon_store_root_(daemon_store_root) {
  DCHECK(smb_filesystem_factory_);
  DCHECK(delegate_);
  DCHECK(!daemon_store_root_.empty());
  receiver_.set_disconnect_handler(base::Bind(
      &SmbFsBootstrapImpl::OnMojoConnectionError, base::Unretained(this)));
}

SmbFsBootstrapImpl::~SmbFsBootstrapImpl() = default;

void SmbFsBootstrapImpl::Start(BootstrapCompleteCallback callback) {
  DCHECK(!completion_callback_);
  completion_callback_ = std::move(callback);
}

void SmbFsBootstrapImpl::MountShare(
    mojom::MountOptionsPtr options,
    mojo::PendingRemote<mojom::SmbFsDelegate> smbfs_delegate,
    MountShareCallback callback) {
  if (!completion_callback_) {
    LOG(ERROR) << "Mojo bootstrap not active";
    std::move(callback).Run(mojom::MountError::kUnknown,
                            mojo::PendingRemote<smbfs::mojom::SmbFs>());
    return;
  }

  if (options->share_path.find("smb://") != 0) {
    // TODO(amistry): More extensive URL validation.
    LOG(ERROR) << "Invalid share path: " << options->share_path;
    std::move(callback).Run(mojom::MountError::kInvalidUrl,
                            mojo::PendingRemote<smbfs::mojom::SmbFs>());
    return;
  }

  std::unique_ptr<SmbCredential> credential = std::make_unique<SmbCredential>(
      options->workgroup, options->username, nullptr);
  if (options->kerberos_config) {
    delegate_->SetupKerberos(
        std::move(options->kerberos_config),
        base::BindOnce(&SmbFsBootstrapImpl::OnCredentialsSetup,
                       base::Unretained(this), std::move(options),
                       std::move(smbfs_delegate), std::move(callback),
                       std::move(credential), true /* use_kerberos */));
    return;
  }

  if (options->password) {
    credential->password = std::move(options->password.value());
  }

  OnCredentialsSetup(std::move(options), std::move(smbfs_delegate),
                     std::move(callback), std::move(credential),
                     false /* use_kerberos */, true /* setup_success */);
}

void SmbFsBootstrapImpl::OnCredentialsSetup(
    mojom::MountOptionsPtr options,
    mojo::PendingRemote<mojom::SmbFsDelegate> smbfs_delegate,
    MountShareCallback callback,
    std::unique_ptr<SmbCredential> credential,
    bool use_kerberos,
    bool setup_success) {
  DCHECK(credential);

  if (!setup_success) {
    std::move(callback).Run(mojom::MountError::kUnknown,
                            mojo::PendingRemote<smbfs::mojom::SmbFs>());
    return;
  }

  base::FilePath pass_file_path;
  brillo::SecureVector obfuscated_password;
  if (!use_kerberos && options->credential_storage_options &&
      !credential->username.empty()) {
    CHECK_GE(options->credential_storage_options->salt.size(),
             mojom::CredentialStorageOptions::kMinSaltLength);
    const base::FilePath pass_file_name = MakePasswordFileName(
        options->share_path, credential->username, credential->workgroup,
        options->credential_storage_options->salt);
    pass_file_path = GetUserDaemonStoreDirectory(
                         options->credential_storage_options->account_hash)
                         .Append(pass_file_name);
    delegate_->OnPasswordFilePathSet(pass_file_path);

    if (credential->password) {
      // We obfuscate the password now because |credential| is moved into the
      // SmbFilesystem and is unavailable when we know the connection is
      // successful.
      obfuscated_password = ObfuscatePassword(
          *credential->password, options->credential_storage_options->salt);
    } else {
      credential->password = ReadPasswordFromFile(
          pass_file_path, options->credential_storage_options->salt);
    }
  }

  SmbFilesystem::Options smb_options;
  smb_options.share_path = options->share_path;
  smb_options.credentials = std::move(credential);
  smb_options.allow_ntlm = options->allow_ntlm;
  auto fs = smb_filesystem_factory_.Run(std::move(smb_options));
  // Don't use the resolved address if Kerberos is set up. Kerberos requires the
  // full hostname to obtain auth tickets.
  if (options->resolved_host && !use_kerberos) {
    if (options->resolved_host->address_bytes.size() != 4) {
      LOG(ERROR) << "Invalid IP address size: "
                 << options->resolved_host->address_bytes.size();
      std::move(callback).Run(mojom::MountError::kInvalidOptions,
                              mojo::PendingRemote<smbfs::mojom::SmbFs>());
      return;
    }
    fs->SetResolvedAddress(options->resolved_host->address_bytes);
  }
  if (!options->skip_connect) {
    SmbFilesystem::ConnectError error = fs->EnsureConnected();
    if (error != SmbFilesystem::ConnectError::kOk) {
      LOG(ERROR) << "Unable to connect to SMB share " << options->share_path
                 << ": " << error;
      std::move(callback).Run(ConnectErrorToMountError(error),
                              mojo::PendingRemote<smbfs::mojom::SmbFs>());
      return;
    }
  }

  // Now that the share connection was successful, we can save the password.
  if (!obfuscated_password.empty()) {
    DCHECK(!pass_file_path.empty());
    CHECK(SavePasswordToFile(pass_file_path, obfuscated_password));
  }

  mojo::PendingRemote<mojom::SmbFs> smbfs;
  std::move(completion_callback_)
      .Run(std::move(fs), smbfs.InitWithNewPipeAndPassReceiver(),
           std::move(smbfs_delegate));

  std::move(callback).Run(mojom::MountError::kOk, std::move(smbfs));
}

void SmbFsBootstrapImpl::OnMojoConnectionError() {
  if (completion_callback_) {
    std::move(completion_callback_)
        .Run(nullptr,
             mojo::PendingRemote<smbfs::mojom::SmbFs>()
                 .InitWithNewPipeAndPassReceiver(),
             mojo::PendingRemote<smbfs::mojom::SmbFsDelegate>());
  }
}

base::FilePath SmbFsBootstrapImpl::GetUserDaemonStoreDirectory(
    const std::string& username_hash) const {
  CHECK(!username_hash.empty());
  return daemon_store_root_.Append(username_hash);
}

}  // namespace smbfs
