From 51419d63415ae2aa029f8829099b6789b264edc5 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 20 Apr 2021 09:37:56 +0200 Subject: [PATCH] sm: New command --show-certs * sm/keylist.c (do_show_certs): New. (gpgsm_show_certs): New. * sm/gpgsm.c (aShowCerts): New. (opts): Add --show-certs. (main): Call gpgsm_show_certs. -- I have been using libksba test programs for countless times to look at certificates and I always wanted to add such a feature to gpgsm. This is simply much more convenient. Signed-off-by: Werner Koch --- doc/gpgsm.texi | 11 ++++++ sm/gpgsm.c | 12 +++++++ sm/gpgsm.h | 2 ++ sm/keylist.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+) diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index 886521076..1d3a7e07e 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -221,6 +221,17 @@ List certificates matching @var{pattern} using an external server. This utilizes the @code{dirmngr} service. It uses a format useful mainly for debugging. +@item --show-certs [@var{files}] +@opindex show-certs +This command takes certificate files as input and prints information +about them in the same format as @option{--dump-cert} does. Each file +may either contain a single binary certificate or several PEM encoded +certificates. If no files are given, the input is taken from stdin. + +Please note that the listing format may be changed in future releases +and that the option @option{--with-colons} has currently no effect. + + @item --keydb-clear-some-cert-flags @opindex keydb-clear-some-cert-flags This is a debugging aid to reset certain flags in the key database diff --git a/sm/gpgsm.c b/sm/gpgsm.c index e292aa160..ca30358ec 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -96,6 +96,7 @@ enum cmd_and_opt_values { aDumpChain, aDumpSecretKeys, aDumpExternalKeys, + aShowCerts, aKeydbClearSomeCertFlags, aFingerprint, @@ -252,6 +253,7 @@ static gpgrt_opt_t opts[] = { ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"), ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"), + ARGPARSE_c (aShowCerts, "show-certs", "@"), ARGPARSE_c (aDumpKeys, "dump-cert", "@"), ARGPARSE_c (aDumpKeys, "dump-keys", "@"), ARGPARSE_c (aDumpChain, "dump-chain", "@"), @@ -1212,6 +1214,7 @@ main ( int argc, char **argv) case aExportSecretKeyP12: case aExportSecretKeyP8: case aExportSecretKeyRaw: + case aShowCerts: case aDumpKeys: case aDumpChain: case aDumpExternalKeys: @@ -2121,6 +2124,15 @@ main ( int argc, char **argv) } break; + case aShowCerts: + { + estream_t fp; + + fp = open_es_fwrite (opt.outfile?opt.outfile:"-"); + gpgsm_show_certs (&ctrl, argc, argv, fp); + es_fclose (fp); + } + break; case aKeygen: /* Generate a key; well kind of. */ { diff --git a/sm/gpgsm.h b/sm/gpgsm.h index e96f15743..7c27c586e 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -389,6 +389,8 @@ int gpgsm_find_cert (ctrl_t ctrl, const char *name, ksba_sexp_t keyid, /*-- keylist.c --*/ gpg_error_t gpgsm_list_keys (ctrl_t ctrl, strlist_t names, estream_t fp, unsigned int mode); +gpg_error_t gpgsm_show_certs (ctrl_t ctrl, int nfiles, char **files, + estream_t fp); /*-- import.c --*/ int gpgsm_import (ctrl_t ctrl, int in_fd, int reimport_mode); diff --git a/sm/keylist.c b/sm/keylist.c index 1a062d149..3c9e10c81 100644 --- a/sm/keylist.c +++ b/sm/keylist.c @@ -1710,3 +1710,98 @@ gpgsm_list_keys (ctrl_t ctrl, strlist_t names, estream_t fp, err = list_external_keys (ctrl, names, fp, (mode&256)); return err; } + + + +static gpg_error_t +do_show_certs (ctrl_t ctrl, const char *fname, estream_t outfp) +{ + gpg_error_t err; + gnupg_ksba_io_t b64reader = NULL; + ksba_reader_t reader; + ksba_cert_t cert = NULL; + estream_t fp; + int any = 0; + + if (!fname || (fname[0] == '-' && !fname[1])) + { + fp = es_stdin; + fname = "[stdin]"; + } + else + { + fp = es_fopen (fname, "rb"); + if (!fp) + { + err = gpg_error_from_syserror (); + log_error (_("can't open '%s': %s\n"), fname, gpg_strerror (err)); + return err; + } + } + + err = gnupg_ksba_create_reader + (&b64reader, ((ctrl->is_pem? GNUPG_KSBA_IO_PEM : 0) + | (ctrl->is_base64? GNUPG_KSBA_IO_BASE64 : 0) + | (ctrl->autodetect_encoding? GNUPG_KSBA_IO_AUTODETECT : 0) + | GNUPG_KSBA_IO_MULTIPEM), + fp, &reader); + if (err) + { + log_error ("can't create reader: %s\n", gpg_strerror (err)); + goto leave; + } + + /* We need to loop here to handle multiple PEM objects per file. */ + do + { + ksba_cert_release (cert); cert = NULL; + + err = ksba_cert_new (&cert); + if (err) + goto leave; + + err = ksba_cert_read_der (cert, reader); + if (err) + goto leave; + + es_fprintf (outfp, "File ........: %s\n", fname); + list_cert_raw (ctrl, NULL, cert, outfp, 0, 0); + es_putc ('\n', outfp); + any = 1; + + ksba_reader_clear (reader, NULL, NULL); + } + while (!gnupg_ksba_reader_eof_seen (b64reader)); + + leave: + if (any && gpg_err_code (err) == GPG_ERR_EOF) + err = 0; + ksba_cert_release (cert); + gnupg_ksba_destroy_reader (b64reader); + if (fp != es_stdin) + es_fclose (fp); + return err; +} + + +/* Show a raw dump of the certificates found in the files given in + * the arrag FILES. Write output to FP. */ +gpg_error_t +gpgsm_show_certs (ctrl_t ctrl, int nfiles, char **files, estream_t fp) +{ + gpg_error_t saveerr = 0; + gpg_error_t err; + + if (!nfiles) + saveerr = do_show_certs (ctrl, NULL, fp); + else + { + for (; nfiles; nfiles--, files++) + { + err = do_show_certs (ctrl, *files, fp); + if (err && !saveerr) + saveerr = err; + } + } + return saveerr; +}