blob: 600477a52ae1495312f6eae4476bed6bdc2ec2db [file] [log] [blame]
// Copyright 2024 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.
#include "src/developer/vsock-sshd-host/data_dir.h"
#include <fidl/fuchsia.io/cpp/fidl.h>
#include <lib/fdio/namespace.h>
#include <lib/syslog/cpp/macros.h>
#include <sys/stat.h>
#include <zircon/errors.h>
#include "src/lib/files/file.h"
#include "src/storage/memfs/memfs.h"
#include "src/storage/memfs/vnode_dir.h"
extern "C" {
// clang-format off
#include "third_party/openssh-portable/authfile.h"
#include "third_party/openssh-portable/includes.h"
#include "third_party/openssh-portable/ssherr.h"
#include "third_party/openssh-portable/sshkey.h"
// clang-format on
}
namespace {
void CopyAuthorizedKeys() {
constexpr char kSshDir[] = "/tmp/ssh";
constexpr char kAuthorizeKeysPath[] = "/data/ssh/authorized_keys";
constexpr char kNewAuthorizeKeysPath[] = "/tmp/ssh/authorized_keys";
// ignore errors, if the dir already exists, this is benign, if it does not
// and this fails, the write will fail.
mkdir(kSshDir, 0700);
std::string str;
ZX_ASSERT(files::ReadFileToString(kAuthorizeKeysPath, &str) == true);
ZX_ASSERT(files::WriteFile(kNewAuthorizeKeysPath, str) == true);
}
void sshkey_auto_free(struct sshkey** key) { sshkey_free(*key); }
void GenerateHostKeys() {
constexpr char key_type[] = "ed25519";
constexpr char kPath[] = "/tmp/ssh/ssh_host_ed25519_key";
__attribute__((cleanup(sshkey_auto_free))) struct sshkey* private_key = nullptr;
__attribute__((cleanup(sshkey_auto_free))) struct sshkey* public_key = nullptr;
int type = sshkey_type_from_name(key_type);
if (int r = sshkey_generate(type, 0, &private_key); r != 0) {
FX_LOGS(FATAL) << "sshkey_generate failed: " << ssh_err(r);
}
if (int r = sshkey_from_private(private_key, &public_key); r != 0) {
FX_LOGS(FATAL) << "sshkey_from_private failed: " << ssh_err(r);
}
if (int r = sshkey_save_private(private_key, kPath, "", "", 1, nullptr, 0); r != 0) {
FX_LOGS(FATAL) << "Saving key " << kPath << "failed: " << ssh_err(r);
}
}
} // namespace
zx::result<> BuildDataDir(async::Loop& loop, memfs::Memfs* memfs,
fbl::RefPtr<memfs::VnodeDir> data_dir) {
auto [client, server] = fidl::Endpoints<fuchsia_io::Directory>::Create();
if (zx_status_t status = memfs->ServeDirectory(std::move(data_dir), std::move(server));
status != ZX_OK) {
FX_LOGS(ERROR) << "Serve failed";
return zx::error(status);
}
fdio_ns_t* ns;
if (zx_status_t status = fdio_ns_get_installed(&ns); status != ZX_OK) {
FX_LOGS(ERROR) << "fdio_ns_get_installed failed";
return zx::error(status);
}
constexpr char kPath[] = "/tmp";
if (zx_status_t status = fdio_ns_bind(ns, kPath, client.TakeChannel().release());
status != ZX_OK) {
FX_LOGS(ERROR) << "fdio_ns_bind failed";
return zx::error(status);
}
auto unbind_cleanup = fit::defer(
[&ns, &kPath]() { [[maybe_unused]] zx_status_t status = fdio_ns_unbind(ns, kPath); });
std::thread t([&loop]() {
CopyAuthorizedKeys();
GenerateHostKeys();
loop.Quit();
});
loop.Run();
t.join();
loop.ResetQuit();
return zx::ok();
}