2005-04-18 10:44:46 +00:00
|
|
|
|
/* keylist.c - Print certificates in various formats.
|
2011-12-07 16:15:15 +01:00
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2008, 2009,
|
|
|
|
|
* 2010, 2011 Free Software Foundation, Inc.
|
2003-08-05 17:11:04 +00:00
|
|
|
|
*
|
|
|
|
|
* 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
|
2003-08-05 17:11:04 +00:00
|
|
|
|
* (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
|
2016-11-05 12:02:19 +01:00
|
|
|
|
* along with this program; if not, see <https://www.gnu.org/licenses/>.
|
2003-08-05 17:11:04 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <errno.h>
|
2011-02-04 12:57:53 +01:00
|
|
|
|
#include <unistd.h>
|
2003-08-05 17:11:04 +00:00
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
#include "gpgsm.h"
|
|
|
|
|
|
|
|
|
|
#include <gcrypt.h>
|
|
|
|
|
#include <ksba.h>
|
|
|
|
|
|
|
|
|
|
#include "keydb.h"
|
2004-02-02 17:09:35 +00:00
|
|
|
|
#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
|
2003-08-05 17:11:04 +00:00
|
|
|
|
#include "i18n.h"
|
2008-06-26 19:09:07 +00:00
|
|
|
|
#include "tlv.h"
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2011-02-04 12:57:53 +01:00
|
|
|
|
struct list_external_parm_s
|
2007-03-19 14:35:04 +00:00
|
|
|
|
{
|
2004-02-17 15:05:04 +00:00
|
|
|
|
ctrl_t ctrl;
|
2007-03-19 14:35:04 +00:00
|
|
|
|
estream_t fp;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
int print_header;
|
|
|
|
|
int with_colons;
|
|
|
|
|
int with_chain;
|
2004-04-22 13:03:44 +00:00
|
|
|
|
int raw_mode;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2004-02-20 13:46:21 +00:00
|
|
|
|
/* This table is to map Extended Key Usage OIDs to human readable
|
|
|
|
|
names. */
|
2007-03-19 14:35:04 +00:00
|
|
|
|
struct
|
|
|
|
|
{
|
2004-02-20 13:46:21 +00:00
|
|
|
|
const char *oid;
|
|
|
|
|
const char *name;
|
|
|
|
|
} key_purpose_map[] = {
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.1", "serverAuth" },
|
2011-02-04 12:57:53 +01:00
|
|
|
|
{ "1.3.6.1.5.5.7.3.2", "clientAuth" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.3", "codeSigning" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.4", "emailProtection" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.5", "ipsecEndSystem" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.6", "ipsecTunnel" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.7", "ipsecUser" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.8", "timeStamping" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.9", "ocspSigning" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.10", "dvcs" },
|
2004-02-20 13:46:21 +00:00
|
|
|
|
{ "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.3.13", "eapOverPPP" },
|
2011-02-04 12:57:53 +01:00
|
|
|
|
{ "1.3.6.1.5.5.7.3.14", "wlanSSID" },
|
2005-11-13 19:07:06 +00:00
|
|
|
|
|
|
|
|
|
{ "2.16.840.1.113730.4.1", "serverGatedCrypto.ns" }, /* Netscape. */
|
|
|
|
|
{ "1.3.6.1.4.1.311.10.3.3", "serverGatedCrypto.ms"}, /* Microsoft. */
|
2006-09-06 11:53:24 +00:00
|
|
|
|
|
|
|
|
|
{ "1.3.6.1.5.5.7.48.1.5", "ocspNoCheck" },
|
|
|
|
|
|
2004-02-20 13:46:21 +00:00
|
|
|
|
{ NULL, NULL }
|
|
|
|
|
};
|
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2008-06-26 19:09:07 +00:00
|
|
|
|
/* Do not print this extension in the list of extensions. This is set
|
|
|
|
|
for oids which are already available via ksba fucntions. */
|
|
|
|
|
#define OID_FLAG_SKIP 1
|
|
|
|
|
/* The extension is a simple UTF8String and should be printed. */
|
2011-02-04 12:57:53 +01:00
|
|
|
|
#define OID_FLAG_UTF8 2
|
2008-06-26 19:09:07 +00:00
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
/* A table mapping OIDs to a descriptive string. */
|
2011-02-04 12:57:53 +01:00
|
|
|
|
static struct
|
2007-03-19 14:35:04 +00:00
|
|
|
|
{
|
2004-04-23 10:34:25 +00:00
|
|
|
|
char *oid;
|
|
|
|
|
char *name;
|
2008-06-26 19:09:07 +00:00
|
|
|
|
unsigned int flag; /* A flag as described above. */
|
2004-04-23 10:34:25 +00:00
|
|
|
|
} oidtranstbl[] = {
|
|
|
|
|
|
|
|
|
|
/* Algorithms. */
|
|
|
|
|
{ "1.2.840.10040.4.1", "dsa" },
|
|
|
|
|
{ "1.2.840.10040.4.3", "dsaWithSha1" },
|
|
|
|
|
|
|
|
|
|
{ "1.2.840.113549.1.1.1", "rsaEncryption" },
|
|
|
|
|
{ "1.2.840.113549.1.1.2", "md2WithRSAEncryption" },
|
|
|
|
|
{ "1.2.840.113549.1.1.3", "md4WithRSAEncryption" },
|
|
|
|
|
{ "1.2.840.113549.1.1.4", "md5WithRSAEncryption" },
|
|
|
|
|
{ "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" },
|
|
|
|
|
{ "1.2.840.113549.1.1.7", "rsaOAEP" },
|
|
|
|
|
{ "1.2.840.113549.1.1.8", "rsaOAEP-MGF" },
|
|
|
|
|
{ "1.2.840.113549.1.1.9", "rsaOAEP-pSpecified" },
|
|
|
|
|
{ "1.2.840.113549.1.1.10", "rsaPSS" },
|
|
|
|
|
{ "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" },
|
|
|
|
|
{ "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" },
|
|
|
|
|
{ "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" },
|
|
|
|
|
|
|
|
|
|
{ "1.3.14.3.2.26", "sha1" },
|
|
|
|
|
{ "1.3.14.3.2.29", "sha-1WithRSAEncryption" },
|
|
|
|
|
{ "1.3.36.3.3.1.2", "rsaSignatureWithripemd160" },
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Telesec extensions. */
|
|
|
|
|
{ "0.2.262.1.10.12.0", "certExtensionLiabilityLimitationExt" },
|
|
|
|
|
{ "0.2.262.1.10.12.1", "telesecCertIdExt" },
|
|
|
|
|
{ "0.2.262.1.10.12.2", "telesecPolicyIdentifier" },
|
|
|
|
|
{ "0.2.262.1.10.12.3", "telesecPolicyQualifierID" },
|
|
|
|
|
{ "0.2.262.1.10.12.4", "telesecCRLFilteredExt" },
|
|
|
|
|
{ "0.2.262.1.10.12.5", "telesecCRLFilterExt"},
|
|
|
|
|
{ "0.2.262.1.10.12.6", "telesecNamingAuthorityExt" },
|
2008-06-26 19:09:07 +00:00
|
|
|
|
#define OIDSTR_restriction \
|
|
|
|
|
"1.3.36.8.3.8"
|
|
|
|
|
{ OIDSTR_restriction, "restriction", OID_FLAG_UTF8 },
|
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
|
|
|
|
|
/* PKIX private extensions. */
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.1", "authorityInfoAccess" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.2", "biometricInfo" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.3", "qcStatements" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.4", "acAuditIdentity" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.5", "acTargeting" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.6", "acAaControls" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.7", "sbgp-ipAddrBlock" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.8", "sbgp-autonomousSysNum" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.9", "sbgp-routerIdentifier" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.10", "acProxying" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.1.11", "subjectInfoAccess" },
|
|
|
|
|
|
2006-09-06 11:53:24 +00:00
|
|
|
|
{ "1.3.6.1.5.5.7.48.1", "ocsp" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.48.2", "caIssuers" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.48.3", "timeStamping" },
|
|
|
|
|
{ "1.3.6.1.5.5.7.48.5", "caRepository" },
|
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
/* X.509 id-ce */
|
2008-06-26 19:09:07 +00:00
|
|
|
|
{ "2.5.29.14", "subjectKeyIdentifier", OID_FLAG_SKIP},
|
|
|
|
|
{ "2.5.29.15", "keyUsage", OID_FLAG_SKIP},
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{ "2.5.29.16", "privateKeyUsagePeriod" },
|
2008-06-26 19:09:07 +00:00
|
|
|
|
{ "2.5.29.17", "subjectAltName", OID_FLAG_SKIP},
|
|
|
|
|
{ "2.5.29.18", "issuerAltName", OID_FLAG_SKIP},
|
|
|
|
|
{ "2.5.29.19", "basicConstraints", OID_FLAG_SKIP},
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{ "2.5.29.20", "cRLNumber" },
|
|
|
|
|
{ "2.5.29.21", "cRLReason" },
|
|
|
|
|
{ "2.5.29.22", "expirationDate" },
|
2011-02-04 12:57:53 +01:00
|
|
|
|
{ "2.5.29.23", "instructionCode" },
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{ "2.5.29.24", "invalidityDate" },
|
|
|
|
|
{ "2.5.29.27", "deltaCRLIndicator" },
|
|
|
|
|
{ "2.5.29.28", "issuingDistributionPoint" },
|
|
|
|
|
{ "2.5.29.29", "certificateIssuer" },
|
|
|
|
|
{ "2.5.29.30", "nameConstraints" },
|
2008-06-26 19:09:07 +00:00
|
|
|
|
{ "2.5.29.31", "cRLDistributionPoints", OID_FLAG_SKIP},
|
|
|
|
|
{ "2.5.29.32", "certificatePolicies", OID_FLAG_SKIP},
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{ "2.5.29.32.0", "anyPolicy" },
|
|
|
|
|
{ "2.5.29.33", "policyMappings" },
|
2008-06-26 19:09:07 +00:00
|
|
|
|
{ "2.5.29.35", "authorityKeyIdentifier", OID_FLAG_SKIP},
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{ "2.5.29.36", "policyConstraints" },
|
2008-06-26 19:09:07 +00:00
|
|
|
|
{ "2.5.29.37", "extKeyUsage", OID_FLAG_SKIP},
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{ "2.5.29.46", "freshestCRL" },
|
|
|
|
|
{ "2.5.29.54", "inhibitAnyPolicy" },
|
|
|
|
|
|
|
|
|
|
/* Netscape certificate extensions. */
|
|
|
|
|
{ "2.16.840.1.113730.1.1", "netscape-cert-type" },
|
|
|
|
|
{ "2.16.840.1.113730.1.2", "netscape-base-url" },
|
|
|
|
|
{ "2.16.840.1.113730.1.3", "netscape-revocation-url" },
|
|
|
|
|
{ "2.16.840.1.113730.1.4", "netscape-ca-revocation-url" },
|
|
|
|
|
{ "2.16.840.1.113730.1.7", "netscape-cert-renewal-url" },
|
|
|
|
|
{ "2.16.840.1.113730.1.8", "netscape-ca-policy-url" },
|
|
|
|
|
{ "2.16.840.1.113730.1.9", "netscape-homePage-url" },
|
|
|
|
|
{ "2.16.840.1.113730.1.10", "netscape-entitylogo" },
|
|
|
|
|
{ "2.16.840.1.113730.1.11", "netscape-userPicture" },
|
|
|
|
|
{ "2.16.840.1.113730.1.12", "netscape-ssl-server-name" },
|
|
|
|
|
{ "2.16.840.1.113730.1.13", "netscape-comment" },
|
|
|
|
|
|
2005-11-13 19:07:06 +00:00
|
|
|
|
/* GnuPG extensions */
|
|
|
|
|
{ "1.3.6.1.4.1.11591.2.1.1", "pkaAddress" },
|
2011-03-01 14:42:56 +01:00
|
|
|
|
{ "1.3.6.1.4.1.11591.2.2.1", "standaloneCertificate" },
|
2011-12-06 19:57:27 +01:00
|
|
|
|
{ "1.3.6.1.4.1.11591.2.2.2", "wellKnownPrivateKey" },
|
2005-11-13 19:07:06 +00:00
|
|
|
|
|
2007-08-10 16:52:05 +00:00
|
|
|
|
/* Extensions used by the Bundesnetzagentur. */
|
|
|
|
|
{ "1.3.6.1.4.1.8301.3.5", "validityModel" },
|
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{ NULL }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2011-02-04 12:57:53 +01:00
|
|
|
|
/* Return the description for OID; if no description is available
|
2004-04-23 10:34:25 +00:00
|
|
|
|
NULL is returned. */
|
|
|
|
|
static const char *
|
|
|
|
|
get_oid_desc (const char *oid, unsigned int *flag)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (oid)
|
|
|
|
|
for (i=0; oidtranstbl[i].oid; i++)
|
|
|
|
|
if (!strcmp (oidtranstbl[i].oid, oid))
|
|
|
|
|
{
|
|
|
|
|
if (flag)
|
|
|
|
|
*flag = oidtranstbl[i].flag;
|
|
|
|
|
return oidtranstbl[i].name;
|
|
|
|
|
}
|
|
|
|
|
if (flag)
|
|
|
|
|
*flag = 0;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
static void
|
2007-03-19 14:35:04 +00:00
|
|
|
|
print_key_data (ksba_cert_t cert, estream_t fp)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2011-02-04 12:57:53 +01:00
|
|
|
|
#if 0
|
2003-08-05 17:11:04 +00:00
|
|
|
|
int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
|
|
|
|
|
int i;
|
|
|
|
|
|
2011-02-04 12:57:53 +01:00
|
|
|
|
for(i=0; i < n; i++ )
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
|
2003-08-05 17:11:04 +00:00
|
|
|
|
mpi_print(stdout, pk->pkey[i], 1 );
|
|
|
|
|
putchar(':');
|
|
|
|
|
putchar('\n');
|
|
|
|
|
}
|
2008-10-20 13:53:23 +00:00
|
|
|
|
#else
|
|
|
|
|
(void)cert;
|
|
|
|
|
(void)fp;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2007-03-19 14:35:04 +00:00
|
|
|
|
print_capabilities (ksba_cert_t cert, estream_t fp)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2003-12-17 12:28:24 +00:00
|
|
|
|
gpg_error_t err;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
unsigned int use;
|
2005-11-13 19:07:06 +00:00
|
|
|
|
size_t buflen;
|
|
|
|
|
char buffer[1];
|
|
|
|
|
|
2011-02-04 12:57:53 +01:00
|
|
|
|
err = ksba_cert_get_user_data (cert, "is_qualified",
|
2005-11-13 19:07:06 +00:00
|
|
|
|
&buffer, sizeof (buffer), &buflen);
|
|
|
|
|
if (!err && buflen)
|
|
|
|
|
{
|
|
|
|
|
if (*buffer)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('q', fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
}
|
2005-11-13 19:07:06 +00:00
|
|
|
|
else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
|
|
|
|
|
; /* Don't know - will not get marked as 'q' */
|
|
|
|
|
else
|
|
|
|
|
log_debug ("get_user_data(is_qualified) failed: %s\n",
|
2011-02-04 12:57:53 +01:00
|
|
|
|
gpg_strerror (err));
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
|
|
|
|
err = ksba_cert_get_key_usage (cert, &use);
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('e', fp);
|
|
|
|
|
es_putc ('s', fp);
|
|
|
|
|
es_putc ('c', fp);
|
|
|
|
|
es_putc ('E', fp);
|
|
|
|
|
es_putc ('S', fp);
|
|
|
|
|
es_putc ('C', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (err)
|
2011-02-04 12:57:53 +01:00
|
|
|
|
{
|
2003-08-05 17:11:04 +00:00
|
|
|
|
log_error (_("error getting key usage information: %s\n"),
|
2003-11-12 15:17:44 +00:00
|
|
|
|
gpg_strerror (err));
|
2003-08-05 17:11:04 +00:00
|
|
|
|
return;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
}
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
|
|
|
|
if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('e', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('s', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('c', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('E', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('S', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('C', fp);
|
2009-07-29 16:05:49 +00:00
|
|
|
|
|
|
|
|
|
es_putc (':', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2007-03-19 14:35:04 +00:00
|
|
|
|
print_time (gnupg_isotime_t t, estream_t fp)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2003-10-31 12:12:47 +00:00
|
|
|
|
if (!t || !*t)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (t, fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-07-20 15:05:05 +00:00
|
|
|
|
/* Return an allocated string with the email address extracted from a
|
2008-03-13 08:46:08 +00:00
|
|
|
|
DN. Note hat we use this code also in ../kbx/keybox-blob.c. */
|
2003-08-05 17:11:04 +00:00
|
|
|
|
static char *
|
|
|
|
|
email_kludge (const char *name)
|
|
|
|
|
{
|
2005-07-20 15:05:05 +00:00
|
|
|
|
const char *p, *string;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
unsigned char *buf;
|
|
|
|
|
int n;
|
|
|
|
|
|
2005-07-20 15:05:05 +00:00
|
|
|
|
string = name;
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
p = strstr (string, "1.2.840.113549.1.9.1=#");
|
|
|
|
|
if (!p)
|
|
|
|
|
return NULL;
|
|
|
|
|
if (p == name || (p > string+1 && p[-1] == ',' && p[-2] != '\\'))
|
|
|
|
|
{
|
|
|
|
|
name = p + 22;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
string = p + 22;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
/* 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,
|
2008-03-13 08:46:08 +00:00
|
|
|
|
OpenSSL generated keys get a nicer and usable listing. */
|
2003-08-05 17:11:04 +00:00
|
|
|
|
for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
|
|
|
|
|
;
|
2005-07-20 15:05:05 +00:00
|
|
|
|
if (!n)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
buf = xtrymalloc (n+3);
|
|
|
|
|
if (!buf)
|
|
|
|
|
return NULL; /* oops, out of core */
|
|
|
|
|
*buf = '<';
|
2005-07-20 15:05:05 +00:00
|
|
|
|
for (n=1, p=name; hexdigitp (p); p +=2, n++)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
buf[n] = xtoi_2 (p);
|
|
|
|
|
buf[n++] = '>';
|
|
|
|
|
buf[n] = 0;
|
2005-06-16 08:12:03 +00:00
|
|
|
|
return (char*)buf;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* List one certificate in colon mode */
|
|
|
|
|
static void
|
2004-02-17 15:05:04 +00:00
|
|
|
|
list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
|
2007-03-19 14:35:04 +00:00
|
|
|
|
estream_t fp, int have_secret)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2004-05-11 19:11:53 +00:00
|
|
|
|
int rc;
|
2004-02-17 15:05:04 +00:00
|
|
|
|
int idx;
|
|
|
|
|
char truststring[2];
|
2003-08-05 17:11:04 +00:00
|
|
|
|
char *p;
|
2003-12-17 12:28:24 +00:00
|
|
|
|
ksba_sexp_t sexp;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
char *fpr;
|
2003-10-31 12:12:47 +00:00
|
|
|
|
ksba_isotime_t t;
|
2004-02-17 15:05:04 +00:00
|
|
|
|
gpg_error_t valerr;
|
2004-05-11 15:36:48 +00:00
|
|
|
|
int algo;
|
|
|
|
|
unsigned int nbits;
|
2004-05-11 19:11:53 +00:00
|
|
|
|
const char *chain_id;
|
|
|
|
|
char *chain_id_buffer = NULL;
|
|
|
|
|
int is_root = 0;
|
2007-08-10 16:52:05 +00:00
|
|
|
|
char *kludge_uid;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2004-02-17 15:05:04 +00:00
|
|
|
|
if (ctrl->with_validation)
|
2007-08-10 16:52:05 +00:00
|
|
|
|
valerr = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, NULL, 0, NULL);
|
2004-02-02 17:09:35 +00:00
|
|
|
|
else
|
2004-02-17 15:05:04 +00:00
|
|
|
|
valerr = 0;
|
|
|
|
|
|
2004-05-11 19:11:53 +00:00
|
|
|
|
|
|
|
|
|
/* We need to get the fingerprint and the chaining ID in advance. */
|
|
|
|
|
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
|
|
|
|
|
{
|
|
|
|
|
ksba_cert_t next;
|
|
|
|
|
|
2008-02-13 16:47:14 +00:00
|
|
|
|
rc = gpgsm_walk_cert_chain (ctrl, cert, &next);
|
2004-05-11 19:11:53 +00:00
|
|
|
|
if (!rc) /* We known the issuer's certificate. */
|
|
|
|
|
{
|
|
|
|
|
p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
|
|
|
|
|
chain_id_buffer = p;
|
|
|
|
|
chain_id = chain_id_buffer;
|
|
|
|
|
ksba_cert_release (next);
|
|
|
|
|
}
|
|
|
|
|
else if (rc == -1) /* We have reached the root certificate. */
|
|
|
|
|
{
|
|
|
|
|
chain_id = fpr;
|
|
|
|
|
is_root = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
chain_id = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (have_secret? "crs:":"crt:", fp);
|
2004-09-30 13:24:33 +00:00
|
|
|
|
|
|
|
|
|
/* Note: We can't use multiple flags, like "ei", because the
|
|
|
|
|
validation check does only return one error. */
|
2004-02-17 15:05:04 +00:00
|
|
|
|
truststring[0] = 0;
|
|
|
|
|
truststring[1] = 0;
|
|
|
|
|
if ((validity & VALIDITY_REVOKED)
|
|
|
|
|
|| gpg_err_code (valerr) == GPG_ERR_CERT_REVOKED)
|
|
|
|
|
*truststring = 'r';
|
|
|
|
|
else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED)
|
|
|
|
|
*truststring = 'e';
|
2011-02-04 12:57:53 +01:00
|
|
|
|
else
|
2004-03-15 08:39:48 +00:00
|
|
|
|
{
|
|
|
|
|
/* Lets also check whether the certificate under question
|
|
|
|
|
expired. This is merely a hack until we found a proper way
|
|
|
|
|
to store the expiration flag in the keybox. */
|
|
|
|
|
ksba_isotime_t current_time, not_after;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2004-03-15 08:39:48 +00:00
|
|
|
|
gnupg_get_isotime (current_time);
|
|
|
|
|
if (!opt.ignore_expiration
|
|
|
|
|
&& !ksba_cert_get_validity (cert, 1, not_after)
|
|
|
|
|
&& *not_after && strcmp (current_time, not_after) > 0 )
|
|
|
|
|
*truststring = 'e';
|
2004-09-30 13:24:33 +00:00
|
|
|
|
else if (valerr)
|
2011-12-07 16:15:15 +01:00
|
|
|
|
{
|
|
|
|
|
if (gpgsm_cert_has_well_known_private_key (cert))
|
|
|
|
|
*truststring = 'w'; /* Well, this is dummy CA. */
|
|
|
|
|
else
|
|
|
|
|
*truststring = 'i';
|
|
|
|
|
}
|
2008-08-13 15:41:48 +00:00
|
|
|
|
else if (ctrl->with_validation && !is_root)
|
|
|
|
|
*truststring = 'f';
|
2004-03-15 08:39:48 +00:00
|
|
|
|
}
|
2004-05-11 19:11:53 +00:00
|
|
|
|
|
2006-09-25 18:29:20 +00:00
|
|
|
|
/* If we have no truststring yet (i.e. the certificate might be
|
2004-05-11 19:11:53 +00:00
|
|
|
|
good) and this is a root certificate, we ask the agent whether
|
|
|
|
|
this is a trusted root certificate. */
|
|
|
|
|
if (!*truststring && is_root)
|
|
|
|
|
{
|
2006-09-25 18:29:20 +00:00
|
|
|
|
struct rootca_flags_s dummy_flags;
|
|
|
|
|
|
2011-12-07 16:15:15 +01:00
|
|
|
|
if (gpgsm_cert_has_well_known_private_key (cert))
|
|
|
|
|
*truststring = 'w'; /* Well, this is dummy CA. */
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rc = gpgsm_agent_istrusted (ctrl, cert, NULL, &dummy_flags);
|
|
|
|
|
if (!rc)
|
|
|
|
|
*truststring = 'u'; /* Yes, we trust this one (ultimately). */
|
|
|
|
|
else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
|
|
|
|
|
*truststring = 'n'; /* No, we do not trust this one. */
|
|
|
|
|
/* (in case of an error we can't tell anything.) */
|
|
|
|
|
}
|
2004-05-11 19:11:53 +00:00
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2004-02-17 15:05:04 +00:00
|
|
|
|
if (*truststring)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (truststring, fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2004-05-11 15:36:48 +00:00
|
|
|
|
algo = gpgsm_get_key_algo_info (cert, &nbits);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2003-10-31 12:12:47 +00:00
|
|
|
|
ksba_cert_get_validity (cert, 0, t);
|
|
|
|
|
print_time (t, fp);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc (':', fp);
|
2003-10-31 12:12:47 +00:00
|
|
|
|
ksba_cert_get_validity (cert, 1, t);
|
|
|
|
|
print_time ( t, fp);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc (':', fp);
|
2004-03-15 08:39:48 +00:00
|
|
|
|
/* Field 8, serial number: */
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ((sexp = ksba_cert_get_serial (cert)))
|
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
const unsigned char *s = sexp;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2003-08-05 17:11:04 +00: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++)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp,"%02X", *s);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
xfree (sexp);
|
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc (':', fp);
|
2004-03-15 08:39:48 +00:00
|
|
|
|
/* Field 9, ownertrust - not used here */
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc (':', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
/* field 10, old user ID - we use it here for the issuer DN */
|
|
|
|
|
if ((p = ksba_cert_get_issuer (cert,0)))
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_write_sanitized (fp, p, strlen (p), ":", NULL);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc (':', fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
/* Field 11, signature class - not used */
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc (':', fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
/* Field 12, capabilities: */
|
2003-08-05 17:11:04 +00:00
|
|
|
|
print_capabilities (cert, fp);
|
2009-03-06 17:31:27 +00:00
|
|
|
|
/* Field 13, not used: */
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc (':', fp);
|
2014-06-03 21:35:59 +02:00
|
|
|
|
if (have_secret || ctrl->with_secret)
|
2009-03-06 17:31:27 +00:00
|
|
|
|
{
|
|
|
|
|
char *cardsn;
|
|
|
|
|
|
|
|
|
|
p = gpgsm_get_keygrip_hexstring (cert);
|
2014-06-03 21:35:59 +02:00
|
|
|
|
if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn)
|
|
|
|
|
&& (cardsn || ctrl->with_secret))
|
2009-03-06 17:31:27 +00:00
|
|
|
|
{
|
|
|
|
|
/* Field 14, not used: */
|
|
|
|
|
es_putc (':', fp);
|
2014-06-03 21:35:59 +02:00
|
|
|
|
/* Field 15: Token serial number or secret key indicator. */
|
|
|
|
|
if (cardsn)
|
|
|
|
|
es_fputs (cardsn, fp);
|
|
|
|
|
else if (ctrl->with_secret)
|
|
|
|
|
es_putc ('+', fp);
|
2009-03-06 17:31:27 +00:00
|
|
|
|
es_putc (':', fp);
|
|
|
|
|
}
|
|
|
|
|
xfree (cardsn);
|
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
|
|
|
|
/* FPR record */
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "fpr:::::::::%s:::", fpr);
|
2004-03-15 08:39:48 +00:00
|
|
|
|
/* Print chaining ID (field 13)*/
|
2004-05-11 19:11:53 +00:00
|
|
|
|
if (chain_id)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (chain_id, fp);
|
|
|
|
|
es_putc (':', fp);
|
|
|
|
|
es_putc ('\n', fp);
|
2004-05-11 19:11:53 +00:00
|
|
|
|
xfree (fpr); fpr = NULL; chain_id = NULL;
|
|
|
|
|
xfree (chain_id_buffer); chain_id_buffer = NULL;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
|
|
|
|
if (opt.with_key_data)
|
|
|
|
|
{
|
|
|
|
|
if ( (p = gpgsm_get_keygrip_hexstring (cert)))
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "grp:::::::::%s:\n", p);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
|
|
|
|
print_key_data (cert, fp);
|
|
|
|
|
}
|
|
|
|
|
|
2007-08-10 16:52:05 +00:00
|
|
|
|
kludge_uid = NULL;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
|
|
|
|
|
{
|
2008-01-26 22:12:23 +00:00
|
|
|
|
/* In the case that the same email address is in the subject DN
|
|
|
|
|
as well as in an alternate subject name we avoid printing it
|
2007-08-10 16:52:05 +00:00
|
|
|
|
a second time. */
|
|
|
|
|
if (kludge_uid && !strcmp (kludge_uid, p))
|
|
|
|
|
continue;
|
|
|
|
|
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "uid:%s::::::::", truststring);
|
|
|
|
|
es_write_sanitized (fp, p, strlen (p), ":", NULL);
|
|
|
|
|
es_putc (':', fp);
|
|
|
|
|
es_putc (':', fp);
|
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00: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 */
|
2007-08-10 16:52:05 +00:00
|
|
|
|
kludge_uid = email_kludge (p);
|
|
|
|
|
if (kludge_uid)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "uid:%s::::::::", truststring);
|
2007-08-10 16:52:05 +00:00
|
|
|
|
es_write_sanitized (fp, kludge_uid, strlen (kludge_uid),
|
|
|
|
|
":", NULL);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc (':', fp);
|
|
|
|
|
es_putc (':', fp);
|
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
2007-08-10 16:52:05 +00:00
|
|
|
|
xfree (kludge_uid);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
static void
|
2007-03-19 14:35:04 +00:00
|
|
|
|
print_name_raw (estream_t fp, const char *string)
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{
|
|
|
|
|
if (!string)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("[error]", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_write_sanitized (fp, string, strlen (string), NULL, NULL);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2007-03-19 14:35:04 +00:00
|
|
|
|
print_names_raw (estream_t fp, int indent, ksba_name_t name)
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{
|
|
|
|
|
int idx;
|
|
|
|
|
const char *s;
|
|
|
|
|
int indent_all;
|
|
|
|
|
|
|
|
|
|
if ((indent_all = (indent < 0)))
|
|
|
|
|
indent = - indent;
|
|
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("none\n", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
|
|
|
|
|
{
|
|
|
|
|
char *p = ksba_name_get_uri (name, idx);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "%*s", idx||indent_all?indent:0, "");
|
|
|
|
|
es_write_sanitized (fp, p?p:s, strlen (p?p:s), NULL, NULL);
|
|
|
|
|
es_putc ('\n', fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-06-26 19:09:07 +00:00
|
|
|
|
static void
|
2011-02-04 12:57:53 +01:00
|
|
|
|
print_utf8_extn_raw (estream_t fp, int indent,
|
2008-06-26 19:09:07 +00:00
|
|
|
|
const unsigned char *der, size_t derlen)
|
|
|
|
|
{
|
|
|
|
|
gpg_error_t err;
|
|
|
|
|
int class, tag, constructed, ndef;
|
|
|
|
|
size_t objlen, hdrlen;
|
|
|
|
|
|
|
|
|
|
if (indent < 0)
|
|
|
|
|
indent = - indent;
|
|
|
|
|
|
|
|
|
|
err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
|
|
|
|
|
&ndef, &objlen, &hdrlen);
|
|
|
|
|
if (!err && (objlen > derlen || tag != TAG_UTF8_STRING))
|
|
|
|
|
err = gpg_error (GPG_ERR_INV_OBJ);
|
|
|
|
|
if (err)
|
|
|
|
|
{
|
|
|
|
|
es_fprintf (fp, "%*s[%s]\n", indent, "", gpg_strerror (err));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-01-12 10:08:55 +00:00
|
|
|
|
es_fprintf (fp, "%*s(%.*s)\n", indent, "", (int)objlen, der);
|
2008-06-26 19:09:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2011-02-04 12:57:53 +01:00
|
|
|
|
print_utf8_extn (estream_t fp, int indent,
|
2008-06-26 19:09:07 +00:00
|
|
|
|
const unsigned char *der, size_t derlen)
|
|
|
|
|
{
|
|
|
|
|
gpg_error_t err;
|
|
|
|
|
int class, tag, constructed, ndef;
|
|
|
|
|
size_t objlen, hdrlen;
|
|
|
|
|
int indent_all;
|
|
|
|
|
|
|
|
|
|
if ((indent_all = (indent < 0)))
|
|
|
|
|
indent = - indent;
|
|
|
|
|
|
|
|
|
|
err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
|
|
|
|
|
&ndef, &objlen, &hdrlen);
|
|
|
|
|
if (!err && (objlen > derlen || tag != TAG_UTF8_STRING))
|
|
|
|
|
err = gpg_error (GPG_ERR_INV_OBJ);
|
|
|
|
|
if (err)
|
|
|
|
|
{
|
2008-06-26 19:21:45 +00:00
|
|
|
|
es_fprintf (fp, "%*s[%s%s]\n",
|
|
|
|
|
indent_all? indent:0, "", _("Error - "), gpg_strerror (err));
|
2008-06-26 19:09:07 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
es_fprintf (fp, "%*s\"", indent_all? indent:0, "");
|
|
|
|
|
/* Fixme: we should implement word wrapping */
|
|
|
|
|
es_write_sanitized (fp, der, objlen, "\"", NULL);
|
|
|
|
|
es_fputs ("\"\n", fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-04-22 13:03:44 +00:00
|
|
|
|
/* List one certificate in raw mode useful to have a closer look at
|
2004-07-22 09:37:36 +00:00
|
|
|
|
the certificate. This one does no beautification and only minimal
|
2004-04-22 13:03:44 +00:00
|
|
|
|
output sanitation. It is mainly useful for debugging. */
|
|
|
|
|
static void
|
2004-08-06 16:14:10 +00:00
|
|
|
|
list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
|
2007-03-19 14:35:04 +00:00
|
|
|
|
ksba_cert_t cert, estream_t fp, int have_secret,
|
2004-04-22 13:03:44 +00:00
|
|
|
|
int with_validation)
|
|
|
|
|
{
|
|
|
|
|
gpg_error_t err;
|
2004-04-23 10:34:25 +00:00
|
|
|
|
size_t off, len;
|
2005-04-18 10:44:46 +00:00
|
|
|
|
ksba_sexp_t sexp, keyid;
|
2004-04-22 13:03:44 +00:00
|
|
|
|
char *dn;
|
|
|
|
|
ksba_isotime_t t;
|
|
|
|
|
int idx, i;
|
|
|
|
|
int is_ca, chainlen;
|
|
|
|
|
unsigned int kusage;
|
|
|
|
|
char *string, *p, *pend;
|
2004-04-23 10:34:25 +00:00
|
|
|
|
const char *oid, *s;
|
|
|
|
|
ksba_name_t name, name2;
|
|
|
|
|
unsigned int reason;
|
2008-06-26 19:09:07 +00:00
|
|
|
|
const unsigned char *cert_der = NULL;
|
2004-04-22 13:03:44 +00:00
|
|
|
|
|
2008-10-20 13:53:23 +00:00
|
|
|
|
(void)have_secret;
|
|
|
|
|
|
2007-08-10 16:52:05 +00:00
|
|
|
|
es_fprintf (fp, " ID: 0x%08lX\n",
|
2009-03-25 16:05:16 +00:00
|
|
|
|
gpgsm_get_short_fingerprint (cert, NULL));
|
2007-08-10 16:52:05 +00:00
|
|
|
|
|
2004-04-22 13:03:44 +00:00
|
|
|
|
sexp = ksba_cert_get_serial (cert);
|
2007-08-10 16:52:05 +00:00
|
|
|
|
es_fputs (" S/N: ", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
gpgsm_print_serial (fp, sexp);
|
|
|
|
|
ksba_free (sexp);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
|
|
|
|
|
dn = ksba_cert_get_issuer (cert, 0);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" Issuer: ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
print_name_raw (fp, dn);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
ksba_free (dn);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" aka: ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
print_name_raw (fp, dn);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
ksba_free (dn);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dn = ksba_cert_get_subject (cert, 0);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" Subject: ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
print_name_raw (fp, dn);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
ksba_free (dn);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" aka: ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
print_name_raw (fp, dn);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
ksba_free (dn);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
dn = gpgsm_get_fingerprint_string (cert, 0);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " sha1_fpr: %s\n", dn?dn:"error");
|
2004-04-23 10:34:25 +00:00
|
|
|
|
xfree (dn);
|
|
|
|
|
|
|
|
|
|
dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " md5_fpr: %s\n", dn?dn:"error");
|
2004-04-23 10:34:25 +00:00
|
|
|
|
xfree (dn);
|
|
|
|
|
|
2006-06-20 17:21:37 +00:00
|
|
|
|
dn = gpgsm_get_certid (cert);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " certid: %s\n", dn?dn:"error");
|
2006-06-20 17:21:37 +00:00
|
|
|
|
xfree (dn);
|
|
|
|
|
|
2004-07-22 09:37:36 +00:00
|
|
|
|
dn = gpgsm_get_keygrip_hexstring (cert);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " keygrip: %s\n", dn?dn:"error");
|
2004-07-22 09:37:36 +00:00
|
|
|
|
xfree (dn);
|
|
|
|
|
|
2004-04-22 13:03:44 +00:00
|
|
|
|
ksba_cert_get_validity (cert, 0, t);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" notBefore: ", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
gpgsm_print_time (fp, t);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
|
|
|
|
es_fputs (" notAfter: ", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
ksba_cert_get_validity (cert, 1, t);
|
|
|
|
|
gpgsm_print_time (fp, t);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
oid = ksba_cert_get_digest_algo (cert);
|
|
|
|
|
s = get_oid_desc (oid, NULL);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " hashAlgo: %s%s%s%s\n", oid, s?" (":"",s?s:"",s?")":"");
|
2004-04-23 10:34:25 +00:00
|
|
|
|
|
2004-05-11 15:36:48 +00:00
|
|
|
|
{
|
|
|
|
|
const char *algoname;
|
|
|
|
|
unsigned int nbits;
|
|
|
|
|
|
|
|
|
|
algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " keyType: %u bit %s\n",
|
|
|
|
|
nbits, algoname? algoname:"?");
|
2004-05-11 15:36:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-04-18 10:44:46 +00:00
|
|
|
|
/* subjectKeyIdentifier */
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" subjKeyId: ", fp);
|
2005-04-18 10:44:46 +00:00
|
|
|
|
err = ksba_cert_get_subj_key_id (cert, NULL, &keyid);
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
|
2005-04-18 10:44:46 +00:00
|
|
|
|
{
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("[none]\n", fp);
|
2005-04-18 10:44:46 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
gpgsm_print_serial (fp, keyid);
|
|
|
|
|
ksba_free (keyid);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2005-04-18 10:44:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("[?]\n", fp);
|
2005-04-18 10:44:46 +00:00
|
|
|
|
|
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
/* authorityKeyIdentifier */
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" authKeyId: ", fp);
|
2005-04-18 10:44:46 +00:00
|
|
|
|
err = ksba_cert_get_auth_key_id (cert, &keyid, &name, &sexp);
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
|
2004-04-23 10:34:25 +00:00
|
|
|
|
{
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("[none]\n", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
gpgsm_print_serial (fp, sexp);
|
|
|
|
|
ksba_free (sexp);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
print_names_raw (fp, -15, name);
|
|
|
|
|
ksba_name_release (name);
|
|
|
|
|
}
|
2005-04-18 10:44:46 +00:00
|
|
|
|
if (keyid)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" authKeyId.ki: ", fp);
|
2005-04-18 10:44:46 +00:00
|
|
|
|
gpgsm_print_serial (fp, keyid);
|
|
|
|
|
ksba_free (keyid);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2005-04-18 10:44:46 +00:00
|
|
|
|
}
|
2004-04-23 10:34:25 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("[?]\n", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" keyUsage:", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
err = ksba_cert_get_key_usage (cert, &kusage);
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (gpg_err_code (err) != GPG_ERR_NO_DATA)
|
2004-04-22 13:03:44 +00:00
|
|
|
|
{
|
|
|
|
|
if (err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " [error: %s]", gpg_strerror (err));
|
2004-04-22 13:03:44 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" digitalSignature", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" nonRepudiation", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" keyEncipherment", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" dataEncipherment", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" keyAgreement", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" certSign", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" crlSign", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" encipherOnly", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" decipherOnly", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
2004-04-23 10:34:25 +00:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" [none]\n", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" extKeyUsage: ", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
err = ksba_cert_get_ext_key_usages (cert, &string);
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (gpg_err_code (err) != GPG_ERR_NO_DATA)
|
2011-02-04 12:57:53 +01:00
|
|
|
|
{
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if (err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "[error: %s]", gpg_strerror (err));
|
2004-04-22 13:03:44 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
p = string;
|
|
|
|
|
while (p && (pend=strchr (p, ':')))
|
|
|
|
|
{
|
|
|
|
|
*pend++ = 0;
|
|
|
|
|
for (i=0; key_purpose_map[i].oid; i++)
|
|
|
|
|
if ( !strcmp (key_purpose_map[i].oid, p) )
|
|
|
|
|
break;
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
p = pend;
|
|
|
|
|
if (*p != 'C')
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" (suggested)", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if ((p = strchr (p, '\n')))
|
|
|
|
|
{
|
|
|
|
|
p++;
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("\n ", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
xfree (string);
|
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
2004-04-23 10:34:25 +00:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("[none]\n", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" policies: ", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
err = ksba_cert_get_cert_policies (cert, &string);
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (gpg_err_code (err) != GPG_ERR_NO_DATA)
|
2004-04-22 13:03:44 +00:00
|
|
|
|
{
|
|
|
|
|
if (err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "[error: %s]", gpg_strerror (err));
|
2004-04-22 13:03:44 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2004-04-23 10:34:25 +00:00
|
|
|
|
p = string;
|
|
|
|
|
while (p && (pend=strchr (p, ':')))
|
2004-04-22 13:03:44 +00:00
|
|
|
|
{
|
2004-04-23 10:34:25 +00:00
|
|
|
|
*pend++ = 0;
|
|
|
|
|
for (i=0; key_purpose_map[i].oid; i++)
|
|
|
|
|
if ( !strcmp (key_purpose_map[i].oid, p) )
|
|
|
|
|
break;
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (p, fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
p = pend;
|
|
|
|
|
if (*p == 'C')
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" (critical)", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
if ((p = strchr (p, '\n')))
|
|
|
|
|
{
|
|
|
|
|
p++;
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("\n ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
}
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
|
|
|
|
xfree (string);
|
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
2004-04-23 10:34:25 +00:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("[none]\n", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" chainLength: ", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
|
|
|
|
|
if (err || is_ca)
|
|
|
|
|
{
|
2006-10-18 17:19:08 +00:00
|
|
|
|
if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "[none]");
|
2006-10-18 17:19:08 +00:00
|
|
|
|
else if (err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "[error: %s]", gpg_strerror (err));
|
2004-04-22 13:03:44 +00:00
|
|
|
|
else if (chainlen == -1)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("unlimited", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "%d", chainlen);
|
|
|
|
|
es_putc ('\n', fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
2004-04-23 10:34:25 +00:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("not a CA\n", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
|
|
|
|
|
|
2004-04-23 10:34:25 +00:00
|
|
|
|
/* CRL distribution point */
|
|
|
|
|
for (idx=0; !(err=ksba_cert_get_crl_dist_point (cert, idx, &name, &name2,
|
|
|
|
|
&reason)) ;idx++)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" crlDP: ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
print_names_raw (fp, 15, name);
|
|
|
|
|
if (reason)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" reason: ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
if ( (reason & KSBA_CRLREASON_UNSPECIFIED))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" unused", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
if ( (reason & KSBA_CRLREASON_KEY_COMPROMISE))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" keyCompromise", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
if ( (reason & KSBA_CRLREASON_CA_COMPROMISE))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" caCompromise", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
if ( (reason & KSBA_CRLREASON_AFFILIATION_CHANGED))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" affiliationChanged", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
if ( (reason & KSBA_CRLREASON_SUPERSEDED))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" superseded", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
if ( (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" cessationOfOperation", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
if ( (reason & KSBA_CRLREASON_CERTIFICATE_HOLD))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" certificateHold", fp);
|
|
|
|
|
es_putc ('\n', fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" issuer: ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
print_names_raw (fp, 23, name2);
|
|
|
|
|
ksba_name_release (name);
|
|
|
|
|
ksba_name_release (name2);
|
|
|
|
|
}
|
2006-10-18 17:19:08 +00:00
|
|
|
|
if (err && gpg_err_code (err) != GPG_ERR_EOF
|
|
|
|
|
&& gpg_err_code (err) != GPG_ERR_NO_VALUE)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" crlDP: [error]\n", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
else if (!idx)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" crlDP: [none]\n", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* authorityInfoAccess. */
|
|
|
|
|
for (idx=0; !(err=ksba_cert_get_authority_info_access (cert, idx, &string,
|
|
|
|
|
&name)); idx++)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" authInfo: ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
s = get_oid_desc (string, NULL);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
|
2004-04-23 10:34:25 +00:00
|
|
|
|
print_names_raw (fp, -15, name);
|
|
|
|
|
ksba_name_release (name);
|
|
|
|
|
ksba_free (string);
|
|
|
|
|
}
|
2006-10-18 17:19:08 +00:00
|
|
|
|
if (err && gpg_err_code (err) != GPG_ERR_EOF
|
|
|
|
|
&& gpg_err_code (err) != GPG_ERR_NO_VALUE)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" authInfo: [error]\n", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
else if (!idx)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" authInfo: [none]\n", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
|
|
|
|
|
/* subjectInfoAccess. */
|
|
|
|
|
for (idx=0; !(err=ksba_cert_get_subject_info_access (cert, idx, &string,
|
|
|
|
|
&name)); idx++)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" subjectInfo: ", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
s = get_oid_desc (string, NULL);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
|
2004-04-23 10:34:25 +00:00
|
|
|
|
print_names_raw (fp, -15, name);
|
|
|
|
|
ksba_name_release (name);
|
|
|
|
|
ksba_free (string);
|
|
|
|
|
}
|
2006-10-18 17:19:08 +00:00
|
|
|
|
if (err && gpg_err_code (err) != GPG_ERR_EOF
|
|
|
|
|
&& gpg_err_code (err) != GPG_ERR_NO_VALUE)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" subjInfo: [error]\n", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
else if (!idx)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" subjInfo: [none]\n", fp);
|
2004-04-23 10:34:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
|
|
|
|
|
&oid, &i, &off, &len));idx++)
|
|
|
|
|
{
|
|
|
|
|
unsigned int flag;
|
|
|
|
|
|
|
|
|
|
s = get_oid_desc (oid, &flag);
|
2008-06-26 19:09:07 +00:00
|
|
|
|
if ((flag & OID_FLAG_SKIP))
|
|
|
|
|
continue;
|
2004-04-23 10:34:25 +00:00
|
|
|
|
|
2008-06-26 19:09:07 +00:00
|
|
|
|
es_fprintf (fp, " %s: %s%s%s%s [%d octets]\n",
|
|
|
|
|
i? "critExtn":" extn",
|
|
|
|
|
oid, s?" (":"", s?s:"", s?")":"", (int)len);
|
|
|
|
|
if ((flag & OID_FLAG_UTF8))
|
|
|
|
|
{
|
|
|
|
|
if (!cert_der)
|
|
|
|
|
cert_der = ksba_cert_get_image (cert, NULL);
|
|
|
|
|
assert (cert_der);
|
|
|
|
|
print_utf8_extn_raw (fp, -15, cert_der+off, len);
|
|
|
|
|
}
|
2004-04-23 10:34:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-04-22 13:03:44 +00:00
|
|
|
|
|
|
|
|
|
if (with_validation)
|
|
|
|
|
{
|
2007-08-10 16:52:05 +00:00
|
|
|
|
err = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, fp, 0, NULL);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if (!err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " [certificate is good]\n");
|
2004-04-22 13:03:44 +00:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err));
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
2004-08-06 16:14:10 +00:00
|
|
|
|
|
2009-03-06 17:31:27 +00:00
|
|
|
|
if (hd)
|
2004-08-06 16:14:10 +00:00
|
|
|
|
{
|
|
|
|
|
unsigned int blobflags;
|
|
|
|
|
|
|
|
|
|
err = keydb_get_flags (hd, KEYBOX_FLAG_BLOB, 0, &blobflags);
|
|
|
|
|
if (err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " [error getting keyflags: %s]\n",gpg_strerror (err));
|
2007-03-20 16:57:40 +00:00
|
|
|
|
else if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " [stored as ephemeral]\n");
|
2004-08-06 16:14:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-04-22 13:03:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
/* List one certificate in standard mode */
|
|
|
|
|
static void
|
2007-03-19 14:35:04 +00:00
|
|
|
|
list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
|
2004-02-17 15:05:04 +00:00
|
|
|
|
int with_validation)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2004-02-17 15:05:04 +00:00
|
|
|
|
gpg_error_t err;
|
2003-12-17 12:28:24 +00:00
|
|
|
|
ksba_sexp_t sexp;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
char *dn;
|
2003-10-31 12:12:47 +00:00
|
|
|
|
ksba_isotime_t t;
|
2004-02-20 13:46:21 +00:00
|
|
|
|
int idx, i;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
int is_ca, chainlen;
|
|
|
|
|
unsigned int kusage;
|
2004-02-20 13:46:21 +00:00
|
|
|
|
char *string, *p, *pend;
|
2008-06-26 19:09:07 +00:00
|
|
|
|
size_t off, len;
|
|
|
|
|
const char *oid;
|
|
|
|
|
const unsigned char *cert_der = NULL;
|
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2007-08-10 16:52:05 +00:00
|
|
|
|
es_fprintf (fp, " ID: 0x%08lX\n",
|
2009-03-25 16:05:16 +00:00
|
|
|
|
gpgsm_get_short_fingerprint (cert, NULL));
|
2007-08-10 16:52:05 +00:00
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
sexp = ksba_cert_get_serial (cert);
|
2007-08-10 16:52:05 +00:00
|
|
|
|
es_fputs (" S/N: ", fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
gpgsm_print_serial (fp, sexp);
|
|
|
|
|
ksba_free (sexp);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
|
|
|
|
dn = ksba_cert_get_issuer (cert, 0);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" Issuer: ", fp);
|
|
|
|
|
gpgsm_es_print_name (fp, dn);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
ksba_free (dn);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" aka: ", fp);
|
|
|
|
|
gpgsm_es_print_name (fp, dn);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
ksba_free (dn);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dn = ksba_cert_get_subject (cert, 0);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" Subject: ", fp);
|
|
|
|
|
gpgsm_es_print_name (fp, dn);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
ksba_free (dn);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" aka: ", fp);
|
|
|
|
|
gpgsm_es_print_name (fp, dn);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
ksba_free (dn);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-10-31 12:12:47 +00:00
|
|
|
|
ksba_cert_get_validity (cert, 0, t);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" validity: ", fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
gpgsm_print_time (fp, t);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" through ", fp);
|
2003-10-31 12:12:47 +00:00
|
|
|
|
ksba_cert_get_validity (cert, 1, t);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
gpgsm_print_time (fp, t);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2004-05-11 15:36:48 +00:00
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
const char *algoname;
|
|
|
|
|
unsigned int nbits;
|
|
|
|
|
|
|
|
|
|
algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " key type: %u bit %s\n",
|
|
|
|
|
nbits, algoname? algoname:"?");
|
2004-05-11 15:36:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-02-17 15:05:04 +00:00
|
|
|
|
err = ksba_cert_get_key_usage (cert, &kusage);
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (gpg_err_code (err) != GPG_ERR_NO_DATA)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" key usage:", fp);
|
2004-02-17 15:05:04 +00:00
|
|
|
|
if (err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " [error: %s]", gpg_strerror (err));
|
2003-08-05 17:11:04 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" digitalSignature", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" nonRepudiation", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" keyEncipherment", fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" dataEncipherment", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" keyAgreement", fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" certSign", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" crlSign", fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" encipherOnly", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" decipherOnly", fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2004-02-20 13:46:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ksba_cert_get_ext_key_usages (cert, &string);
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (gpg_err_code (err) != GPG_ERR_NO_DATA)
|
2011-02-04 12:57:53 +01:00
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("ext key usage: ", fp);
|
2004-02-20 13:46:21 +00:00
|
|
|
|
if (err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "[error: %s]", gpg_strerror (err));
|
2004-02-20 13:46:21 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
p = string;
|
|
|
|
|
while (p && (pend=strchr (p, ':')))
|
|
|
|
|
{
|
|
|
|
|
*pend++ = 0;
|
|
|
|
|
for (i=0; key_purpose_map[i].oid; i++)
|
|
|
|
|
if ( !strcmp (key_purpose_map[i].oid, p) )
|
|
|
|
|
break;
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
|
2004-02-20 13:46:21 +00:00
|
|
|
|
p = pend;
|
|
|
|
|
if (*p != 'C')
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" (suggested)", fp);
|
2004-02-20 13:46:21 +00:00
|
|
|
|
if ((p = strchr (p, '\n')))
|
|
|
|
|
{
|
|
|
|
|
p++;
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (", ", fp);
|
2004-02-20 13:46:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
xfree (string);
|
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-06-26 19:09:07 +00:00
|
|
|
|
/* Print restrictions. */
|
|
|
|
|
for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
|
|
|
|
|
&oid, NULL, &off, &len));idx++)
|
|
|
|
|
{
|
|
|
|
|
if (!strcmp (oid, OIDSTR_restriction) )
|
|
|
|
|
{
|
|
|
|
|
if (!cert_der)
|
|
|
|
|
cert_der = ksba_cert_get_image (cert, NULL);
|
|
|
|
|
assert (cert_der);
|
|
|
|
|
es_fputs (" restriction: ", fp);
|
|
|
|
|
print_utf8_extn (fp, 15, cert_der+off, len);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Print policies. */
|
2004-02-17 15:05:04 +00:00
|
|
|
|
err = ksba_cert_get_cert_policies (cert, &string);
|
2007-07-04 19:49:40 +00:00
|
|
|
|
if (gpg_err_code (err) != GPG_ERR_NO_DATA)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" policies: ", fp);
|
2004-02-17 15:05:04 +00:00
|
|
|
|
if (err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "[error: %s]", gpg_strerror (err));
|
2003-08-05 17:11:04 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (p=string; *p; p++)
|
|
|
|
|
{
|
|
|
|
|
if (*p == '\n')
|
|
|
|
|
*p = ',';
|
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_write_sanitized (fp, string, strlen (string), NULL, NULL);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
xfree (string);
|
|
|
|
|
}
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-02-17 15:05:04 +00:00
|
|
|
|
err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
|
|
|
|
|
if (err || is_ca)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" chain length: ", fp);
|
2006-10-18 17:19:08 +00:00
|
|
|
|
if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "none");
|
2006-10-18 17:19:08 +00:00
|
|
|
|
else if (err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "[error: %s]", gpg_strerror (err));
|
2003-08-05 17:11:04 +00:00
|
|
|
|
else if (chainlen == -1)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("unlimited", fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "%d", chainlen);
|
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-02-17 15:05:04 +00:00
|
|
|
|
if (opt.with_md5_fingerprint)
|
|
|
|
|
{
|
|
|
|
|
dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " md5 fpr: %s\n", dn?dn:"error");
|
2004-02-17 15:05:04 +00:00
|
|
|
|
xfree (dn);
|
|
|
|
|
}
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
|
|
|
|
dn = gpgsm_get_fingerprint_string (cert, 0);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " fingerprint: %s\n", dn?dn:"error");
|
2003-08-05 17:11:04 +00:00
|
|
|
|
xfree (dn);
|
2004-02-17 15:05:04 +00:00
|
|
|
|
|
2010-10-08 11:11:08 +00:00
|
|
|
|
if (opt.with_keygrip)
|
|
|
|
|
{
|
|
|
|
|
dn = gpgsm_get_keygrip_hexstring (cert);
|
|
|
|
|
if (dn)
|
|
|
|
|
{
|
|
|
|
|
es_fprintf (fp, " keygrip: %s\n", dn);
|
|
|
|
|
xfree (dn);
|
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
}
|
2010-10-08 11:11:08 +00:00
|
|
|
|
|
2009-04-02 07:20:35 +00:00
|
|
|
|
if (have_secret)
|
|
|
|
|
{
|
|
|
|
|
char *cardsn;
|
2005-11-13 19:07:06 +00:00
|
|
|
|
|
2009-04-02 07:20:35 +00:00
|
|
|
|
p = gpgsm_get_keygrip_hexstring (cert);
|
|
|
|
|
if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn) && cardsn)
|
|
|
|
|
es_fprintf (fp, " card s/n: %s\n", cardsn);
|
|
|
|
|
xfree (cardsn);
|
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
2005-11-13 19:07:06 +00:00
|
|
|
|
|
2004-02-17 15:05:04 +00:00
|
|
|
|
if (with_validation)
|
|
|
|
|
{
|
2005-11-13 19:07:06 +00:00
|
|
|
|
gpg_error_t tmperr;
|
|
|
|
|
size_t buflen;
|
|
|
|
|
char buffer[1];
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2007-08-10 16:52:05 +00:00
|
|
|
|
err = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, fp, 0, NULL);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
tmperr = ksba_cert_get_user_data (cert, "is_qualified",
|
2005-11-13 19:07:06 +00:00
|
|
|
|
&buffer, sizeof (buffer), &buflen);
|
|
|
|
|
if (!tmperr && buflen)
|
|
|
|
|
{
|
|
|
|
|
if (*buffer)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs (" [qualified]\n", fp);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
}
|
2005-11-13 19:07:06 +00:00
|
|
|
|
else if (gpg_err_code (tmperr) == GPG_ERR_NOT_FOUND)
|
|
|
|
|
; /* Don't know - will not get marked as 'q' */
|
|
|
|
|
else
|
|
|
|
|
log_debug ("get_user_data(is_qualified) failed: %s\n",
|
2011-02-04 12:57:53 +01:00
|
|
|
|
gpg_strerror (tmperr));
|
2005-11-13 19:07:06 +00:00
|
|
|
|
|
2004-02-17 15:05:04 +00:00
|
|
|
|
if (!err)
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " [certificate is good]\n");
|
2004-02-17 15:05:04 +00:00
|
|
|
|
else
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err));
|
2004-02-17 15:05:04 +00:00
|
|
|
|
}
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-02-17 15:05:04 +00:00
|
|
|
|
|
|
|
|
|
/* Same as standard mode mode list all certifying certs too. */
|
2003-08-05 17:11:04 +00:00
|
|
|
|
static void
|
2004-08-06 16:14:10 +00:00
|
|
|
|
list_cert_chain (ctrl_t ctrl, KEYDB_HANDLE hd,
|
|
|
|
|
ksba_cert_t cert, int raw_mode,
|
2007-03-19 14:35:04 +00:00
|
|
|
|
estream_t fp, int with_validation)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2003-12-17 12:28:24 +00:00
|
|
|
|
ksba_cert_t next = NULL;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if (raw_mode)
|
2004-08-06 16:14:10 +00:00
|
|
|
|
list_cert_raw (ctrl, hd, cert, fp, 0, with_validation);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
else
|
|
|
|
|
list_cert_std (ctrl, cert, fp, 0, with_validation);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
ksba_cert_ref (cert);
|
2008-02-13 16:47:14 +00:00
|
|
|
|
while (!gpgsm_walk_cert_chain (ctrl, cert, &next))
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
|
|
|
|
ksba_cert_release (cert);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fputs ("Certified by\n", fp);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if (raw_mode)
|
2004-08-06 16:14:10 +00:00
|
|
|
|
list_cert_raw (ctrl, hd, next, fp, 0, with_validation);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
else
|
|
|
|
|
list_cert_std (ctrl, next, fp, 0, with_validation);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
cert = next;
|
|
|
|
|
}
|
|
|
|
|
ksba_cert_release (cert);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-04-22 13:03:44 +00:00
|
|
|
|
/* List all internal keys or just the keys given as NAMES. MODE is a
|
|
|
|
|
bit vector to specify what keys are to be included; see
|
|
|
|
|
gpgsm_list_keys (below) for details. If RAW_MODE is true, the raw
|
2006-09-13 15:57:30 +00:00
|
|
|
|
output mode will be used instead of the standard beautified one.
|
2003-08-05 17:11:04 +00:00
|
|
|
|
*/
|
2004-02-21 13:05:52 +00:00
|
|
|
|
static gpg_error_t
|
2007-03-19 14:35:04 +00:00
|
|
|
|
list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
|
2004-04-22 13:03:44 +00:00
|
|
|
|
unsigned int mode, int raw_mode)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
|
|
|
|
KEYDB_HANDLE hd;
|
|
|
|
|
KEYDB_SEARCH_DESC *desc = NULL;
|
2006-10-02 11:54:35 +00:00
|
|
|
|
strlist_t sl;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
int ndesc;
|
2003-12-17 12:28:24 +00:00
|
|
|
|
ksba_cert_t cert = NULL;
|
2008-01-30 17:21:28 +00:00
|
|
|
|
ksba_cert_t lastcert = NULL;
|
2004-02-21 13:05:52 +00:00
|
|
|
|
gpg_error_t rc = 0;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
const char *lastresname, *resname;
|
|
|
|
|
int have_secret;
|
2009-03-18 11:18:56 +00:00
|
|
|
|
int want_ephemeral = ctrl->with_ephemeral_keys;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2016-11-10 15:38:14 +01:00
|
|
|
|
hd = keydb_new ();
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if (!hd)
|
|
|
|
|
{
|
|
|
|
|
log_error ("keydb_new failed\n");
|
2004-02-21 13:05:52 +00:00
|
|
|
|
rc = gpg_error (GPG_ERR_GENERAL);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!names)
|
|
|
|
|
ndesc = 1;
|
|
|
|
|
else
|
|
|
|
|
{
|
2011-02-04 12:57:53 +01:00
|
|
|
|
for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
desc = xtrycalloc (ndesc, sizeof *desc);
|
|
|
|
|
if (!ndesc)
|
|
|
|
|
{
|
2006-09-14 16:50:33 +00:00
|
|
|
|
rc = gpg_error_from_syserror ();
|
2003-08-05 17:11:04 +00:00
|
|
|
|
log_error ("out of core\n");
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!names)
|
|
|
|
|
desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
else
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2011-02-04 12:57:53 +01:00
|
|
|
|
for (ndesc=0, sl=names; sl; sl = sl->next)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2011-04-25 23:56:47 +02:00
|
|
|
|
rc = classify_user_id (sl->d, desc+ndesc, 0);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if (rc)
|
|
|
|
|
{
|
2012-06-05 19:29:22 +02:00
|
|
|
|
log_error ("key '%s' not found: %s\n",
|
2003-08-05 17:11:04 +00:00
|
|
|
|
sl->d, gpg_strerror (rc));
|
|
|
|
|
rc = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ndesc++;
|
|
|
|
|
}
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-06 17:31:27 +00:00
|
|
|
|
/* If all specifications are done by fingerprint or keygrip, we
|
|
|
|
|
switch to ephemeral mode so that _all_ currently available and
|
|
|
|
|
matching certificates are listed. */
|
|
|
|
|
if (!want_ephemeral && names && ndesc)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i=0; (i < ndesc
|
|
|
|
|
&& (desc[i].mode == KEYDB_SEARCH_MODE_FPR
|
|
|
|
|
|| desc[i].mode == KEYDB_SEARCH_MODE_FPR20
|
|
|
|
|
|| desc[i].mode == KEYDB_SEARCH_MODE_FPR16
|
|
|
|
|
|| desc[i].mode == KEYDB_SEARCH_MODE_KEYGRIP)); i++)
|
|
|
|
|
;
|
|
|
|
|
if (i == ndesc)
|
|
|
|
|
want_ephemeral = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (want_ephemeral)
|
2004-08-06 16:14:10 +00:00
|
|
|
|
keydb_set_ephemeral (hd, 1);
|
|
|
|
|
|
2004-02-17 15:05:04 +00:00
|
|
|
|
/* It would be nice to see which of the given users did actually
|
2003-08-05 17:11:04 +00:00
|
|
|
|
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 */
|
|
|
|
|
|
2008-01-30 17:21:28 +00:00
|
|
|
|
/* Suppress duplicates at least when they follow each other. */
|
2003-08-05 17:11:04 +00:00
|
|
|
|
lastresname = NULL;
|
2016-11-10 17:01:19 +01:00
|
|
|
|
while (!(rc = keydb_search (ctrl, hd, desc, ndesc)))
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2004-02-02 17:09:35 +00:00
|
|
|
|
unsigned int validity;
|
|
|
|
|
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if (!names)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
|
|
|
|
|
|
2004-02-02 17:09:35 +00:00
|
|
|
|
rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
|
|
|
|
|
if (rc)
|
|
|
|
|
{
|
|
|
|
|
log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
2003-08-05 17:11:04 +00:00
|
|
|
|
rc = keydb_get_cert (hd, &cert);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if (rc)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
|
|
|
|
log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
2008-01-30 17:21:28 +00:00
|
|
|
|
/* Skip duplicated certificates, at least if they follow each
|
|
|
|
|
others. This works best if a single key is searched for and
|
|
|
|
|
expected. FIXME: Non-sequential duplicates remain. */
|
|
|
|
|
if (gpgsm_certs_identical_p (cert, lastcert))
|
|
|
|
|
{
|
|
|
|
|
ksba_cert_release (cert);
|
2009-03-20 19:04:47 +00:00
|
|
|
|
cert = NULL;
|
2008-01-30 17:21:28 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
resname = keydb_get_resource_name (hd);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
|
|
|
|
if (lastresname != resname )
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
|
|
|
|
int i;
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if (ctrl->no_server)
|
|
|
|
|
{
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (fp, "%s\n", resname );
|
2003-08-05 17:11:04 +00:00
|
|
|
|
for (i=strlen(resname); i; i-- )
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('-', fp);
|
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
lastresname = resname;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
have_secret = 0;
|
|
|
|
|
if (mode)
|
|
|
|
|
{
|
|
|
|
|
char *p = gpgsm_get_keygrip_hexstring (cert);
|
|
|
|
|
if (p)
|
|
|
|
|
{
|
2011-02-04 12:57:53 +01:00
|
|
|
|
rc = gpgsm_agent_havekey (ctrl, p);
|
2010-02-02 14:06:19 +00:00
|
|
|
|
if (!rc)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
have_secret = 1;
|
2004-02-21 13:05:52 +00:00
|
|
|
|
else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
|
|
|
|
|
goto leave;
|
|
|
|
|
rc = 0;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
xfree (p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-10 17:01:19 +01:00
|
|
|
|
if (!mode || ((mode & 1) && !have_secret)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|| ((mode & 2) && have_secret) )
|
|
|
|
|
{
|
|
|
|
|
if (ctrl->with_colons)
|
2004-02-17 15:05:04 +00:00
|
|
|
|
list_cert_colon (ctrl, cert, validity, fp, have_secret);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
else if (ctrl->with_chain)
|
2004-08-06 16:14:10 +00:00
|
|
|
|
list_cert_chain (ctrl, hd, cert,
|
|
|
|
|
raw_mode, fp, ctrl->with_validation);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if (raw_mode)
|
2004-08-06 16:14:10 +00:00
|
|
|
|
list_cert_raw (ctrl, hd, cert, fp, have_secret,
|
2004-04-22 13:03:44 +00:00
|
|
|
|
ctrl->with_validation);
|
|
|
|
|
else
|
|
|
|
|
list_cert_std (ctrl, cert, fp, have_secret,
|
|
|
|
|
ctrl->with_validation);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2008-01-30 17:21:28 +00:00
|
|
|
|
|
2011-02-04 12:57:53 +01:00
|
|
|
|
ksba_cert_release (lastcert);
|
2008-01-30 17:21:28 +00:00
|
|
|
|
lastcert = cert;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
cert = NULL;
|
|
|
|
|
}
|
2004-02-21 13:05:52 +00:00
|
|
|
|
if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
|
|
|
|
|
rc = 0;
|
|
|
|
|
if (rc)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
|
2011-02-04 12:57:53 +01:00
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
leave:
|
|
|
|
|
ksba_cert_release (cert);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
ksba_cert_release (lastcert);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
xfree (desc);
|
|
|
|
|
keydb_release (hd);
|
2004-02-21 13:05:52 +00:00
|
|
|
|
return rc;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2003-12-17 12:28:24 +00:00
|
|
|
|
list_external_cb (void *cb_value, ksba_cert_t cert)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
|
|
|
|
struct list_external_parm_s *parm = cb_value;
|
|
|
|
|
|
2016-11-10 17:01:19 +01:00
|
|
|
|
if (keydb_store_cert (parm->ctrl, cert, 1, NULL))
|
2003-08-05 17:11:04 +00:00
|
|
|
|
log_error ("error storing certificate as ephemeral\n");
|
|
|
|
|
|
|
|
|
|
if (parm->print_header)
|
|
|
|
|
{
|
|
|
|
|
const char *resname = "[external keys]";
|
|
|
|
|
int i;
|
|
|
|
|
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_fprintf (parm->fp, "%s\n", resname );
|
2003-08-05 17:11:04 +00:00
|
|
|
|
for (i=strlen(resname); i; i-- )
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc('-', parm->fp);
|
|
|
|
|
es_putc ('\n', parm->fp);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
parm->print_header = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parm->with_colons)
|
2004-02-17 15:05:04 +00:00
|
|
|
|
list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
else if (parm->with_chain)
|
2004-08-06 16:14:10 +00:00
|
|
|
|
list_cert_chain (parm->ctrl, NULL, cert, parm->raw_mode, parm->fp, 0);
|
2003-08-05 17:11:04 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2004-04-22 13:03:44 +00:00
|
|
|
|
if (parm->raw_mode)
|
2004-08-06 16:14:10 +00:00
|
|
|
|
list_cert_raw (parm->ctrl, NULL, cert, parm->fp, 0, 0);
|
2004-04-22 13:03:44 +00:00
|
|
|
|
else
|
|
|
|
|
list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
|
2007-03-19 14:35:04 +00:00
|
|
|
|
es_putc ('\n', parm->fp);
|
2003-08-05 17:11:04 +00: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 */
|
2004-02-21 13:05:52 +00:00
|
|
|
|
static gpg_error_t
|
2007-03-19 14:35:04 +00:00
|
|
|
|
list_external_keys (ctrl_t ctrl, strlist_t names, estream_t fp, int raw_mode)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
struct list_external_parm_s parm;
|
|
|
|
|
|
|
|
|
|
parm.fp = fp;
|
2004-02-17 15:05:04 +00:00
|
|
|
|
parm.ctrl = ctrl,
|
2003-08-05 17:11:04 +00:00
|
|
|
|
parm.print_header = ctrl->no_server;
|
|
|
|
|
parm.with_colons = ctrl->with_colons;
|
|
|
|
|
parm.with_chain = ctrl->with_chain;
|
2004-04-22 13:03:44 +00:00
|
|
|
|
parm.raw_mode = raw_mode;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
|
2008-02-13 16:47:14 +00:00
|
|
|
|
rc = gpgsm_dirmngr_lookup (ctrl, names, 0, list_external_cb, &parm);
|
2011-02-04 12:57:53 +01:00
|
|
|
|
if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1
|
2008-05-06 14:03:36 +00:00
|
|
|
|
|| gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
|
|
|
|
|
rc = 0; /* "Not found" is not an error here. */
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if (rc)
|
|
|
|
|
log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
|
2004-02-21 13:05:52 +00:00
|
|
|
|
return rc;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* List all keys or just the key given as NAMES.
|
2011-02-04 12:57:53 +01:00
|
|
|
|
MODE controls the operation mode:
|
2003-08-05 17:11:04 +00:00
|
|
|
|
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
|
2004-04-22 13:03:44 +00:00
|
|
|
|
Bit 8: Do a raw format dump.
|
2003-08-05 17:11:04 +00:00
|
|
|
|
*/
|
2004-02-21 13:05:52 +00:00
|
|
|
|
gpg_error_t
|
2007-03-19 14:35:04 +00:00
|
|
|
|
gpgsm_list_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
|
|
|
|
|
unsigned int mode)
|
2003-08-05 17:11:04 +00:00
|
|
|
|
{
|
2004-02-21 13:05:52 +00:00
|
|
|
|
gpg_error_t err = 0;
|
|
|
|
|
|
2003-08-05 17:11:04 +00:00
|
|
|
|
if ((mode & (1<<6)))
|
2004-04-22 13:03:44 +00:00
|
|
|
|
err = list_internal_keys (ctrl, names, fp, (mode & 3), (mode&256));
|
2004-02-21 13:05:52 +00:00
|
|
|
|
if (!err && (mode & (1<<7)))
|
2011-02-04 12:57:53 +01:00
|
|
|
|
err = list_external_keys (ctrl, names, fp, (mode&256));
|
2004-02-21 13:05:52 +00:00
|
|
|
|
return err;
|
2003-08-05 17:11:04 +00:00
|
|
|
|
}
|