2001-11-19 17:52:10 +01:00
|
|
|
|
/* keylist.c
|
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001 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
|
|
|
|
|
* the Free Software Foundation; either version 2 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
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
#include <gcrypt.h>
|
|
|
|
|
#include <ksba.h>
|
|
|
|
|
|
|
|
|
|
#include "gpgsm.h"
|
|
|
|
|
#include "keydb.h"
|
2002-04-12 20:54:34 +02:00
|
|
|
|
#include "i18n.h"
|
2001-11-19 17:52:10 +01:00
|
|
|
|
|
2002-05-21 21:20:40 +02:00
|
|
|
|
struct list_external_parm_s {
|
|
|
|
|
FILE *fp;
|
|
|
|
|
int print_header;
|
|
|
|
|
int with_colons;
|
2002-06-04 11:41:59 +02:00
|
|
|
|
int with_chain;
|
2002-05-21 21:20:40 +02:00
|
|
|
|
};
|
|
|
|
|
|
2001-11-19 17:52:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_key_data (KsbaCert cert, FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
#if 0
|
|
|
|
|
int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for(i=0; i < n; i++ )
|
|
|
|
|
{
|
|
|
|
|
fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
|
|
|
|
|
mpi_print(stdout, pk->pkey[i], 1 );
|
|
|
|
|
putchar(':');
|
|
|
|
|
putchar('\n');
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_capabilities (KsbaCert cert, FILE *fp)
|
|
|
|
|
{
|
2002-04-12 20:54:34 +02:00
|
|
|
|
KsbaError err;
|
|
|
|
|
unsigned int use;
|
|
|
|
|
|
|
|
|
|
err = ksba_cert_get_key_usage (cert, &use);
|
|
|
|
|
if (err == KSBA_No_Data)
|
|
|
|
|
{
|
|
|
|
|
putc ('e', fp);
|
|
|
|
|
putc ('s', fp);
|
|
|
|
|
putc ('c', fp);
|
|
|
|
|
putc ('E', fp);
|
|
|
|
|
putc ('S', fp);
|
|
|
|
|
putc ('C', fp);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (err)
|
|
|
|
|
{
|
|
|
|
|
log_error (_("error getting key usage information: %s\n"),
|
|
|
|
|
ksba_strerror (err));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2002-06-20 12:43:02 +02:00
|
|
|
|
if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
|
2002-04-12 20:54:34 +02:00
|
|
|
|
putc ('e', fp);
|
2002-06-20 12:43:02 +02:00
|
|
|
|
if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
|
2002-04-12 20:54:34 +02:00
|
|
|
|
putc ('s', fp);
|
|
|
|
|
if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
|
|
|
|
|
putc ('c', fp);
|
2002-06-20 12:43:02 +02:00
|
|
|
|
if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
|
2002-04-12 20:54:34 +02:00
|
|
|
|
putc ('E', fp);
|
2002-06-20 12:43:02 +02:00
|
|
|
|
if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
|
2002-04-12 20:54:34 +02:00
|
|
|
|
putc ('S', fp);
|
|
|
|
|
if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
|
|
|
|
|
putc ('C', fp);
|
2001-11-19 17:52:10 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-12-13 14:11:40 +01:00
|
|
|
|
static void
|
|
|
|
|
print_time (time_t t, FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
if (!t)
|
|
|
|
|
;
|
|
|
|
|
else if ( t == (time_t)(-1) )
|
|
|
|
|
putc ('?', fp);
|
|
|
|
|
else
|
|
|
|
|
fprintf (fp, "%lu", (unsigned long)t);
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-19 17:52:10 +01:00
|
|
|
|
|
2001-12-14 21:48:26 +01:00
|
|
|
|
/* return an allocated string with the email address extracted from a
|
|
|
|
|
DN */
|
|
|
|
|
static char *
|
|
|
|
|
email_kludge (const char *name)
|
|
|
|
|
{
|
|
|
|
|
const unsigned char *p;
|
|
|
|
|
unsigned char *buf;
|
|
|
|
|
int n;
|
|
|
|
|
|
|
|
|
|
if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
|
|
|
|
|
return NULL;
|
|
|
|
|
/* This looks pretty much like an email address in the subject's DN
|
|
|
|
|
we use this to add an additional user ID entry. This way,
|
|
|
|
|
openSSL generated keys get a nicer and usable listing */
|
|
|
|
|
name += 22;
|
|
|
|
|
for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
|
|
|
|
|
;
|
|
|
|
|
if (*p != '#' || !n)
|
|
|
|
|
return NULL;
|
|
|
|
|
buf = xtrymalloc (n+3);
|
|
|
|
|
if (!buf)
|
|
|
|
|
return NULL; /* oops, out of core */
|
|
|
|
|
*buf = '<';
|
|
|
|
|
for (n=1, p=name; *p != '#'; p +=2, n++)
|
|
|
|
|
buf[n] = xtoi_2 (p);
|
|
|
|
|
buf[n++] = '>';
|
|
|
|
|
buf[n] = 0;
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-11-19 17:52:10 +01:00
|
|
|
|
/* List one certificate in colon mode */
|
|
|
|
|
static void
|
2002-01-29 11:05:24 +01:00
|
|
|
|
list_cert_colon (KsbaCert cert, FILE *fp, int have_secret)
|
2001-11-19 17:52:10 +01:00
|
|
|
|
{
|
2001-12-13 14:11:40 +01:00
|
|
|
|
int idx, trustletter = 0;
|
2001-12-18 18:37:48 +01:00
|
|
|
|
char *p;
|
|
|
|
|
KsbaSexp sexp;
|
2002-08-10 11:14:21 +02:00
|
|
|
|
char *fpr;
|
2001-11-19 17:52:10 +01:00
|
|
|
|
|
2002-01-29 11:05:24 +01:00
|
|
|
|
fputs (have_secret? "crs:":"crt:", fp);
|
2001-11-19 17:52:10 +01:00
|
|
|
|
trustletter = 0;
|
|
|
|
|
#if 0
|
|
|
|
|
if (is_not_valid (cert))
|
|
|
|
|
putc ('i', fp);
|
|
|
|
|
else if ( is_revoked (cert) )
|
|
|
|
|
putc ('r', fp);
|
|
|
|
|
else if ( has_expired (cert))
|
|
|
|
|
putcr ('e', fp);
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
trustletter = '?'; /*get_validity_info ( pk, NULL );*/
|
|
|
|
|
putc (trustletter, fp);
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-10 11:14:21 +02:00
|
|
|
|
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
|
|
|
|
|
fprintf (fp, ":%u:%d:%s:",
|
2001-11-19 17:52:10 +01:00
|
|
|
|
/*keylen_of_cert (cert)*/1024,
|
2002-08-10 11:14:21 +02:00
|
|
|
|
/* pubkey_algo_of_cert (cert)*/1,
|
|
|
|
|
fpr+24);
|
2001-12-13 14:11:40 +01:00
|
|
|
|
|
|
|
|
|
/* we assume --fixed-list-mode for gpgsm */
|
|
|
|
|
print_time ( ksba_cert_get_validity (cert, 0), fp);
|
|
|
|
|
putc (':', fp);
|
|
|
|
|
print_time ( ksba_cert_get_validity (cert, 1), fp);
|
|
|
|
|
putc (':', fp);
|
2002-03-28 17:36:25 +01:00
|
|
|
|
/* field 8, serial number: */
|
2001-12-18 18:37:48 +01:00
|
|
|
|
if ((sexp = ksba_cert_get_serial (cert)))
|
2001-12-13 14:11:40 +01:00
|
|
|
|
{
|
2001-12-18 18:37:48 +01:00
|
|
|
|
int len;
|
|
|
|
|
const unsigned char *s = sexp;
|
|
|
|
|
|
2001-12-20 14:25:08 +01:00
|
|
|
|
if (*s == '(')
|
|
|
|
|
{
|
|
|
|
|
s++;
|
|
|
|
|
for (len=0; *s && *s != ':' && digitp (s); s++)
|
|
|
|
|
len = len*10 + atoi_1 (s);
|
|
|
|
|
if (*s == ':')
|
|
|
|
|
for (s++; len; len--, s++)
|
|
|
|
|
fprintf (fp,"%02X", *s);
|
|
|
|
|
}
|
2001-12-18 18:37:48 +01:00
|
|
|
|
xfree (sexp);
|
2001-12-13 14:11:40 +01:00
|
|
|
|
}
|
|
|
|
|
putc (':', fp);
|
2002-03-28 17:36:25 +01:00
|
|
|
|
/* field 9, ownertrust - not used here */
|
2001-11-19 17:52:10 +01:00
|
|
|
|
putc (':', fp);
|
2002-03-28 17:36:25 +01:00
|
|
|
|
/* field 10, old user ID - we use it here for the issuer DN */
|
2001-12-13 14:11:40 +01:00
|
|
|
|
if ((p = ksba_cert_get_issuer (cert,0)))
|
|
|
|
|
{
|
2002-02-07 19:43:22 +01:00
|
|
|
|
print_sanitized_string (fp, p, ':');
|
2001-12-13 14:11:40 +01:00
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
2001-11-19 17:52:10 +01:00
|
|
|
|
putc (':', fp);
|
2002-03-28 17:36:25 +01:00
|
|
|
|
/* field 11, signature class - not used */
|
|
|
|
|
putc (':', fp);
|
|
|
|
|
/* field 12, capabilities: */
|
2001-11-19 17:52:10 +01:00
|
|
|
|
print_capabilities (cert, fp);
|
2002-03-28 17:36:25 +01:00
|
|
|
|
putc (':', fp);
|
2001-11-19 17:52:10 +01:00
|
|
|
|
putc ('\n', fp);
|
2001-12-13 14:11:40 +01:00
|
|
|
|
|
2002-03-28 17:36:25 +01:00
|
|
|
|
/* FPR record */
|
2002-08-10 11:14:21 +02:00
|
|
|
|
fprintf (fp, "fpr:::::::::%s:::", fpr);
|
|
|
|
|
xfree (fpr); fpr = NULL;
|
2002-03-28 17:36:25 +01:00
|
|
|
|
/* print chaining ID (field 13)*/
|
|
|
|
|
{
|
|
|
|
|
KsbaCert next;
|
|
|
|
|
|
|
|
|
|
if (!gpgsm_walk_cert_chain (cert, &next))
|
|
|
|
|
{
|
|
|
|
|
p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
|
|
|
|
|
fputs (p, fp);
|
|
|
|
|
xfree (p);
|
|
|
|
|
ksba_cert_release (next);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
putc (':', fp);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
|
|
|
|
|
|
2001-11-19 17:52:10 +01:00
|
|
|
|
if (opt.with_key_data)
|
2001-12-13 14:11:40 +01:00
|
|
|
|
{
|
|
|
|
|
if ( (p = gpgsm_get_keygrip_hexstring (cert)))
|
|
|
|
|
{
|
|
|
|
|
fprintf (fp, "grp:::::::::%s:\n", p);
|
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
|
|
|
|
print_key_data (cert, fp);
|
|
|
|
|
}
|
2001-11-19 17:52:10 +01:00
|
|
|
|
|
2001-12-13 14:11:40 +01:00
|
|
|
|
for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
|
|
|
|
|
{
|
|
|
|
|
fprintf (fp, "uid:%c::::::::", trustletter);
|
2002-02-07 19:43:22 +01:00
|
|
|
|
print_sanitized_string (fp, p, ':');
|
2001-12-13 14:11:40 +01:00
|
|
|
|
putc (':', fp);
|
|
|
|
|
putc (':', fp);
|
|
|
|
|
putc ('\n', fp);
|
2001-12-14 21:48:26 +01:00
|
|
|
|
if (!idx)
|
|
|
|
|
{
|
|
|
|
|
/* It would be better to get the faked email address from
|
|
|
|
|
the keydb. But as long as we don't have a way to pass
|
|
|
|
|
the meta data back, we just check it the same way as the
|
|
|
|
|
code used to create the keybox meta data does */
|
|
|
|
|
char *pp = email_kludge (p);
|
|
|
|
|
if (pp)
|
|
|
|
|
{
|
|
|
|
|
fprintf (fp, "uid:%c::::::::", trustletter);
|
2002-02-07 19:43:22 +01:00
|
|
|
|
print_sanitized_string (fp, pp, ':');
|
2001-12-14 21:48:26 +01:00
|
|
|
|
putc (':', fp);
|
|
|
|
|
putc (':', fp);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
xfree (pp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
xfree (p);
|
2001-12-13 14:11:40 +01:00
|
|
|
|
}
|
2001-11-19 17:52:10 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2002-06-04 11:41:59 +02:00
|
|
|
|
/* List one certificate in standard mode */
|
|
|
|
|
static void
|
|
|
|
|
list_cert_std (KsbaCert cert, FILE *fp, int have_secret)
|
|
|
|
|
{
|
|
|
|
|
KsbaError kerr;
|
|
|
|
|
KsbaSexp sexp;
|
|
|
|
|
char *dn;
|
|
|
|
|
time_t t;
|
|
|
|
|
int idx;
|
2002-08-16 15:55:03 +02:00
|
|
|
|
int is_ca, chainlen;
|
2002-06-04 11:41:59 +02:00
|
|
|
|
unsigned int kusage;
|
|
|
|
|
char *string, *p;
|
|
|
|
|
|
|
|
|
|
sexp = ksba_cert_get_serial (cert);
|
|
|
|
|
fputs ("Serial number: ", fp);
|
|
|
|
|
gpgsm_print_serial (fp, sexp);
|
|
|
|
|
ksba_free (sexp);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
|
|
|
|
|
dn = ksba_cert_get_issuer (cert, 0);
|
|
|
|
|
fputs (" Issuer: ", fp);
|
|
|
|
|
gpgsm_print_name (fp, dn);
|
|
|
|
|
ksba_free (dn);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
|
|
|
|
|
{
|
|
|
|
|
fputs (" aka: ", fp);
|
|
|
|
|
gpgsm_print_name (fp, dn);
|
|
|
|
|
ksba_free (dn);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dn = ksba_cert_get_subject (cert, 0);
|
|
|
|
|
fputs (" Subject: ", fp);
|
|
|
|
|
gpgsm_print_name (fp, dn);
|
|
|
|
|
ksba_free (dn);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
|
|
|
|
|
{
|
|
|
|
|
fputs (" aka: ", fp);
|
|
|
|
|
gpgsm_print_name (fp, dn);
|
|
|
|
|
ksba_free (dn);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t = ksba_cert_get_validity (cert, 0);
|
|
|
|
|
fputs (" validity: ", fp);
|
|
|
|
|
gpgsm_print_time (fp, t);
|
|
|
|
|
fputs (" through ", fp);
|
|
|
|
|
t = ksba_cert_get_validity (cert, 1);
|
|
|
|
|
gpgsm_print_time (fp, t);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
|
|
|
|
|
kerr = ksba_cert_get_key_usage (cert, &kusage);
|
|
|
|
|
if (kerr != KSBA_No_Data)
|
|
|
|
|
{
|
|
|
|
|
fputs (" key usage:", fp);
|
|
|
|
|
if (kerr)
|
|
|
|
|
fprintf (fp, " [error: %s]", ksba_strerror (kerr));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
|
|
|
|
|
fputs (" digitalSignature", fp);
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
|
|
|
|
|
fputs (" nonRepudiation", fp);
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
|
|
|
|
|
fputs (" keyEncipherment", fp);
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
|
2002-08-16 15:55:03 +02:00
|
|
|
|
fputs (" dataEncipherment", fp);
|
2002-06-04 11:41:59 +02:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
|
|
|
|
|
fputs (" keyAgreement", fp);
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
|
|
|
|
|
fputs (" certSign", fp);
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
|
|
|
|
|
fputs (" crlSign", fp);
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
|
|
|
|
|
fputs (" encipherOnly", fp);
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
|
|
|
|
|
fputs (" decipherOnly", fp);
|
|
|
|
|
}
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kerr = ksba_cert_get_cert_policies (cert, &string);
|
|
|
|
|
if (kerr != KSBA_No_Data)
|
|
|
|
|
{
|
|
|
|
|
fputs (" policies: ", fp);
|
|
|
|
|
if (kerr)
|
|
|
|
|
fprintf (fp, "[error: %s]", ksba_strerror (kerr));
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (p=string; *p; p++)
|
|
|
|
|
{
|
|
|
|
|
if (*p == '\n')
|
|
|
|
|
*p = ',';
|
|
|
|
|
}
|
|
|
|
|
print_sanitized_string (fp, string, 0);
|
|
|
|
|
xfree (string);
|
|
|
|
|
}
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
}
|
|
|
|
|
|
2002-08-16 15:55:03 +02:00
|
|
|
|
kerr = ksba_cert_is_ca (cert, &is_ca, &chainlen);
|
2002-06-04 11:41:59 +02:00
|
|
|
|
if (kerr || is_ca)
|
|
|
|
|
{
|
2002-08-16 15:55:03 +02:00
|
|
|
|
fputs (" chain length: ", fp);
|
2002-06-04 11:41:59 +02:00
|
|
|
|
if (kerr)
|
|
|
|
|
fprintf (fp, "[error: %s]", ksba_strerror (kerr));
|
2002-08-16 15:55:03 +02:00
|
|
|
|
else if (chainlen == -1)
|
2002-06-04 11:41:59 +02:00
|
|
|
|
fputs ("unlimited", fp);
|
|
|
|
|
else
|
2002-08-16 15:55:03 +02:00
|
|
|
|
fprintf (fp, "%d", chainlen);
|
2002-06-04 11:41:59 +02:00
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dn = gpgsm_get_fingerprint_string (cert, 0);
|
|
|
|
|
fprintf (fp, " fingerprint: %s\n", dn?dn:"error");
|
|
|
|
|
xfree (dn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Same as standard mode mode list all certifying certts too */
|
|
|
|
|
static void
|
|
|
|
|
list_cert_chain (KsbaCert cert, FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
KsbaCert next = NULL;
|
|
|
|
|
|
|
|
|
|
list_cert_std (cert, fp, 0);
|
|
|
|
|
ksba_cert_ref (cert);
|
|
|
|
|
while (!gpgsm_walk_cert_chain (cert, &next))
|
|
|
|
|
{
|
|
|
|
|
ksba_cert_release (cert);
|
|
|
|
|
fputs ("Certified by\n", fp);
|
|
|
|
|
list_cert_std (next, fp, 0);
|
|
|
|
|
cert = next;
|
|
|
|
|
}
|
|
|
|
|
ksba_cert_release (cert);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-19 17:52:10 +01:00
|
|
|
|
|
|
|
|
|
|
2002-05-21 21:20:40 +02:00
|
|
|
|
/* List all internal keys or just the key given as NAMES.
|
2002-01-29 11:05:24 +01:00
|
|
|
|
*/
|
2002-05-21 21:20:40 +02:00
|
|
|
|
static void
|
|
|
|
|
list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
|
2001-11-19 17:52:10 +01:00
|
|
|
|
{
|
|
|
|
|
KEYDB_HANDLE hd;
|
2002-03-06 17:13:47 +01:00
|
|
|
|
KEYDB_SEARCH_DESC *desc = NULL;
|
|
|
|
|
STRLIST sl;
|
|
|
|
|
int ndesc;
|
2001-11-19 17:52:10 +01:00
|
|
|
|
KsbaCert cert = NULL;
|
|
|
|
|
int rc=0;
|
|
|
|
|
const char *lastresname, *resname;
|
2002-01-29 11:05:24 +01:00
|
|
|
|
int have_secret;
|
2001-11-19 17:52:10 +01:00
|
|
|
|
|
|
|
|
|
hd = keydb_new (0);
|
|
|
|
|
if (!hd)
|
2002-03-06 17:13:47 +01:00
|
|
|
|
{
|
|
|
|
|
log_error ("keydb_new failed\n");
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!names)
|
|
|
|
|
ndesc = 1;
|
2001-11-19 17:52:10 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
2002-03-06 17:13:47 +01:00
|
|
|
|
for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
desc = xtrycalloc (ndesc, sizeof *desc);
|
|
|
|
|
if (!ndesc)
|
|
|
|
|
{
|
|
|
|
|
log_error ("out of core\n");
|
2001-11-19 17:52:10 +01:00
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-06 17:13:47 +01:00
|
|
|
|
if (!names)
|
|
|
|
|
desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (ndesc=0, sl=names; sl; sl = sl->next)
|
|
|
|
|
{
|
|
|
|
|
rc = keydb_classify_name (sl->d, desc+ndesc);
|
|
|
|
|
if (rc)
|
|
|
|
|
{
|
|
|
|
|
log_error ("key `%s' not found: %s\n",
|
|
|
|
|
sl->d, gnupg_strerror (rc));
|
|
|
|
|
rc = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ndesc++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* it would be nice to see which of the given users did actually
|
|
|
|
|
match one in the keyring. To implement this we need to have a
|
|
|
|
|
found flag for each entry in desc and to set this we must check
|
|
|
|
|
all those entries after a match to mark all matched one -
|
|
|
|
|
currently we stop at the first match. To do this we need an
|
|
|
|
|
extra flag to enable this feature so */
|
|
|
|
|
|
2001-11-19 17:52:10 +01:00
|
|
|
|
lastresname = NULL;
|
2002-03-06 17:13:47 +01:00
|
|
|
|
while (!(rc = keydb_search (hd, desc, ndesc)))
|
2001-11-19 17:52:10 +01:00
|
|
|
|
{
|
2002-03-06 17:13:47 +01:00
|
|
|
|
if (!names)
|
|
|
|
|
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
|
|
|
|
|
|
2001-11-19 17:52:10 +01:00
|
|
|
|
rc = keydb_get_cert (hd, &cert);
|
|
|
|
|
if (rc)
|
|
|
|
|
{
|
2001-11-24 18:43:43 +01:00
|
|
|
|
log_error ("keydb_get_cert failed: %s\n", gnupg_strerror (rc));
|
2001-11-19 17:52:10 +01:00
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resname = keydb_get_resource_name (hd);
|
|
|
|
|
|
|
|
|
|
if (lastresname != resname )
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (ctrl->no_server)
|
|
|
|
|
{
|
|
|
|
|
fprintf (fp, "%s\n", resname );
|
|
|
|
|
for (i=strlen(resname); i; i-- )
|
|
|
|
|
putchar('-');
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
lastresname = resname;
|
|
|
|
|
}
|
2001-11-26 14:08:36 +01:00
|
|
|
|
}
|
2002-01-29 11:05:24 +01:00
|
|
|
|
|
|
|
|
|
have_secret = 0;
|
|
|
|
|
if (mode)
|
|
|
|
|
{
|
|
|
|
|
char *p = gpgsm_get_keygrip_hexstring (cert);
|
|
|
|
|
if (p)
|
|
|
|
|
{
|
|
|
|
|
if (!gpgsm_agent_havekey (p))
|
|
|
|
|
have_secret = 1;
|
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!mode
|
|
|
|
|
|| ((mode & 1) && !have_secret)
|
|
|
|
|
|| ((mode & 2) && have_secret) )
|
|
|
|
|
{
|
|
|
|
|
if (ctrl->with_colons)
|
|
|
|
|
list_cert_colon (cert, fp, have_secret);
|
2002-06-04 11:41:59 +02:00
|
|
|
|
else if (ctrl->with_chain)
|
|
|
|
|
list_cert_chain (cert, fp);
|
2002-01-29 11:05:24 +01:00
|
|
|
|
else
|
2002-06-04 11:41:59 +02:00
|
|
|
|
{
|
|
|
|
|
list_cert_std (cert, fp, have_secret);
|
|
|
|
|
putc ('\n', fp);
|
|
|
|
|
}
|
2002-01-29 11:05:24 +01:00
|
|
|
|
}
|
2001-11-26 14:08:36 +01:00
|
|
|
|
ksba_cert_release (cert);
|
|
|
|
|
cert = NULL;
|
2001-11-19 17:52:10 +01:00
|
|
|
|
}
|
|
|
|
|
if (rc && rc != -1)
|
2002-03-06 17:13:47 +01:00
|
|
|
|
log_error ("keydb_search failed: %s\n", gnupg_strerror (rc));
|
2001-11-19 17:52:10 +01:00
|
|
|
|
|
|
|
|
|
leave:
|
|
|
|
|
ksba_cert_release (cert);
|
2002-03-06 17:13:47 +01:00
|
|
|
|
xfree (desc);
|
2001-11-19 17:52:10 +01:00
|
|
|
|
keydb_release (hd);
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-06 17:13:47 +01:00
|
|
|
|
|
|
|
|
|
|
2002-05-21 21:20:40 +02:00
|
|
|
|
static void
|
|
|
|
|
list_external_cb (void *cb_value, KsbaCert cert)
|
|
|
|
|
{
|
|
|
|
|
struct list_external_parm_s *parm = cb_value;
|
|
|
|
|
|
2002-07-02 12:40:12 +02:00
|
|
|
|
if (keydb_store_cert (cert, 1, NULL))
|
2002-06-19 10:30:10 +02:00
|
|
|
|
log_error ("error storing certificate as ephemeral\n");
|
|
|
|
|
|
2002-05-21 21:20:40 +02:00
|
|
|
|
if (parm->print_header)
|
|
|
|
|
{
|
|
|
|
|
const char *resname = "[external keys]";
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
fprintf (parm->fp, "%s\n", resname );
|
|
|
|
|
for (i=strlen(resname); i; i-- )
|
|
|
|
|
putchar('-');
|
|
|
|
|
putc ('\n', parm->fp);
|
|
|
|
|
parm->print_header = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parm->with_colons)
|
|
|
|
|
list_cert_colon (cert, parm->fp, 0);
|
2002-06-04 11:41:59 +02:00
|
|
|
|
else if (parm->with_chain)
|
|
|
|
|
list_cert_chain (cert, parm->fp);
|
2002-05-21 21:20:40 +02:00
|
|
|
|
else
|
2002-06-04 11:41:59 +02:00
|
|
|
|
{
|
|
|
|
|
list_cert_std (cert, parm->fp, 0);
|
|
|
|
|
putc ('\n', parm->fp);
|
|
|
|
|
}
|
2002-05-21 21:20:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* List external keys similar to internal one. Note: mode does not
|
|
|
|
|
make sense here because it would be unwise to list external secret
|
|
|
|
|
keys */
|
|
|
|
|
static void
|
|
|
|
|
list_external_keys (CTRL ctrl, STRLIST names, FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
struct list_external_parm_s parm;
|
|
|
|
|
|
|
|
|
|
parm.fp = fp;
|
|
|
|
|
parm.print_header = ctrl->no_server;
|
|
|
|
|
parm.with_colons = ctrl->with_colons;
|
2002-06-04 11:41:59 +02:00
|
|
|
|
parm.with_chain = ctrl->with_chain;
|
2002-05-21 21:20:40 +02:00
|
|
|
|
|
2002-06-12 16:35:41 +02:00
|
|
|
|
rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
|
2002-05-21 21:20:40 +02:00
|
|
|
|
if (rc)
|
|
|
|
|
log_error ("listing external keys failed: %s\n", gnupg_strerror (rc));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* List all keys or just the key given as NAMES.
|
|
|
|
|
MODE controls the operation mode:
|
|
|
|
|
Bit 0-2:
|
|
|
|
|
0 = list all public keys but don't flag secret ones
|
|
|
|
|
1 = list only public keys
|
|
|
|
|
2 = list only secret keys
|
|
|
|
|
3 = list secret and public keys
|
|
|
|
|
Bit 6: list internal keys
|
|
|
|
|
Bit 7: list external keys
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
|
|
|
|
|
{
|
|
|
|
|
if ((mode & (1<<6)))
|
|
|
|
|
list_internal_keys (ctrl, names, fp, (mode & 3));
|
|
|
|
|
if ((mode & (1<<7)))
|
|
|
|
|
list_external_keys (ctrl, names, fp);
|
|
|
|
|
}
|