blob: c11cdee1ef42f92d4e720084cbe67a5c0ee46656 [file] [log] [blame]
// 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 <stdio.h>
#include <sysexits.h>
#include <memory>
#include <string>
#include <attestation/proto_bindings/pca_agent.pb.h>
#include <base/command_line.h>
#include <base/files/file_util.h>
#include <base/optional.h>
#include <brillo/syslog_logging.h>
#include <dbus/bus.h>
#include "attestation/common/print_interface_proto.h"
#include "attestation/pca_agent/dbus-proxies.h"
namespace {
const char kEnrollCommand[] = "enroll";
const char kGetCertificateCommand[] = "get_certificate";
const char kUsage[] = R"(
Usage: pca_agent_client <command> [<args>]
Commands:
enroll --input=<input_file> --output=<output_file>
Sends the enroll request stored in |input| to PCA server and stores the
response in |output|.
get_certificate --input=<input_file> --output=<output_file>
Sends the cert request stored in |input| to PCA server and stores the
response in |output|.
)";
const char kInputSwitch[] = "input";
const char kOutputSwitch[] = "output";
const char kACATypeSwitch[] = "aca_type";
base::Optional<attestation::ACAType> GetACAType(base::CommandLine* cmd_line) {
const std::string val = cmd_line->GetSwitchValueASCII(kACATypeSwitch);
if (val.empty() || val == "default") {
return attestation::DEFAULT_ACA;
}
if (val == "test") {
return attestation::TEST_ACA;
}
return base::nullopt;
}
} // namespace
int main(int argc, char* argv[]) {
base::CommandLine::Init(argc, argv);
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
const auto& args = command_line->GetArgs();
brillo::InitLog(brillo::kLogToStderr);
// dbus proxy setup
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
auto pca_agent = std::make_unique<org::chromium::PcaAgentProxy>(bus);
brillo::ErrorPtr error;
if (command_line->HasSwitch("help") || command_line->HasSwitch("h") ||
args.empty()) {
printf("%s", kUsage);
return EX_USAGE;
}
if (args.front() == kEnrollCommand) {
std::string input_filename =
command_line->GetSwitchValueASCII(kInputSwitch);
std::string output_filename =
command_line->GetSwitchValueASCII(kOutputSwitch);
if (input_filename.empty() || output_filename.empty()) {
printf("%s", kUsage);
return EX_USAGE;
}
auto aca_type = GetACAType(command_line);
if (!aca_type) {
printf("%s", kUsage);
return EX_USAGE;
}
attestation::pca_agent::EnrollRequest req;
if (!base::ReadFileToString(base::FilePath(input_filename),
req.mutable_request())) {
LOG(ERROR) << "Failed to read file: " << input_filename;
return EX_IOERR;
}
req.set_aca_type(*aca_type);
attestation::pca_agent::EnrollReply reply;
if (!pca_agent->Enroll(req, &reply, &error)) {
LOG(ERROR) << "Error sending dbus message: " << error->GetMessage();
return EX_SOFTWARE;
}
if (reply.status() != attestation::STATUS_SUCCESS) {
LOG(ERROR) << "Failed to enroll: " << GetProtoDebugString(reply.status());
return EX_SOFTWARE;
}
if (reply.response().empty()) {
LOG(ERROR) << "Unexpected empty response";
return EX_SOFTWARE;
}
if (base::WriteFile(base::FilePath(output_filename),
reply.response().data(), reply.response().size()) !=
static_cast<int>(reply.response().size())) {
LOG(ERROR) << "Failed to write file: " << output_filename;
return EX_IOERR;
}
} else if (args.front() == kGetCertificateCommand) {
std::string input_filename =
command_line->GetSwitchValueASCII(kInputSwitch);
std::string output_filename =
command_line->GetSwitchValueASCII(kOutputSwitch);
if (input_filename.empty() || output_filename.empty()) {
printf("%s", kUsage);
return EX_USAGE;
}
auto aca_type = GetACAType(command_line);
if (!aca_type) {
printf("%s", kUsage);
return EX_USAGE;
}
attestation::pca_agent::GetCertificateRequest req;
if (!base::ReadFileToString(base::FilePath(input_filename),
req.mutable_request())) {
LOG(ERROR) << "Failed to read file: " << input_filename;
return EX_IOERR;
}
req.set_aca_type(*aca_type);
attestation::pca_agent::GetCertificateReply reply;
if (!pca_agent->GetCertificate(req, &reply, &error)) {
LOG(ERROR) << "Error sending dbus message: " << error->GetMessage();
return EX_SOFTWARE;
}
if (reply.status() != attestation::STATUS_SUCCESS) {
LOG(ERROR) << "Failed to get certificate: "
<< GetProtoDebugString(reply.status());
return EX_SOFTWARE;
}
if (reply.response().empty()) {
LOG(ERROR) << "Unexpected empty response";
return EX_SOFTWARE;
}
if (base::WriteFile(base::FilePath(output_filename),
reply.response().data(), reply.response().size()) !=
static_cast<int>(reply.response().size())) {
LOG(ERROR) << "Failed to write file: " << output_filename;
return EX_IOERR;
}
}
return EX_OK;
}