blob: fd0f342a80fe02621aba39b23b8ea908c94bb7b8 [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 <lib/syslog/cpp/macros.h>
#include <lib/zx/vmo.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <fbl/ref_ptr.h>
#include "src/lib/files/file.h"
#include "src/storage/lib/vfs/cpp/pseudo_dir.h"
#include "src/storage/lib/vfs/cpp/vmo_file.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/sshbuf.h"
#include "third_party/openssh-portable/ssherr.h"
#include "third_party/openssh-portable/sshkey.h"
// clang-format on
}
namespace {
fbl::RefPtr<fs::VmoFile> CreateVmoFile(const void* data, size_t len) {
zx::vmo vmo;
if (zx_status_t status = zx::vmo::create(len, 0, &vmo); status != ZX_OK) {
FX_LOGS(FATAL) << "Failed to create vmo: " << zx_status_get_string(status);
}
if (zx_status_t status = vmo.write(data, 0, len); status != ZX_OK) {
FX_LOGS(FATAL) << "Failed to write file contents to vmo: " << zx_status_get_string(status);
}
return fbl::MakeRefCounted<fs::VmoFile>(std::move(vmo), len);
}
fbl::RefPtr<fs::VmoFile> CopyAuthorizedKeys() {
constexpr char kAuthorizeKeysPath[] = "/data/ssh/authorized_keys";
std::vector<uint8_t> contents;
FX_CHECK(files::ReadFileToVector(kAuthorizeKeysPath, &contents))
<< "Failed to read authorized_keys file";
return CreateVmoFile(contents.data(), contents.size());
}
void sshkey_auto_free(struct sshkey** key) { sshkey_free(*key); }
void sshbuf_auto_free(struct sshbuf** key) { sshbuf_free(*key); }
fbl::RefPtr<fs::VmoFile> GenerateHostKeys() {
constexpr char key_type[] = "ed25519";
__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);
}
__attribute__((cleanup(sshbuf_auto_free))) struct sshbuf* private_key_blob = sshbuf_new();
if (private_key_blob == nullptr) {
FX_LOGS(FATAL) << "sshbuf_new failed";
}
if (int r = sshkey_private_to_fileblob(private_key, private_key_blob, "", "", 1, nullptr, 0);
r != 0) {
FX_LOGS(FATAL) << "Serializing key failed: " << ssh_err(r);
}
return CreateVmoFile(sshbuf_ptr(private_key_blob), sshbuf_len(private_key_blob));
}
} // namespace
fbl::RefPtr<fs::PseudoDir> BuildDataDir() {
auto ssh_dir = fbl::MakeRefCounted<fs::PseudoDir>();
ssh_dir->AddEntry("authorized_key", CopyAuthorizedKeys());
ssh_dir->AddEntry("ssh_host_ed25519_key", GenerateHostKeys());
auto data_dir = fbl::MakeRefCounted<fs::PseudoDir>();
data_dir->AddEntry("ssh", ssh_dir);
return data_dir;
}