1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-24 10:39:57 +01:00
gnupg/g10/keylist.c

1643 lines
42 KiB
C
Raw Normal View History

2010-01-09 19:00:46 +00:00
/* keylist.c - Print information about OpenPGP keys
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2010-01-09 19:00:46 +00:00
* 2008, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
2007-07-04 19:49:40 +00:00
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
2007-07-04 19:49:40 +00:00
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
2008-12-09 08:58:02 +00:00
#ifdef HAVE_DOSISH_SYSTEM
2010-01-09 19:00:46 +00:00
#include <fcntl.h> /* for setmode() */
2008-12-09 08:58:02 +00:00
#endif
#include "gpg.h"
#include "options.h"
#include "packet.h"
#include "status.h"
#include "keydb.h"
#include "photoid.h"
#include "util.h"
#include "ttyio.h"
#include "trustdb.h"
#include "main.h"
#include "i18n.h"
#include "status.h"
2010-10-13 15:57:08 +00:00
#include "call-agent.h"
2010-01-09 19:00:46 +00:00
static void list_all (int);
static void list_one (strlist_t names, int secret);
static void locate_one (ctrl_t ctrl, strlist_t names);
2010-10-13 15:57:08 +00:00
static void print_card_serialno (const char *serialno);
struct sig_stats
{
int inv_sigs;
int no_key;
int oth_err;
};
2008-12-09 08:58:02 +00:00
/* The stream used to write attribute packets to. */
static estream_t attrib_fp;
2010-01-09 19:00:46 +00:00
/* List the keys. If list is NULL, all available keys are listed.
With LOCATE_MODE set the locate algorithm is used to find a
key. */
void
public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode)
{
if (opt.with_colons)
{
2010-01-09 19:00:46 +00:00
byte trust_model, marginals, completes, cert_depth;
ulong created, nextcheck;
2010-01-09 19:00:46 +00:00
read_trust_options (&trust_model, &created, &nextcheck,
&marginals, &completes, &cert_depth);
es_fprintf (es_stdout, "tru:");
2010-01-09 19:00:46 +00:00
if (nextcheck && nextcheck <= make_timestamp ())
es_fprintf (es_stdout, "o");
2010-01-09 19:00:46 +00:00
if (trust_model != opt.trust_model)
es_fprintf (es_stdout, "t");
2010-01-09 19:00:46 +00:00
if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC)
{
2010-01-09 19:00:46 +00:00
if (marginals != opt.marginals_needed)
es_fprintf (es_stdout, "m");
2010-01-09 19:00:46 +00:00
if (completes != opt.completes_needed)
es_fprintf (es_stdout, "c");
2010-01-09 19:00:46 +00:00
if (cert_depth != opt.max_cert_depth)
es_fprintf (es_stdout, "d");
}
es_fprintf (es_stdout, ":%d:%lu:%lu", trust_model, created, nextcheck);
/* Only show marginals, completes, and cert_depth in the classic
2010-01-09 19:00:46 +00:00
or PGP trust models since they are not meaningful
otherwise. */
2010-01-09 19:00:46 +00:00
if (trust_model == TM_PGP || trust_model == TM_CLASSIC)
es_fprintf (es_stdout, ":%d:%d:%d", marginals, completes, cert_depth);
es_fprintf (es_stdout, "\n");
}
/* We need to do the stale check right here because it might need to
update the keyring while we already have the keyring open. This
is very bad for W32 because of a sharing violation. For real OSes
it might lead to false results if we are later listing a keyring
which is associated with the inode of a deleted file. */
check_trustdb_stale ();
if (locate_mode)
locate_one (ctrl, list);
else if (!list)
list_all (0);
else
list_one (list, 0);
}
void
secret_key_list (ctrl_t ctrl, strlist_t list)
{
(void)ctrl;
2010-01-09 19:00:46 +00:00
check_trustdb_stale ();
2010-01-09 19:00:46 +00:00
if (!list)
list_all (1);
else /* List by user id */
list_one (list, 1);
}
void
print_seckey_info (PKT_public_key *pk)
{
u32 keyid[2];
char *p;
keyid_from_pk (pk, keyid);
2010-01-09 19:00:46 +00:00
p = get_user_id_native (keyid);
tty_printf ("\nsec %4u%c/%s %s %s\n",
nbits_from_pk (pk),
pubkey_letter (pk->pubkey_algo),
keystr (keyid), datestr_from_pk (pk), p);
2010-01-09 19:00:46 +00:00
xfree (p);
}
/* Print information about the public key. With FP passed as NULL,
the tty output interface is used, otherwise output is directted to
2010-01-09 19:00:46 +00:00
the given stream. */
void
print_pubkey_info (estream_t fp, PKT_public_key * pk)
{
u32 keyid[2];
char *p;
keyid_from_pk (pk, keyid);
/* If the pk was chosen by a particular user ID, that is the one to
2010-01-09 19:00:46 +00:00
print. */
if (pk->user_id)
p = utf8_to_native (pk->user_id->name, pk->user_id->len, 0);
else
2010-01-09 19:00:46 +00:00
p = get_user_id_native (keyid);
if (fp)
tty_printf ("\n");
tty_fprintf (fp, "pub %4u%c/%s %s %s\n",
nbits_from_pk (pk),
pubkey_letter (pk->pubkey_algo),
keystr (keyid), datestr_from_pk (pk), p);
xfree (p);
}
/* Print basic information of a secret key including the card serial
2010-01-09 19:00:46 +00:00
number information. */
2010-10-13 15:57:08 +00:00
#ifdef ENABLE_CARD_SUPPORT
void
print_card_key_info (estream_t fp, kbnode_t keyblock)
{
kbnode_t node;
char *hexgrip;
char *serialno;
int s2k_char;
for (node = keyblock; node; node = node->next)
{
if (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
int rc;
PKT_public_key *pk = node->pkt->pkt.public_key;
serialno = NULL;
rc = hexkeygrip_from_pk (pk, &hexgrip);
if (rc)
{
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
s2k_char = '?';
}
else if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
s2k_char = serialno? '>':' ';
else
s2k_char = '#'; /* Key not found. */
tty_fprintf (fp, "%s%c %4u%c/%s ",
node->pkt->pkttype == PKT_PUBLIC_KEY ? "sec" : "ssb",
s2k_char, nbits_from_pk (pk),
pubkey_letter (pk->pubkey_algo), keystr_from_pk (pk));
tty_fprintf (fp, _("created: %s"), datestr_from_pk (pk));
tty_fprintf (fp, " ");
tty_fprintf (fp, _("expires: %s"), expirestr_from_pk (pk));
if (serialno)
{
tty_fprintf (fp, "\n ");
tty_fprintf (fp, _("card-no: "));
if (strlen (serialno) == 32
&& !strncmp (serialno, "D27600012401", 12))
{
/* This is an OpenPGP card. Print the relevant part. */
/* Example: D2760001240101010001000003470000 */
/* xxxxyyyyyyyy */
tty_fprintf (fp, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
}
else
tty_fprintf (fp, "%s", serialno);
}
tty_fprintf (fp, "\n");
xfree (hexgrip);
xfree (serialno);
}
}
}
2010-10-13 15:57:08 +00:00
#endif /*ENABLE_CARD_SUPPORT*/
2010-01-09 19:00:46 +00:00
/* Flags = 0x01 hashed 0x02 critical. */
static void
2010-01-09 19:00:46 +00:00
status_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
const byte * buf)
{
char status[40];
/* Don't print these. */
2010-01-09 19:00:46 +00:00
if (len > 256)
return;
snprintf (status, sizeof status,
"%d %u %u ", type, flags, (unsigned int) len);
2010-01-09 19:00:46 +00:00
write_status_text_and_buffer (STATUS_SIG_SUBPACKET, status, buf, len, 0);
}
2010-01-09 19:00:46 +00:00
/* Print a policy URL. Allowed values for MODE are:
* 0 - print to stdout.
* 1 - use log_info and emit status messages.
* 2 - emit only status messages.
*/
void
2010-01-09 19:00:46 +00:00
show_policy_url (PKT_signature * sig, int indent, int mode)
{
const byte *p;
size_t len;
2010-01-09 19:00:46 +00:00
int seq = 0, crit;
estream_t fp = mode ? log_get_stream () : es_stdout;
2010-01-09 19:00:46 +00:00
while ((p =
enum_sig_subpkt (sig->hashed, SIGSUBPKT_POLICY, &len, &seq, &crit)))
{
2010-01-09 19:00:46 +00:00
if (mode != 2)
{
int i;
const char *str;
2010-01-09 19:00:46 +00:00
for (i = 0; i < indent; i++)
es_putc (' ', fp);
2010-01-09 19:00:46 +00:00
if (crit)
str = _("Critical signature policy: ");
else
2010-01-09 19:00:46 +00:00
str = _("Signature policy: ");
if (mode)
log_info ("%s", str);
else
es_fprintf (fp, "%s", str);
print_utf8_buffer (fp, p, len);
es_fprintf (fp, "\n");
}
2010-01-09 19:00:46 +00:00
if (mode)
write_status_buffer (STATUS_POLICY_URL, p, len, 0);
}
}
2010-01-09 19:00:46 +00:00
/*
mode=0 for stdout.
mode=1 for log_info + status messages
mode=2 for status messages only
*/
/* TODO: use this */
void
2010-01-09 19:00:46 +00:00
show_keyserver_url (PKT_signature * sig, int indent, int mode)
{
const byte *p;
size_t len;
2010-01-09 19:00:46 +00:00
int seq = 0, crit;
estream_t fp = mode ? log_get_stream () : es_stdout;
2010-01-09 19:00:46 +00:00
while ((p =
enum_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_KS, &len, &seq,
&crit)))
{
2010-01-09 19:00:46 +00:00
if (mode != 2)
{
int i;
const char *str;
2010-01-09 19:00:46 +00:00
for (i = 0; i < indent; i++)
es_putc (' ', es_stdout);
2010-01-09 19:00:46 +00:00
if (crit)
str = _("Critical preferred keyserver: ");
else
2010-01-09 19:00:46 +00:00
str = _("Preferred keyserver: ");
if (mode)
log_info ("%s", str);
else
es_fprintf (es_stdout, "%s", str);
print_utf8_buffer (fp, p, len);
es_fprintf (fp, "\n");
}
2010-01-09 19:00:46 +00:00
if (mode)
status_one_subpacket (SIGSUBPKT_PREF_KS, len,
(crit ? 0x02 : 0) | 0x01, p);
}
}
/*
mode=0 for stdout.
mode=1 for log_info + status messages
mode=2 for status messages only
2010-01-09 19:00:46 +00:00
Defined bits in WHICH:
1 == standard notations
2 == user notations
*/
void
2010-01-09 19:00:46 +00:00
show_notation (PKT_signature * sig, int indent, int mode, int which)
{
estream_t fp = mode ? log_get_stream () : es_stdout;
2010-01-09 19:00:46 +00:00
struct notation *nd, *notations;
2010-01-09 19:00:46 +00:00
if (which == 0)
which = 3;
2010-01-09 19:00:46 +00:00
notations = sig_to_notation (sig);
/* There may be multiple notations in the same sig. */
2010-01-09 19:00:46 +00:00
for (nd = notations; nd; nd = nd->next)
{
2010-01-09 19:00:46 +00:00
if (mode != 2)
{
2010-01-09 19:00:46 +00:00
int has_at = !!strchr (nd->name, '@');
2010-01-09 19:00:46 +00:00
if ((which & 1 && !has_at) || (which & 2 && has_at))
{
int i;
const char *str;
2010-01-09 19:00:46 +00:00
for (i = 0; i < indent; i++)
es_putc (' ', es_stdout);
2010-01-09 19:00:46 +00:00
if (nd->flags.critical)
str = _("Critical signature notation: ");
else
2010-01-09 19:00:46 +00:00
str = _("Signature notation: ");
if (mode)
log_info ("%s", str);
else
es_fprintf (es_stdout, "%s", str);
/* This is all UTF8 */
print_utf8_buffer (fp, nd->name, strlen (nd->name));
es_fprintf (fp, "=");
print_utf8_buffer (fp, nd->value, strlen (nd->value));
es_fprintf (fp, "\n");
}
}
2010-01-09 19:00:46 +00:00
if (mode)
{
2010-01-09 19:00:46 +00:00
write_status_buffer (STATUS_NOTATION_NAME,
nd->name, strlen (nd->name), 0);
write_status_buffer (STATUS_NOTATION_DATA,
nd->value, strlen (nd->value), 50);
}
}
2010-01-09 19:00:46 +00:00
free_notation (notations);
}
static void
2010-01-09 19:00:46 +00:00
print_signature_stats (struct sig_stats *s)
{
2010-01-09 19:00:46 +00:00
if (s->inv_sigs == 1)
tty_printf (_("1 bad signature\n"));
else if (s->inv_sigs)
tty_printf (_("%d bad signatures\n"), s->inv_sigs);
if (s->no_key == 1)
tty_printf (_("1 signature not checked due to a missing key\n"));
else if (s->no_key)
tty_printf (_("%d signatures not checked due to missing keys\n"),
s->no_key);
if (s->oth_err == 1)
tty_printf (_("1 signature not checked due to an error\n"));
else if (s->oth_err)
tty_printf (_("%d signatures not checked due to errors\n"), s->oth_err);
}
static void
2010-01-09 19:00:46 +00:00
list_all (int secret)
{
2010-01-09 19:00:46 +00:00
KEYDB_HANDLE hd;
KBNODE keyblock = NULL;
int rc = 0;
const char *lastresname, *resname;
struct sig_stats stats;
memset (&stats, 0, sizeof (stats));
hd = keydb_new ();
2010-01-09 19:00:46 +00:00
if (!hd)
rc = gpg_error (GPG_ERR_GENERAL);
2010-01-09 19:00:46 +00:00
else
rc = keydb_search_first (hd);
if (rc)
{
if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
2010-01-09 19:00:46 +00:00
log_error ("keydb_search_first failed: %s\n", g10_errstr (rc));
goto leave;
}
2010-01-09 19:00:46 +00:00
lastresname = NULL;
do
{
rc = keydb_get_keyblock (hd, &keyblock);
if (rc)
{
log_error ("keydb_get_keyblock failed: %s\n", g10_errstr (rc));
goto leave;
}
2010-10-13 15:57:08 +00:00
if (secret && agent_probe_any_secret_key (NULL, keyblock))
; /* Secret key listing requested but this isn't one. */
else
{
if (!opt.with_colons)
{
resname = keydb_get_resource_name (hd);
if (lastresname != resname)
{
int i;
es_fprintf (es_stdout, "%s\n", resname);
for (i = strlen (resname); i; i--)
es_putc ('-', es_stdout);
es_putc ('\n', es_stdout);
lastresname = resname;
}
}
merge_keys_and_selfsig (keyblock);
list_keyblock (keyblock, secret, opt.fingerprint,
opt.check_sigs ? &stats : NULL);
}
2010-01-09 19:00:46 +00:00
release_kbnode (keyblock);
keyblock = NULL;
}
while (!(rc = keydb_search_next (hd)));
if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
2010-01-09 19:00:46 +00:00
log_error ("keydb_search_next failed: %s\n", g10_errstr (rc));
if (opt.check_sigs && !opt.with_colons)
print_signature_stats (&stats);
leave:
release_kbnode (keyblock);
keydb_release (hd);
}
static void
2010-01-09 19:00:46 +00:00
list_one (strlist_t names, int secret)
{
2010-01-09 19:00:46 +00:00
int rc = 0;
KBNODE keyblock = NULL;
GETKEY_CTX ctx;
const char *resname;
const char *keyring_str = _("Keyring");
int i;
struct sig_stats stats;
memset (&stats, 0, sizeof (stats));
/* fixme: using the bynames function has the disadvantage that we
* don't know wether one of the names given was not found. OTOH,
* this function has the advantage to list the names in the
* sequence as defined by the keyDB and does not duplicate
* outputs. A solution could be do test whether all given have
* been listed (this needs a way to use the keyDB search
* functions) or to have the search function return indicators for
* found names. Yet another way is to use the keydb search
* facilities directly. */
rc = getkey_bynames (&ctx, NULL, names, secret, &keyblock);
if (rc)
2010-01-09 19:00:46 +00:00
{
log_error ("error reading key: %s\n", g10_errstr (rc));
2010-01-09 19:00:46 +00:00
get_pubkey_end (ctx);
return;
}
do
{
if ((opt.list_options & LIST_SHOW_KEYRING) && !opt.with_colons)
{
resname = keydb_get_resource_name (get_ctx_handle (ctx));
es_fprintf (es_stdout, "%s: %s\n", keyring_str, resname);
for (i = strlen (resname) + strlen (keyring_str) + 2; i; i--)
es_putc ('-', es_stdout);
es_putc ('\n', es_stdout);
}
list_keyblock (keyblock, secret, opt.fingerprint,
(!secret && opt.check_sigs)? &stats : NULL);
release_kbnode (keyblock);
}
while (!getkey_next (ctx, NULL, &keyblock));
getkey_end (ctx);
2010-01-09 19:00:46 +00:00
if (opt.check_sigs && !opt.with_colons)
print_signature_stats (&stats);
}
static void
locate_one (ctrl_t ctrl, strlist_t names)
{
int rc = 0;
strlist_t sl;
GETKEY_CTX ctx = NULL;
KBNODE keyblock = NULL;
struct sig_stats stats;
2010-01-09 19:00:46 +00:00
memset (&stats, 0, sizeof (stats));
for (sl = names; sl; sl = sl->next)
{
rc = get_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, NULL, 1, 0);
if (rc)
2010-01-09 19:00:46 +00:00
{
if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
log_error ("error reading key: %s\n", g10_errstr (rc));
}
else
2010-01-09 19:00:46 +00:00
{
do
{
list_keyblock (keyblock, 0, opt.fingerprint,
opt.check_sigs ? &stats : NULL);
release_kbnode (keyblock);
}
while (ctx && !get_pubkey_next (ctx, NULL, &keyblock));
get_pubkey_end (ctx);
ctx = NULL;
}
}
2010-01-09 19:00:46 +00:00
if (opt.check_sigs && !opt.with_colons)
print_signature_stats (&stats);
}
static void
2010-01-09 19:00:46 +00:00
print_key_data (PKT_public_key * pk)
{
2010-01-09 19:00:46 +00:00
int n = pk ? pubkey_get_npkey (pk->pubkey_algo) : 0;
int i;
for (i = 0; i < n; i++)
{
es_fprintf (es_stdout, "pkd:%d:%u:", i, mpi_get_nbits (pk->pkey[i]));
mpi_print (es_stdout, pk->pkey[i], 1);
es_putc (':', es_stdout);
es_putc ('\n', es_stdout);
}
}
static void
print_capabilities (PKT_public_key *pk, KBNODE keyblock)
{
unsigned int use = pk->pubkey_usage;
int c_printed = 0;
if (use & PUBKEY_USAGE_ENC)
es_putc ('e', es_stdout);
if (use & PUBKEY_USAGE_SIG)
{
es_putc ('s', es_stdout);
if (pk->flags.primary)
{
es_putc ('c', es_stdout);
/* The PUBKEY_USAGE_CERT flag was introduced later and we
used to always print 'c' for a primary key. To avoid any
regression here we better track whether we printed 'c'
already. */
c_printed = 1;
}
}
if ((use & PUBKEY_USAGE_CERT) && !c_printed)
es_putc ('c', es_stdout);
2009-02-09 11:09:57 +00:00
if ((use & PUBKEY_USAGE_AUTH))
es_putc ('a', es_stdout);
2010-01-09 19:00:46 +00:00
if (keyblock)
{
/* Figure out the usable capabilities. */
2010-01-09 19:00:46 +00:00
KBNODE k;
int enc = 0, sign = 0, cert = 0, auth = 0, disabled = 0;
for (k = keyblock; k; k = k->next)
{
if (k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
pk = k->pkt->pkt.public_key;
if (pk->flags.primary)
2010-01-09 19:00:46 +00:00
disabled = pk_is_disabled (pk);
if (pk->flags.valid && !pk->flags.revoked && !pk->has_expired)
2010-01-09 19:00:46 +00:00
{
if (pk->pubkey_usage & PUBKEY_USAGE_ENC)
enc = 1;
if (pk->pubkey_usage & PUBKEY_USAGE_SIG)
{
sign = 1;
if (pk->flags.primary)
2010-01-09 19:00:46 +00:00
cert = 1;
}
if (pk->pubkey_usage & PUBKEY_USAGE_CERT)
cert = 1;
if ((pk->pubkey_usage & PUBKEY_USAGE_AUTH))
auth = 1;
}
}
}
if (enc)
es_putc ('E', es_stdout);
2010-01-09 19:00:46 +00:00
if (sign)
es_putc ('S', es_stdout);
2010-01-09 19:00:46 +00:00
if (cert)
es_putc ('C', es_stdout);
2010-01-09 19:00:46 +00:00
if (auth)
es_putc ('A', es_stdout);
2010-01-09 19:00:46 +00:00
if (disabled)
es_putc ('D', es_stdout);
}
es_putc (':', es_stdout);
}
2010-01-09 19:00:46 +00:00
/* FLAGS: 0x01 hashed
0x02 critical */
static void
2010-01-09 19:00:46 +00:00
print_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
const byte * buf)
{
size_t i;
es_fprintf (es_stdout, "spk:%d:%u:%u:", type, flags, (unsigned int) len);
2010-01-09 19:00:46 +00:00
for (i = 0; i < len; i++)
{
/* printable ascii other than : and % */
2010-01-09 19:00:46 +00:00
if (buf[i] >= 32 && buf[i] <= 126 && buf[i] != ':' && buf[i] != '%')
es_fprintf (es_stdout, "%c", buf[i]);
else
es_fprintf (es_stdout, "%%%02X", buf[i]);
}
es_fprintf (es_stdout, "\n");
}
void
2010-01-09 19:00:46 +00:00
print_subpackets_colon (PKT_signature * sig)
{
byte *i;
2010-01-09 19:00:46 +00:00
assert (opt.show_subpackets);
2010-01-09 19:00:46 +00:00
for (i = opt.show_subpackets; *i; i++)
{
const byte *p;
size_t len;
2010-01-09 19:00:46 +00:00
int seq, crit;
2010-01-09 19:00:46 +00:00
seq = 0;
2010-01-09 19:00:46 +00:00
while ((p = enum_sig_subpkt (sig->hashed, *i, &len, &seq, &crit)))
print_one_subpacket (*i, len, 0x01 | (crit ? 0x02 : 0), p);
2010-01-09 19:00:46 +00:00
seq = 0;
2010-01-09 19:00:46 +00:00
while ((p = enum_sig_subpkt (sig->unhashed, *i, &len, &seq, &crit)))
print_one_subpacket (*i, len, 0x00 | (crit ? 0x02 : 0), p);
}
}
void
dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
{
int i;
2010-01-09 19:00:46 +00:00
if (!attrib_fp)
return;
2010-01-09 19:00:46 +00:00
for (i = 0; i < uid->numattribs; i++)
{
2010-01-09 19:00:46 +00:00
if (is_status_enabled ())
{
byte array[MAX_FINGERPRINT_LEN], *p;
2010-01-09 19:00:46 +00:00
char buf[(MAX_FINGERPRINT_LEN * 2) + 90];
size_t j, n;
if (!pk)
BUG ();
fingerprint_from_pk (pk, array, &n);
p = array;
2010-01-09 19:00:46 +00:00
for (j = 0; j < n; j++, p++)
sprintf (buf + 2 * j, "%02X", *p);
sprintf (buf + strlen (buf), " %lu %u %u %u %lu %lu %u",
(ulong) uid->attribs[i].len, uid->attribs[i].type, i + 1,
uid->numattribs, (ulong) uid->created,
(ulong) uid->expiredate,
((uid->is_primary ? 0x01 : 0) | (uid->
is_revoked ? 0x02 : 0) |
(uid->is_expired ? 0x04 : 0)));
write_status_text (STATUS_ATTRIBUTE, buf);
}
es_fwrite (uid->attribs[i].data, uid->attribs[i].len, 1, attrib_fp);
es_fflush (attrib_fp);
}
}
static void
2010-01-09 19:00:46 +00:00
list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque)
{
2010-10-13 15:57:08 +00:00
int rc;
2010-01-09 19:00:46 +00:00
KBNODE kbctx;
KBNODE node;
PKT_public_key *pk;
struct sig_stats *stats = opaque;
int skip_sigs = 0;
int s2k_char;
2010-10-13 15:57:08 +00:00
char *hexgrip = NULL;
char *serialno = NULL;
2010-01-09 19:00:46 +00:00
/* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
2010-01-09 19:00:46 +00:00
if (!node)
{
log_error ("Oops; key lost!\n");
dump_kbnode (keyblock);
return;
}
pk = node->pkt->pkt.public_key;
2010-10-13 15:57:08 +00:00
if (secret || opt.with_keygrip)
{
rc = hexkeygrip_from_pk (pk, &hexgrip);
if (rc)
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
}
if (secret)
{
if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
s2k_char = serialno? '>':' ';
else
s2k_char = '#'; /* Key not found. */
}
else
s2k_char = ' ';
check_trustdb_stale ();
2010-01-09 19:00:46 +00:00
es_fprintf (es_stdout, "%s%c %4u%c/%s %s",
secret? "sec":"pub",
s2k_char,
nbits_from_pk (pk), pubkey_letter (pk->pubkey_algo),
keystr_from_pk (pk), datestr_from_pk (pk));
2010-01-09 19:00:46 +00:00
if (pk->flags.revoked)
{
es_fprintf (es_stdout, " [");
es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk));
es_fprintf (es_stdout, "]");
}
else if (pk->has_expired)
2010-01-09 19:00:46 +00:00
{
es_fprintf (es_stdout, " [");
es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk));
es_fprintf (es_stdout, "]");
}
else if (pk->expiredate)
{
es_fprintf (es_stdout, " [");
es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk));
es_fprintf (es_stdout, "]");
}
#if 0
/* I need to think about this some more. It's easy enough to
include, but it looks sort of confusing in the listing... */
if (opt.list_options & LIST_SHOW_VALIDITY)
{
int validity = get_validity (pk, NULL);
es_fprintf (es_stdout, " [%s]", trust_value_to_string (validity));
}
#endif
es_fprintf (es_stdout, "\n");
2010-01-09 19:00:46 +00:00
if (fpr)
print_fingerprint (pk, 0);
2010-10-13 15:57:08 +00:00
if (opt.with_keygrip && hexgrip)
es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
2010-10-08 11:11:08 +00:00
2010-10-13 15:57:08 +00:00
if (serialno)
print_card_serialno (serialno);
2010-01-09 19:00:46 +00:00
if (opt.with_key_data)
print_key_data (pk);
2010-01-09 19:00:46 +00:00
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
{
if (node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode)
{
PKT_user_id *uid = node->pkt->pkt.user_id;
if (pk && (uid->is_expired || uid->is_revoked)
&& !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
{
skip_sigs = 1;
continue;
}
2010-01-09 19:00:46 +00:00
else
skip_sigs = 0;
if (attrib_fp && uid->attrib_data != NULL)
dump_attribs (uid, pk);
2010-01-09 19:00:46 +00:00
if ((uid->is_revoked || uid->is_expired)
|| ((opt.list_options & LIST_SHOW_UID_VALIDITY) && pk))
{
const char *validity;
int indent;
validity = uid_trust_string_fixed (pk, uid);
indent =
(keystrlen () + 9) -
atoi (uid_trust_string_fixed (NULL, NULL));
if (indent < 0 || indent > 40)
indent = 0;
es_fprintf (es_stdout, "uid%*s%s ", indent, "", validity);
}
2010-01-09 19:00:46 +00:00
else
es_fprintf (es_stdout, "uid%*s", (int) keystrlen () + 10, "");
print_utf8_buffer (es_stdout, uid->name, uid->len);
es_putc ('\n', es_stdout);
2010-01-09 19:00:46 +00:00
if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL)
show_photos (uid->attribs, uid->numattribs, pk, uid);
2010-01-09 19:00:46 +00:00
}
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
PKT_public_key *pk2 = node->pkt->pkt.public_key;
if ((pk2->flags.revoked || pk2->has_expired)
2010-01-09 19:00:46 +00:00
&& !(opt.list_options & LIST_SHOW_UNUSABLE_SUBKEYS))
{
skip_sigs = 1;
continue;
}
2010-01-09 19:00:46 +00:00
else
skip_sigs = 0;
2010-10-13 15:57:08 +00:00
xfree (serialno); serialno = NULL;
xfree (hexgrip); hexgrip = NULL;
if (secret || opt.with_keygrip)
{
rc = hexkeygrip_from_pk (pk2, &hexgrip);
if (rc)
log_error ("error computing a keygrip: %s\n",
gpg_strerror (rc));
}
if (secret)
{
if (!agent_get_keyinfo (NULL, hexgrip, &serialno))
s2k_char = serialno? '>':' ';
else
s2k_char = '#'; /* Key not found. */
}
else
s2k_char = ' ';
es_fprintf (es_stdout, "%s%c %4u%c/%s %s",
secret? "ssb":"sub",
s2k_char,
2010-01-09 19:00:46 +00:00
nbits_from_pk (pk2), pubkey_letter (pk2->pubkey_algo),
keystr_from_pk (pk2), datestr_from_pk (pk2));
if (pk2->flags.revoked)
2010-01-09 19:00:46 +00:00
{
es_fprintf (es_stdout, " [");
es_fprintf (es_stdout, _("revoked: %s"), revokestr_from_pk (pk2));
es_fprintf (es_stdout, "]");
2010-01-09 19:00:46 +00:00
}
else if (pk2->has_expired)
{
es_fprintf (es_stdout, " [");
es_fprintf (es_stdout, _("expired: %s"), expirestr_from_pk (pk2));
es_fprintf (es_stdout, "]");
2010-01-09 19:00:46 +00:00
}
else if (pk2->expiredate)
{
es_fprintf (es_stdout, " [");
es_fprintf (es_stdout, _("expires: %s"), expirestr_from_pk (pk2));
es_fprintf (es_stdout, "]");
}
es_putc ('\n', es_stdout);
2010-01-09 19:00:46 +00:00
if (fpr > 1)
{
print_fingerprint (pk2, 0);
2010-10-13 15:57:08 +00:00
if (serialno)
print_card_serialno (serialno);
2010-10-08 11:11:08 +00:00
}
2010-10-13 15:57:08 +00:00
if (opt.with_keygrip && hexgrip)
es_fprintf (es_stdout, " Keygrip = %s\n", hexgrip);
2010-01-09 19:00:46 +00:00
if (opt.with_key_data)
print_key_data (pk2);
}
else if (opt.list_sigs
&& node->pkt->pkttype == PKT_SIGNATURE && !skip_sigs)
{
PKT_signature *sig = node->pkt->pkt.signature;
int sigrc;
char *sigstr;
2010-01-09 19:00:46 +00:00
if (stats)
{
rc = check_key_signature (keyblock, node, NULL);
switch (gpg_err_code (rc))
{
case 0:
sigrc = '!';
break;
case GPG_ERR_BAD_SIGNATURE:
stats->inv_sigs++;
sigrc = '-';
break;
case GPG_ERR_NO_PUBKEY:
case GPG_ERR_UNUSABLE_PUBKEY:
stats->no_key++;
continue;
default:
stats->oth_err++;
sigrc = '%';
break;
}
2010-01-09 19:00:46 +00:00
/* 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
{
rc = 0;
sigrc = ' ';
}
2010-01-09 19:00:46 +00:00
if (sig->sig_class == 0x20 || sig->sig_class == 0x28
|| sig->sig_class == 0x30)
sigstr = "rev";
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 "
2010-01-09 19:00:46 +00:00
"[unexpected signature class 0x%02x]\n",
sig->sig_class);
continue;
}
es_fputs (sigstr, es_stdout);
es_fprintf (es_stdout, "%c%c %c%c%c%c%c%c %s %s",
2010-01-09 19:00:46 +00:00
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, " ");
2010-01-09 19:00:46 +00:00
if (sigrc == '%')
es_fprintf (es_stdout, "[%s] ", g10_errstr (rc));
2010-01-09 19:00:46 +00:00
else if (sigrc == '?')
;
else if (!opt.fast_list_mode)
{
size_t n;
char *p = get_user_id (sig->keyid, &n);
print_utf8_buffer (es_stdout, p, n);
2010-01-09 19:00:46 +00:00
xfree (p);
}
es_putc ('\n', es_stdout);
2010-01-09 19:00:46 +00:00
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.pref_ks
&& (opt.list_options & LIST_SHOW_KEYSERVER_URLS))
show_keyserver_url (sig, 3, 0);
/* fixme: check or list other sigs here */
}
}
es_putc ('\n', es_stdout);
2010-10-13 15:57:08 +00:00
xfree (serialno);
xfree (hexgrip);
}
void
2010-01-09 19:00:46 +00:00
print_revokers (PKT_public_key * pk)
{
/* print the revoker record */
2010-01-09 19:00:46 +00:00
if (!pk->revkey && pk->numrevkeys)
BUG ();
else
{
2010-01-09 19:00:46 +00:00
int i, j;
2010-01-09 19:00:46 +00:00
for (i = 0; i < pk->numrevkeys; i++)
{
byte *p;
es_fprintf (es_stdout, "rvk:::%d::::::", pk->revkey[i].algid);
p = pk->revkey[i].fpr;
2010-01-09 19:00:46 +00:00
for (j = 0; j < 20; j++, p++)
es_fprintf (es_stdout, "%02X", *p);
es_fprintf (es_stdout, ":%02x%s:\n", pk->revkey[i].class,
2010-01-09 19:00:46 +00:00
(pk->revkey[i].class & 0x40) ? "s" : "");
}
}
}
static void
2010-01-09 19:00:46 +00:00
list_keyblock_colon (KBNODE keyblock, int secret, int fpr)
{
2010-10-13 15:57:08 +00:00
int rc;
2008-06-11 08:07:54 +00:00
KBNODE kbctx;
KBNODE node;
PKT_public_key *pk;
u32 keyid[2];
int trustletter = 0;
int ulti_hack = 0;
int i;
char *p;
2010-10-13 15:57:08 +00:00
char *hexgrip = NULL;
char *serialno = NULL;
int stubkey;
/* Get the keyid from the keyblock. */
node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
2010-01-09 19:00:46 +00:00
if (!node)
2008-06-11 08:07:54 +00:00
{
2010-01-09 19:00:46 +00:00
log_error ("Oops; key lost!\n");
dump_kbnode (keyblock);
2008-06-11 08:07:54 +00:00
return;
}
pk = node->pkt->pkt.public_key;
2010-10-13 15:57:08 +00:00
if (secret || opt.with_keygrip || opt.with_key_data)
{
rc = hexkeygrip_from_pk (pk, &hexgrip);
if (rc)
log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
}
stubkey = 0;
if (secret && agent_get_keyinfo (NULL, hexgrip, &serialno))
stubkey = 1; /* Key not found. */
keyid_from_pk (pk, keyid);
es_fputs (secret? "sec:":"pub:", es_stdout);
if (!pk->flags.valid)
es_putc ('i', es_stdout);
else if (pk->flags.revoked)
es_putc ('r', es_stdout);
else if (pk->has_expired)
es_putc ('e', es_stdout);
else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
;
2008-06-11 08:07:54 +00:00
else
{
trustletter = get_validity_info (pk, NULL);
if (trustletter == 'u')
ulti_hack = 1;
es_putc (trustletter, es_stdout);
2008-06-11 08:07:54 +00:00
}
es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s::",
nbits_from_pk (pk),
pk->pubkey_algo,
(ulong) keyid[0], (ulong) keyid[1],
colon_datestr_from_pk (pk), colon_strtime (pk->expiredate));
if (!opt.fast_list_mode && !opt.no_expensive_trust_checks)
es_putc (get_ownertrust_info (pk), es_stdout);
es_putc (':', es_stdout);
es_putc (':', es_stdout);
es_putc (':', es_stdout);
print_capabilities (pk, keyblock);
2008-06-11 08:07:54 +00:00
if (secret)
{
es_putc (':', es_stdout); /* End of field 13. */
es_putc (':', es_stdout); /* End of field 14. */
2010-10-13 15:57:08 +00:00
if (stubkey)
es_putc ('#', es_stdout);
else if (serialno)
es_fputs(serialno, es_stdout);
es_putc (':', es_stdout); /* End of field 15. */
2008-06-11 08:07:54 +00:00
}
es_putc ('\n', es_stdout);
print_revokers (pk);
2008-06-11 08:07:54 +00:00
if (fpr)
print_fingerprint (pk, 0);
2010-10-08 11:11:08 +00:00
if (opt.with_key_data || opt.with_keygrip)
{
2010-10-13 15:57:08 +00:00
if (hexgrip)
es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
2010-10-08 11:11:08 +00:00
if (opt.with_key_data)
print_key_data (pk);
}
2010-01-09 19:00:46 +00:00
for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
2008-06-11 08:07:54 +00:00
{
2010-01-09 19:00:46 +00:00
if (node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode)
{
char *str;
PKT_user_id *uid = node->pkt->pkt.user_id;
if (attrib_fp && node->pkt->pkt.user_id->attrib_data != NULL)
dump_attribs (node->pkt->pkt.user_id, pk);
2010-01-09 19:00:46 +00:00
/*
* Fixme: We need a valid flag here too
2010-01-09 19:00:46 +00:00
*/
str = uid->attrib_data ? "uat" : "uid";
if (uid->is_revoked)
es_fprintf (es_stdout, "%s:r::::", str);
2010-01-09 19:00:46 +00:00
else if (uid->is_expired)
es_fprintf (es_stdout, "%s:e::::", str);
2010-01-09 19:00:46 +00:00
else if (opt.no_expensive_trust_checks)
es_fprintf (es_stdout, "%s:::::", str);
2010-01-09 19:00:46 +00:00
else
{
int uid_validity;
if (pk && !ulti_hack)
uid_validity = get_validity_info (pk, uid);
else
uid_validity = 'u';
es_fprintf (es_stdout, "%s:%c::::", str, uid_validity);
2010-01-09 19:00:46 +00:00
}
es_fprintf (es_stdout, "%s:", colon_strtime (uid->created));
es_fprintf (es_stdout, "%s:", colon_strtime (uid->expiredate));
2010-01-09 19:00:46 +00:00
namehash_from_uid (uid);
for (i = 0; i < 20; i++)
es_fprintf (es_stdout, "%02X", uid->namehash[i]);
2010-01-09 19:00:46 +00:00
es_fprintf (es_stdout, "::");
2010-01-09 19:00:46 +00:00
if (uid->attrib_data)
es_fprintf (es_stdout, "%u %lu", uid->numattribs, uid->attrib_len);
2010-01-09 19:00:46 +00:00
else
es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL);
es_putc (':', es_stdout);
es_putc ('\n', es_stdout);
2010-01-09 19:00:46 +00:00
}
else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
{
u32 keyid2[2];
2010-10-13 15:57:08 +00:00
PKT_public_key *pk2;
pk2 = node->pkt->pkt.public_key;
xfree (hexgrip); hexgrip = NULL;
xfree (serialno); serialno = NULL;
if (secret || opt.with_keygrip || opt.with_key_data)
{
rc = hexkeygrip_from_pk (pk2, &hexgrip);
if (rc)
log_error ("error computing a keygrip: %s\n",
gpg_strerror (rc));
}
stubkey = 0;
if (secret && agent_get_keyinfo (NULL, hexgrip, &serialno))
stubkey = 1; /* Key not found. */
2010-01-09 19:00:46 +00:00
keyid_from_pk (pk2, keyid2);
es_fputs (secret? "ssb:":"sub:", es_stdout);
if (!pk2->flags.valid)
es_putc ('i', es_stdout);
else if (pk2->flags.revoked)
es_putc ('r', es_stdout);
2010-01-09 19:00:46 +00:00
else if (pk2->has_expired)
es_putc ('e', es_stdout);
2010-01-09 19:00:46 +00:00
else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
;
else
{
/* TRUSTLETTER should always be defined here. */
if (trustletter)
es_fprintf (es_stdout, "%c", trustletter);
2010-01-09 19:00:46 +00:00
}
es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s:::::",
2010-01-09 19:00:46 +00:00
nbits_from_pk (pk2),
pk2->pubkey_algo,
(ulong) keyid2[0], (ulong) keyid2[1],
colon_datestr_from_pk (pk2), colon_strtime (pk2->expiredate)
/* fixme: add LID and ownertrust here */
);
print_capabilities (pk2, NULL);
if (secret)
{
es_putc (':', es_stdout); /* End of field 13. */
es_putc (':', es_stdout); /* End of field 14. */
2010-10-13 15:57:08 +00:00
if (stubkey)
es_putc ('#', es_stdout);
else if (serialno)
es_fputs (serialno, es_stdout);
es_putc (':', es_stdout); /* End of field 15. */
}
es_putc ('\n', es_stdout);
2010-01-09 19:00:46 +00:00
if (fpr > 1)
print_fingerprint (pk2, 0);
2010-10-08 11:11:08 +00:00
if (opt.with_key_data || opt.with_keygrip)
{
2010-10-13 15:57:08 +00:00
if (hexgrip)
es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
2010-10-08 11:11:08 +00:00
if (opt.with_key_data)
print_key_data (pk2);
}
2010-01-09 19:00:46 +00:00
}
else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE)
{
PKT_signature *sig = node->pkt->pkt.signature;
int sigrc, fprokay = 0;
char *sigstr;
size_t fplen;
byte fparray[MAX_FINGERPRINT_LEN];
if (sig->sig_class == 0x20 || sig->sig_class == 0x28
|| sig->sig_class == 0x30)
sigstr = "rev";
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::::::::::%02x%c:\n",
2010-01-09 19:00:46 +00:00
sig->sig_class, sig->flags.exportable ? 'x' : 'l');
continue;
}
if (opt.check_sigs)
{
PKT_public_key *signer_pk = NULL;
fflush (stdout);
if (opt.no_sig_cache)
signer_pk = xmalloc_clear (sizeof (PKT_public_key));
rc = check_key_signature2 (keyblock, node, NULL, signer_pk,
NULL, NULL, NULL);
switch (gpg_err_code (rc))
{
case 0:
sigrc = '!';
break;
case GPG_ERR_BAD_SIGNATURE:
sigrc = '-';
break;
case GPG_ERR_NO_PUBKEY:
case GPG_ERR_UNUSABLE_PUBKEY:
sigrc = '?';
break;
default:
sigrc = '%';
break;
}
if (opt.no_sig_cache)
{
if (!rc)
{
fingerprint_from_pk (signer_pk, fparray, &fplen);
fprokay = 1;
}
free_public_key (signer_pk);
}
}
else
{
rc = 0;
sigrc = ' ';
}
es_fputs (sigstr, es_stdout);
es_putc (':', es_stdout);
2010-01-09 19:00:46 +00:00
if (sigrc != ' ')
es_putc (sigrc, es_stdout);
es_fprintf (es_stdout, "::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
2010-01-09 19:00:46 +00:00
(ulong) sig->keyid[0], (ulong) sig->keyid[1],
colon_datestr_from_sig (sig),
colon_expirestr_from_sig (sig));
if (sig->trust_depth || sig->trust_value)
es_fprintf (es_stdout, "%d %d", sig->trust_depth, sig->trust_value);
es_fprintf (es_stdout, ":");
2010-01-09 19:00:46 +00:00
if (sig->trust_regexp)
es_write_sanitized (es_stdout, sig->trust_regexp,
strlen (sig->trust_regexp), ":", NULL);
es_fprintf (es_stdout, ":");
2010-01-09 19:00:46 +00:00
if (sigrc == '%')
es_fprintf (es_stdout, "[%s] ", g10_errstr (rc));
2010-01-09 19:00:46 +00:00
else if (sigrc == '?')
;
else if (!opt.fast_list_mode)
{
size_t n;
p = get_user_id (sig->keyid, &n);
es_write_sanitized (es_stdout, p, n, ":", NULL);
2010-01-09 19:00:46 +00:00
xfree (p);
}
es_fprintf (es_stdout, ":%02x%c:", sig->sig_class,
2010-01-09 19:00:46 +00:00
sig->flags.exportable ? 'x' : 'l');
if (opt.no_sig_cache && opt.check_sigs && fprokay)
{
es_putc (':', es_stdout);
2010-01-09 19:00:46 +00:00
for (i = 0; i < fplen; i++)
es_fprintf (es_stdout, "%02X", fparray[i]);
2010-01-09 19:00:46 +00:00
es_putc (':', es_stdout);
2010-01-09 19:00:46 +00:00
}
es_fprintf (es_stdout, "\n");
2010-01-09 19:00:46 +00:00
if (opt.show_subpackets)
print_subpackets_colon (sig);
/* fixme: check or list other sigs here */
}
}
2010-10-13 15:57:08 +00:00
xfree (hexgrip);
xfree (serialno);
}
/*
* Reorder the keyblock so that the primary user ID (and not attribute
* packet) comes first. Fixme: Replace this by a generic sort
* function. */
static void
2010-01-09 19:00:46 +00:00
do_reorder_keyblock (KBNODE keyblock, int attr)
{
2010-01-09 19:00:46 +00:00
KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
KBNODE last, node;
for (node = keyblock; node; primary0 = node, node = node->next)
{
if (node->pkt->pkttype == PKT_USER_ID &&
((attr && node->pkt->pkt.user_id->attrib_data) ||
(!attr && !node->pkt->pkt.user_id->attrib_data)) &&
node->pkt->pkt.user_id->is_primary)
{
primary = primary2 = node;
for (node = node->next; node; primary2 = node, node = node->next)
{
if (node->pkt->pkttype == PKT_USER_ID
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY)
{
break;
}
}
break;
}
}
2010-01-09 19:00:46 +00:00
if (!primary)
return; /* No primary key flag found (should not happen). */
2010-01-09 19:00:46 +00:00
for (last = NULL, node = keyblock; node; last = node, node = node->next)
{
if (node->pkt->pkttype == PKT_USER_ID)
break;
}
2010-01-09 19:00:46 +00:00
assert (node);
assert (last); /* The user ID is never the first packet. */
assert (primary0); /* Ditto (this is the node before primary). */
if (node == primary)
return; /* Already the first one. */
last->next = primary;
primary0->next = primary2->next;
primary2->next = node;
}
void
reorder_keyblock (KBNODE keyblock)
{
2010-01-09 19:00:46 +00:00
do_reorder_keyblock (keyblock, 1);
do_reorder_keyblock (keyblock, 0);
}
void
2010-01-09 19:00:46 +00:00
list_keyblock (KBNODE keyblock, int secret, int fpr, void *opaque)
{
2010-01-09 19:00:46 +00:00
reorder_keyblock (keyblock);
if (opt.with_colons)
list_keyblock_colon (keyblock, secret, fpr);
else
list_keyblock_print (keyblock, secret, fpr, opaque);
}
/*
* Function to print the finperprint.
* mode 0: as used in key listings, opt.with_colons is honored
* 1: print using log_info ()
* 2: direct use of tty
* 3: direct use of tty but only primary key.
*
* Modes 1 and 2 will try and print both subkey and primary key
* fingerprints. A MODE with bit 7 set is used internally.
*/
void
print_fingerprint (PKT_public_key *pk, int mode)
{
2010-01-09 19:00:46 +00:00
byte array[MAX_FINGERPRINT_LEN], *p;
size_t i, n;
estream_t fp;
2010-01-09 19:00:46 +00:00
const char *text;
int primary = 0;
if (pk->main_keyid[0] == pk->keyid[0]
&& pk->main_keyid[1] == pk->keyid[1])
primary = 1;
2010-01-09 19:00:46 +00:00
/* Just to be safe */
if ((mode & 0x80) && !primary)
2010-01-09 19:00:46 +00:00
{
log_error ("primary key is not really primary!\n");
return;
}
mode &= ~0x80;
if (!primary && (mode == 1 || mode == 2))
{
PKT_public_key *primary_pk = xmalloc_clear (sizeof (*primary_pk));
get_pubkey (primary_pk, pk->main_keyid);
print_fingerprint (primary_pk, mode | 0x80);
free_public_key (primary_pk);
}
2010-01-09 19:00:46 +00:00
if (mode == 1)
{
fp = log_get_stream ();
if (primary)
text = _("Primary key fingerprint:");
else
text = _(" Subkey fingerprint:");
}
else if (mode == 2)
{
fp = NULL; /* Use tty. */
if (primary)
/* TRANSLATORS: this should fit into 24 bytes to that the
* fingerprint data is properly aligned with the user ID */
text = _(" Primary key fingerprint:");
else
text = _(" Subkey fingerprint:");
}
2010-01-09 19:00:46 +00:00
else if (mode == 3)
{
fp = NULL; /* Use tty. */
text = _(" Key fingerprint =");
}
2010-01-09 19:00:46 +00:00
else
{
fp = es_stdout;
2010-01-09 19:00:46 +00:00
text = _(" Key fingerprint =");
}
2010-01-09 19:00:46 +00:00
fingerprint_from_pk (pk, array, &n);
2010-01-09 19:00:46 +00:00
p = array;
if (opt.with_colons && !mode)
{
es_fprintf (fp, "fpr:::::::::");
2010-01-09 19:00:46 +00:00
for (i = 0; i < n; i++, p++)
es_fprintf (fp, "%02X", *p);
es_putc (':', fp);
}
2010-01-09 19:00:46 +00:00
else
{
tty_fprintf (fp, "%s", text);
2010-01-09 19:00:46 +00:00
if (n == 20)
{
for (i = 0; i < n; i++, i++, p += 2)
tty_fprintf (fp, "%s %02X%02X", i==10? " ":"", *p, p[1]);
}
2010-01-09 19:00:46 +00:00
else
{
for (i = 0; i < n; i++, p++)
tty_fprintf (fp, "%s %02X", (i && !(i % 8))? " ":"", *p);
}
}
tty_fprintf (fp, "\n");
}
2010-01-09 19:00:46 +00:00
/* Print the serial number of an OpenPGP card if available. */
static void
2010-10-13 15:57:08 +00:00
print_card_serialno (const char *serialno)
{
2010-10-13 15:57:08 +00:00
if (!serialno)
return;
if (opt.with_colons)
return; /* Handled elsewhere. */
2010-10-13 15:57:08 +00:00
es_fputs (_(" Card serial no. ="), es_stdout);
es_putc (' ', es_stdout);
if (strlen (serialno) == 32 && !strncmp (serialno, "D27600012401", 12))
{
/* This is an OpenPGP card. Print the relevant part. */
/* Example: D2760001240101010001000003470000 */
/* xxxxyyyyyyyy */
es_fprintf (es_stdout, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
}
else
es_fputs (serialno, es_stdout);
es_putc ('\n', es_stdout);
}
2008-12-09 08:58:02 +00:00
void
set_attrib_fd (int fd)
{
2010-01-09 19:00:46 +00:00
static int last_fd = -1;
2010-01-09 19:00:46 +00:00
if (fd != -1 && last_fd == fd)
return;
/* Fixme: Do we need to check for the log stream here? */
if (attrib_fp && attrib_fp != log_get_stream ())
es_fclose (attrib_fp);
attrib_fp = NULL;
2010-01-09 19:00:46 +00:00
if (fd == -1)
return;
2008-12-09 08:58:02 +00:00
#ifdef HAVE_DOSISH_SYSTEM
2008-12-09 12:03:04 +00:00
setmode (fd, O_BINARY);
2008-12-09 08:58:02 +00:00
#endif
2010-01-09 19:00:46 +00:00
if (fd == 1)
attrib_fp = es_stdout;
2010-01-09 19:00:46 +00:00
else if (fd == 2)
attrib_fp = es_stderr;
else
attrib_fp = es_fdopen (fd, "wb");
2010-01-09 19:00:46 +00:00
if (!attrib_fp)
2008-12-09 08:58:02 +00:00
{
2010-01-09 19:00:46 +00:00
log_fatal ("can't open fd %d for attribute output: %s\n",
fd, strerror (errno));
2008-12-09 08:58:02 +00:00
}
2010-01-09 19:00:46 +00:00
last_fd = fd;
}