aboutsummaryrefslogtreecommitdiffstats
path: root/g10/keylist.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/keylist.c')
-rw-r--r--g10/keylist.c454
1 files changed, 284 insertions, 170 deletions
diff --git a/g10/keylist.c b/g10/keylist.c
index cc1e23d7f..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;
}
@@ -1171,6 +1175,77 @@ dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
}
+static void
+print_keygrip (const char *keygrip)
+{
+ const char *s;
+
+ s = strchr (keygrip, ',');
+ if (s)
+ es_fprintf (es_stdout, " Keygrip = %.*s,\n%*s%s\n",
+ (int)(s-keygrip), keygrip, 16, "", s+1);
+ else
+ es_fprintf (es_stdout, " Keygrip = %s\n", keygrip);
+}
+
+
+/* If PK is given the output is written to a new file instead of
+ * stdout. */
+static void
+print_x509_notations (struct notation *nots, PKT_public_key *pk)
+{
+ gpg_error_t err;
+ 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)
+ {
+ 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 ();
+ goto b64fail;
+ }
+ err = gpgrt_b64enc_write (state, nots->bdat, nots->blen);
+ if (err)
+ goto b64fail;
+ 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);
+}
+
+
/* Order two signatures. We first order by keyid and then by creation
* time. */
int
@@ -1220,170 +1295,186 @@ 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;
- int rc, sigrc;
- char *sigstr;
- char *reason_text = NULL;
- char *reason_comment = NULL;
- size_t reason_commentlen;
- int reason_code = 0;
+ PKT_signature *sig = node->pkt->pkt.signature;
+ int rc, sigrc;
+ char *sigstr;
+ char *reason_text = NULL;
+ char *reason_comment = NULL;
+ size_t reason_commentlen;
+ int reason_code = 0;
+
+ if (listctx->check_sigs)
+ {
+ rc = check_key_signature (ctrl, keyblock, node, NULL);
+ switch (gpg_err_code (rc))
+ {
+ case 0:
+ listctx->good_sigs++;
+ sigrc = '!';
+ break;
+ case GPG_ERR_BAD_SIGNATURE:
+ listctx->inv_sigs++;
+ sigrc = '-';
+ break;
+ case GPG_ERR_NO_PUBKEY:
+ case GPG_ERR_UNUSABLE_PUBKEY:
+ listctx->no_key++;
+ return;
+ case GPG_ERR_DIGEST_ALGO:
+ case GPG_ERR_PUBKEY_ALGO:
+ if (!(opt.list_options & LIST_SHOW_UNUSABLE_SIGS))
+ return;
+ /* fallthru. */
+ default:
+ listctx->oth_err++;
+ sigrc = '%';
+ break;
+ }
- if (listctx->check_sigs)
- {
- rc = check_key_signature (ctrl, keyblock, node, NULL);
- switch (gpg_err_code (rc))
- {
- case 0:
- listctx->good_sigs++;
- sigrc = '!';
- break;
- case GPG_ERR_BAD_SIGNATURE:
- listctx->inv_sigs++;
- sigrc = '-';
- break;
- case GPG_ERR_NO_PUBKEY:
- case GPG_ERR_UNUSABLE_PUBKEY:
- listctx->no_key++;
- return;
- case GPG_ERR_DIGEST_ALGO:
- case GPG_ERR_PUBKEY_ALGO:
- if (!(opt.list_options & LIST_SHOW_UNUSABLE_SIGS))
- return;
- /* fallthru. */
- default:
- listctx->oth_err++;
- sigrc = '%';
- break;
- }
+ /* TODO: Make sure a cached sig record here still has
+ the pk that issued it. See also
+ keyedit.c:print_and_check_one_sig */
+ }
+ else
+ {
+ if (!(opt.list_options & LIST_SHOW_UNUSABLE_SIGS)
+ && (gpg_err_code (openpgp_pk_test_algo (sig->pubkey_algo)
+ == GPG_ERR_PUBKEY_ALGO)
+ || gpg_err_code (openpgp_md_test_algo (sig->digest_algo)
+ == GPG_ERR_DIGEST_ALGO)
+ || (sig->digest_algo == DIGEST_ALGO_SHA1
+ && !(node->flag & NODFLG_MARK_B) /*no selfsig*/
+ && !opt.flags.allow_weak_key_signatures)))
+ return;
+ rc = 0;
+ sigrc = ' ';
+ }
- /* TODO: Make sure a cached sig record here still has
- the pk that issued it. See also
- keyedit.c:print_and_check_one_sig */
- }
- else
- {
- if (!(opt.list_options & LIST_SHOW_UNUSABLE_SIGS)
- && (gpg_err_code (openpgp_pk_test_algo (sig->pubkey_algo)
- == GPG_ERR_PUBKEY_ALGO)
- || gpg_err_code (openpgp_md_test_algo (sig->digest_algo)
- == GPG_ERR_DIGEST_ALGO)
- || (sig->digest_algo == DIGEST_ALGO_SHA1
- && !(node->flag & NODFLG_MARK_B) /*no selfsig*/
- && !opt.flags.allow_weak_key_signatures)))
- return;
- rc = 0;
- sigrc = ' ';
- }
+ if (IS_KEY_REV (sig) || IS_SUBKEY_REV (sig) || IS_UID_REV (sig))
+ {
+ sigstr = "rev";
+ reason_code = get_revocation_reason (sig, &reason_text,
+ &reason_comment,
+ &reason_commentlen);
+ }
+ else if (IS_UID_SIG (sig))
+ sigstr = "sig";
+ else if (IS_SUBKEY_SIG (sig))
+ sigstr = "sig";
+ else if (IS_KEY_SIG (sig))
+ sigstr = "sig";
+ else
+ {
+ es_fprintf (es_stdout, "sig "
+ "[unexpected signature class 0x%02x]\n",
+ sig->sig_class);
+ return;
+ }
- if (sig->sig_class == 0x20 || sig->sig_class == 0x28
- || sig->sig_class == 0x30)
- {
- sigstr = "rev";
- reason_code = get_revocation_reason (sig, &reason_text,
- &reason_comment,
- &reason_commentlen);
- }
- else if ((sig->sig_class & ~3) == 0x10)
- sigstr = "sig";
- else if (sig->sig_class == 0x18)
- sigstr = "sig";
- else if (sig->sig_class == 0x1F)
- sigstr = "sig";
- else
- {
- es_fprintf (es_stdout, "sig "
- "[unexpected signature class 0x%02x]\n",
- sig->sig_class);
- return;
- }
+ es_fputs (sigstr, es_stdout);
+ es_fprintf (es_stdout, "%c%c %c%c%c%c%c%c %s %s",
+ sigrc, (sig->sig_class - 0x10 > 0 &&
+ sig->sig_class - 0x10 <
+ 4) ? '0' + sig->sig_class - 0x10 : ' ',
+ sig->flags.exportable ? ' ' : 'L',
+ sig->flags.revocable ? ' ' : 'R',
+ sig->flags.policy_url ? 'P' : ' ',
+ sig->flags.notation ? 'N' : ' ',
+ sig->flags.expired ? 'X' : ' ',
+ (sig->trust_depth > 9) ? 'T' : (sig->trust_depth >
+ 0) ? '0' +
+ sig->trust_depth : ' ', keystr (sig->keyid),
+ datestr_from_sig (sig));
+ if (opt.list_options & LIST_SHOW_SIG_EXPIRE)
+ es_fprintf (es_stdout, " %s", expirestr_from_sig (sig));
+ es_fprintf (es_stdout, " ");
+ if (sigrc == '%')
+ es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
+ else if (sigrc == '?')
+ ;
+ else if ((node->flag & NODFLG_MARK_B))
+ es_fputs (_("[self-signature]"), es_stdout);
+ else if (!opt.fast_list_mode )
+ {
+ size_t n;
+ char *p = get_user_id (ctrl, sig->keyid, &n, NULL);
+ print_utf8_buffer (es_stdout, p, n);
+ xfree (p);
+ }
+ es_putc ('\n', es_stdout);
- es_fputs (sigstr, es_stdout);
- es_fprintf (es_stdout, "%c%c %c%c%c%c%c%c %s %s",
- sigrc, (sig->sig_class - 0x10 > 0 &&
- sig->sig_class - 0x10 <
- 4) ? '0' + sig->sig_class - 0x10 : ' ',
- sig->flags.exportable ? ' ' : 'L',
- sig->flags.revocable ? ' ' : 'R',
- sig->flags.policy_url ? 'P' : ' ',
- sig->flags.notation ? 'N' : ' ',
- sig->flags.expired ? 'X' : ' ',
- (sig->trust_depth > 9) ? 'T' : (sig->trust_depth >
- 0) ? '0' +
- sig->trust_depth : ' ', keystr (sig->keyid),
- datestr_from_sig (sig));
- if (opt.list_options & LIST_SHOW_SIG_EXPIRE)
- es_fprintf (es_stdout, " %s", expirestr_from_sig (sig));
- es_fprintf (es_stdout, " ");
- if (sigrc == '%')
- es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
- else if (sigrc == '?')
- ;
- else if ((node->flag & NODFLG_MARK_B))
- es_fputs (_("[self-signature]"), es_stdout);
- else if (!opt.fast_list_mode )
- {
- size_t n;
- char *p = get_user_id (ctrl, sig->keyid, &n, NULL);
- print_utf8_buffer (es_stdout, p, n);
- xfree (p);
- }
- es_putc ('\n', es_stdout);
+ if (sig->flags.policy_url
+ && (opt.list_options & LIST_SHOW_POLICY_URLS))
+ show_policy_url (sig, 3, 0);
+
+ if (sig->flags.notation && (opt.list_options & LIST_SHOW_NOTATIONS))
+ show_notation (sig, 3, 0,
+ ((opt.
+ list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0)
+ +
+ ((opt.
+ list_options & LIST_SHOW_USER_NOTATIONS) ? 2 :
+ 0));
+
+ if (sig->flags.notation
+ && (opt.list_options
+ & (LIST_SHOW_X509_NOTATIONS|LIST_STORE_X509_NOTATIONS)))
+ {
+ struct notation *nots;
- if (sig->flags.policy_url
- && (opt.list_options & LIST_SHOW_POLICY_URLS))
- show_policy_url (sig, 3, 0);
+ if ((IS_KEY_SIG (sig) || IS_SUBKEY_SIG (sig))
+ && (nots = search_sig_notations (sig,
+ {
+ if ((opt.list_options & LIST_STORE_X509_NOTATIONS))
+ print_x509_notations (nots, lastpk);
+ else
+ print_x509_notations (nots, NULL);
+ free_notation (nots);
+ }
+ }
- if (sig->flags.notation && (opt.list_options & LIST_SHOW_NOTATIONS))
- show_notation (sig, 3, 0,
- ((opt.
- list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0)
- +
- ((opt.
- list_options & LIST_SHOW_USER_NOTATIONS) ? 2 :
- 0));
+ if (sig->flags.pref_ks
+ && (opt.list_options & LIST_SHOW_KEYSERVER_URLS))
+ show_keyserver_url (sig, 3, 0);
- if (sig->flags.pref_ks
- && (opt.list_options & LIST_SHOW_KEYSERVER_URLS))
- show_keyserver_url (sig, 3, 0);
+ if (reason_text && (reason_code || reason_comment))
+ {
+ es_fprintf (es_stdout, " %s%s\n",
+ _("reason for revocation: "), reason_text);
+ if (reason_comment)
+ {
+ const byte *s, *s_lf;
+ size_t n, n_lf;
- if (reason_text && (reason_code || reason_comment))
+ s = reason_comment;
+ n = reason_commentlen;
+ s_lf = NULL;
+ do
{
- es_fprintf (es_stdout, " %s%s\n",
- _("reason for revocation: "), reason_text);
- if (reason_comment)
+ /* We don't want any empty lines, so we skip them. */
+ for (;n && *s == '\n'; s++, n--)
+ ;
+ if (n)
{
- const byte *s, *s_lf;
- size_t n, n_lf;
-
- s = reason_comment;
- n = reason_commentlen;
- s_lf = NULL;
- do
- {
- /* We don't want any empty lines, so we skip them. */
- for (;n && *s == '\n'; s++, n--)
- ;
- if (n)
- {
- s_lf = memchr (s, '\n', n);
- n_lf = s_lf? s_lf - s : n;
- es_fprintf (es_stdout, " %s",
- _("revocation comment: "));
- es_write_sanitized (es_stdout, s, n_lf, NULL, NULL);
- es_putc ('\n', es_stdout);
- s += n_lf; n -= n_lf;
- }
- } while (s_lf);
+ s_lf = memchr (s, '\n', n);
+ n_lf = s_lf? s_lf - s : n;
+ es_fprintf (es_stdout, " %s",
+ _("revocation comment: "));
+ es_write_sanitized (es_stdout, s, n_lf, NULL, NULL);
+ es_putc ('\n', es_stdout);
+ s += n_lf; n -= n_lf;
}
- }
+ } while (s_lf);
+ }
+ }
- xfree (reason_text);
- xfree (reason_comment);
+ xfree (reason_text);
+ xfree (reason_comment);
- /* fixme: check or list other sigs here */
+ /* fixme: check or list other sigs here */
}
@@ -1394,6 +1485,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;
@@ -1410,6 +1502,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)
{
@@ -1437,7 +1530,7 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
print_fingerprint (ctrl, NULL, pk, 0);
if (opt.with_keygrip && hexgrip)
- es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
+ print_keygrip (hexgrip);
if (serialno)
print_card_serialno (serialno);
@@ -1558,6 +1651,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))
{
@@ -1593,13 +1687,15 @@ list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
print_card_serialno (serialno);
}
if (opt.with_keygrip && hexgrip)
- es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
+ print_keygrip (hexgrip);
if (opt.with_key_data)
print_key_data (pk2);
if (opt.with_key_screening)
print_pk_screening (pk2, 0);
}
- else if (opt.list_sigs
+ 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;
@@ -1627,7 +1723,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);
}
}
@@ -2232,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)
@@ -2254,7 +2358,7 @@ list_keyblock (ctrl_t ctrl,
}
}
if (!selected)
- return; /* Skip this one. */
+ return 0; /* Skip this one. */
}
if (opt.with_colons)
@@ -2268,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;
}