#include "printing.hpp" #include "certificate.hpp" #include "exception.hpp" #include #include #include #include #include #include #include #include #include namespace vanetza { namespace pki { namespace { struct Context { std::string input_file; bool input_stdin = false; bool print_role = false; // certificate only }; const char* role_token(CertificateRole role) { switch (role) { case CertificateRole::RootCa: return "root-ca"; case CertificateRole::EnrolmentAuthority: return "enrolment-authority"; case CertificateRole::AuthorizationAuthority: return "authorization-authority"; case CertificateRole::EnrolmentCredential: return "enrolment-credential"; case CertificateRole::AuthorizationTicket: return "authorization-ticket"; case CertificateRole::Tlm: return "tlm"; case CertificateRole::Unknown: return "unknown"; } return "unknown"; } // Read the OER bytes from the chosen input source, or boost::none if neither // was given (should not happen: the input-source group requires exactly one). boost::optional read_input(const Context& ctx) { ByteBuffer input; if (!ctx.input_file.empty()) { std::ifstream ifs(ctx.input_file, std::ios::binary); std::istreambuf_iterator begin(ifs), end; input.assign(begin, end); } else if (ctx.input_stdin) { std::istreambuf_iterator begin(std::cin), end; input.assign(begin, end); } else { return boost::none; } return input; } void add_input_source(CLI::App& app, Context& ctx) { auto group = app.add_option_group("input source", "read data from the given source"); group->add_option("-f,--file", ctx.input_file, "filename")->check(CLI::ExistingFile); group->add_flag("--stdin", ctx.input_stdin, "read from stdin"); group->require_option(1); } void print_certificate(const ByteBuffer& input, bool role) { if (role) { Certificate cert; if (cert.decode(input)) { std::cout << role_token(certificate_role(cert)) << "\n"; } else { throw DecodingFailure("EtsiTs103097Certificate"); } return; } asn1::asn1c_oer_wrapper cert(asn_DEF_Vanetza_Security_EtsiTs103097Certificate); if (cert.decode(input)) { xer_fprint(stdout, &asn_DEF_Vanetza_Security_EtsiTs103097Certificate, &*cert); } else { throw DecodingFailure("EtsiTs103097Certificate"); } } void print_data(const ByteBuffer& input) { asn1::asn1c_oer_wrapper data(asn_DEF_Vanetza_Security_EtsiTs103097Data); if (data.decode(input)) { xer_fprint(stdout, &asn_DEF_Vanetza_Security_EtsiTs103097Data, &*data); } else { throw DecodingFailure("EtsiTs103097Data"); } } void print_mgmt_data(const ByteBuffer& input) { asn1::asn1c_oer_wrapper data(asn_DEF_Vanetza_Security_EtsiTs102941Data); if (data.decode(input)) { xer_fprint(stdout, &asn_DEF_Vanetza_Security_EtsiTs102941Data, &*data); } else { throw DecodingFailure("EtsiTs102941Data"); } } } // namespace std::shared_ptr build_print_command() { auto ctx = std::make_shared(); auto app = std::make_shared("printing ASN.1 OER encoded certificates, trust lists and alike", "print"); auto certificate = app->add_subcommand("certificate", "EtsiTs103097Certificate"); certificate->alias("cert"); add_input_source(*certificate, *ctx); certificate->add_flag("--role", ctx->print_role, "print the certificate's PKI role instead of its content"); certificate->callback([ctx]() { if (auto input = read_input(*ctx)) { print_certificate(*input, ctx->print_role); } }); auto data = app->add_subcommand("data", "EtsiTs103097Data"); add_input_source(*data, *ctx); data->callback([ctx]() { if (auto input = read_input(*ctx)) { print_data(*input); } }); auto mgmt = app->add_subcommand("mgmt-data", "EtsiTs102941Data"); add_input_source(*mgmt, *ctx); mgmt->callback([ctx]() { if (auto input = read_input(*ctx)) { print_mgmt_data(*input); } }); app->require_subcommand(1); return app; } } // namespace pki } // namespace vanetza