blob: e60c99fab111bf870a915d43a63198d27c0d9dcb [file] [log] [blame]
// Copyright 2019 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/sshd-host/authorized_keys.h"
#include <fcntl.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/result.h>
#include <lib/zx/vmo.h>
#include <stdio.h>
#include <sys/stat.h>
#include <memory>
#include <fbl/unique_fd.h>
#include "src/developer/sshd-host/constants.h"
namespace sshd_host {
zx_status_t provision_authorized_keys_from_bootloader_file(
fidl::SyncClient<fuchsia_boot::Items>& boot_items) {
auto result =
boot_items->GetBootloaderFile({{.filename = std::string(kAuthorizedKeysBootloaderFileName)}});
if (result.is_error()) {
FX_PLOGS(ERROR, result.error_value().status())
<< "Provisioning keys from boot item: GetBootloaderFile failed";
return result.error_value().status();
}
zx::vmo vmo = std::move(result->payload());
if (!vmo.is_valid()) {
FX_LOGS(INFO) << "Provisioning keys from boot item: bootloader file not found: "
<< kAuthorizedKeysBootloaderFileName;
return ZX_ERR_NOT_FOUND;
}
uint64_t size;
if (zx_status_t status = vmo.get_property(ZX_PROP_VMO_CONTENT_SIZE, &size, sizeof(size));
status != ZX_OK) {
FX_PLOGS(ERROR, status) << "Provisioning keys from boot item: unable to get file size";
return status;
}
std::unique_ptr buffer = std::make_unique<uint8_t[]>(size);
if (zx_status_t status = vmo.read(buffer.get(), 0, size); status != ZX_OK) {
FX_PLOGS(ERROR, status) << "Provisioning keys from boot item: failed to read file";
return status;
}
if (mkdir(kSshDirectory, 0700) && errno != EEXIST) {
FX_LOGS(ERROR) << "Provisioning keys from boot item: failed to create directory: "
<< kSshDirectory << " Error: " << strerror(errno);
return ZX_ERR_IO;
}
fbl::unique_fd kfd(open(kAuthorizedKeysPath, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR));
if (!kfd) {
FX_LOGS(ERROR) << "Provisioning keys from boot item: open failed: " << kAuthorizedKeysPath
<< " error: " << strerror(errno);
return errno == EEXIST ? ZX_ERR_ALREADY_EXISTS : ZX_ERR_IO;
}
if (write(kfd.get(), buffer.get(), size) != static_cast<ssize_t>(size)) {
FX_LOGS(ERROR) << "Provisioning keys from boot item: write failed: " << strerror(errno);
return ZX_ERR_IO;
}
fsync(kfd.get());
if (close(kfd.release())) {
FX_LOGS(ERROR) << "Provisioning keys from boot item: close failed: " << strerror(errno);
return ZX_ERR_IO;
}
FX_LOGS(INFO) << "Provisioning keys from boot item: authorized_keys provisioned";
return ZX_OK;
}
} // namespace sshd_host