LCOV - code coverage report
Current view: top level - sm - keylist.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 759 0.0 %
Date: 2015-11-05 17:10:59 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           0 :   es_putc (':', fp);
     498             :   /* Field 13, not used: */
     499           0 :   es_putc (':', fp);
     500           0 :   if (have_secret || ctrl->with_secret)
     501             :     {
     502             :       char *cardsn;
     503             : 
     504           0 :       p = gpgsm_get_keygrip_hexstring (cert);
     505           0 :       if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn)
     506           0 :           && (cardsn || ctrl->with_secret))
     507             :         {
     508             :           /* Field 14, not used: */
     509           0 :           es_putc (':', fp);
     510             :           /* Field 15:  Token serial number or secret key indicator.  */
     511           0 :           if (cardsn)
     512           0 :             es_fputs (cardsn, fp);
     513           0 :           else if (ctrl->with_secret)
     514           0 :             es_putc ('+', fp);
     515           0 :           es_putc (':', fp);
     516             :         }
     517           0 :       xfree (cardsn);
     518           0 :       xfree (p);
     519             :     }
     520           0 :   es_putc ('\n', fp);
     521             : 
     522             :   /* FPR record */
     523           0 :   es_fprintf (fp, "fpr:::::::::%s:::", fpr);
     524             :   /* Print chaining ID (field 13)*/
     525           0 :   if (chain_id)
     526           0 :     es_fputs (chain_id, fp);
     527           0 :   es_putc (':', fp);
     528           0 :   es_putc ('\n', fp);
     529           0 :   xfree (fpr); fpr = NULL; chain_id = NULL;
     530           0 :   xfree (chain_id_buffer); chain_id_buffer = NULL;
     531             : 
     532           0 :   if (opt.with_key_data)
     533             :     {
     534           0 :       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
     535             :         {
     536           0 :           es_fprintf (fp, "grp:::::::::%s:\n", p);
     537           0 :           xfree (p);
     538             :         }
     539           0 :       print_key_data (cert, fp);
     540             :     }
     541             : 
     542           0 :   kludge_uid = NULL;
     543           0 :   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
     544             :     {
     545             :       /* In the case that the same email address is in the subject DN
     546             :          as well as in an alternate subject name we avoid printing it
     547             :          a second time. */
     548           0 :       if (kludge_uid && !strcmp (kludge_uid, p))
     549           0 :         continue;
     550             : 
     551           0 :       es_fprintf (fp, "uid:%s::::::::", truststring);
     552           0 :       es_write_sanitized (fp, p, strlen (p), ":", NULL);
     553           0 :       es_putc (':', fp);
     554           0 :       es_putc (':', fp);
     555           0 :       es_putc ('\n', fp);
     556           0 :       if (!idx)
     557             :         {
     558             :           /* It would be better to get the faked email address from
     559             :              the keydb.  But as long as we don't have a way to pass
     560             :              the meta data back, we just check it the same way as the
     561             :              code used to create the keybox meta data does */
     562           0 :           kludge_uid = email_kludge (p);
     563           0 :           if (kludge_uid)
     564             :             {
     565           0 :               es_fprintf (fp, "uid:%s::::::::", truststring);
     566           0 :               es_write_sanitized (fp, kludge_uid, strlen (kludge_uid),
     567             :                                   ":", NULL);
     568           0 :               es_putc (':', fp);
     569           0 :               es_putc (':', fp);
     570           0 :               es_putc ('\n', fp);
     571             :             }
     572             :         }
     573           0 :       xfree (p);
     574             :     }
     575           0 :   xfree (kludge_uid);
     576           0 : }
     577             : 
     578             : 
     579             : static void
     580           0 : print_name_raw (estream_t fp, const char *string)
     581             : {
     582           0 :   if (!string)
     583           0 :     es_fputs ("[error]", fp);
     584             :   else
     585           0 :     es_write_sanitized (fp, string, strlen (string), NULL, NULL);
     586           0 : }
     587             : 
     588             : static void
     589           0 : print_names_raw (estream_t fp, int indent, ksba_name_t name)
     590             : {
     591             :   int idx;
     592             :   const char *s;
     593             :   int indent_all;
     594             : 
     595           0 :   if ((indent_all = (indent < 0)))
     596           0 :     indent = - indent;
     597             : 
     598           0 :   if (!name)
     599             :     {
     600           0 :       es_fputs ("none\n", fp);
     601           0 :       return;
     602             :     }
     603             : 
     604           0 :   for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
     605             :     {
     606           0 :       char *p = ksba_name_get_uri (name, idx);
     607           0 :       es_fprintf (fp, "%*s", idx||indent_all?indent:0, "");
     608           0 :       es_write_sanitized (fp, p?p:s, strlen (p?p:s), NULL, NULL);
     609           0 :       es_putc ('\n', fp);
     610           0 :       xfree (p);
     611             :     }
     612             : }
     613             : 
     614             : 
     615             : static void
     616           0 : print_utf8_extn_raw (estream_t fp, int indent,
     617             :                      const unsigned char *der, size_t derlen)
     618             : {
     619             :   gpg_error_t err;
     620             :   int class, tag, constructed, ndef;
     621             :   size_t objlen, hdrlen;
     622             : 
     623           0 :   if (indent < 0)
     624           0 :     indent = - indent;
     625             : 
     626           0 :   err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
     627             :                           &ndef, &objlen, &hdrlen);
     628           0 :   if (!err && (objlen > derlen || tag != TAG_UTF8_STRING))
     629           0 :     err = gpg_error (GPG_ERR_INV_OBJ);
     630           0 :   if (err)
     631             :     {
     632           0 :       es_fprintf (fp, "%*s[%s]\n", indent, "", gpg_strerror (err));
     633           0 :       return;
     634             :     }
     635           0 :   es_fprintf (fp, "%*s(%.*s)\n", indent, "", (int)objlen, der);
     636             : }
     637             : 
     638             : 
     639             : static void
     640           0 : print_utf8_extn (estream_t fp, int indent,
     641             :                  const unsigned char *der, size_t derlen)
     642             : {
     643             :   gpg_error_t err;
     644             :   int class, tag, constructed, ndef;
     645             :   size_t objlen, hdrlen;
     646             :   int indent_all;
     647             : 
     648           0 :   if ((indent_all = (indent < 0)))
     649           0 :     indent = - indent;
     650             : 
     651           0 :   err = parse_ber_header (&der, &derlen, &class, &tag, &constructed,
     652             :                           &ndef, &objlen, &hdrlen);
     653           0 :   if (!err && (objlen > derlen || tag != TAG_UTF8_STRING))
     654           0 :     err = gpg_error (GPG_ERR_INV_OBJ);
     655           0 :   if (err)
     656             :     {
     657           0 :       es_fprintf (fp, "%*s[%s%s]\n",
     658             :                   indent_all? indent:0, "", _("Error - "), gpg_strerror (err));
     659           0 :       return;
     660             :     }
     661           0 :   es_fprintf (fp, "%*s\"", indent_all? indent:0, "");
     662             :   /* Fixme: we should implement word wrapping */
     663           0 :   es_write_sanitized (fp, der, objlen, "\"", NULL);
     664           0 :   es_fputs ("\"\n", fp);
     665             : }
     666             : 
     667             : 
     668             : /* List one certificate in raw mode useful to have a closer look at
     669             :    the certificate.  This one does no beautification and only minimal
     670             :    output sanitation.  It is mainly useful for debugging. */
     671             : static void
     672           0 : list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
     673             :                ksba_cert_t cert, estream_t fp, int have_secret,
     674             :                int with_validation)
     675             : {
     676             :   gpg_error_t err;
     677             :   size_t off, len;
     678             :   ksba_sexp_t sexp, keyid;
     679             :   char *dn;
     680             :   ksba_isotime_t t;
     681             :   int idx, i;
     682             :   int is_ca, chainlen;
     683             :   unsigned int kusage;
     684             :   char *string, *p, *pend;
     685             :   const char *oid, *s;
     686             :   ksba_name_t name, name2;
     687             :   unsigned int reason;
     688           0 :   const unsigned char *cert_der = NULL;
     689             : 
     690             :   (void)have_secret;
     691             : 
     692           0 :   es_fprintf (fp, "           ID: 0x%08lX\n",
     693             :               gpgsm_get_short_fingerprint (cert, NULL));
     694             : 
     695           0 :   sexp = ksba_cert_get_serial (cert);
     696           0 :   es_fputs ("          S/N: ", fp);
     697           0 :   gpgsm_print_serial (fp, sexp);
     698           0 :   ksba_free (sexp);
     699           0 :   es_putc ('\n', fp);
     700             : 
     701           0 :   dn = ksba_cert_get_issuer (cert, 0);
     702           0 :   es_fputs ("       Issuer: ", fp);
     703           0 :   print_name_raw (fp, dn);
     704           0 :   ksba_free (dn);
     705           0 :   es_putc ('\n', fp);
     706           0 :   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
     707             :     {
     708           0 :       es_fputs ("          aka: ", fp);
     709           0 :       print_name_raw (fp, dn);
     710           0 :       ksba_free (dn);
     711           0 :       es_putc ('\n', fp);
     712             :     }
     713             : 
     714           0 :   dn = ksba_cert_get_subject (cert, 0);
     715           0 :   es_fputs ("      Subject: ", fp);
     716           0 :   print_name_raw (fp, dn);
     717           0 :   ksba_free (dn);
     718           0 :   es_putc ('\n', fp);
     719           0 :   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
     720             :     {
     721           0 :       es_fputs ("          aka: ", fp);
     722           0 :       print_name_raw (fp, dn);
     723           0 :       ksba_free (dn);
     724           0 :       es_putc ('\n', fp);
     725             :     }
     726             : 
     727           0 :   dn = gpgsm_get_fingerprint_string (cert, 0);
     728           0 :   es_fprintf (fp, "     sha1_fpr: %s\n", dn?dn:"error");
     729           0 :   xfree (dn);
     730             : 
     731           0 :   dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
     732           0 :   es_fprintf (fp, "      md5_fpr: %s\n", dn?dn:"error");
     733           0 :   xfree (dn);
     734             : 
     735           0 :   dn = gpgsm_get_certid (cert);
     736           0 :   es_fprintf (fp, "       certid: %s\n", dn?dn:"error");
     737           0 :   xfree (dn);
     738             : 
     739           0 :   dn = gpgsm_get_keygrip_hexstring (cert);
     740           0 :   es_fprintf (fp, "      keygrip: %s\n", dn?dn:"error");
     741           0 :   xfree (dn);
     742             : 
     743           0 :   ksba_cert_get_validity (cert, 0, t);
     744           0 :   es_fputs ("    notBefore: ", fp);
     745           0 :   gpgsm_print_time (fp, t);
     746           0 :   es_putc ('\n', fp);
     747           0 :   es_fputs ("     notAfter: ", fp);
     748           0 :   ksba_cert_get_validity (cert, 1, t);
     749           0 :   gpgsm_print_time (fp, t);
     750           0 :   es_putc ('\n', fp);
     751             : 
     752           0 :   oid = ksba_cert_get_digest_algo (cert);
     753           0 :   s = get_oid_desc (oid, NULL);
     754           0 :   es_fprintf (fp, "     hashAlgo: %s%s%s%s\n", oid, s?" (":"",s?s:"",s?")":"");
     755             : 
     756             :   {
     757             :     const char *algoname;
     758             :     unsigned int nbits;
     759             : 
     760           0 :     algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
     761           0 :     es_fprintf (fp, "      keyType: %u bit %s\n",
     762             :                 nbits, algoname? algoname:"?");
     763             :   }
     764             : 
     765             :   /* subjectKeyIdentifier */
     766           0 :   es_fputs ("    subjKeyId: ", fp);
     767           0 :   err = ksba_cert_get_subj_key_id (cert, NULL, &keyid);
     768           0 :   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
     769             :     {
     770           0 :       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
     771           0 :         es_fputs ("[none]\n", fp);
     772             :       else
     773             :         {
     774           0 :           gpgsm_print_serial (fp, keyid);
     775           0 :           ksba_free (keyid);
     776           0 :           es_putc ('\n', fp);
     777             :         }
     778             :     }
     779             :   else
     780           0 :     es_fputs ("[?]\n", fp);
     781             : 
     782             : 
     783             :   /* authorityKeyIdentifier */
     784           0 :   es_fputs ("    authKeyId: ", fp);
     785           0 :   err = ksba_cert_get_auth_key_id (cert, &keyid, &name, &sexp);
     786           0 :   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
     787             :     {
     788           0 :       if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name)
     789           0 :         es_fputs ("[none]\n", fp);
     790             :       else
     791             :         {
     792           0 :           gpgsm_print_serial (fp, sexp);
     793           0 :           ksba_free (sexp);
     794           0 :           es_putc ('\n', fp);
     795           0 :           print_names_raw (fp, -15, name);
     796           0 :           ksba_name_release (name);
     797             :         }
     798           0 :       if (keyid)
     799             :         {
     800           0 :           es_fputs (" authKeyId.ki: ", fp);
     801           0 :           gpgsm_print_serial (fp, keyid);
     802           0 :           ksba_free (keyid);
     803           0 :           es_putc ('\n', fp);
     804             :         }
     805             :     }
     806             :   else
     807           0 :     es_fputs ("[?]\n", fp);
     808             : 
     809           0 :   es_fputs ("     keyUsage:", fp);
     810           0 :   err = ksba_cert_get_key_usage (cert, &kusage);
     811           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
     812             :     {
     813           0 :       if (err)
     814           0 :         es_fprintf (fp, " [error: %s]", gpg_strerror (err));
     815             :       else
     816             :         {
     817           0 :           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
     818           0 :             es_fputs (" digitalSignature", fp);
     819           0 :           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
     820           0 :             es_fputs (" nonRepudiation", fp);
     821           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
     822           0 :             es_fputs (" keyEncipherment", fp);
     823           0 :           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
     824           0 :             es_fputs (" dataEncipherment", fp);
     825           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
     826           0 :             es_fputs (" keyAgreement", fp);
     827           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
     828           0 :             es_fputs (" certSign", fp);
     829           0 :           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
     830           0 :             es_fputs (" crlSign", fp);
     831           0 :           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
     832           0 :             es_fputs (" encipherOnly", fp);
     833           0 :           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
     834           0 :             es_fputs (" decipherOnly", fp);
     835             :         }
     836           0 :       es_putc ('\n', fp);
     837             :     }
     838             :   else
     839           0 :     es_fputs (" [none]\n", fp);
     840             : 
     841           0 :   es_fputs ("  extKeyUsage: ", fp);
     842           0 :   err = ksba_cert_get_ext_key_usages (cert, &string);
     843           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
     844             :     {
     845           0 :       if (err)
     846           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
     847             :       else
     848             :         {
     849           0 :           p = string;
     850           0 :           while (p && (pend=strchr (p, ':')))
     851             :             {
     852           0 :               *pend++ = 0;
     853           0 :               for (i=0; key_purpose_map[i].oid; i++)
     854           0 :                 if ( !strcmp (key_purpose_map[i].oid, p) )
     855           0 :                   break;
     856           0 :               es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
     857           0 :               p = pend;
     858           0 :               if (*p != 'C')
     859           0 :                 es_fputs (" (suggested)", fp);
     860           0 :               if ((p = strchr (p, '\n')))
     861             :                 {
     862           0 :                   p++;
     863           0 :                   es_fputs ("\n               ", fp);
     864             :                 }
     865             :             }
     866           0 :           xfree (string);
     867             :         }
     868           0 :       es_putc ('\n', fp);
     869             :     }
     870             :   else
     871           0 :     es_fputs ("[none]\n", fp);
     872             : 
     873             : 
     874           0 :   es_fputs ("     policies: ", fp);
     875           0 :   err = ksba_cert_get_cert_policies (cert, &string);
     876           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
     877             :     {
     878           0 :       if (err)
     879           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
     880             :       else
     881             :         {
     882           0 :           p = string;
     883           0 :           while (p && (pend=strchr (p, ':')))
     884             :             {
     885           0 :               *pend++ = 0;
     886           0 :               for (i=0; key_purpose_map[i].oid; i++)
     887           0 :                 if ( !strcmp (key_purpose_map[i].oid, p) )
     888           0 :                   break;
     889           0 :               es_fputs (p, fp);
     890           0 :               p = pend;
     891           0 :               if (*p == 'C')
     892           0 :                 es_fputs (" (critical)", fp);
     893           0 :               if ((p = strchr (p, '\n')))
     894             :                 {
     895           0 :                   p++;
     896           0 :                   es_fputs ("\n               ", fp);
     897             :                 }
     898             :             }
     899           0 :           xfree (string);
     900             :         }
     901           0 :       es_putc ('\n', fp);
     902             :     }
     903             :   else
     904           0 :     es_fputs ("[none]\n", fp);
     905             : 
     906           0 :   es_fputs ("  chainLength: ", fp);
     907           0 :   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
     908           0 :   if (err || is_ca)
     909             :     {
     910           0 :       if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
     911           0 :         es_fprintf (fp, "[none]");
     912           0 :       else if (err)
     913           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
     914           0 :       else if (chainlen == -1)
     915           0 :         es_fputs ("unlimited", fp);
     916             :       else
     917           0 :         es_fprintf (fp, "%d", chainlen);
     918           0 :       es_putc ('\n', fp);
     919             :     }
     920             :   else
     921           0 :     es_fputs ("not a CA\n", fp);
     922             : 
     923             : 
     924             :   /* CRL distribution point */
     925           0 :   for (idx=0; !(err=ksba_cert_get_crl_dist_point (cert, idx, &name, &name2,
     926           0 :                                                   &reason)) ;idx++)
     927             :     {
     928           0 :       es_fputs ("        crlDP: ", fp);
     929           0 :       print_names_raw (fp, 15, name);
     930           0 :       if (reason)
     931             :         {
     932           0 :           es_fputs ("               reason: ", fp);
     933           0 :           if ( (reason & KSBA_CRLREASON_UNSPECIFIED))
     934           0 :             es_fputs (" unused", fp);
     935           0 :           if ( (reason & KSBA_CRLREASON_KEY_COMPROMISE))
     936           0 :             es_fputs (" keyCompromise", fp);
     937           0 :           if ( (reason & KSBA_CRLREASON_CA_COMPROMISE))
     938           0 :             es_fputs (" caCompromise", fp);
     939           0 :           if ( (reason & KSBA_CRLREASON_AFFILIATION_CHANGED))
     940           0 :             es_fputs (" affiliationChanged", fp);
     941           0 :           if ( (reason & KSBA_CRLREASON_SUPERSEDED))
     942           0 :             es_fputs (" superseded", fp);
     943           0 :           if ( (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION))
     944           0 :             es_fputs (" cessationOfOperation", fp);
     945           0 :           if ( (reason & KSBA_CRLREASON_CERTIFICATE_HOLD))
     946           0 :             es_fputs (" certificateHold", fp);
     947           0 :           es_putc ('\n', fp);
     948             :         }
     949           0 :       es_fputs ("               issuer: ", fp);
     950           0 :       print_names_raw (fp, 23, name2);
     951           0 :       ksba_name_release (name);
     952           0 :       ksba_name_release (name2);
     953             :     }
     954           0 :   if (err && gpg_err_code (err) != GPG_ERR_EOF
     955           0 :       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
     956           0 :     es_fputs ("        crlDP: [error]\n", fp);
     957           0 :   else if (!idx)
     958           0 :     es_fputs ("        crlDP: [none]\n", fp);
     959             : 
     960             : 
     961             :   /* authorityInfoAccess. */
     962           0 :   for (idx=0; !(err=ksba_cert_get_authority_info_access (cert, idx, &string,
     963           0 :                                                          &name)); idx++)
     964             :     {
     965           0 :       es_fputs ("     authInfo: ", fp);
     966           0 :       s = get_oid_desc (string, NULL);
     967           0 :       es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
     968           0 :       print_names_raw (fp, -15, name);
     969           0 :       ksba_name_release (name);
     970           0 :       ksba_free (string);
     971             :     }
     972           0 :   if (err && gpg_err_code (err) != GPG_ERR_EOF
     973           0 :       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
     974           0 :     es_fputs ("     authInfo: [error]\n", fp);
     975           0 :   else if (!idx)
     976           0 :     es_fputs ("     authInfo: [none]\n", fp);
     977             : 
     978             :   /* subjectInfoAccess. */
     979           0 :   for (idx=0; !(err=ksba_cert_get_subject_info_access (cert, idx, &string,
     980           0 :                                                          &name)); idx++)
     981             :     {
     982           0 :       es_fputs ("  subjectInfo: ", fp);
     983           0 :       s = get_oid_desc (string, NULL);
     984           0 :       es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
     985           0 :       print_names_raw (fp, -15, name);
     986           0 :       ksba_name_release (name);
     987           0 :       ksba_free (string);
     988             :     }
     989           0 :   if (err && gpg_err_code (err) != GPG_ERR_EOF
     990           0 :       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
     991           0 :     es_fputs ("     subjInfo: [error]\n", fp);
     992           0 :   else if (!idx)
     993           0 :     es_fputs ("     subjInfo: [none]\n", fp);
     994             : 
     995             : 
     996           0 :   for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
     997           0 :                                              &oid, &i, &off, &len));idx++)
     998             :     {
     999             :       unsigned int flag;
    1000             : 
    1001           0 :       s = get_oid_desc (oid, &flag);
    1002           0 :       if ((flag & OID_FLAG_SKIP))
    1003           0 :         continue;
    1004             : 
    1005           0 :       es_fprintf (fp, "     %s: %s%s%s%s  [%d octets]\n",
    1006           0 :                   i? "critExtn":"    extn",
    1007             :                   oid, s?" (":"", s?s:"", s?")":"", (int)len);
    1008           0 :       if ((flag & OID_FLAG_UTF8))
    1009             :         {
    1010           0 :           if (!cert_der)
    1011           0 :             cert_der = ksba_cert_get_image (cert, NULL);
    1012           0 :           assert (cert_der);
    1013           0 :           print_utf8_extn_raw (fp, -15, cert_der+off, len);
    1014             :         }
    1015             :     }
    1016             : 
    1017             : 
    1018           0 :   if (with_validation)
    1019             :     {
    1020           0 :       err = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, fp, 0, NULL);
    1021           0 :       if (!err)
    1022           0 :         es_fprintf (fp, "  [certificate is good]\n");
    1023             :       else
    1024           0 :         es_fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
    1025             :     }
    1026             : 
    1027           0 :   if (hd)
    1028             :     {
    1029             :       unsigned int blobflags;
    1030             : 
    1031           0 :       err = keydb_get_flags (hd, KEYBOX_FLAG_BLOB, 0, &blobflags);
    1032           0 :       if (err)
    1033           0 :         es_fprintf (fp, "  [error getting keyflags: %s]\n",gpg_strerror (err));
    1034           0 :       else if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
    1035           0 :         es_fprintf (fp, "  [stored as ephemeral]\n");
    1036             :     }
    1037             : 
    1038           0 : }
    1039             : 
    1040             : 
    1041             : 
    1042             : 
    1043             : /* List one certificate in standard mode */
    1044             : static void
    1045           0 : list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
    1046             :                int with_validation)
    1047             : {
    1048             :   gpg_error_t err;
    1049             :   ksba_sexp_t sexp;
    1050             :   char *dn;
    1051             :   ksba_isotime_t t;
    1052             :   int idx, i;
    1053             :   int is_ca, chainlen;
    1054             :   unsigned int kusage;
    1055             :   char *string, *p, *pend;
    1056             :   size_t off, len;
    1057             :   const char *oid;
    1058           0 :   const unsigned char *cert_der = NULL;
    1059             : 
    1060             : 
    1061           0 :   es_fprintf (fp, "           ID: 0x%08lX\n",
    1062             :               gpgsm_get_short_fingerprint (cert, NULL));
    1063             : 
    1064           0 :   sexp = ksba_cert_get_serial (cert);
    1065           0 :   es_fputs ("          S/N: ", fp);
    1066           0 :   gpgsm_print_serial (fp, sexp);
    1067           0 :   ksba_free (sexp);
    1068           0 :   es_putc ('\n', fp);
    1069             : 
    1070           0 :   dn = ksba_cert_get_issuer (cert, 0);
    1071           0 :   es_fputs ("       Issuer: ", fp);
    1072           0 :   gpgsm_es_print_name (fp, dn);
    1073           0 :   ksba_free (dn);
    1074           0 :   es_putc ('\n', fp);
    1075           0 :   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
    1076             :     {
    1077           0 :       es_fputs ("          aka: ", fp);
    1078           0 :       gpgsm_es_print_name (fp, dn);
    1079           0 :       ksba_free (dn);
    1080           0 :       es_putc ('\n', fp);
    1081             :     }
    1082             : 
    1083           0 :   dn = ksba_cert_get_subject (cert, 0);
    1084           0 :   es_fputs ("      Subject: ", fp);
    1085           0 :   gpgsm_es_print_name (fp, dn);
    1086           0 :   ksba_free (dn);
    1087           0 :   es_putc ('\n', fp);
    1088           0 :   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
    1089             :     {
    1090           0 :       es_fputs ("          aka: ", fp);
    1091           0 :       gpgsm_es_print_name (fp, dn);
    1092           0 :       ksba_free (dn);
    1093           0 :       es_putc ('\n', fp);
    1094             :     }
    1095             : 
    1096           0 :   ksba_cert_get_validity (cert, 0, t);
    1097           0 :   es_fputs ("     validity: ", fp);
    1098           0 :   gpgsm_print_time (fp, t);
    1099           0 :   es_fputs (" through ", fp);
    1100           0 :   ksba_cert_get_validity (cert, 1, t);
    1101           0 :   gpgsm_print_time (fp, t);
    1102           0 :   es_putc ('\n', fp);
    1103             : 
    1104             : 
    1105             :   {
    1106             :     const char *algoname;
    1107             :     unsigned int nbits;
    1108             : 
    1109           0 :     algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
    1110           0 :     es_fprintf (fp, "     key type: %u bit %s\n",
    1111             :                 nbits, algoname? algoname:"?");
    1112             :   }
    1113             : 
    1114             : 
    1115           0 :   err = ksba_cert_get_key_usage (cert, &kusage);
    1116           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
    1117             :     {
    1118           0 :       es_fputs ("    key usage:", fp);
    1119           0 :       if (err)
    1120           0 :         es_fprintf (fp, " [error: %s]", gpg_strerror (err));
    1121             :       else
    1122             :         {
    1123           0 :           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
    1124           0 :             es_fputs (" digitalSignature", fp);
    1125           0 :           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))
    1126           0 :             es_fputs (" nonRepudiation", fp);
    1127           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
    1128           0 :             es_fputs (" keyEncipherment", fp);
    1129           0 :           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
    1130           0 :             es_fputs (" dataEncipherment", fp);
    1131           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))
    1132           0 :             es_fputs (" keyAgreement", fp);
    1133           0 :           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
    1134           0 :             es_fputs (" certSign", fp);
    1135           0 :           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))
    1136           0 :             es_fputs (" crlSign", fp);
    1137           0 :           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
    1138           0 :             es_fputs (" encipherOnly", fp);
    1139           0 :           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))
    1140           0 :             es_fputs (" decipherOnly", fp);
    1141             :         }
    1142           0 :       es_putc ('\n', fp);
    1143             :     }
    1144             : 
    1145           0 :   err = ksba_cert_get_ext_key_usages (cert, &string);
    1146           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
    1147             :     {
    1148           0 :       es_fputs ("ext key usage: ", fp);
    1149           0 :       if (err)
    1150           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
    1151             :       else
    1152             :         {
    1153           0 :           p = string;
    1154           0 :           while (p && (pend=strchr (p, ':')))
    1155             :             {
    1156           0 :               *pend++ = 0;
    1157           0 :               for (i=0; key_purpose_map[i].oid; i++)
    1158           0 :                 if ( !strcmp (key_purpose_map[i].oid, p) )
    1159           0 :                   break;
    1160           0 :               es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
    1161           0 :               p = pend;
    1162           0 :               if (*p != 'C')
    1163           0 :                 es_fputs (" (suggested)", fp);
    1164           0 :               if ((p = strchr (p, '\n')))
    1165             :                 {
    1166           0 :                   p++;
    1167           0 :                   es_fputs (", ", fp);
    1168             :                 }
    1169             :             }
    1170           0 :           xfree (string);
    1171             :         }
    1172           0 :       es_putc ('\n', fp);
    1173             :     }
    1174             : 
    1175             :   /* Print restrictions.  */
    1176           0 :   for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
    1177           0 :                                              &oid, NULL, &off, &len));idx++)
    1178             :     {
    1179           0 :       if (!strcmp (oid, OIDSTR_restriction) )
    1180             :         {
    1181           0 :           if (!cert_der)
    1182           0 :             cert_der = ksba_cert_get_image (cert, NULL);
    1183           0 :           assert (cert_der);
    1184           0 :           es_fputs ("  restriction: ", fp);
    1185           0 :           print_utf8_extn (fp, 15, cert_der+off, len);
    1186             :         }
    1187             :     }
    1188             : 
    1189             :   /* Print policies.  */
    1190           0 :   err = ksba_cert_get_cert_policies (cert, &string);
    1191           0 :   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
    1192             :     {
    1193           0 :       es_fputs ("     policies: ", fp);
    1194           0 :       if (err)
    1195           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
    1196             :       else
    1197             :         {
    1198           0 :           for (p=string; *p; p++)
    1199             :             {
    1200           0 :               if (*p == '\n')
    1201           0 :                 *p = ',';
    1202             :             }
    1203           0 :           es_write_sanitized (fp, string, strlen (string), NULL, NULL);
    1204           0 :           xfree (string);
    1205             :         }
    1206           0 :       es_putc ('\n', fp);
    1207             :     }
    1208             : 
    1209           0 :   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
    1210           0 :   if (err || is_ca)
    1211             :     {
    1212           0 :       es_fputs (" chain length: ", fp);
    1213           0 :       if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
    1214           0 :         es_fprintf (fp, "none");
    1215           0 :       else if (err)
    1216           0 :         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
    1217           0 :       else if (chainlen == -1)
    1218           0 :         es_fputs ("unlimited", fp);
    1219             :       else
    1220           0 :         es_fprintf (fp, "%d", chainlen);
    1221           0 :       es_putc ('\n', fp);
    1222             :     }
    1223             : 
    1224           0 :   if (opt.with_md5_fingerprint)
    1225             :     {
    1226           0 :       dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
    1227           0 :       es_fprintf (fp, "      md5 fpr: %s\n", dn?dn:"error");
    1228           0 :       xfree (dn);
    1229             :     }
    1230             : 
    1231           0 :   dn = gpgsm_get_fingerprint_string (cert, 0);
    1232           0 :   es_fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
    1233           0 :   xfree (dn);
    1234             : 
    1235           0 :   if (opt.with_keygrip)
    1236             :     {
    1237           0 :       dn = gpgsm_get_keygrip_hexstring (cert);
    1238           0 :       if (dn)
    1239             :         {
    1240           0 :           es_fprintf (fp, "      keygrip: %s\n", dn);
    1241           0 :           xfree (dn);
    1242             :         }
    1243             :     }
    1244             : 
    1245           0 :   if (have_secret)
    1246             :     {
    1247             :       char *cardsn;
    1248             : 
    1249           0 :       p = gpgsm_get_keygrip_hexstring (cert);
    1250           0 :       if (!gpgsm_agent_keyinfo (ctrl, p, &cardsn) && cardsn)
    1251           0 :         es_fprintf (fp, "     card s/n: %s\n", cardsn);
    1252           0 :       xfree (cardsn);
    1253           0 :       xfree (p);
    1254             :     }
    1255             : 
    1256           0 :   if (with_validation)
    1257             :     {
    1258             :       gpg_error_t tmperr;
    1259             :       size_t buflen;
    1260             :       char buffer[1];
    1261             : 
    1262           0 :       err = gpgsm_validate_chain (ctrl, cert, "", NULL, 1, fp, 0, NULL);
    1263           0 :       tmperr = ksba_cert_get_user_data (cert, "is_qualified",
    1264             :                                         &buffer, sizeof (buffer), &buflen);
    1265           0 :       if (!tmperr && buflen)
    1266             :         {
    1267           0 :           if (*buffer)
    1268           0 :             es_fputs ("  [qualified]\n", fp);
    1269             :         }
    1270           0 :       else if (gpg_err_code (tmperr) == GPG_ERR_NOT_FOUND)
    1271             :         ; /* Don't know - will not get marked as 'q' */
    1272             :       else
    1273           0 :         log_debug ("get_user_data(is_qualified) failed: %s\n",
    1274             :                    gpg_strerror (tmperr));
    1275             : 
    1276           0 :       if (!err)
    1277           0 :         es_fprintf (fp, "  [certificate is good]\n");
    1278             :       else
    1279           0 :         es_fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
    1280             :     }
    1281           0 : }
    1282             : 
    1283             : 
    1284             : /* Same as standard mode mode list all certifying certs too. */
    1285             : static void
    1286           0 : list_cert_chain (ctrl_t ctrl, KEYDB_HANDLE hd,
    1287             :                  ksba_cert_t cert, int raw_mode,
    1288             :                  estream_t fp, int with_validation)
    1289             : {
    1290           0 :   ksba_cert_t next = NULL;
    1291             : 
    1292           0 :   if (raw_mode)
    1293           0 :     list_cert_raw (ctrl, hd, cert, fp, 0, with_validation);
    1294             :   else
    1295           0 :     list_cert_std (ctrl, cert, fp, 0, with_validation);
    1296           0 :   ksba_cert_ref (cert);
    1297           0 :   while (!gpgsm_walk_cert_chain (ctrl, cert, &next))
    1298             :     {
    1299           0 :       ksba_cert_release (cert);
    1300           0 :       es_fputs ("Certified by\n", fp);
    1301           0 :       if (raw_mode)
    1302           0 :         list_cert_raw (ctrl, hd, next, fp, 0, with_validation);
    1303             :       else
    1304           0 :         list_cert_std (ctrl, next, fp, 0, with_validation);
    1305           0 :       cert = next;
    1306             :     }
    1307           0 :   ksba_cert_release (cert);
    1308           0 :   es_putc ('\n', fp);
    1309           0 : }
    1310             : 
    1311             : 
    1312             : 
    1313             : /* List all internal keys or just the keys given as NAMES.  MODE is a
    1314             :    bit vector to specify what keys are to be included; see
    1315             :    gpgsm_list_keys (below) for details.  If RAW_MODE is true, the raw
    1316             :    output mode will be used instead of the standard beautified one.
    1317             :  */
    1318             : static gpg_error_t
    1319           0 : list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
    1320             :                     unsigned int mode, int raw_mode)
    1321             : {
    1322             :   KEYDB_HANDLE hd;
    1323           0 :   KEYDB_SEARCH_DESC *desc = NULL;
    1324             :   strlist_t sl;
    1325             :   int ndesc;
    1326           0 :   ksba_cert_t cert = NULL;
    1327           0 :   ksba_cert_t lastcert = NULL;
    1328           0 :   gpg_error_t rc = 0;
    1329             :   const char *lastresname, *resname;
    1330             :   int have_secret;
    1331           0 :   int want_ephemeral = ctrl->with_ephemeral_keys;
    1332             : 
    1333           0 :   hd = keydb_new (0);
    1334           0 :   if (!hd)
    1335             :     {
    1336           0 :       log_error ("keydb_new failed\n");
    1337           0 :       rc = gpg_error (GPG_ERR_GENERAL);
    1338           0 :       goto leave;
    1339             :     }
    1340             : 
    1341           0 :   if (!names)
    1342           0 :     ndesc = 1;
    1343             :   else
    1344             :     {
    1345           0 :       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
    1346             :         ;
    1347             :     }
    1348             : 
    1349           0 :   desc = xtrycalloc (ndesc, sizeof *desc);
    1350           0 :   if (!ndesc)
    1351             :     {
    1352           0 :       rc = gpg_error_from_syserror ();
    1353           0 :       log_error ("out of core\n");
    1354           0 :       goto leave;
    1355             :     }
    1356             : 
    1357           0 :   if (!names)
    1358           0 :     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
    1359             :   else
    1360             :     {
    1361           0 :       for (ndesc=0, sl=names; sl; sl = sl->next)
    1362             :         {
    1363           0 :           rc = classify_user_id (sl->d, desc+ndesc, 0);
    1364           0 :           if (rc)
    1365             :             {
    1366           0 :               log_error ("key '%s' not found: %s\n",
    1367           0 :                          sl->d, gpg_strerror (rc));
    1368           0 :               rc = 0;
    1369             :             }
    1370             :           else
    1371           0 :             ndesc++;
    1372             :         }
    1373             : 
    1374             :     }
    1375             : 
    1376             :   /* If all specifications are done by fingerprint or keygrip, we
    1377             :      switch to ephemeral mode so that _all_ currently available and
    1378             :      matching certificates are listed.  */
    1379           0 :   if (!want_ephemeral && names && ndesc)
    1380             :     {
    1381             :       int i;
    1382             : 
    1383           0 :       for (i=0; (i < ndesc
    1384           0 :                  && (desc[i].mode == KEYDB_SEARCH_MODE_FPR
    1385           0 :                      || desc[i].mode == KEYDB_SEARCH_MODE_FPR20
    1386           0 :                      || desc[i].mode == KEYDB_SEARCH_MODE_FPR16
    1387           0 :                      || desc[i].mode == KEYDB_SEARCH_MODE_KEYGRIP)); i++)
    1388             :         ;
    1389           0 :       if (i == ndesc)
    1390           0 :         want_ephemeral = 1;
    1391             :     }
    1392             : 
    1393           0 :   if (want_ephemeral)
    1394           0 :     keydb_set_ephemeral (hd, 1);
    1395             : 
    1396             :   /* It would be nice to see which of the given users did actually
    1397             :      match one in the keyring.  To implement this we need to have a
    1398             :      found flag for each entry in desc and to set this we must check
    1399             :      all those entries after a match to mark all matched one -
    1400             :      currently we stop at the first match.  To do this we need an
    1401             :      extra flag to enable this feature so */
    1402             : 
    1403             :   /* Suppress duplicates at least when they follow each other.  */
    1404           0 :   lastresname = NULL;
    1405           0 :   while (!(rc = keydb_search (hd, desc, ndesc)))
    1406             :     {
    1407             :       unsigned int validity;
    1408             : 
    1409           0 :       if (!names)
    1410           0 :         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
    1411             : 
    1412           0 :       rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
    1413           0 :       if (rc)
    1414             :         {
    1415           0 :           log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
    1416           0 :           goto leave;
    1417             :         }
    1418           0 :       rc = keydb_get_cert (hd, &cert);
    1419           0 :       if (rc)
    1420             :         {
    1421           0 :           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
    1422           0 :           goto leave;
    1423             :         }
    1424             :       /* Skip duplicated certificates, at least if they follow each
    1425             :          others.  This works best if a single key is searched for and
    1426             :          expected.  FIXME: Non-sequential duplicates remain.  */
    1427           0 :       if (gpgsm_certs_identical_p (cert, lastcert))
    1428             :         {
    1429           0 :           ksba_cert_release (cert);
    1430           0 :           cert = NULL;
    1431           0 :           continue;
    1432             :         }
    1433             : 
    1434           0 :       resname = keydb_get_resource_name (hd);
    1435             : 
    1436           0 :       if (lastresname != resname )
    1437             :         {
    1438             :           int i;
    1439             : 
    1440           0 :           if (ctrl->no_server)
    1441             :             {
    1442           0 :               es_fprintf (fp, "%s\n", resname );
    1443           0 :               for (i=strlen(resname); i; i-- )
    1444           0 :                 es_putc ('-', fp);
    1445           0 :               es_putc ('\n', fp);
    1446           0 :               lastresname = resname;
    1447             :             }
    1448             :         }
    1449             : 
    1450           0 :       have_secret = 0;
    1451           0 :       if (mode)
    1452             :         {
    1453           0 :           char *p = gpgsm_get_keygrip_hexstring (cert);
    1454           0 :           if (p)
    1455             :             {
    1456           0 :               rc = gpgsm_agent_havekey (ctrl, p);
    1457           0 :               if (!rc)
    1458           0 :                 have_secret = 1;
    1459           0 :               else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
    1460           0 :                 goto leave;
    1461           0 :               rc = 0;
    1462           0 :               xfree (p);
    1463             :             }
    1464             :         }
    1465             : 
    1466           0 :       if (!mode
    1467           0 :           || ((mode & 1) && !have_secret)
    1468           0 :           || ((mode & 2) && have_secret)  )
    1469             :         {
    1470           0 :           if (ctrl->with_colons)
    1471           0 :             list_cert_colon (ctrl, cert, validity, fp, have_secret);
    1472           0 :           else if (ctrl->with_chain)
    1473           0 :             list_cert_chain (ctrl, hd, cert,
    1474             :                              raw_mode, fp, ctrl->with_validation);
    1475             :           else
    1476             :             {
    1477           0 :               if (raw_mode)
    1478           0 :                 list_cert_raw (ctrl, hd, cert, fp, have_secret,
    1479             :                                ctrl->with_validation);
    1480             :               else
    1481           0 :                 list_cert_std (ctrl, cert, fp, have_secret,
    1482             :                                ctrl->with_validation);
    1483           0 :               es_putc ('\n', fp);
    1484             :             }
    1485             :         }
    1486             : 
    1487           0 :       ksba_cert_release (lastcert);
    1488           0 :       lastcert = cert;
    1489           0 :       cert = NULL;
    1490             :     }
    1491           0 :   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
    1492           0 :     rc = 0;
    1493           0 :   if (rc)
    1494           0 :     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
    1495             : 
    1496             :  leave:
    1497           0 :   ksba_cert_release (cert);
    1498           0 :   ksba_cert_release (lastcert);
    1499           0 :   xfree (desc);
    1500           0 :   keydb_release (hd);
    1501           0 :   return rc;
    1502             : }
    1503             : 
    1504             : 
    1505             : 
    1506             : static void
    1507           0 : list_external_cb (void *cb_value, ksba_cert_t cert)
    1508             : {
    1509           0 :   struct list_external_parm_s *parm = cb_value;
    1510             : 
    1511           0 :   if (keydb_store_cert (cert, 1, NULL))
    1512           0 :     log_error ("error storing certificate as ephemeral\n");
    1513             : 
    1514           0 :   if (parm->print_header)
    1515             :     {
    1516           0 :       const char *resname = "[external keys]";
    1517             :       int i;
    1518             : 
    1519           0 :       es_fprintf (parm->fp, "%s\n", resname );
    1520           0 :       for (i=strlen(resname); i; i-- )
    1521           0 :         es_putc('-', parm->fp);
    1522           0 :       es_putc ('\n', parm->fp);
    1523           0 :       parm->print_header = 0;
    1524             :     }
    1525             : 
    1526           0 :   if (parm->with_colons)
    1527           0 :     list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
    1528           0 :   else if (parm->with_chain)
    1529           0 :     list_cert_chain (parm->ctrl, NULL, cert, parm->raw_mode, parm->fp, 0);
    1530             :   else
    1531             :     {
    1532           0 :       if (parm->raw_mode)
    1533           0 :         list_cert_raw (parm->ctrl, NULL, cert, parm->fp, 0, 0);
    1534             :       else
    1535           0 :         list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
    1536           0 :       es_putc ('\n', parm->fp);
    1537             :     }
    1538           0 : }
    1539             : 
    1540             : 
    1541             : /* List external keys similar to internal one.  Note: mode does not
    1542             :    make sense here because it would be unwise to list external secret
    1543             :    keys */
    1544             : static gpg_error_t
    1545           0 : list_external_keys (ctrl_t ctrl, strlist_t names, estream_t fp, int raw_mode)
    1546             : {
    1547             :   int rc;
    1548             :   struct list_external_parm_s parm;
    1549             : 
    1550           0 :   parm.fp = fp;
    1551           0 :   parm.ctrl = ctrl,
    1552           0 :   parm.print_header = ctrl->no_server;
    1553           0 :   parm.with_colons = ctrl->with_colons;
    1554           0 :   parm.with_chain = ctrl->with_chain;
    1555           0 :   parm.raw_mode  = raw_mode;
    1556             : 
    1557           0 :   rc = gpgsm_dirmngr_lookup (ctrl, names, 0, list_external_cb, &parm);
    1558           0 :   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1
    1559           0 :       || gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
    1560           0 :     rc = 0; /* "Not found" is not an error here. */
    1561           0 :   if (rc)
    1562           0 :     log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
    1563           0 :   return rc;
    1564             : }
    1565             : 
    1566             : /* List all keys or just the key given as NAMES.
    1567             :    MODE controls the operation mode:
    1568             :     Bit 0-2:
    1569             :       0 = list all public keys but don't flag secret ones
    1570             :       1 = list only public keys
    1571             :       2 = list only secret keys
    1572             :       3 = list secret and public keys
    1573             :     Bit 6: list internal keys
    1574             :     Bit 7: list external keys
    1575             :     Bit 8: Do a raw format dump.
    1576             :  */
    1577             : gpg_error_t
    1578           0 : gpgsm_list_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
    1579             :                  unsigned int mode)
    1580             : {
    1581           0 :   gpg_error_t err = 0;
    1582             : 
    1583           0 :   if ((mode & (1<<6)))
    1584           0 :     err = list_internal_keys (ctrl, names, fp, (mode & 3), (mode&256));
    1585           0 :   if (!err && (mode & (1<<7)))
    1586           0 :     err = list_external_keys (ctrl, names, fp, (mode&256));
    1587           0 :   return err;
    1588             : }

Generated by: LCOV version 1.11