/* * SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "internal.h" #include #include #include #include #include #include "virgettext.h" static void glib_auto_cleanup_gnutls_x509_crt_t(gnutls_x509_crt_t *pointer) { gnutls_x509_crt_deinit(*pointer); } static void print_usage(const char *progname, FILE *out) { fprintf(out, _("Usage:\n" " %s FILE\n" " %s { -v | -h }\n" "\n" "Extract Distinguished Name from a PEM certificate.\n" "The output is meant to be used in the tls_allowed_dn_list\n" "configuration option in the libvirtd.conf file.\n" "\n" " FILE certificate file to extract the DN from\n" "\n" "options:\n" " -h | --help display this help and exit\n" " -v | --version output version information and exit\n"), progname, progname); } int main(int argc, char **argv) { const char *progname = NULL; const char *filename = NULL; size_t dnamesize = 256; size_t bufsize = 0; g_autofree char *dname = g_new0(char, dnamesize); g_autofree char *buf = NULL; g_auto(gnutls_x509_crt_t) crt = {0}; gnutls_datum_t crt_data = {0}; g_autoptr(GError) error = NULL; int arg = 0; int rv = 0; struct option opt[] = { {"help", no_argument, NULL, 'h'}, {"version", optional_argument, NULL, 'v'}, {NULL, 0, NULL, 0} }; if (virGettextInitialize() < 0) return EXIT_FAILURE; if (!(progname = strrchr(argv[0], '/'))) progname = argv[0]; else progname++; while ((arg = getopt_long(argc, argv, "hv", opt, NULL)) != -1) { switch (arg) { case 'v': printf("%s\n", PACKAGE_VERSION); return EXIT_SUCCESS; case 'h': print_usage(progname, stdout); return EXIT_SUCCESS; default: print_usage(progname, stderr); return EXIT_FAILURE; } } if (optind != argc - 1) { print_usage(progname, stderr); return EXIT_FAILURE; } filename = argv[optind]; g_file_get_contents(filename, &buf, &bufsize, &error); if (error) { g_printerr("%s: %s\n", progname, error->message); return EXIT_FAILURE; } if (bufsize > UINT_MAX) { g_printerr(_("%s: File '%s' is too large\n"), progname, filename); return EXIT_FAILURE; } crt_data.data = (unsigned char *)buf; crt_data.size = bufsize; rv = gnutls_x509_crt_init(&crt); if (rv < 0) { g_printerr(_("Unable to initialize certificate: %s\n"), gnutls_strerror(rv)); return EXIT_FAILURE; } rv = gnutls_x509_crt_import(crt, &crt_data, GNUTLS_X509_FMT_PEM); if (rv < 0) { g_printerr(_("Unable to load certificate, make sure it is in PEM format: %s\n"), gnutls_strerror(rv)); return EXIT_FAILURE; } rv = gnutls_x509_crt_get_dn(crt, dname, &dnamesize); if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER) { dname = g_realloc(dname, dnamesize); rv = gnutls_x509_crt_get_dn(crt, dname, &dnamesize); } if (rv != 0) { g_printerr(_("Failed to get distinguished name: %s\n"), gnutls_strerror(rv)); return EXIT_FAILURE; } printf("%s\n", dname); return EXIT_SUCCESS; }