1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 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"
" %1$s FILE\n"
" %2$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", no_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(_("%1$s: File '%2$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: %1$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: %1$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: %1$s\n"),
gnutls_strerror(rv));
return EXIT_FAILURE;
}
printf("%s\n", dname);
return EXIT_SUCCESS;
}
|