From f78501c54532fe091174b1b8a1c747fa4c4cda4f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 14 Mar 2024 20:58:01 +0100 Subject: [PATCH] gpg: new list-option store-x509-notations. * g10/options.h (LIST_STORE_X509_NOTATIONS): New. * g10/gpg.c (parse_list_options): Add "store-x509-notations". * g10/keylist.c (print_x509_notations): Add arg PK and code to write a file. (list_signature_print): Add arg lastpk and handle new option. (list_keyblock_print): Track last key or subkey and pass to list_signature_print. --- doc/gpg.texi | 6 ++++++ g10/gpg.c | 1 + g10/keylist.c | 54 +++++++++++++++++++++++++++++++++++++++++++-------- g10/options.h | 1 + 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/doc/gpg.texi b/doc/gpg.texi index fb8d0f578..e3a6109c9 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -1416,6 +1416,12 @@ give the opposite meaning. The options are: This is intended for debugging and the output format may change without notice. + @item store-x509-notations + @opindex list-options:store-x509-notations + Store X.509 certificates embedded in key signatures as PEM data + files. The filename consists the 4 byte key ID of the certificate, + a dash, the fingerprint of the key or subkey, and the suffix ".pem". + @item show-keyserver-urls @opindex list-options:show-keyserver-urls Show any preferred keyserver URL in the diff --git a/g10/gpg.c b/g10/gpg.c index 8e0c6479e..658b7c7c8 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -2087,6 +2087,7 @@ parse_list_options(char *str) {"show-user-notations",LIST_SHOW_USER_NOTATIONS,NULL, N_("show user-supplied notations during signature listings")}, {"show-x509-notations",LIST_SHOW_X509_NOTATIONS,NULL, NULL }, + {"store-x509-notations",LIST_STORE_X509_NOTATIONS,NULL, NULL }, {"show-keyserver-urls",LIST_SHOW_KEYSERVER_URLS,NULL, N_("show preferred keyserver URLs during signature listings")}, {"show-uid-validity",LIST_SHOW_UID_VALIDITY,NULL, diff --git a/g10/keylist.c b/g10/keylist.c index 20862b0f8..3d43d9e63 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -1172,15 +1172,36 @@ dump_attribs (const PKT_user_id *uid, PKT_public_key *pk) +/* If PK is given the output is written to a new file instead of + * stdout. */ static void -print_x509_notations (struct notation *nots) +print_x509_notations (struct notation *nots, PKT_public_key *pk) { gpg_error_t err; - gpgrt_b64state_t state; + gpgrt_b64state_t state = NULL; + char hexfpr[2*4 + 1 + 2*MAX_FINGERPRINT_LEN+4+1]; + char sha1[20]; + estream_t fp; for (; nots; nots = nots->next) { - state = gpgrt_b64enc_start (es_stdout, "CERTIFICATE"); + if (pk) + { + gcry_md_hash_buffer (GCRY_MD_SHA1, sha1, nots->bdat, nots->blen); + bin2hex (sha1+16, 4, hexfpr); + hexfpr[2*4] = '-'; + hexfingerprint (pk, hexfpr + 2*4+1, 2*MAX_FINGERPRINT_LEN); + strcat (hexfpr, ".pem"); + fp = es_fopen (hexfpr, "w"); + if (!fp) + { + err = gpg_err_code_from_syserror (); + goto b64fail; + } + } + else + fp = es_stdout; + state = gpgrt_b64enc_start (fp, "CERTIFICATE"); if (!state) { err = gpg_err_code_from_syserror (); @@ -1192,12 +1213,19 @@ print_x509_notations (struct notation *nots) err = gpgrt_b64enc_finish (state); if (err) goto b64fail; + if (fp != es_stdout) + { + es_fclose (fp); + fp = NULL; + } } return; b64fail: log_error ("error writing base64 encoded notation: %s\n", gpg_strerror (err)); gpgrt_b64enc_finish (state); + if (fp && fp != es_stdout) + gpgrt_fcancel (fp); } @@ -1250,7 +1278,7 @@ cmp_signodes (const void *av, const void *bv) * NODFLG_MARK_B to indicate self-signatures. */ static void list_signature_print (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node, - struct keylist_context *listctx) + struct keylist_context *listctx, PKT_public_key *lastpk) { /* (extra indentation to keep the diff history short) */ PKT_signature *sig = node->pkt->pkt.signature; @@ -1375,7 +1403,8 @@ list_signature_print (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node, 0)); if (sig->flags.notation - && (opt.list_options & LIST_SHOW_X509_NOTATIONS)) + && (opt.list_options + & (LIST_SHOW_X509_NOTATIONS|LIST_STORE_X509_NOTATIONS))) { struct notation *nots; @@ -1383,7 +1412,10 @@ list_signature_print (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node, && (nots = search_sig_notations (sig, "x509certificate@pgp.com"))) { - print_x509_notations (nots); + if ((opt.list_options & LIST_STORE_X509_NOTATIONS)) + print_x509_notations (nots, lastpk); + else + print_x509_notations (nots, NULL); free_notation (nots); } } @@ -1437,6 +1469,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr, int rc; kbnode_t node; PKT_public_key *pk; + PKT_public_key *lastpk; u32 *mainkid; int skip_sigs = 0; char *hexgrip = NULL; @@ -1453,6 +1486,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr, pk = node->pkt->pkt.public_key; mainkid = pk_keyid (pk); + lastpk = pk; if (secret || opt.with_keygrip) { @@ -1601,6 +1635,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr, { PKT_public_key *pk2 = node->pkt->pkt.public_key; + lastpk = pk2; if ((pk2->flags.revoked || pk2->has_expired) && !(opt.list_options & LIST_SHOW_UNUSABLE_SUBKEYS)) { @@ -1642,7 +1677,9 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr, if (opt.with_key_screening) print_pk_screening (pk2, 0); } - else if ((opt.list_sigs || (opt.list_options & LIST_SHOW_X509_NOTATIONS)) + else if ((opt.list_sigs + || (opt.list_options + & (LIST_SHOW_X509_NOTATIONS|LIST_STORE_X509_NOTATIONS))) && node->pkt->pkttype == PKT_SIGNATURE && !skip_sigs) { kbnode_t n; @@ -1670,7 +1707,8 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr, qsort (sigarray, sigcount, sizeof *sigarray, cmp_signodes); for (idx=0; idx < sigcount; idx++) - list_signature_print (ctrl, keyblock, sigarray[idx], listctx); + list_signature_print (ctrl, keyblock, sigarray[idx], listctx, + lastpk); xfree (sigarray); } } diff --git a/g10/options.h b/g10/options.h index e4303a801..ed8e122a3 100644 --- a/g10/options.h +++ b/g10/options.h @@ -445,6 +445,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode; #define LIST_SHOW_PREF_VERBOSE (1<<15) #define LIST_SHOW_UNUSABLE_SIGS (1<<16) #define LIST_SHOW_X509_NOTATIONS (1<<17) +#define LIST_STORE_X509_NOTATIONS (1<<18) #define VERIFY_SHOW_PHOTOS (1<<0) #define VERIFY_SHOW_POLICY_URLS (1<<1)