2021-11-11 17:35:38 +03:00
/*
* 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 "
2023-03-09 17:54:58 +03:00
" %1$s FILE \n "
" %2$s { -v | -h } \n "
2021-11-11 17:35:38 +03:00
" \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 [ ] = {
2022-11-22 04:50:01 +03:00
{ " help " , no_argument , NULL , ' h ' } ,
2024-06-07 12:57:16 +03:00
{ " version " , no_argument , NULL , ' v ' } ,
2022-11-22 04:50:01 +03:00
{ NULL , 0 , NULL , 0 } ,
2021-11-11 17:35:38 +03:00
} ;
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 ) {
2023-03-09 17:54:58 +03:00
g_printerr ( _ ( " %1$s: File '%2$s' is too large \n " ) , progname , filename ) ;
2021-11-11 17:35:38 +03:00
return EXIT_FAILURE ;
}
crt_data . data = ( unsigned char * ) buf ;
crt_data . size = bufsize ;
rv = gnutls_x509_crt_init ( & crt ) ;
if ( rv < 0 ) {
2023-03-09 17:54:58 +03:00
g_printerr ( _ ( " Unable to initialize certificate: %1$s \n " ) ,
2021-11-11 17:35:38 +03:00
gnutls_strerror ( rv ) ) ;
return EXIT_FAILURE ;
}
rv = gnutls_x509_crt_import ( crt , & crt_data , GNUTLS_X509_FMT_PEM ) ;
if ( rv < 0 ) {
2023-03-09 17:54:58 +03:00
g_printerr ( _ ( " Unable to load certificate, make sure it is in PEM format: %1$s \n " ) ,
2021-11-11 17:35:38 +03:00
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 ) {
2023-03-09 17:54:58 +03:00
g_printerr ( _ ( " Failed to get distinguished name: %1$s \n " ) ,
2021-11-11 17:35:38 +03:00
gnutls_strerror ( rv ) ) ;
return EXIT_FAILURE ;
}
printf ( " %s \n " , dname ) ;
return EXIT_SUCCESS ;
}