From b36e557c5b05ba21942f385c03988f138d57dfb9 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Wed, 15 May 2024 09:56:40 +0200 Subject: gpg: Terminate key listing on output write error. * g10/keylist.c (list_all): Handle error from list_keyblock. (list_one): Ditto. (locate_one): Ditto. (list_keyblock): Detect write error, print, and return it. (list_keyblock_direct): Return error from list_keyblock. * g10/import.c (import_one_real): Break on listing error. -- Test by using gpg -k >/dev/full GnuPG-bug-id: 6185 --- g10/import.c | 4 +++- g10/keygen.c | 5 ++++- g10/keylist.c | 53 +++++++++++++++++++++++++++++++++++++---------------- g10/main.h | 4 ++-- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/g10/import.c b/g10/import.c index ff8847cb6..bbeeebdfe 100644 --- a/g10/import.c +++ b/g10/import.c @@ -2175,10 +2175,12 @@ import_one_real (ctrl_t ctrl, merge_keys_done = 1; /* Note that we do not want to show the validity because the key * has not yet imported. */ - list_keyblock_direct (ctrl, keyblock, from_sk, 0, + err = list_keyblock_direct (ctrl, keyblock, from_sk, 0, opt.fingerprint || opt.with_fingerprint, 1); es_fflush (es_stdout); no_usable_encr_subkeys_warning (keyblock); + if (err) + goto leave; } /* Write the keyblock to the output and do not actually import. */ diff --git a/g10/keygen.c b/g10/keygen.c index fe9a5d8f2..4bdb9f53a 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -6292,9 +6292,12 @@ do_generate_keypair (ctrl_t ctrl, struct para_data_s *para, list_keyblock_direct (ctrl, pub_root, 0, 1, opt.fingerprint || opt.with_fingerprint, 1); + /* Note that we ignore errors from the list function + * because that would only be an additional info. It + * has already been remarked that the key has been + * created. */ } - if (!opt.batch && (get_parameter_algo (ctrl, para, pKEYTYPE, NULL) == PUBKEY_ALGO_DSA diff --git a/g10/keylist.c b/g10/keylist.c index c6667936d..81d6805a5 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -82,7 +82,7 @@ static estream_t attrib_fp; -static void list_keyblock (ctrl_t ctrl, +static gpg_error_t list_keyblock (ctrl_t ctrl, kbnode_t keyblock, int secret, int has_secret, int fpr, struct keylist_context *listctx); @@ -745,6 +745,7 @@ list_all (ctrl_t ctrl, int secret, int mark_secret) int any_secret; const char *lastresname, *resname; struct keylist_context listctx; + gpg_error_t listerr = 0; memset (&listctx, 0, sizeof (listctx)); if (opt.check_sigs) @@ -802,13 +803,13 @@ list_all (ctrl_t ctrl, int secret, int mark_secret) } } merge_keys_and_selfsig (ctrl, keyblock); - list_keyblock (ctrl, keyblock, secret, any_secret, opt.fingerprint, - &listctx); + listerr = list_keyblock (ctrl, keyblock, secret, any_secret, + opt.fingerprint, &listctx); } release_kbnode (keyblock); keyblock = NULL; } - while (!(rc = keydb_search_next (hd))); + while (!listerr && !(rc = keydb_search_next (hd))); es_fflush (es_stdout); if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND) log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc)); @@ -839,6 +840,7 @@ list_one (ctrl_t ctrl, strlist_t names, int secret, int mark_secret) const char *keyring_str = _("Keyring"); int i; struct keylist_context listctx; + gpg_error_t listerr = 0; memset (&listctx, 0, sizeof (listctx)); if (!secret && opt.check_sigs) @@ -887,12 +889,12 @@ list_one (ctrl_t ctrl, strlist_t names, int secret, int mark_secret) es_putc ('-', es_stdout); es_putc ('\n', es_stdout); } - list_keyblock (ctrl, keyblock, secret, any_secret, - opt.fingerprint, &listctx); + listerr = list_keyblock (ctrl, keyblock, secret, any_secret, + opt.fingerprint, &listctx); } release_kbnode (keyblock); } - while (!getkey_next (ctrl, ctx, NULL, &keyblock)); + while (!listerr && !getkey_next (ctrl, ctx, NULL, &keyblock)); getkey_end (ctrl, ctx); if (opt.check_sigs && !opt.with_colons) @@ -910,12 +912,13 @@ locate_one (ctrl_t ctrl, strlist_t names, int no_local) GETKEY_CTX ctx = NULL; KBNODE keyblock = NULL; struct keylist_context listctx; + gpg_error_t listerr = 0; memset (&listctx, 0, sizeof (listctx)); if (opt.check_sigs) listctx.check_sigs = 1; - for (sl = names; sl; sl = sl->next) + for (sl = names; sl && !listerr; sl = sl->next) { rc = get_best_pubkey_byname (ctrl, no_local? GET_PUBKEY_NO_LOCAL @@ -933,10 +936,11 @@ locate_one (ctrl_t ctrl, strlist_t names, int no_local) { do { - list_keyblock (ctrl, keyblock, 0, 0, opt.fingerprint, &listctx); + listerr = list_keyblock (ctrl, keyblock, 0, 0, + opt.fingerprint, &listctx); release_kbnode (keyblock); } - while (ctx && !getkey_next (ctrl, ctx, NULL, &keyblock)); + while (!listerr && ctx && !getkey_next (ctrl, ctx, NULL, &keyblock)); getkey_end (ctrl, ctx); ctx = NULL; } @@ -2325,11 +2329,18 @@ reorder_keyblock (KBNODE keyblock) } -static void +/* Note: If this function returns an error the caller is expected to + * honor this and stop all further processing. Any error returned + * will be a write error (to stdout) and a diagnostics is always + * printed using log_error. */ +static gpg_error_t list_keyblock (ctrl_t ctrl, KBNODE keyblock, int secret, int has_secret, int fpr, struct keylist_context *listctx) { + gpg_error_t err = 0; + + es_clearerr (es_stdout); reorder_keyblock (keyblock); if (list_filter.selkey) @@ -2347,7 +2358,7 @@ list_keyblock (ctrl_t ctrl, } } if (!selected) - return; /* Skip this one. */ + return 0; /* Skip this one. */ } if (opt.with_colons) @@ -2361,24 +2372,34 @@ list_keyblock (ctrl_t ctrl, else list_keyblock_print (ctrl, keyblock, secret, fpr, listctx); - if (secret) - es_fflush (es_stdout); + if (es_ferror (es_stdout)) + err = gpg_error_from_syserror (); + + if (secret && es_fflush (es_stdout) && !err) + err = gpg_error_from_syserror (); + + if (err) + log_error (_("error writing to stdout: %s\n"), gpg_strerror (err)); + + return err; } /* Public function used by keygen to list a keyblock. If NO_VALIDITY * is set the validity of a key is never shown. */ -void +gpg_error_t list_keyblock_direct (ctrl_t ctrl, kbnode_t keyblock, int secret, int has_secret, int fpr, int no_validity) { struct keylist_context listctx; + gpg_error_t err; memset (&listctx, 0, sizeof (listctx)); listctx.no_validity = !!no_validity; - list_keyblock (ctrl, keyblock, secret, has_secret, fpr, &listctx); + err = list_keyblock (ctrl, keyblock, secret, has_secret, fpr, &listctx); keylist_context_release (&listctx); + return err; } diff --git a/g10/main.h b/g10/main.h index 5123dd03b..2443aa7fe 100644 --- a/g10/main.h +++ b/g10/main.h @@ -470,8 +470,8 @@ void secret_key_list (ctrl_t ctrl, strlist_t list ); gpg_error_t parse_and_set_list_filter (const char *string); void print_subpackets_colon(PKT_signature *sig); void reorder_keyblock (KBNODE keyblock); -void list_keyblock_direct (ctrl_t ctrl, kbnode_t keyblock, int secret, - int has_secret, int fpr, int no_validity); +gpg_error_t list_keyblock_direct (ctrl_t ctrl, kbnode_t keyblock, int secret, + int has_secret, int fpr, int no_validity); int cmp_signodes (const void *av, const void *bv); void print_fingerprint (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, int mode); -- cgit v1.2.3