]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
tools: Add virt-pki-query-dn binary
authorMartin Kletzander <mkletzan@redhat.com>
Thu, 11 Nov 2021 14:35:38 +0000 (15:35 +0100)
committerMartin Kletzander <mkletzan@redhat.com>
Fri, 12 Nov 2021 11:37:29 +0000 (12:37 +0100)
With this program we do not have to depend on the output of `certtool -i`, which
changed the order of the fields at some point and the newest version is
incompatible with what libvirt expects in tls_allowed_dn_list configuration
option.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
libvirt.spec.in
po/POTFILES.in
tools/meson.build
tools/virt-pki-query-dn.c [new file with mode: 0644]

index 4ecb28114ce85ae6bd7affbc803fbaee4785a154..5f1773ef93f25e97ee6ffc9c7ff1fe6c6b7acfae 100644 (file)
@@ -1983,6 +1983,7 @@ exit 0
 %{_mandir}/man1/virt-pki-validate.1*
 %{_bindir}/virsh
 %{_bindir}/virt-xml-validate
+%{_bindir}/virt-pki-query-dn
 %{_bindir}/virt-pki-validate
 
 %{_datadir}/bash-completion/completions/virsh
index 8a726f624e383a84d9d012b6f9eeccd48d5eeb88..bf0a3b352979486fe418a45c6bcda014a7450346 100644 (file)
 @SRCDIR@tools/virt-host-validate-qemu.c
 @SRCDIR@tools/virt-host-validate.c
 @SRCDIR@tools/virt-login-shell-helper.c
+@SRCDIR@tools/virt-pki-query-dn.c
 @SRCDIR@tools/vsh-table.c
 @SRCDIR@tools/vsh.c
 @SRCDIR@tools/vsh.h
index bf0eab8b6bf22bb6481ae00d7c11bd8f1aff2925..3fba313e5f49f3e3a458b340cb7be5a5dbd29941 100644 (file)
@@ -257,6 +257,33 @@ configure_file(
   install_mode: 'rwxrwxr-x',
 )
 
+executable(
+  'virt-pki-query-dn',
+  [
+    'virt-pki-query-dn.c',
+  ],
+  dependencies: [
+    glib_dep,
+    gnutls_dep,
+  ],
+  include_directories: [
+    libvirt_inc,
+    src_inc_dir,
+    top_inc_dir,
+    util_inc_dir,
+  ],
+  link_args: (
+    libvirt_relro
+    + libvirt_no_indirect
+    + libvirt_no_undefined
+  ),
+  link_with: [
+    libvirt_lib
+  ],
+  install: true,
+  install_dir: bindir,
+)
+
 if conf.has('WITH_SANLOCK')
   configure_file(
     input: 'virt-sanlock-cleanup.in',
diff --git a/tools/virt-pki-query-dn.c b/tools/virt-pki-query-dn.c
new file mode 100644 (file)
index 0000000..ee3783c
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <config.h>
+#include "internal.h"
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#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;
+}