LCOV - code coverage report
Current view: top level - sm - keylist.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 758 0.0 %
Date: 2016-09-12 12:29:17 Functions: 0 17 0.0 %

          Line data    Source code
       1             : /* keylist.c - Print certificates in various formats.
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2008, 2009,
       3             :  *               2010, 2011 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : #include <unistd.h>
      27             : #include <time.h>
      28             : #include <assert.h>
      29             : 
      30             : #include "gpgsm.h"
      31             : 
      32             : #include <gcrypt.h>
      33             : #include <ksba.h>
      34             : 
      35             : #include "keydb.h"
      36             : #include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
      37             : #include "i18n.h"
      38             : #include "tlv.h"
      39             : 
      40             : struct list_external_parm_s
      41             : {
      42             :   ctrl_t ctrl;
      43             :   estream_t fp;
      44             :   int print_header;
      45             :   int with_colons;
      46             :   int with_chain;
      47             :   int raw_mode;
      48             : };
      49             : 
      50             : 
      51             : /* This table is to map Extended Key Usage OIDs to human readable
      52             :    names.  */
      53             : struct
      54             : {
      55             :   const char *oid;
      56             :   const char *name;
      57             : } key_purpose_map[] = {
      58             :   { "1.3.6.1.5.5.7.3.1",  "serverAuth" },
      59             :   { "1.3.6.1.5.5.7.3.2",  "clientAuth" },
      60             :   { "1.3.6.1.5.5.7.3.3",  "codeSigning" },
      61             :   { "1.3.6.1.5.5.7.3.4",  "emailProtection" },
      62             :   { "1.3.6.1.5.5.7.3.5",  "ipsecEndSystem" },
      63             :   { "1.3.6.1.5.5.7.3.6",  "ipsecTunnel" },
      64             :   { "1.3.6.1.5.5.7.3.7",  "ipsecUser" },
      65             :   { "1.3.6.1.5.5.7.3.8",  "timeStamping" },
      66             :   { "1.3.6.1.5.5.7.3.9",  "ocspSigning" },
      67             :   { "1.3.6.1.5.5.7.3.10", "dvcs" },
      68             :   { "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" },
      69             :   { "1.3.6.1.5.5.7.3.13", "eapOverPPP" },
      70             :   { "1.3.6.1.5.5.7.3.14", "wlanSSID" },
      71             : 
      72             :   { "2.16.840.1.113730.4.1", "serverGatedCrypto.ns" }, /* Netscape. */
      73             :   { "1.3.6.1.4.1.311.10.3.3", "serverGatedCrypto.ms"}, /* Microsoft. */
      74             : 
      75             :   { "1.3.6.1.5.5.7.48.1.5", "ocspNoCheck" },
      76             : 
      77             :   { NULL, NULL }
      78             : };
      79             : 
      80             : 
      81             : /* Do not print this extension in the list of extensions.  This is set
      82             :    for oids which are already available via ksba fucntions. */
      83             : #define OID_FLAG_SKIP 1
      84             : /* The extension is a simple UTF8String and should be printed.  */
      85             : #define OID_FLAG_UTF8 2
      86             : 
      87             : /* A table mapping OIDs to a descriptive string. */
      88             : static struct
      89             : {
      90             :   char *oid;
      91             :   char *name;
      92             :   unsigned int flag; /* A flag as described above.  */
      93             : } oidtranstbl[] = {
      94             : 
      95             :   /* Algorithms. */
      96             :   { "1.2.840.10040.4.1", "dsa" },
      97             :   { "1.2.840.10040.4.3", "dsaWithSha1" },
      98             : 
      99             :   { "1.2.840.113549.1.1.1", "rsaEncryption" },
     100             :   { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" },
     101             :   { "1.2.840.113549.1.1.3", "md4WithRSAEncryption" },
     102             :   { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" },
     103             :   { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" },
     104             :   { "1.2.840.113549.1.1.7", "rsaOAEP" },
     105             :   { "1.2.840.113549.1.1.8", "rsaOAEP-MGF" },
     106             :   { "1.2.840.113549.1.1.9", "rsaOAEP-pSpecified" },
     107             :   { "1.2.840.113549.1.1.10", "rsaPSS" },
     108             :   { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" },
     109             :   { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" },
     110             :   { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" },
     111             : 
     112             :   { "1.3.14.3.2.26", "sha1" },
     113             :   { "1.3.14.3.2.29",  "sha-1WithRSAEncryption" },
     114             :   { "1.3.36.3.3.1.2", "rsaSignatureWithripemd160" },
     115             : 
     116             : 
     117             :   /* Telesec extensions. */
     118             :   { "0.2.262.1.10.12.0", "certExtensionLiabilityLimitationExt" },
     119             :   { "0.2.262.1.10.12.1", "telesecCertIdExt" },
     120             :   { "0.2.262.1.10.12.2", "telesecPolicyIdentifier" },
     121             :   { "0.2.262.1.10.12.3", "telesecPolicyQualifierID" },
     122             :   { "0.2.262.1.10.12.4", "telesecCRLFilteredExt" },
     123             :   { "0.2.262.1.10.12.5", "telesecCRLFilterExt"},
     124             :   { "0.2.262.1.10.12.6", "telesecNamingAuthorityExt" },
     125             : #define OIDSTR_restriction \
     126             :     "1.3.36.8.3.8"
     127             :   { OIDSTR_restriction,      "restriction", OID_FLAG_UTF8 },
     128             : 
     129             : 
     130             :   /* PKIX private extensions. */
     131             :   { "1.3.6.1.5.5.7.1.1", "authorityInfoAccess" },
     132             :   { "1.3.6.1.5.5.7.1.2", "biometricInfo" },
     133             :   { "1.3.6.1.5.5.7.1.3", "qcStatements" },
     134             :   { "1.3.6.1.5.5.7.1.4", "acAuditIdentity" },
     135             :   { "1.3.6.1.5.5.7.1.5", "acTargeting" },
     136             :   { "1.3.6.1.5.5.7.1.6", "acAaControls" },
     137             :   { "1.3.6.1.5.5.7.1.7", "sbgp-ipAddrBlock" },
     138             :   { "1.3.6.1.5.5.7.1.8", "sbgp-autonomousSysNum" },
     139             :   { "1.3.6.1.5.5.7.1.9", "sbgp-routerIdentifier" },
     140             :   { "1.3.6.1.5.5.7.1.10", "acProxying" },
     141             :   { "1.3.6.1.5.5.7.1.11", "subjectInfoAccess" },
     142             : 
     143             :   { "1.3.6.1.5.5.7.48.1", "ocsp" },
     144             :   { "1.3.6.1.5.5.7.48.2", "caIssuers" },
     145             :   { "1.3.6.1.5.5.7.48.3", "timeStamping" },
     146             :   { "1.3.6.1.5.5.7.48.5", "caRepository" },
     147             : 
     148             :   /* X.509 id-ce */
     149             :   { "2.5.29.14", "subjectKeyIdentifier", OID_FLAG_SKIP},
     150             :   { "2.5.29.15", "keyUsage", OID_FLAG_SKIP},
     151             :   { "2.5.29.16", "privateKeyUsagePeriod" },
     152             :   { "2.5.29.17", "subjectAltName", OID_FLAG_SKIP},
     153             :   { "2.5.29.18", "issuerAltName", OID_FLAG_SKIP},
     154             :   { "2.5.29.19", "basicConstraints", OID_FLAG_SKIP},
     155             :   { "2.5.29.20", "cRLNumber" },
     156             :   { "2.5.29.21", "cRLReason" },
     157             :   { "2.5.29.22", "expirationDate" },
     158             :   { "2.5.29.23", "instructionCode" },
     159             :   { "2.5.29.24", "invalidityDate" },
     160             :   { "2.5.29.27", "deltaCRLIndicator" },
     161             :   { "2.5.29.28", "issuingDistributionPoint" },
     162             :   { "2.5.29.29", "certificateIssuer" },
     163             :   { "2.5.29.30", "nameConstraints" },
     164             :   { "2.5.29.31", "cRLDistributionPoints", OID_FLAG_SKIP},
     165             :   { "2.5.29.32", "certificatePolicies", OID_FLAG_SKIP},
     166             :   { "2.5.29.32.0", "anyPolicy" },
     167             :   { "2.5.29.33", "policyMappings" },
     168             :   { "2.5.29.35", "authorityKeyIdentifier", OID_FLAG_SKIP},
     169             :   { "2.5.29.36", "policyConstraints" },
     170             :   { "2.5.29.37", "extKeyUsage", OID_FLAG_SKIP},
     171             :   { "2.5.29.46", "freshestCRL" },
     172             :   { "2.5.29.54", "inhibitAnyPolicy" },
     173             : 
     174             :   /* Netscape certificate extensions. */
     175             :   { "2.16.840.1.113730.1.1", "netscape-cert-type" },
     176             :   { "2.16.840.1.113730.1.2", "netscape-base-url" },
     177             :   { "2.16.840.1.113730.1.3", "netscape-revocation-url" },
     178             :   { "2.16.840.1.113730.1.4", "netscape-ca-revocation-url" },
     179             :   { "2.16.840.1.113730.1.7", "netscape-cert-renewal-url" },
     180             :   { "2.16.840.1.113730.1.8", "netscape-ca-policy-url" },
     181             :   { "2.16.840.1.113730.1.9", "netscape-homePage-url" },
     182             :   { "2.16.840.1.113730.1.10", "netscape-entitylogo" },
     183             :   { "2.16.840.1.113730.1.11", "netscape-userPicture" },
     184             :   { "2.16.840.1.113730.1.12", "netscape-ssl-server-name" },
     185             :   { "2.16.840.1.113730.1.13", "netscape-comment" },
     186             : 
     187             :   /* GnuPG extensions */
     188             :   { "1.3.6.1.4.1.11591.2.1.1", "pkaAddress" },
     189             :   { "1.3.6.1.4.1.11591.2.2.1", "standaloneCertificate" },
     190             :   { "1.3.6.1.4.1.11591.2.2.2", "wellKnownPrivateKey" },
     191             : 
     192             :   /* Extensions used by the Bundesnetzagentur.  */
     193             :   { "1.3.6.1.4.1.8301.3.5", "validityModel" },
     194             : 
     195             :   { NULL }
     196             : };
     197             : 
     198             : 
     199             : /* Return the description for OID; if no description is available
     200             :    NULL is returned. */
     201             : static const char *
     202           0 : get_oid_desc (const char *oid, unsigned int *flag)
     203             : {
     204             :   int i;
     205             : 
     206           0 :   if (oid)
     207           0 :     for (i=0; oidtranstbl[i].oid; i++)
     208           0 :       if (!strcmp (oidtranstbl[i].oid, oid))
     209             :         {
     210           0 :           if (flag)
     211           0 :             *flag = oidtranstbl[i].flag;
     212           0 :           return oidtranstbl[i].name;
     213             :         }
     214           0 :   if (flag)
     215           0 :     *flag = 0;
     216           0 :   return NULL;
     217             : }
     218             : 
     219             : 
     220             : static void
     221           0 : print_key_data (ksba_cert_t cert, estream_t fp)
     222             : {
     223             : #if 0
     224             :   int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
     225             :   int i;
     226             : 
     227             :   for(i=0; i < n; i++ )
     228             :     {
     229             :       es_fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
     230             :       mpi_print(stdout, pk->pkey[i], 1 );
     231             :       putchar(':');
     232             :       putchar('\n');
     233             :     }
     234             : #else
     235             :   (void)cert;
     236             :   (void)fp;
     237             : #endif
     238           0 : }
     239             : 
     240             : static void
     241           0 : print_capabilities (ksba_cert_t cert, estream_t fp)
     242             : {
     243             :   gpg_error_t err;
     244             :   unsigned int use;
     245             :   size_t buflen;
     246             :   char buffer[1];
     247             : 
     248           0 :   err = ksba_cert_get_user_data (cert, "is_qualified",
     249             :                                  &buffer, sizeof (buffer), &buflen);
     250           0 :   if (!err && buflen)
     251             :     {
     252           0 :       if (*buffer)
     253           0 :         es_putc ('q', fp);
     254             :     }
     255           0 :   else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
     256             :     ; /* Don't know - will not get marked as 'q' */
     257             :   else
     258           0 :     log_debug ("get_user_data(is_qualified) failed: %s\n",
     259             :                gpg_strerror (err));
     260             : 
     261           0 :   err = ksba_cert_get_key_usage (cert, &use);
     262           0 :   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
     263             :     {
     264           0 :       es_putc ('e', fp);
     265           0 :       es_putc ('s', fp);
     266           0 :       es_putc ('c', fp);
     267           0 :       es_putc ('E', fp);
     268           0 :       es_putc ('S', fp);
     269           0 :       es_putc ('C', fp);
     270           0 :       return;
     271             :     }
     272           0 :   if (err)
     273             :     {
     274           0 :       log_error (_("error getting key usage information: %s\n"),
     275             :                  gpg_strerror (err));
     276           0 :       return;
     277             :     }
     278             : 
     279           0 :   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
     280           0 :     es_putc ('e', fp);
     281           0 :   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
     282           0 :     es_putc ('s', fp);
     283           0 :   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
     284           0 :     es_putc ('c', fp);
     285           0 :   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
     286           0 :     es_putc ('E', fp);
     287           0 :   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
     288           0 :     es_putc ('S', fp);
     289           0 :   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
     290           0 :     es_putc ('C', fp);
     291             : 
     292           0 :   es_putc (':', fp);
     293             : }
     294             : 
     295             : 
     296             : static void
     297           0 : print_time (gnupg_isotime_t t, estream_t fp)
     298             : {
     299           0 :   if (!t || !*t)
     300             :     ;
     301             :   else
     302           0 :     es_fputs (t, fp);
     303           0 : }
     304             : 
     305             : 
     306             : /* Return an allocated string with the email address extracted from a
     307             :    DN.  Note hat we use this code also in ../kbx/keybox-blob.c.  */
     308             : static char *
     309           0 : email_kludge (const char *name)
     310             : {
     311             :   const char *p, *string;
     312             :   unsigned char *buf;
     313             :   int n;
     314             : 
     315           0 :   string = name;
     316             :   for (;;)
     317             :     {
     318           0 :       p = strstr (string, "1.2.840.113549.1.9.1=#");
     319           0 :       if (!p)
     320           0 :         return NULL;
     321           0 :       if (p == name || (p > string+1 && p[-1] == ',' && p[-2] != '\\'))
     322             :         {
     323           0 :           name = p + 22;
     324           0 :           break;
     325             :         }
     326           0 :       string = p + 22;
     327           0 :     }
     328             : 
     329             : 
     330             :   /* This looks pretty much like an email address in the subject's DN
     331             :      we use this to add an additional user ID entry.  This way,
     332             :      OpenSSL generated keys get a nicer and usable listing.  */
     333           0 :   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
     334             :     ;
     335           0 :   if (!n)
     336           0 :     return NULL;
     337           0 :   buf = xtrymalloc (n+3);
     338           0 :   if (!buf)
     339           0 :     return NULL; /* oops, out of core */
     340           0 :   *buf = '<';
     341           0 :   for (n=1, p=name; hexdigitp (p); p +=2, n++)
     342           0 :     buf[n] = xtoi_2 (p);
     343           0 :   buf[n++] = '>';
     344           0 :   buf[n] = 0;
     345           0 :   return (char*)buf;
     346             : }
     347             : 
     348             : 
     349             : 
     350             : 
     351             : /* List one certificate in colon mode */
     352             : static void
     353           0 : list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
     354             :                  estream_t fp, int have_secret)
     355             : {
     356             :   int rc;
     357             :   int idx;
     358             :   char truststring[2];
     359             :   char *p;
     360             :   ksba_sexp_t sexp;
     361             :   char *fpr;
     362             :   ksba_isotime_t t;
     363             :   gpg_error_t valerr;
     364             :   int algo;
     365             :   unsigned int nbits;
     366             :   const char *chain_id;
     367           0 :   char *chain_id_buffer = NULL;
     368           0 :   int is_root = 0;
     369             :   char *kludge_uid;
     370             : 
     371           0 :   if (ctrl->with_validation)
     372           0 :     valerr = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, NULL, 0, NULL);
     373             :   else
     374           0 :     valerr = 0;
     375             : 
     376             : 
     377             :   /* We need to get the fingerprint and the chaining ID in advance. */
     378           0 :   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
     379             :   {
     380             :     ksba_cert_t next;
     381             : 
     382           0 :     rc = gpgsm_walk_cert_chain (ctrl, cert, &next);
     383           0 :     if (!rc) /* We known the issuer's certificate. */
     384             :       {
     385           0 :         p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
     386           0 :         chain_id_buffer = p;
     387           0 :         chain_id = chain_id_buffer;
     388           0 :         ksba_cert_release (next);
     389             :       }
     390           0 :     else if (rc == -1)  /* We have reached the root certificate. */
     391             :       {
     392           0 :         chain_id = fpr;
     393           0 :         is_root = 1;
     394             :       }
     395             :     else
     396           0 :       chain_id = NULL;
     397             :   }
     398             : 
     399             : 
     400           0 :   es_fputs (have_secret? "crs:":"crt:", fp);
     401             : 
     402             :   /* Note: We can't use multiple flags, like "ei", because the
     403             :      validation check does only return one error.  */
     404           0 :   truststring[0] = 0;
     405           0 :   truststring[1] = 0;
     406           0 :   if ((validity & VALIDITY_REVOKED)
     407           0 :       || gpg_err_code (valerr) == GPG_ERR_CERT_REVOKED)
     408           0 :     *truststring = 'r';
     409           0 :   else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED)
     410           0 :     *truststring = 'e';
     411             :   else
     412             :     {
     413             :       /* Lets also check whether the certificate under question
     414             :          expired.  This is merely a hack until we found a proper way
     415             :          to store the expiration flag in the keybox. */
     416             :       ksba_isotime_t current_time, not_after;
     417             : 
     418           0 :       gnupg_get_isotime (current_time);
     419           0 :       if (!opt.ignore_expiration
     420           0 :           && !ksba_cert_get_validity (cert, 1, not_after)
     421           0 :           && *not_after && strcmp (current_time, not_after) > 0 )
     422           0 :         *truststring = 'e';
     423           0 :       else if (valerr)
     424             :         {
     425           0 :           if (gpgsm_cert_has_well_known_private_key (cert))
     426           0 :             *truststring = 'w';  /* Well, this is dummy CA.  */
     427             :           else
     428           0 :             *truststring = 'i';
     429             :         }
     430           0 :       else if (ctrl->with_validation && !is_root)
     431           0 :         *truststring = 'f';
     432             :     }
     433             : 
     434             :   /* If we have no truststring yet (i.e. the certificate might be
     435             :      good) and this is a root certificate, we ask the agent whether
     436             :      this is a trusted root certificate. */
     437           0 :   if (!*truststring && is_root)
     438             :     {
     439             :       struct rootca_flags_s dummy_flags;
     440             : 
     441           0 :       if (gpgsm_cert_has_well_known_private_key (cert))
     442           0 :         *truststring = 'w';  /* Well, this is dummy CA.  */
     443             :       else
     444             :         {
     445           0 :           rc = gpgsm_agent_istrusted (ctrl, cert, NULL, &dummy_flags);
     446           0 :           if (!rc)
     447           0 :             *truststring = 'u';  /* Yes, we trust this one (ultimately). */
     448           0 :           else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
     449           0 :             *truststring = 'n';  /* No, we do not trust this one. */
     450             :           /* (in case of an error we can't tell anything.) */
     451             :         }
     452             :     }
     453             : 
     454           0 :   if (*truststring)
     455           0 :     es_fputs (truststring, fp);
     456             : 
     457           0 :   algo = gpgsm_get_key_algo_info (cert, &nbits);
     458           0 :   es_fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24);
     459             : 
     460           0 :   ksba_cert_get_validity (cert, 0, t);
     461           0 :   print_time (t, fp);
     462           0 :   es_putc (':', fp);
     463           0 :   ksba_cert_get_validity (cert, 1, t);
     464           0 :   print_time ( t, fp);
     465           0 :   es_putc (':', fp);
     466             :   /* Field 8, serial number: */
     467           0 :   if ((sexp = ksba_cert_get_serial (cert)))
     468             :     {
     469             :       int len;
     470           0 :       const unsigned char *s = sexp;
     471             : 
     472           0 :       if (*s == '(')
     473             :         {
     474           0 :           s++;
     475           0 :           for (len=0; *s && *s != ':' && digitp (s); s++)
     476           0 :             len = len*10 + atoi_1 (s);
     477           0 :           if (*s == ':')
     478           0 :             for (s++; len; len--, s++)
     479           0 :               es_fprintf (fp,"%02X", *s);
     480             :         }
     481           0 :       xfree (sexp);
     482             :     }
     483           0 :   es_putc (':', fp);
     484             :   /* Field 9, ownertrust - not used here */
     485           0 :   es_putc (':', fp);
     486             :   /* field 10, old user ID - we use it here for the issuer DN */
     487           0 :   if ((p = ksba_cert_get_issuer (cert,0)))
     488             :     {
     489           0 :       es_write_sanitized (fp, p, strlen (p), ":", NULL);
     490           0 :       xfree (p);
     491             :     }
     492           0 :   es_putc (':', fp);
     493             :   /* Field 11, signature class - not used */
     494           0 :   es_putc (':', fp);
     495             :   /* Field 12, capabilities: */
     496           0 :   print_capabilities (cert, fp);
     497             :   /* Field 13, not used: */
     498           0 :   es_putc (':', fp);
     499           0 :   if (have_secret || ctrl->with_secret)
     500             :     {
     501             :       char *cardsn;
     502             : 
     503           0 :       p = gpgsm_get_keygrip_hexstring (cert);
     504           0 :       if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn)
     505           0 :           && (cardsn || ctrl->with_secret))
     506             :         {
     507             :           /* Field 14, not used: */
     508           0 :           es_putc (':', fp);
     509             :           /* Field 15:  Token serial number or secret key indicator.  */
     510           0 :           if (cardsn)
     511           0 :             es_fputs (cardsn, fp);
     512           0 :           else if (ctrl->with_secret)
     513           0 :             es_putc ('+', fp);
     514           0 :           es_putc (':', fp);
     515             :         }
     516           0 :       xfree (cardsn);
     517           0 :       xfree (p);
     518             :     }
     519           0 :   es_putc ('\n', fp);
     520             : 
     521             :   /* FPR record */
     522           0 :   es_fprintf (fp, "fpr:::::::::%s:::", fpr);
     523             :   /* Print chaining ID (field 13)*/
     524           0 :   if (chain_id)
     525           0 :     es_fputs (chain_id, fp);
     526           0 :   es_putc (':', fp);
     527           0 :   es_putc ('\n', fp);
     528           0 :   xfree (fpr); fpr = NULL; chain_id = NULL;
     529           0 :   xfree (chain_id_buffer); chain_id_buffer = NULL;
     530             : 
     531           0 :   if (opt.with_key_data)
     532             :     {
     533           0 :       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
     534             :         {
     535           0 :           es_fprintf (fp, "grp:::::::::%s:\n", p);
     536           0 :           xfree (p);
     537             :         }
     538           0 :       print_key_data (cert, fp);
     539             :     }
     540             : 
     541           0 :   kludge_uid = NULL;
     542           0 :   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
     543             :     {
     544             :       /* In the case that the same email address is in the subject DN
     545             :          as well as in an alternate subject name we avoid printing it
     546             :          a second time. */
     547           0 :       if (kludge_uid && !strcmp (kludge_uid, p))
     548           0 :         continue;
     549             : 
     550           0 :       es_fprintf (fp, "uid:%s::::::::", truststring);
     551           0 :       es_write_sanitized (fp, p, strlen (p), ":", NULL);
     552           0 :       es_putc (':', fp);
     553           0 :       es_putc (':', fp);
     554           0 :       es_putc ('\n', fp);
     555           0 :       if (!idx)
     556             :         {
     557             :           /* It would be better to get the faked email address from
     558             :              the keydb.  But as long as we don't have a way to pass
     559             :              the meta data back, we just check it the same way as the
     560             :              code used to create the keybox meta data does */
     561           0 :           kludge_uid = email_kludge (p);
     562           0 :           if (kludge_uid)
     563             :             {
     564           0 :               es_fprintf (fp, "uid:%s::::::::", truststring);
     565           0 :               es_write_sanitized (fp, kludge_uid, strlen (kludge_uid),
     566             :                                   ":", NULL);
     567           0 :               es_putc (':', fp);
     568           0 :               es_putc (':', fp);
     569           0 :               es_putc ('\n', fp);
     570             :             }
     571             :         }
     572           0 :       xfree (p);
     573             :     }
     574           0 :   xfree (kludge_uid);
     575           0 : }
     576             : 
     577             : 
     578             : static void
     579           0 : print_name_raw (estream_t fp, const char *string)
     580             : {
     581           0 :   if (!string)
     582           0 :     es_fputs ("[error]", fp);
     583             :   else
     584           0 :     es_write_sanitized (fp, string, strlen (string), NULL, NULL);
     585           0 : }
     586             : 
     587             : static void
     588           0 : print_names_raw (estream_t fp, int indent, ksba_name_t name)
     589             : {
     590             :   int idx;
     591             :   const char *s;
     592             :   int indent_all;
     593             : 
     594           0 :   if ((indent_all = (indent < 0)))
     595           0 :     indent = - indent;
     596             : 
     597           0 :   if (!name)
     598             :     {
     599           0 :       es_fputs ("none\n", fp);
     600           0 :       return;
     601             :     }
     602             : 
     603           0 :   for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
     604             :     {
     605           0 :       char *p = ksba_name_get_uri (name, idx);
     606           0 :       es_fprintf (fp, "%*s", idx||indent_all?indent:0, "");
     607           0 :       es_write_sanitized (fp, p?p:s, strlen (p?p:s), NULL, NULL);
     608           0 :       es_putc ('\n', fp);
     609           0 :       xfree (p);
     610             :     }
     611             : }
     612             : 
     613             : 
     614             : static void
     615           0 : print_utf8_extn_raw (estream_t fp, int indent,
     616             :                      const unsigned char *der, size_t derlen)
     617             : {
     618             :   gpg_error_t err;
     619             :   int class, tag, constructed, ndef;
     620             :   size_t objlen, hdrlen;
     621             : 
     622           0 :   if (indent < 0)
     623           0 :     indent = - indent;
     624             : 
     625           0 :   err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
     626             :                           &ndef, &objlen, &hdrlen);
     627           0 :   if (!err && (objlen > derlen || tag != TAG_UTF8_STRING))
     628           0 :     err = gpg_error (GPG_ERR_INV_OBJ);
     629           0 :   if (err)
     630             :     {
     631           0 :       es_fprintf (fp, "%*s[%s]\n", indent, "", gpg_strerror (err));
     632           0 :       return;
     633             :     }
     634           0 :   es_fprintf (fp, "%*s(%.*s)\n", indent, "", (int)objlen, der);
     635             : }
     636             : 
     637             : 
     638             : static void
     639           0 : print_utf8_extn (estream_t fp, int indent,
     640             :                  const unsigned char *der, size_t derlen)
     641             : {
     642             :   gpg_error_t err;
     643             :   int class, tag, constructed, ndef;
     644             :   size_t objlen, hdrlen;
     645             :   int indent_all;
     646             : 
     647           0 :   if ((indent_all = (indent < 0)))
     648           0 :     indent = - indent;
     649             : 
     650           0 :   err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
     651             :                           &ndef, &objlen, &hdrlen);
     652           0 :   if (!err && (objlen > derlen || tag != TAG_UTF8_STRING))
     653           0 :     err = gpg_error (GPG_ERR_INV_OBJ);
     654           0 :   if (err)
     655             :     {
     656           0 :       es_fprintf (fp, "%*s[%s%s]\n",
     657             :                   indent_all? indent:0, "", _("Error - "), gpg_strerror (err));
     658           0 :       return;
     659             :     }
     660           0 :   es_fprintf (fp, "%*s\"", indent_all? indent:0, "");
     661             :   /* Fixme: we should implement word wrapping */
     662           0 :   es_write_sanitized (fp, der, objlen, "\"", NULL);
     663           0 :   es_fputs ("\"\n", fp);
     664             : }
     665             : 
     666             : 
     667             : /* List one certificate in raw mode useful to have a closer look at
     668             :    the certificate.  This one does no beautification and only minimal
     669             :    output sanitation.  It is mainly useful for debugging. */
     670             : static void
     671           0 : list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
     672             :                ksba_cert_t cert, estream_t fp, int have_secret,
     673             :                int with_validation)
     674             : {
     675             :   gpg_error_t err;
     676             :   size_t off, len;
     677             :   ksba_sexp_t sexp, keyid;
     678             :   char *dn;
     679             :   ksba_isotime_t t;
     680             :   int idx, i;
     681             :   int is_ca, chainlen;
     682             :   unsigned int kusage;
     683             :   char *string, *p, *pend;
     684             :   const char *oid, *s;
     685             :   ksba_name_t name, name2;
     686             :   unsigned int reason;
     687           0 :   const unsigned char *cert_der = NULL;
     688             : 
     689             :   (void)have_secret;
     690             : 
     691           0 :   es_fprintf (fp, "           ID: 0x%08lX\n",
     692             :               gpgsm_get_short_fingerprint (cert, NULL));
     693             : 
     694           0 :   sexp = ksba_cert_get_serial (cert);
     695           0 :   es_fputs ("          S/N: ", fp);
     696           0 :   gpgsm_print_serial (fp, sexp);
     697           0 :   ksba_free (sexp);
     698           0 :   es_putc ('\n', fp);
     699             : 
     700           0 :   dn = ksba_cert_get_issuer (cert, 0);
     701           0 :   es_fputs ("       Issuer: ", fp);
     702           0 :   print_name_raw (fp, dn);
     703           0 :   ksba_free (dn);
     704           0 :   es_putc ('\n', fp);
     705           0 :   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
     706             :     {
     707           0 :       es_fputs ("          aka: ", fp);
     708           0 :       print_name_raw (fp, dn);
     709           0 :       ksba_free (dn);
     710           0 :       es_putc ('\n', fp);
     711             :     }
     712             : 
     713           0 :   dn = ksba_cert_get_subject (cert, 0);
     714           0 :   es_fputs ("      Subject: ", fp);
     715           0 :   print_name_raw (fp, dn);
     716           0 :   ksba_free (dn);
     717           0 :   es_putc ('\n', fp);
     718           0 :   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
     719             :     {
     720           0 :       es_fputs ("          aka: ", fp);
     721           0 :       print_name_raw (fp, dn);
     722           0 :       ksba_free (dn);
     723           0 :       es_putc ('\n', fp);
     724             :     }
     725             : 
     726           0 :   dn = gpgsm_get_fingerprint_string (cert, 0);
     727           0 :   es_fprintf (fp, "     sha1_fpr: %s\n", dn?dn:"error");
     728           0 :   xfree (dn);
     729             : 
     730           0 :   dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
     731           0 :   es_fprintf (fp, "      md5_fpr: %s\n", dn?dn:"error");
     732           0 :   xfree (dn);
     733             : 
     734           0 :   dn = gpgsm_get_certid (cert);
     735           0 :   es_fprintf (fp, "       certid: %s\n", dn?dn:"error");
     736           0 :   xfree (dn);
     737             : 
     738           0 :   dn = gpgsm_get_keygrip_hexstring (cert);
     739           0 :   es_fprintf (fp, "      keygrip: %s\n", dn?dn:"error");
     740           0 :   xfree (dn);
     741             : 
     742           0 :   ksba_cert_get_validity (cert, 0, t);
     743           0 :   es_fputs ("    notBefore: ", fp);
     744           0 :   gpgsm_print_time (fp, t);
     745           0 :   es_putc ('\n', fp);
     746           0 :   es_fputs ("     notAfter: ", fp);
     747           0 :   ksba_cert_get_validity (cert, 1, t);
     748           0 :   gpgsm_print_time (fp, t);
     749           0 :   es_putc ('\n', fp);
     750             : 
     751           0 :   oid = ksba_cert_get_digest_algo (cert);
     752           0 :   s = get_oid_desc (oid, NULL);
     753           0 :   es_fprintf (fp, "     hashAlgo: %s%s%s%s\n", oid, s?" (":"",s?s:"",s?")":"");
     754             : 
     755             :   {
     756             :     const char *algoname;
     757             :     unsigned int nbits;
     758             : 
     759           0 :     algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
     760           0 :     es_fprintf (fp, "      keyType: %u bit %s\n",
     761             :                 nbits, algoname? algoname:"?");
     762             :   }
     763             : 
     764             :   /* subjectKeyIdentifier */
     765           0 :   es_fputs ("    subjKeyId: ", fp);
     766           0 :   err = ksba_cert_get_subj_key_id (cert, NULL, &keyid);
     767           0 :   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
     768             :     {
     769           0 :       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
     770           0 :         es_fputs ("[none]\n", fp);
     771             :       else
     772             :         {
     773           0 :           gpgsm_print_serial (fp, keyid);
     774           0 :           ksba_free (keyid);
     775           0 :           es_putc ('\n', fp);
     776             :         }
     777             :     }
     778             :   else
     779           0 :     es_fputs ("[?]\n", fp);
     780             : 
     781             : 
     782             :   /* authorityKeyIdentifier */
     783           0 :   es_fputs ("    authKeyId: ", fp);
     784           0 :   err = ksba_cert_get_auth_key_id (cert, &keyid, &name, &sexp);
     785           0 :   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
     786             :     {
     787           0 :       if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name)
     788           0 :         es_fputs ("[none]\n", fp);
     789             :       else
     790             :         {
     791           0 :           gpgsm_print_serial (fp, sexp);
     792           0 :           ksba_free (sexp);
     793           0 :           es_putc ('\n', fp);
     794           0 :           print_names_raw (fp, -15, name);
     795           0 :           ksba_name_release (name);
     796             :         }
     797           0 :       if (keyid)
     798             :         {
     799           0 :           es_fputs (" authKeyId.ki: ", fp);
     800           0 :           gpgsm_print_serial (fp, keyid);
     801           0 :           ksba_free (keyid);
     802           0 :           es_putc ('\n', fp);
     803             :         }
     804             :     }
     805             :   else
     806           0 :     es_fputs ("[?]\n", fp);
     807             : 
     808           0 :   es_fputs ("     keyUsage:", fp);
     809           0 :   err = ksba_cert_get_key_usage (cert, &kusage);
     810           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
     811             :     {
     812           0 :       if (err)
     813           0 :         es_fprintf (fp, " [error: %s]", gpg_strerror (err));
     814             :       else
     815             :         {
     816           0 :           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
     817           0 :             es_fputs (" digitalSignature", fp);
     818           0 :           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
     819           0 :             es_fputs (" nonRepudiation", fp);
     820           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
     821           0 :             es_fputs (" keyEncipherment", fp);
     822           0 :           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
     823           0 :             es_fputs (" dataEncipherment", fp);
     824           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
     825           0 :             es_fputs (" keyAgreement", fp);
     826           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
     827           0 :             es_fputs (" certSign", fp);
     828           0 :           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
     829           0 :             es_fputs (" crlSign", fp);
     830           0 :           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
     831           0 :             es_fputs (" encipherOnly", fp);
     832           0 :           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
     833           0 :             es_fputs (" decipherOnly", fp);
     834             :         }
     835           0 :       es_putc ('\n', fp);
     836             :     }
     837             :   else
     838           0 :     es_fputs (" [none]\n", fp);
     839             : 
     840           0 :   es_fputs ("  extKeyUsage: ", fp);
     841           0 :   err = ksba_cert_get_ext_key_usages (cert, &string);
     842           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
     843             :     {
     844           0 :       if (err)
     845           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
     846             :       else
     847             :         {
     848           0 :           p = string;
     849           0 :           while (p && (pend=strchr (p, ':')))
     850             :             {
     851           0 :               *pend++ = 0;
     852           0 :               for (i=0; key_purpose_map[i].oid; i++)
     853           0 :                 if ( !strcmp (key_purpose_map[i].oid, p) )
     854           0 :                   break;
     855           0 :               es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
     856           0 :               p = pend;
     857           0 :               if (*p != 'C')
     858           0 :                 es_fputs (" (suggested)", fp);
     859           0 :               if ((p = strchr (p, '\n')))
     860             :                 {
     861           0 :                   p++;
     862           0 :                   es_fputs ("\n               ", fp);
     863             :                 }
     864             :             }
     865           0 :           xfree (string);
     866             :         }
     867           0 :       es_putc ('\n', fp);
     868             :     }
     869             :   else
     870           0 :     es_fputs ("[none]\n", fp);
     871             : 
     872             : 
     873           0 :   es_fputs ("     policies: ", fp);
     874           0 :   err = ksba_cert_get_cert_policies (cert, &string);
     875           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
     876             :     {
     877           0 :       if (err)
     878           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
     879             :       else
     880             :         {
     881           0 :           p = string;
     882           0 :           while (p && (pend=strchr (p, ':')))
     883             :             {
     884           0 :               *pend++ = 0;
     885           0 :               for (i=0; key_purpose_map[i].oid; i++)
     886           0 :                 if ( !strcmp (key_purpose_map[i].oid, p) )
     887           0 :                   break;
     888           0 :               es_fputs (p, fp);
     889           0 :               p = pend;
     890           0 :               if (*p == 'C')
     891           0 :                 es_fputs (" (critical)", fp);
     892           0 :               if ((p = strchr (p, '\n')))
     893             :                 {
     894           0 :                   p++;
     895           0 :                   es_fputs ("\n               ", fp);
     896             :                 }
     897             :             }
     898           0 :           xfree (string);
     899             :         }
     900           0 :       es_putc ('\n', fp);
     901             :     }
     902             :   else
     903           0 :     es_fputs ("[none]\n", fp);
     904             : 
     905           0 :   es_fputs ("  chainLength: ", fp);
     906           0 :   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
     907           0 :   if (err || is_ca)
     908             :     {
     909           0 :       if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
     910           0 :         es_fprintf (fp, "[none]");
     911           0 :       else if (err)
     912           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
     913           0 :       else if (chainlen == -1)
     914           0 :         es_fputs ("unlimited", fp);
     915             :       else
     916           0 :         es_fprintf (fp, "%d", chainlen);
     917           0 :       es_putc ('\n', fp);
     918             :     }
     919             :   else
     920           0 :     es_fputs ("not a CA\n", fp);
     921             : 
     922             : 
     923             :   /* CRL distribution point */
     924           0 :   for (idx=0; !(err=ksba_cert_get_crl_dist_point (cert, idx, &name, &name2,
     925           0 :                                                   &reason)) ;idx++)
     926             :     {
     927           0 :       es_fputs ("        crlDP: ", fp);
     928           0 :       print_names_raw (fp, 15, name);
     929           0 :       if (reason)
     930             :         {
     931           0 :           es_fputs ("               reason: ", fp);
     932           0 :           if ( (reason & KSBA_CRLREASON_UNSPECIFIED))
     933           0 :             es_fputs (" unused", fp);
     934           0 :           if ( (reason & KSBA_CRLREASON_KEY_COMPROMISE))
     935           0 :             es_fputs (" keyCompromise", fp);
     936           0 :           if ( (reason & KSBA_CRLREASON_CA_COMPROMISE))
     937           0 :             es_fputs (" caCompromise", fp);
     938           0 :           if ( (reason & KSBA_CRLREASON_AFFILIATION_CHANGED))
     939           0 :             es_fputs (" affiliationChanged", fp);
     940           0 :           if ( (reason & KSBA_CRLREASON_SUPERSEDED))
     941           0 :             es_fputs (" superseded", fp);
     942           0 :           if ( (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION))
     943           0 :             es_fputs (" cessationOfOperation", fp);
     944           0 :           if ( (reason & KSBA_CRLREASON_CERTIFICATE_HOLD))
     945           0 :             es_fputs (" certificateHold", fp);
     946           0 :           es_putc ('\n', fp);
     947             :         }
     948           0 :       es_fputs ("               issuer: ", fp);
     949           0 :       print_names_raw (fp, 23, name2);
     950           0 :       ksba_name_release (name);
     951           0 :       ksba_name_release (name2);
     952             :     }
     953           0 :   if (err && gpg_err_code (err) != GPG_ERR_EOF
     954           0 :       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
     955           0 :     es_fputs ("        crlDP: [error]\n", fp);
     956           0 :   else if (!idx)
     957           0 :     es_fputs ("        crlDP: [none]\n", fp);
     958             : 
     959             : 
     960             :   /* authorityInfoAccess. */
     961           0 :   for (idx=0; !(err=ksba_cert_get_authority_info_access (cert, idx, &string,
     962           0 :                                                          &name)); idx++)
     963             :     {
     964           0 :       es_fputs ("     authInfo: ", fp);
     965           0 :       s = get_oid_desc (string, NULL);
     966           0 :       es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
     967           0 :       print_names_raw (fp, -15, name);
     968           0 :       ksba_name_release (name);
     969           0 :       ksba_free (string);
     970             :     }
     971           0 :   if (err && gpg_err_code (err) != GPG_ERR_EOF
     972           0 :       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
     973           0 :     es_fputs ("     authInfo: [error]\n", fp);
     974           0 :   else if (!idx)
     975           0 :     es_fputs ("     authInfo: [none]\n", fp);
     976             : 
     977             :   /* subjectInfoAccess. */
     978           0 :   for (idx=0; !(err=ksba_cert_get_subject_info_access (cert, idx, &string,
     979           0 :                                                          &name)); idx++)
     980             :     {
     981           0 :       es_fputs ("  subjectInfo: ", fp);
     982           0 :       s = get_oid_desc (string, NULL);
     983           0 :       es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
     984           0 :       print_names_raw (fp, -15, name);
     985           0 :       ksba_name_release (name);
     986           0 :       ksba_free (string);
     987             :     }
     988           0 :   if (err && gpg_err_code (err) != GPG_ERR_EOF
     989           0 :       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
     990           0 :     es_fputs ("     subjInfo: [error]\n", fp);
     991           0 :   else if (!idx)
     992           0 :     es_fputs ("     subjInfo: [none]\n", fp);
     993             : 
     994             : 
     995           0 :   for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
     996           0 :                                              &oid, &i, &off, &len));idx++)
     997             :     {
     998             :       unsigned int flag;
     999             : 
    1000           0 :       s = get_oid_desc (oid, &flag);
    1001           0 :       if ((flag & OID_FLAG_SKIP))
    1002           0 :         continue;
    1003             : 
    1004           0 :       es_fprintf (fp, "     %s: %s%s%s%s  [%d octets]\n",
    1005           0 :                   i? "critExtn":"    extn",
    1006             :                   oid, s?" (":"", s?s:"", s?")":"", (int)len);
    1007           0 :       if ((flag & OID_FLAG_UTF8))
    1008             :         {
    1009           0 :           if (!cert_der)
    1010           0 :             cert_der = ksba_cert_get_image (cert, NULL);
    1011           0 :           assert (cert_der);
    1012           0 :           print_utf8_extn_raw (fp, -15, cert_der+off, len);
    1013             :         }
    1014             :     }
    1015             : 
    1016             : 
    1017           0 :   if (with_validation)
    1018             :     {
    1019           0 :       err = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, fp, 0, NULL);
    1020           0 :       if (!err)
    1021           0 :         es_fprintf (fp, "  [certificate is good]\n");
    1022             :       else
    1023           0 :         es_fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
    1024             :     }
    1025             : 
    1026           0 :   if (hd)
    1027             :     {
    1028             :       unsigned int blobflags;
    1029             : 
    1030           0 :       err = keydb_get_flags (hd, KEYBOX_FLAG_BLOB, 0, &blobflags);
    1031           0 :       if (err)
    1032           0 :         es_fprintf (fp, "  [error getting keyflags: %s]\n",gpg_strerror (err));
    1033           0 :       else if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
    1034           0 :         es_fprintf (fp, "  [stored as ephemeral]\n");
    1035             :     }
    1036             : 
    1037           0 : }
    1038             : 
    1039             : 
    1040             : 
    1041             : 
    1042             : /* List one certificate in standard mode */
    1043             : static void
    1044           0 : list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
    1045             :                int with_validation)
    1046             : {
    1047             :   gpg_error_t err;
    1048             :   ksba_sexp_t sexp;
    1049             :   char *dn;
    1050             :   ksba_isotime_t t;
    1051             :   int idx, i;
    1052             :   int is_ca, chainlen;
    1053             :   unsigned int kusage;
    1054             :   char *string, *p, *pend;
    1055             :   size_t off, len;
    1056             :   const char *oid;
    1057           0 :   const unsigned char *cert_der = NULL;
    1058             : 
    1059             : 
    1060           0 :   es_fprintf (fp, "           ID: 0x%08lX\n",
    1061             :               gpgsm_get_short_fingerprint (cert, NULL));
    1062             : 
    1063           0 :   sexp = ksba_cert_get_serial (cert);
    1064           0 :   es_fputs ("          S/N: ", fp);
    1065           0 :   gpgsm_print_serial (fp, sexp);
    1066           0 :   ksba_free (sexp);
    1067           0 :   es_putc ('\n', fp);
    1068             : 
    1069           0 :   dn = ksba_cert_get_issuer (cert, 0);
    1070           0 :   es_fputs ("       Issuer: ", fp);
    1071           0 :   gpgsm_es_print_name (fp, dn);
    1072           0 :   ksba_free (dn);
    1073           0 :   es_putc ('\n', fp);
    1074           0 :   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
    1075             :     {
    1076           0 :       es_fputs ("          aka: ", fp);
    1077           0 :       gpgsm_es_print_name (fp, dn);
    1078           0 :       ksba_free (dn);
    1079           0 :       es_putc ('\n', fp);
    1080             :     }
    1081             : 
    1082           0 :   dn = ksba_cert_get_subject (cert, 0);
    1083           0 :   es_fputs ("      Subject: ", fp);
    1084           0 :   gpgsm_es_print_name (fp, dn);
    1085           0 :   ksba_free (dn);
    1086           0 :   es_putc ('\n', fp);
    1087           0 :   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
    1088             :     {
    1089           0 :       es_fputs ("          aka: ", fp);
    1090           0 :       gpgsm_es_print_name (fp, dn);
    1091           0 :       ksba_free (dn);
    1092           0 :       es_putc ('\n', fp);
    1093             :     }
    1094             : 
    1095           0 :   ksba_cert_get_validity (cert, 0, t);
    1096           0 :   es_fputs ("     validity: ", fp);
    1097           0 :   gpgsm_print_time (fp, t);
    1098           0 :   es_fputs (" through ", fp);
    1099           0 :   ksba_cert_get_validity (cert, 1, t);
    1100           0 :   gpgsm_print_time (fp, t);
    1101           0 :   es_putc ('\n', fp);
    1102             : 
    1103             : 
    1104             :   {
    1105             :     const char *algoname;
    1106             :     unsigned int nbits;
    1107             : 
    1108           0 :     algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
    1109           0 :     es_fprintf (fp, "     key type: %u bit %s\n",
    1110             :                 nbits, algoname? algoname:"?");
    1111             :   }
    1112             : 
    1113             : 
    1114           0 :   err = ksba_cert_get_key_usage (cert, &kusage);
    1115           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
    1116             :     {
    1117           0 :       es_fputs ("    key usage:", fp);
    1118           0 :       if (err)
    1119           0 :         es_fprintf (fp, " [error: %s]", gpg_strerror (err));
    1120             :       else
    1121             :         {
    1122           0 :           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
    1123           0 :             es_fputs (" digitalSignature", fp);
    1124           0 :           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
    1125           0 :             es_fputs (" nonRepudiation", fp);
    1126           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
    1127           0 :             es_fputs (" keyEncipherment", fp);
    1128           0 :           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
    1129           0 :             es_fputs (" dataEncipherment", fp);
    1130           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
    1131           0 :             es_fputs (" keyAgreement", fp);
    1132           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
    1133           0 :             es_fputs (" certSign", fp);
    1134           0 :           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
    1135           0 :             es_fputs (" crlSign", fp);
    1136           0 :           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
    1137           0 :             es_fputs (" encipherOnly", fp);
    1138           0 :           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
    1139           0 :             es_fputs (" decipherOnly", fp);
    1140             :         }
    1141           0 :       es_putc ('\n', fp);
    1142             :     }
    1143             : 
    1144           0 :   err = ksba_cert_get_ext_key_usages (cert, &string);
    1145           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
    1146             :     {
    1147           0 :       es_fputs ("ext key usage: ", fp);
    1148           0 :       if (err)
    1149           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
    1150             :       else
    1151             :         {
    1152           0 :           p = string;
    1153           0 :           while (p && (pend=strchr (p, ':')))
    1154             :             {
    1155           0 :               *pend++ = 0;
    1156           0 :               for (i=0; key_purpose_map[i].oid; i++)
    1157           0 :                 if ( !strcmp (key_purpose_map[i].oid, p) )
    1158           0 :                   break;
    1159           0 :               es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
    1160           0 :               p = pend;
    1161           0 :               if (*p != 'C')
    1162           0 :                 es_fputs (" (suggested)", fp);
    1163           0 :               if ((p = strchr (p, '\n')))
    1164             :                 {
    1165           0 :                   p++;
    1166           0 :                   es_fputs (", ", fp);
    1167             :                 }
    1168             :             }
    1169           0 :           xfree (string);
    1170             :         }
    1171           0 :       es_putc ('\n', fp);
    1172             :     }
    1173             : 
    1174             :   /* Print restrictions.  */
    1175           0 :   for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
    1176           0 :                                              &oid, NULL, &off, &len));idx++)
    1177             :     {
    1178           0 :       if (!strcmp (oid, OIDSTR_restriction) )
    1179             :         {
    1180           0 :           if (!cert_der)
    1181           0 :             cert_der = ksba_cert_get_image (cert, NULL);
    1182           0 :           assert (cert_der);
    1183           0 :           es_fputs ("  restriction: ", fp);
    1184           0 :           print_utf8_extn (fp, 15, cert_der+off, len);
    1185             :         }
    1186             :     }
    1187             : 
    1188             :   /* Print policies.  */
    1189           0 :   err = ksba_cert_get_cert_policies (cert, &string);
    1190           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
    1191             :     {
    1192           0 :       es_fputs ("     policies: ", fp);
    1193           0 :       if (err)
    1194           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
    1195             :       else
    1196             :         {
    1197           0 :           for (p=string; *p; p++)
    1198             :             {
    1199           0 :               if (*p == '\n')
    1200           0 :                 *p = ',';
    1201             :             }
    1202           0 :           es_write_sanitized (fp, string, strlen (string), NULL, NULL);
    1203           0 :           xfree (string);
    1204             :         }
    1205           0 :       es_putc ('\n', fp);
    1206             :     }
    1207             : 
    1208           0 :   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
    1209           0 :   if (err || is_ca)
    1210             :     {
    1211           0 :       es_fputs (" chain length: ", fp);
    1212           0 :       if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
    1213           0 :         es_fprintf (fp, "none");
    1214           0 :       else if (err)
    1215           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
    1216           0 :       else if (chainlen == -1)
    1217           0 :         es_fputs ("unlimited", fp);
    1218             :       else
    1219           0 :         es_fprintf (fp, "%d", chainlen);
    1220           0 :       es_putc ('\n', fp);
    1221             :     }
    1222             : 
    1223           0 :   if (opt.with_md5_fingerprint)
    1224             :     {
    1225           0 :       dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
    1226           0 :       es_fprintf (fp, "      md5 fpr: %s\n", dn?dn:"error");
    1227           0 :       xfree (dn);
    1228             :     }
    1229             : 
    1230           0 :   dn = gpgsm_get_fingerprint_string (cert, 0);
    1231           0 :   es_fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
    1232           0 :   xfree (dn);
    1233             : 
    1234           0 :   if (opt.with_keygrip)
    1235             :     {
    1236           0 :       dn = gpgsm_get_keygrip_hexstring (cert);
    1237           0 :       if (dn)
    1238             :         {
    1239           0 :           es_fprintf (fp, "      keygrip: %s\n", dn);
    1240           0 :           xfree (dn);
    1241             :         }
    1242             :     }
    1243             : 
    1244           0 :   if (have_secret)
    1245             :     {
    1246             :       char *cardsn;
    1247             : 
    1248           0 :       p = gpgsm_get_keygrip_hexstring (cert);
    1249           0 :       if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn) && cardsn)
    1250           0 :         es_fprintf (fp, "     card s/n: %s\n", cardsn);
    1251           0 :       xfree (cardsn);
    1252           0 :       xfree (p);
    1253             :     }
    1254             : 
    1255           0 :   if (with_validation)
    1256             :     {
    1257             :       gpg_error_t tmperr;
    1258             :       size_t buflen;
    1259             :       char buffer[1];
    1260             : 
    1261           0 :       err = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, fp, 0, NULL);
    1262           0 :       tmperr = ksba_cert_get_user_data (cert, "is_qualified",
    1263             :                                         &buffer, sizeof (buffer), &buflen);
    1264           0 :       if (!tmperr && buflen)
    1265             :         {
    1266           0 :           if (*buffer)
    1267           0 :             es_fputs ("  [qualified]\n", fp);
    1268             :         }
    1269           0 :       else if (gpg_err_code (tmperr) == GPG_ERR_NOT_FOUND)
    1270             :         ; /* Don't know - will not get marked as 'q' */
    1271             :       else
    1272           0 :         log_debug ("get_user_data(is_qualified) failed: %s\n",
    1273             :                    gpg_strerror (tmperr));
    1274             : 
    1275           0 :       if (!err)
    1276           0 :         es_fprintf (fp, "  [certificate is good]\n");
    1277             :       else
    1278           0 :         es_fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
    1279             :     }
    1280           0 : }
    1281             : 
    1282             : 
    1283             : /* Same as standard mode mode list all certifying certs too. */
    1284             : static void
    1285           0 : list_cert_chain (ctrl_t ctrl, KEYDB_HANDLE hd,
    1286             :                  ksba_cert_t cert, int raw_mode,
    1287             :                  estream_t fp, int with_validation)
    1288             : {
    1289           0 :   ksba_cert_t next = NULL;
    1290             : 
    1291           0 :   if (raw_mode)
    1292           0 :     list_cert_raw (ctrl, hd, cert, fp, 0, with_validation);
    1293             :   else
    1294           0 :     list_cert_std (ctrl, cert, fp, 0, with_validation);
    1295           0 :   ksba_cert_ref (cert);
    1296           0 :   while (!gpgsm_walk_cert_chain (ctrl, cert, &next))
    1297             :     {
    1298           0 :       ksba_cert_release (cert);
    1299           0 :       es_fputs ("Certified by\n", fp);
    1300           0 :       if (raw_mode)
    1301           0 :         list_cert_raw (ctrl, hd, next, fp, 0, with_validation);
    1302             :       else
    1303           0 :         list_cert_std (ctrl, next, fp, 0, with_validation);
    1304           0 :       cert = next;
    1305             :     }
    1306           0 :   ksba_cert_release (cert);
    1307           0 :   es_putc ('\n', fp);
    1308           0 : }
    1309             : 
    1310             : 
    1311             : 
    1312             : /* List all internal keys or just the keys given as NAMES.  MODE is a
    1313             :    bit vector to specify what keys are to be included; see
    1314             :    gpgsm_list_keys (below) for details.  If RAW_MODE is true, the raw
    1315             :    output mode will be used instead of the standard beautified one.
    1316             :  */
    1317             : static gpg_error_t
    1318           0 : list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
    1319             :                     unsigned int mode, int raw_mode)
    1320             : {
    1321             :   KEYDB_HANDLE hd;
    1322           0 :   KEYDB_SEARCH_DESC *desc = NULL;
    1323             :   strlist_t sl;
    1324             :   int ndesc;
    1325           0 :   ksba_cert_t cert = NULL;
    1326           0 :   ksba_cert_t lastcert = NULL;
    1327           0 :   gpg_error_t rc = 0;
    1328             :   const char *lastresname, *resname;
    1329             :   int have_secret;
    1330           0 :   int want_ephemeral = ctrl->with_ephemeral_keys;
    1331             : 
    1332           0 :   hd = keydb_new (0);
    1333           0 :   if (!hd)
    1334             :     {
    1335           0 :       log_error ("keydb_new failed\n");
    1336           0 :       rc = gpg_error (GPG_ERR_GENERAL);
    1337           0 :       goto leave;
    1338             :     }
    1339             : 
    1340           0 :   if (!names)
    1341           0 :     ndesc = 1;
    1342             :   else
    1343             :     {
    1344           0 :       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
    1345             :         ;
    1346             :     }
    1347             : 
    1348           0 :   desc = xtrycalloc (ndesc, sizeof *desc);
    1349           0 :   if (!ndesc)
    1350             :     {
    1351           0 :       rc = gpg_error_from_syserror ();
    1352           0 :       log_error ("out of core\n");
    1353           0 :       goto leave;
    1354             :     }
    1355             : 
    1356           0 :   if (!names)
    1357           0 :     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
    1358             :   else
    1359             :     {
    1360           0 :       for (ndesc=0, sl=names; sl; sl = sl->next)
    1361             :         {
    1362           0 :           rc = classify_user_id (sl->d, desc+ndesc, 0);
    1363           0 :           if (rc)
    1364             :             {
    1365           0 :               log_error ("key '%s' not found: %s\n",
    1366           0 :                          sl->d, gpg_strerror (rc));
    1367           0 :               rc = 0;
    1368             :             }
    1369             :           else
    1370           0 :             ndesc++;
    1371             :         }
    1372             : 
    1373             :     }
    1374             : 
    1375             :   /* If all specifications are done by fingerprint or keygrip, we
    1376             :      switch to ephemeral mode so that _all_ currently available and
    1377             :      matching certificates are listed.  */
    1378           0 :   if (!want_ephemeral && names && ndesc)
    1379             :     {
    1380             :       int i;
    1381             : 
    1382           0 :       for (i=0; (i < ndesc
    1383           0 :                  && (desc[i].mode == KEYDB_SEARCH_MODE_FPR
    1384           0 :                      || desc[i].mode == KEYDB_SEARCH_MODE_FPR20
    1385           0 :                      || desc[i].mode == KEYDB_SEARCH_MODE_FPR16
    1386           0 :                      || desc[i].mode == KEYDB_SEARCH_MODE_KEYGRIP)); i++)
    1387             :         ;
    1388           0 :       if (i == ndesc)
    1389           0 :         want_ephemeral = 1;
    1390             :     }
    1391             : 
    1392           0 :   if (want_ephemeral)
    1393           0 :     keydb_set_ephemeral (hd, 1);
    1394             : 
    1395             :   /* It would be nice to see which of the given users did actually
    1396             :      match one in the keyring.  To implement this we need to have a
    1397             :      found flag for each entry in desc and to set this we must check
    1398             :      all those entries after a match to mark all matched one -
    1399             :      currently we stop at the first match.  To do this we need an
    1400             :      extra flag to enable this feature so */
    1401             : 
    1402             :   /* Suppress duplicates at least when they follow each other.  */
    1403           0 :   lastresname = NULL;
    1404           0 :   while (!(rc = keydb_search (hd, desc, ndesc)))
    1405             :     {
    1406             :       unsigned int validity;
    1407             : 
    1408           0 :       if (!names)
    1409           0 :         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
    1410             : 
    1411           0 :       rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
    1412           0 :       if (rc)
    1413             :         {
    1414           0 :           log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
    1415           0 :           goto leave;
    1416             :         }
    1417           0 :       rc = keydb_get_cert (hd, &cert);
    1418           0 :       if (rc)
    1419             :         {
    1420           0 :           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
    1421           0 :           goto leave;
    1422             :         }
    1423             :       /* Skip duplicated certificates, at least if they follow each
    1424             :          others.  This works best if a single key is searched for and
    1425             :          expected.  FIXME: Non-sequential duplicates remain.  */
    1426           0 :       if (gpgsm_certs_identical_p (cert, lastcert))
    1427             :         {
    1428           0 :           ksba_cert_release (cert);
    1429           0 :           cert = NULL;
    1430           0 :           continue;
    1431             :         }
    1432             : 
    1433           0 :       resname = keydb_get_resource_name (hd);
    1434             : 
    1435           0 :       if (lastresname != resname )
    1436             :         {
    1437             :           int i;
    1438             : 
    1439           0 :           if (ctrl->no_server)
    1440             :             {
    1441           0 :               es_fprintf (fp, "%s\n", resname );
    1442           0 :               for (i=strlen(resname); i; i-- )
    1443           0 :                 es_putc ('-', fp);
    1444           0 :               es_putc ('\n', fp);
    1445           0 :               lastresname = resname;
    1446             :             }
    1447             :         }
    1448             : 
    1449           0 :       have_secret = 0;
    1450           0 :       if (mode)
    1451             :         {
    1452           0 :           char *p = gpgsm_get_keygrip_hexstring (cert);
    1453           0 :           if (p)
    1454             :             {
    1455           0 :               rc = gpgsm_agent_havekey (ctrl, p);
    1456           0 :               if (!rc)
    1457           0 :                 have_secret = 1;
    1458           0 :               else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
    1459           0 :                 goto leave;
    1460           0 :               rc = 0;
    1461           0 :               xfree (p);
    1462             :             }
    1463             :         }
    1464             : 
    1465           0 :       if (!mode
    1466           0 :           || ((mode & 1) && !have_secret)
    1467           0 :           || ((mode & 2) && have_secret)  )
    1468             :         {
    1469           0 :           if (ctrl->with_colons)
    1470           0 :             list_cert_colon (ctrl, cert, validity, fp, have_secret);
    1471           0 :           else if (ctrl->with_chain)
    1472           0 :             list_cert_chain (ctrl, hd, cert,
    1473             :                              raw_mode, fp, ctrl->with_validation);
    1474             :           else
    1475             :             {
    1476           0 :               if (raw_mode)
    1477           0 :                 list_cert_raw (ctrl, hd, cert, fp, have_secret,
    1478             :                                ctrl->with_validation);
    1479             :               else
    1480           0 :                 list_cert_std (ctrl, cert, fp, have_secret,
    1481             :                                ctrl->with_validation);
    1482           0 :               es_putc ('\n', fp);
    1483             :             }
    1484             :         }
    1485             : 
    1486           0 :       ksba_cert_release (lastcert);
    1487           0 :       lastcert = cert;
    1488           0 :       cert = NULL;
    1489             :     }
    1490           0 :   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
    1491           0 :     rc = 0;
    1492           0 :   if (rc)
    1493           0 :     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
    1494             : 
    1495             :  leave:
    1496           0 :   ksba_cert_release (cert);
    1497           0 :   ksba_cert_release (lastcert);
    1498           0 :   xfree (desc);
    1499           0 :   keydb_release (hd);
    1500           0 :   return rc;
    1501             : }
    1502             : 
    1503             : 
    1504             : 
    1505             : static void
    1506           0 : list_external_cb (void *cb_value, ksba_cert_t cert)
    1507             : {
    1508           0 :   struct list_external_parm_s *parm = cb_value;
    1509             : 
    1510           0 :   if (keydb_store_cert (cert, 1, NULL))
    1511           0 :     log_error ("error storing certificate as ephemeral\n");
    1512             : 
    1513           0 :   if (parm->print_header)
    1514             :     {
    1515           0 :       const char *resname = "[external keys]";
    1516             :       int i;
    1517             : 
    1518           0 :       es_fprintf (parm->fp, "%s\n", resname );
    1519           0 :       for (i=strlen(resname); i; i-- )
    1520           0 :         es_putc('-', parm->fp);
    1521           0 :       es_putc ('\n', parm->fp);
    1522           0 :       parm->print_header = 0;
    1523             :     }
    1524             : 
    1525           0 :   if (parm->with_colons)
    1526           0 :     list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
    1527           0 :   else if (parm->with_chain)
    1528           0 :     list_cert_chain (parm->ctrl, NULL, cert, parm->raw_mode, parm->fp, 0);
    1529             :   else
    1530             :     {
    1531           0 :       if (parm->raw_mode)
    1532           0 :         list_cert_raw (parm->ctrl, NULL, cert, parm->fp, 0, 0);
    1533             :       else
    1534           0 :         list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
    1535           0 :       es_putc ('\n', parm->fp);
    1536             :     }
    1537           0 : }
    1538             : 
    1539             : 
    1540             : /* List external keys similar to internal one.  Note: mode does not
    1541             :    make sense here because it would be unwise to list external secret
    1542             :    keys */
    1543             : static gpg_error_t
    1544           0 : list_external_keys (ctrl_t ctrl, strlist_t names, estream_t fp, int raw_mode)
    1545             : {
    1546             :   int rc;
    1547             :   struct list_external_parm_s parm;
    1548             : 
    1549           0 :   parm.fp = fp;
    1550           0 :   parm.ctrl = ctrl,
    1551           0 :   parm.print_header = ctrl->no_server;
    1552           0 :   parm.with_colons = ctrl->with_colons;
    1553           0 :   parm.with_chain = ctrl->with_chain;
    1554           0 :   parm.raw_mode  = raw_mode;
    1555             : 
    1556           0 :   rc = gpgsm_dirmngr_lookup (ctrl, names, 0, list_external_cb, &parm);
    1557           0 :   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1
    1558           0 :       || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
    1559           0 :     rc = 0; /* "Not found" is not an error here. */
    1560           0 :   if (rc)
    1561           0 :     log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
    1562           0 :   return rc;
    1563             : }
    1564             : 
    1565             : /* List all keys or just the key given as NAMES.
    1566             :    MODE controls the operation mode:
    1567             :     Bit 0-2:
    1568             :       0 = list all public keys but don't flag secret ones
    1569             :       1 = list only public keys
    1570             :       2 = list only secret keys
    1571             :       3 = list secret and public keys
    1572             :     Bit 6: list internal keys
    1573             :     Bit 7: list external keys
    1574             :     Bit 8: Do a raw format dump.
    1575             :  */
    1576             : gpg_error_t
    1577           0 : gpgsm_list_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
    1578             :                  unsigned int mode)
    1579             : {
    1580           0 :   gpg_error_t err = 0;
    1581             : 
    1582           0 :   if ((mode & (1<<6)))
    1583           0 :     err = list_internal_keys (ctrl, names, fp, (mode & 3), (mode&256));
    1584           0 :   if (!err && (mode & (1<<7)))
    1585           0 :     err = list_external_keys (ctrl, names, fp, (mode&256));
    1586           0 :   return err;
    1587             : }

Generated by: LCOV version 1.11