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 : }
|