Coverage Report

Created: 2026-01-17 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/keylist.c
Line
Count
Source
1
/* keylist.c - Print information about OpenPGP keys
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3
 *               2008, 2010, 2012 Free Software Foundation, Inc.
4
 * Copyright (C) 2013, 2014  Werner Koch
5
 *
6
 * This file is part of GnuPG.
7
 *
8
 * GnuPG is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * GnuPG is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <config.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <errno.h>
27
#ifdef HAVE_DOSISH_SYSTEM
28
# include <fcntl.h>   /* for setmode() */
29
#endif
30
31
#include "gpg.h"
32
#include "options.h"
33
#include "packet.h"
34
#include "../common/status.h"
35
#include "keydb.h"
36
#include "photoid.h"
37
#include "../common/util.h"
38
#include "../common/ttyio.h"
39
#include "trustdb.h"
40
#include "main.h"
41
#include "../common/i18n.h"
42
#include "../common/status.h"
43
#include "call-agent.h"
44
#include "../common/mbox-util.h"
45
#include "../common/zb32.h"
46
#include "tofu.h"
47
#include "../common/init.h"
48
#include "../common/recsel.h"
49
#include "../common/compliance.h"
50
#include "../common/pkscreening.h"
51
52
53
static void list_all (ctrl_t, int, int);
54
static void list_one (ctrl_t ctrl,
55
                      strlist_t names, int secret, int mark_secret);
56
static void locate_one (ctrl_t ctrl, strlist_t names, int no_local);
57
static void print_card_serialno (const char *serialno);
58
59
struct keylist_context
60
{
61
  int check_sigs;  /* If set signatures shall be verified.  */
62
  int good_sigs;   /* Counter used if CHECK_SIGS is set.  */
63
  int inv_sigs;    /* Counter used if CHECK_SIGS is set.  */
64
  int no_key;      /* Counter used if CHECK_SIGS is set.  */
65
  int oth_err;     /* Counter used if CHECK_SIGS is set.  */
66
  int no_validity; /* Do not show validity.  */
67
};
68
69
/* An object and a global instance to store selectors created from
70
 * --list-filter select=EXPR.
71
 */
72
struct list_filter_s
73
{
74
  recsel_expr_t selkey;
75
};
76
struct list_filter_s list_filter;
77
78
79
/* The stream used to write attribute packets to.  */
80
static estream_t attrib_fp;
81
82
83
84

85
static gpg_error_t list_keyblock (ctrl_t ctrl,
86
                           kbnode_t keyblock, int secret, int has_secret,
87
                           int fpr, struct keylist_context *listctx);
88
89
/* Release resources from a keylist context.  */
90
static void
91
keylist_context_release (struct keylist_context *listctx)
92
1
{
93
1
  (void)listctx; /* Nothing to release.  */
94
1
}
95
96
97
static void
98
release_list_filter (struct list_filter_s *filt)
99
0
{
100
0
  recsel_release (filt->selkey);
101
0
  filt->selkey = NULL;
102
0
}
103
104
105
static void
106
cleanup_keylist_globals (void)
107
0
{
108
0
  release_list_filter (&list_filter);
109
0
}
110
111
112
/* Parse and set an list filter from string.  STRING has the format
113
 * "NAME=EXPR" with NAME being the name of the filter.  Spaces before
114
 * and after NAME are not allowed.  If this function is all called
115
 * several times all expressions for the same NAME are concatenated.
116
 * Supported filter names are:
117
 *
118
 *  - select :: If the expression evaluates to true for a certain key
119
 *              this key will be listed.  The expression may use any
120
 *              variable defined for the export and import filters.
121
 *
122
 */
123
gpg_error_t
124
parse_and_set_list_filter (const char *string)
125
0
{
126
0
  gpg_error_t err;
127
128
  /* Auto register the cleanup function.  */
129
0
  register_mem_cleanup_func (cleanup_keylist_globals);
130
131
0
  if (!strncmp (string, "select=", 7))
132
0
    err = recsel_parse_expr (&list_filter.selkey, string+7);
133
0
  else
134
0
    err = gpg_error (GPG_ERR_INV_NAME);
135
0
  if (!err && DBG_RECSEL)
136
0
    recsel_dump (list_filter.selkey);
137
138
0
  return err;
139
0
}
140
141
142
/* List the keys.  If list is NULL, all available keys are listed.
143
 * With LOCATE_MODE set the locate algorithm is used to find a key; if
144
 * in addition NO_LOCAL is set the locate does not look into the local
145
 * keyring.  */
146
void
147
public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode, int no_local)
148
1
{
149
1
#ifndef NO_TRUST_MODELS
150
1
  if (opt.with_colons)
151
0
    {
152
0
      byte trust_model, marginals, completes, cert_depth, min_cert_level;
153
0
      ulong created, nextcheck;
154
155
0
      read_trust_options (ctrl, &trust_model, &created, &nextcheck,
156
0
        &marginals, &completes, &cert_depth, &min_cert_level);
157
158
0
      es_fprintf (es_stdout, "tru:");
159
160
0
      if (nextcheck && nextcheck <= make_timestamp ())
161
0
  es_fprintf (es_stdout, "o");
162
0
      if (trust_model != opt.trust_model)
163
0
  es_fprintf (es_stdout, "t");
164
0
      if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC
165
0
    || opt.trust_model == TM_TOFU_PGP)
166
0
  {
167
0
    if (marginals != opt.marginals_needed)
168
0
      es_fprintf (es_stdout, "m");
169
0
    if (completes != opt.completes_needed)
170
0
      es_fprintf (es_stdout, "c");
171
0
    if (cert_depth != opt.max_cert_depth)
172
0
      es_fprintf (es_stdout, "d");
173
0
    if (min_cert_level != opt.min_cert_level)
174
0
      es_fprintf (es_stdout, "l");
175
0
  }
176
177
0
      es_fprintf (es_stdout, ":%d:%lu:%lu", trust_model, created, nextcheck);
178
179
      /* Only show marginals, completes, and cert_depth in the classic
180
         or PGP trust models since they are not meaningful
181
         otherwise. */
182
183
0
      if (trust_model == TM_PGP || trust_model == TM_CLASSIC)
184
0
  es_fprintf (es_stdout, ":%d:%d:%d", marginals, completes, cert_depth);
185
0
      es_fprintf (es_stdout, "\n");
186
0
    }
187
1
#endif /*!NO_TRUST_MODELS*/
188
189
  /* We need to do the stale check right here because it might need to
190
     update the keyring while we already have the keyring open.  This
191
     is very bad for W32 because of a sharing violation. For real OSes
192
     it might lead to false results if we are later listing a keyring
193
     which is associated with the inode of a deleted file.  */
194
1
  check_trustdb_stale (ctrl);
195
196
#ifdef USE_TOFU
197
  tofu_begin_batch_update (ctrl);
198
#endif
199
200
1
  if (locate_mode)
201
0
    locate_one (ctrl, list, no_local);
202
1
  else if (!list)
203
1
    list_all (ctrl, 0, opt.with_secret);
204
0
  else
205
0
    list_one (ctrl, list, 0, opt.with_secret);
206
207
#ifdef USE_TOFU
208
  tofu_end_batch_update (ctrl);
209
#endif
210
1
}
211
212
213
void
214
secret_key_list (ctrl_t ctrl, strlist_t list)
215
0
{
216
0
  (void)ctrl;
217
218
0
  check_trustdb_stale (ctrl);
219
220
0
  if (!list)
221
0
    list_all (ctrl, 1, 0);
222
0
  else        /* List by user id */
223
0
    list_one (ctrl, list, 1, 0);
224
0
}
225
226
227
/* Helper for print_key_info and print_key_info_log.  */
228
static char *
229
format_key_info (ctrl_t ctrl, PKT_public_key *pk, int secret)
230
0
{
231
0
  u32 keyid[2];
232
0
  char *p;
233
0
  char pkstrbuf[PUBKEY_STRING_SIZE];
234
0
  char *result;
235
236
0
  keyid_from_pk (pk, keyid);
237
238
  /* If the pk was chosen by a particular user ID, that is the one to
239
     print.  */
240
0
  if (pk->user_id)
241
0
    p = utf8_to_native (pk->user_id->name, pk->user_id->len, 0);
242
0
  else
243
0
    p = get_user_id_native (ctrl, keyid);
244
245
0
  result = xtryasprintf ("%s  %s/%s %s %s",
246
0
                         secret? (pk->flags.primary? "sec":"ssb")
247
0
                         /* */ : (pk->flags.primary? "pub":"sub"),
248
0
                         pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
249
0
                         keystr (keyid), datestr_from_pk (pk), p);
250
0
  xfree (p);
251
0
  return result;
252
0
}
253
254
255
/* Print basic information about a public or secret key.  With FP
256
 * passed as NULL, the tty output interface is used, otherwise output
257
 * is directed to the given stream.  INDENT gives the requested
258
 * indentation; if that is a negative value indentation is suppressed
259
 * for the first line.  SECRET tells that the PK has a secret part.
260
 * FIXME: This is similar in use to print_key_line and thus both
261
 * functions should eventually be united.
262
 */
263
void
264
print_key_info (ctrl_t ctrl, estream_t fp,
265
                int indent, PKT_public_key *pk, int secret)
266
0
{
267
0
  int indentabs = indent >= 0? indent : -indent;
268
0
  char *info;
269
270
  /* Note: Negative values for INDENT are not yet needed. */
271
272
0
  info = format_key_info (ctrl, pk, secret);
273
274
0
  if (!fp && indent >= 0)
275
0
    tty_printf ("\n");  /* (Backward compatibility to old code) */
276
0
  tty_fprintf (fp, "%*s%s\n", indentabs, "",
277
0
               info? info : "[Ooops - out of core]");
278
279
0
  xfree (info);
280
0
}
281
282
283
/* Same as print_key_info put print using the log functions at
284
 * LOGLEVEL.  */
285
void
286
print_key_info_log (ctrl_t ctrl, int loglevel,
287
                    int indent, PKT_public_key *pk, int secret)
288
0
{
289
0
  int indentabs = indent >= 0? indent : -indent;
290
0
  char *info;
291
292
0
  info = format_key_info (ctrl, pk, secret);
293
294
0
  log_log (loglevel, "%*s%s\n", indentabs, "",
295
0
           info? info : "[Ooops - out of core]");
296
297
0
  xfree (info);
298
0
}
299
300
301
/* Print basic information of a secret key including the card serial
302
   number information.  */
303
#ifdef ENABLE_CARD_SUPPORT
304
void
305
print_card_key_info (estream_t fp, kbnode_t keyblock)
306
{
307
  kbnode_t node;
308
  char *hexgrip;
309
  char *serialno;
310
  int s2k_char;
311
  char pkstrbuf[PUBKEY_STRING_SIZE];
312
  int indent;
313
314
  for (node = keyblock; node; node = node->next)
315
    {
316
      if (node->pkt->pkttype == PKT_PUBLIC_KEY
317
          || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
318
        {
319
          int rc;
320
          PKT_public_key *pk = node->pkt->pkt.public_key;
321
322
          serialno = NULL;
323
          rc = hexkeygrip_from_pk (pk, &hexgrip);
324
          if (rc)
325
            {
326
              log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
327
              s2k_char = '?';
328
            }
329
          else if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
330
            s2k_char = serialno? '>':' ';
331
          else
332
            s2k_char = '#';  /* Key not found.  */
333
334
          tty_fprintf (fp, "%s%c  %s/%s  %n",
335
                       node->pkt->pkttype == PKT_PUBLIC_KEY ? "sec" : "ssb",
336
                       s2k_char,
337
                       pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
338
                       keystr_from_pk (pk),
339
                       &indent);
340
          tty_fprintf (fp, _("created: %s"), datestr_from_pk (pk));
341
          tty_fprintf (fp, "  ");
342
          tty_fprintf (fp, _("expires: %s"), expirestr_from_pk (pk));
343
          if (serialno)
344
            {
345
              tty_fprintf (fp, "\n%*s%s", indent, "", _("card-no: "));
346
              if (strlen (serialno) == 32
347
                  && !strncmp (serialno, "D27600012401", 12))
348
                {
349
                  /* This is an OpenPGP card.  Print the relevant part.  */
350
                  /* Example: D2760001240101010001000003470000 */
351
                  /*                          xxxxyyyyyyyy     */
352
                  tty_fprintf (fp, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
353
                }
354
              else
355
                tty_fprintf (fp, "%s", serialno);
356
            }
357
          tty_fprintf (fp, "\n");
358
          xfree (hexgrip);
359
          xfree (serialno);
360
        }
361
    }
362
}
363
#endif /*ENABLE_CARD_SUPPORT*/
364
365
366
/* Print the preferences line.  Allowed values for MODE are:
367
 *  -1 - print to the TTY
368
 *   0 - print to stdout.
369
 *   1 - use log_info
370
 *   2 - print colon delimited pfc record to stdout.
371
 */
372
void
373
show_preferences (PKT_user_id *uid, int indent, int mode, int verbose)
374
0
{
375
0
  estream_t fp;
376
0
  const prefitem_t fake = { 0, 0 };
377
0
  const prefitem_t *prefs;
378
0
  int i;
379
380
0
  if (!uid)
381
0
    return;
382
383
0
  if (uid->prefs)
384
0
    prefs = uid->prefs;
385
0
  else if (verbose)
386
0
    prefs = &fake;
387
0
  else
388
0
    return;
389
390
0
  if (mode < 0 )
391
0
    fp = NULL;
392
0
  else if (mode == 1)
393
0
    fp = log_get_stream ();
394
0
  else /* Mode 0 or 2 */
395
0
    fp = es_stdout;
396
397
0
  if (mode == 2)  /* Print preference record.  */
398
0
    {
399
0
      static char ptypes[] = { PREFTYPE_SYM, PREFTYPE_HASH,
400
0
                               PREFTYPE_ZIP, PREFTYPE_AEAD };
401
0
      int t, any;
402
403
0
      es_fputs ("pfc::", fp); /* Second field is RFU */
404
0
      for (t=0; t < DIM (ptypes); t++)
405
0
        {
406
0
          any = 0;
407
0
          for (i = 0; prefs[i].type; i++)
408
0
            if (prefs[i].type == ptypes[t])
409
0
              {
410
0
                es_fprintf (fp, "%s%d", any? ",":"", prefs[i].value);
411
0
                any = 1;
412
0
              }
413
0
          es_putc (':', fp);
414
0
        }
415
0
      es_putc (':', fp);  /* Two more reserved fields.  */
416
0
      es_putc (':', fp);
417
0
      any = 0;
418
0
      if (uid->flags.mdc)
419
0
        { es_fprintf (fp, "mdc"); any = 1; }
420
0
      if (uid->flags.aead)
421
0
        { es_fprintf (fp, "%saead", any?",":"");  any = 1; };
422
0
      if (!uid->flags.ks_modify)
423
0
        { es_fprintf (fp, "%sno-ks-modify", any?",":""); }
424
0
      es_putc (':', fp); /* One final colon for easier reading.  */
425
0
      es_putc ('\n', fp);
426
0
    }
427
0
  else if (verbose)
428
0
    {
429
0
      int any, des_seen = 0, sha1_seen = 0, uncomp_seen = 0;
430
431
0
      tty_fprintf (fp, "%*s %s", indent, "", _("Cipher: "));
432
0
      for (i = any = 0; prefs[i].type; i++)
433
0
  {
434
0
    if (prefs[i].type == PREFTYPE_SYM)
435
0
      {
436
0
        if (any)
437
0
    tty_fprintf (fp, ", ");
438
0
        any = 1;
439
        /* We don't want to display strings for experimental algos */
440
0
        if (!openpgp_cipher_test_algo (prefs[i].value)
441
0
      && prefs[i].value < 100)
442
0
    tty_fprintf (fp, "%s", openpgp_cipher_algo_name (prefs[i].value));
443
0
        else
444
0
    tty_fprintf (fp, "[%d]", prefs[i].value);
445
0
        if (prefs[i].value == CIPHER_ALGO_3DES)
446
0
    des_seen = 1;
447
0
      }
448
0
  }
449
0
      if (!des_seen)
450
0
  {
451
0
    if (any)
452
0
      tty_fprintf (fp, ", ");
453
0
    tty_fprintf (fp, "%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
454
0
  }
455
0
      tty_fprintf (fp, "\n%*s %s", indent, "", _("AEAD: "));
456
0
      for (i = any = 0; prefs[i].type; i++)
457
0
  {
458
0
    if (prefs[i].type == PREFTYPE_AEAD)
459
0
      {
460
0
        if (any)
461
0
    tty_fprintf (fp, ", ");
462
0
        any = 1;
463
        /* We don't want to display strings for experimental algos */
464
0
        if (!openpgp_aead_test_algo (prefs[i].value)
465
0
      && prefs[i].value < 100)
466
0
    tty_fprintf (fp, "%s", openpgp_aead_algo_name (prefs[i].value));
467
0
        else
468
0
    tty_fprintf (fp, "[%d]", prefs[i].value);
469
0
      }
470
0
  }
471
0
      tty_fprintf (fp, "\n%*s %s", indent, "", _("Digest: "));
472
0
      for (i = any = 0; prefs[i].type; i++)
473
0
  {
474
0
    if (prefs[i].type == PREFTYPE_HASH)
475
0
      {
476
0
        if (any)
477
0
    tty_fprintf (fp, ", ");
478
0
        any = 1;
479
        /* We don't want to display strings for experimental algos */
480
0
        if (!gcry_md_test_algo (prefs[i].value) && prefs[i].value < 100)
481
0
    tty_fprintf (fp, "%s", gcry_md_algo_name (prefs[i].value));
482
0
        else
483
0
    tty_fprintf (fp, "[%d]", prefs[i].value);
484
0
        if (prefs[i].value == DIGEST_ALGO_SHA1)
485
0
    sha1_seen = 1;
486
0
      }
487
0
  }
488
0
      if (!sha1_seen)
489
0
  {
490
0
    if (any)
491
0
      tty_fprintf (fp, ", ");
492
0
    tty_fprintf (fp, "%s", gcry_md_algo_name (DIGEST_ALGO_SHA1));
493
0
  }
494
0
      tty_fprintf (fp, "\n%*s %s", indent, "", _("Compression: "));
495
0
      for (i = any = 0; prefs[i].type; i++)
496
0
  {
497
0
    if (prefs[i].type == PREFTYPE_ZIP)
498
0
      {
499
0
        const char *s = compress_algo_to_string (prefs[i].value);
500
501
0
        if (any)
502
0
    tty_fprintf (fp, ", ");
503
0
        any = 1;
504
        /* We don't want to display strings for experimental algos */
505
0
        if (s && prefs[i].value < 100)
506
0
    tty_fprintf (fp, "%s", s);
507
0
        else
508
0
    tty_fprintf (fp, "[%d]", prefs[i].value);
509
0
        if (prefs[i].value == COMPRESS_ALGO_NONE)
510
0
    uncomp_seen = 1;
511
0
      }
512
0
  }
513
0
      if (!uncomp_seen)
514
0
  {
515
0
    if (any)
516
0
      tty_fprintf (fp, ", ");
517
0
    else
518
0
      {
519
0
        tty_fprintf (fp, "%s",
520
0
                           compress_algo_to_string (COMPRESS_ALGO_ZIP));
521
0
        tty_fprintf (fp, ", ");
522
0
      }
523
0
    tty_fprintf (fp, "%s", compress_algo_to_string (COMPRESS_ALGO_NONE));
524
0
  }
525
0
      if (uid->flags.mdc || uid->flags.aead || !uid->flags.ks_modify)
526
0
  {
527
0
          tty_fprintf (fp, "\n%*s %s", indent, "", _("Features: "));
528
0
    any = 0;
529
0
    if (uid->flags.mdc)
530
0
      {
531
0
        tty_fprintf (fp, "MDC");
532
0
        any = 1;
533
0
      }
534
0
    if (uid->flags.aead)
535
0
      {
536
0
        if (any)
537
0
    tty_fprintf (fp, ", ");
538
0
        tty_fprintf (fp, "AEAD");
539
0
      }
540
0
    if (!uid->flags.ks_modify)
541
0
      {
542
0
        if (any)
543
0
    tty_fprintf (fp, ", ");
544
0
        tty_fprintf (fp, _("Keyserver no-modify"));
545
0
      }
546
0
  }
547
0
      tty_fprintf (fp, "\n");
548
0
    }
549
0
  else
550
0
    {
551
0
      tty_fprintf (fp, "%*s", indent, "");
552
0
      for (i = 0; prefs[i].type; i++)
553
0
        {
554
0
          tty_fprintf (fp, " %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' :
555
0
                       prefs[i].type == PREFTYPE_AEAD ? 'A' :
556
0
                       prefs[i].type == PREFTYPE_HASH ? 'H' :
557
0
                       prefs[i].type == PREFTYPE_ZIP ? 'Z' : '?',
558
0
                       prefs[i].value);
559
0
        }
560
0
      if (uid->flags.mdc)
561
0
        tty_fprintf (fp, " [mdc]");
562
0
      if (uid->flags.aead)
563
0
        tty_fprintf (fp, " [aead]");
564
0
      if (!uid->flags.ks_modify)
565
0
        tty_fprintf (fp, " [no-ks-modify]");
566
0
      tty_fprintf (fp, "\n");
567
0
    }
568
0
}
569
570
571
/* Flags = 0x01 hashed 0x02 critical.  */
572
static void
573
status_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
574
          const byte * buf)
575
0
{
576
0
  char status[40];
577
578
  /* Don't print these. */
579
0
  if (len > 256)
580
0
    return;
581
582
0
  snprintf (status, sizeof status,
583
0
            "%d %u %u ", type, flags, (unsigned int) len);
584
585
0
  write_status_text_and_buffer (STATUS_SIG_SUBPACKET, status, buf, len, 0);
586
0
}
587
588
589
/* Print a policy URL.  Allowed values for MODE are:
590
 *  -1 - print to the TTY
591
 *   0 - print to stdout.
592
 *   1 - use log_info and emit status messages.
593
 *   2 - emit only status messages.
594
 */
595
void
596
show_policy_url (PKT_signature * sig, int indent, int mode)
597
0
{
598
0
  const byte *p;
599
0
  size_t len;
600
0
  int seq = 0, crit;
601
0
  estream_t fp = mode < 0? NULL : mode ? log_get_stream () : es_stdout;
602
603
0
  while ((p = enum_sig_subpkt (sig, 1, SIGSUBPKT_POLICY, &len, &seq, &crit)))
604
0
    {
605
0
      if (mode != 2)
606
0
  {
607
0
    const char *str;
608
609
0
          tty_fprintf (fp, "%*s", indent, "");
610
611
0
    if (crit)
612
0
      str = _("Critical signature policy: ");
613
0
    else
614
0
      str = _("Signature policy: ");
615
0
    if (mode > 0)
616
0
      log_info ("%s", str);
617
0
    else
618
0
      tty_fprintf (fp, "%s", str);
619
0
    tty_print_utf8_string2 (fp, p, len, 0);
620
0
    tty_fprintf (fp, "\n");
621
0
  }
622
623
0
      if (mode > 0)
624
0
  write_status_buffer (STATUS_POLICY_URL, p, len, 0);
625
0
    }
626
0
}
627
628
629
/* Print a keyserver URL.  Allowed values for MODE are:
630
 *  -1 - print to the TTY
631
 *   0 - print to stdout.
632
 *   1 - use log_info and emit status messages.
633
 *   2 - emit only status messages.
634
 */
635
void
636
show_keyserver_url (PKT_signature * sig, int indent, int mode)
637
0
{
638
0
  const byte *p;
639
0
  size_t len;
640
0
  int seq = 0, crit;
641
0
  estream_t fp = mode < 0? NULL : mode ? log_get_stream () : es_stdout;
642
643
0
  while ((p = enum_sig_subpkt (sig, 1, SIGSUBPKT_PREF_KS, &len, &seq, &crit)))
644
0
    {
645
0
      if (mode != 2)
646
0
  {
647
0
    const char *str;
648
649
0
          tty_fprintf (fp, "%*s", indent, "");
650
651
0
    if (crit)
652
0
      str = _("Critical preferred keyserver: ");
653
0
    else
654
0
      str = _("Preferred keyserver: ");
655
0
    if (mode > 0)
656
0
      log_info ("%s", str);
657
0
    else
658
0
      tty_fprintf (fp, "%s", str);
659
0
    tty_print_utf8_string2 (fp, p, len, 0);
660
0
    tty_fprintf (fp, "\n");
661
0
  }
662
663
0
      if (mode > 0)
664
0
  status_one_subpacket (SIGSUBPKT_PREF_KS, len,
665
0
            (crit ? 0x02 : 0) | 0x01, p);
666
0
    }
667
0
}
668
669
670
/* Print notation data.  Allowed values for MODE are:
671
 *  -1 - print to the TTY
672
 *   0 - print to stdout.
673
 *   1 - use log_info and emit status messages.
674
 *   2 - emit only status messages.
675
 *
676
 * Defined bits in WHICH:
677
 *   1 - standard notations
678
 *   2 - user notations
679
 *   4 - print notations normally hidden
680
 */
681
void
682
show_notation (PKT_signature * sig, int indent, int mode, int which)
683
0
{
684
0
  estream_t fp = mode < 0? NULL : mode ? log_get_stream () : es_stdout;
685
0
  notation_t nd, notations;
686
687
0
  if (which == 0)
688
0
    which = 3;
689
690
0
  notations = sig_to_notation (sig);
691
692
  /* There may be multiple notations in the same sig. */
693
0
  for (nd = notations; nd; nd = nd->next)
694
0
    {
695
0
       if (!(which & 4) && !strcmp (nd->name, "manu"))
696
0
        continue;
697
698
0
      if (mode != 2)
699
0
  {
700
0
    int has_at = !!strchr (nd->name, '@');
701
702
0
    if ((which & 1 && !has_at) || (which & 2 && has_at))
703
0
      {
704
0
        const char *str;
705
706
0
              tty_fprintf (fp, "%*s", indent, "");
707
708
0
        if (nd->flags.critical)
709
0
    str = _("Critical signature notation: ");
710
0
        else
711
0
    str = _("Signature notation: ");
712
0
        if (mode > 0)
713
0
    log_info ("%s", str);
714
0
        else
715
0
    tty_fprintf (fp, "%s", str);
716
        /* This is all UTF8 */
717
0
        tty_print_utf8_string2 (fp, nd->name, strlen (nd->name), 0);
718
0
        tty_fprintf (fp, "=");
719
0
        tty_print_utf8_string2 (fp, nd->value, strlen (nd->value), 0);
720
              /* (We need to use log_printf so that the next call to a
721
                  log function does not insert an extra LF.)  */
722
0
              if (mode > 0)
723
0
                log_printf ("\n");
724
0
              else
725
0
                tty_fprintf (fp, "\n");
726
0
      }
727
0
  }
728
729
0
      if (mode > 0)
730
0
  {
731
0
    write_status_buffer (STATUS_NOTATION_NAME,
732
0
             nd->name, strlen (nd->name), 0);
733
0
          if (nd->flags.critical || nd->flags.human)
734
0
            write_status_text (STATUS_NOTATION_FLAGS,
735
0
                               nd->flags.critical && nd->flags.human? "1 1" :
736
0
                               nd->flags.critical? "1 0" : "0 1");
737
0
          if (!nd->flags.human && nd->bdat && nd->blen)
738
0
            write_status_buffer (STATUS_NOTATION_DATA,
739
0
                                 nd->bdat, nd->blen, 250);
740
0
          else
741
0
            write_status_buffer (STATUS_NOTATION_DATA,
742
0
                                 nd->value, strlen (nd->value), 50);
743
0
  }
744
0
    }
745
746
0
  free_notation (notations);
747
0
}
748
749
750
/* Output all the notation data in SIG matching a name given by
751
 * --print-notation to stdout.  */
752
void
753
print_matching_notations (PKT_signature *sig)
754
0
{
755
0
  notation_t nd, notations;
756
0
  strlist_t sl;
757
0
  const char *s;
758
759
0
  if (!opt.print_notations)
760
0
    return;
761
762
0
  notations = sig_to_notation (sig);
763
0
  for (nd = notations; nd; nd = nd->next)
764
0
    {
765
0
      for (sl=opt.print_notations; sl; sl = sl->next)
766
0
        if (!strcmp (sl->d, nd->name))
767
0
          break;
768
0
      if (!sl || !*nd->value)
769
0
        continue;
770
0
      es_fprintf (es_stdout, "%s: ", nd->name);
771
0
      for (s = nd->value; *s; s++)
772
0
        {
773
0
          if (*s == '\n')
774
0
            es_fprintf (es_stdout, "\n%*s", (int)strlen (nd->name)+2, "");
775
0
          else if (*s >= ' ' || *s != '\t')
776
0
            es_putc (*s, es_stdout);
777
0
        }
778
0
      es_putc ('\n', es_stdout);
779
0
    }
780
781
0
  free_notation (notations);
782
0
}
783
784
785
static void
786
print_signature_stats (struct keylist_context *s)
787
0
{
788
0
  if (!s->check_sigs)
789
0
    return;  /* Signature checking was not requested.  */
790
791
  /* Better flush stdout so that the stats are always printed after
792
   * the output.  */
793
0
  es_fflush (es_stdout);
794
795
0
  if (s->good_sigs)
796
0
    log_info (ngettext("%d good signature\n",
797
0
                       "%d good signatures\n", s->good_sigs), s->good_sigs);
798
799
0
  if (s->inv_sigs)
800
0
    log_info (ngettext("%d bad signature\n",
801
0
                       "%d bad signatures\n", s->inv_sigs), s->inv_sigs);
802
803
0
  if (s->no_key)
804
0
    log_info (ngettext("%d signature not checked due to a missing key\n",
805
0
                       "%d signatures not checked due to missing keys\n",
806
0
                       s->no_key), s->no_key);
807
808
0
  if (s->oth_err)
809
0
    log_info (ngettext("%d signature not checked due to an error\n",
810
0
                       "%d signatures not checked due to errors\n",
811
0
                       s->oth_err), s->oth_err);
812
0
}
813
814
815
/* List all keys.  If SECRET is true only secret keys are listed.  If
816
   MARK_SECRET is true secret keys are indicated in a public key
817
   listing.  */
818
static void
819
list_all (ctrl_t ctrl, int secret, int mark_secret)
820
1
{
821
1
  KEYDB_HANDLE hd;
822
1
  KBNODE keyblock = NULL;
823
1
  int rc = 0;
824
1
  int any_secret;
825
1
  const char *lastresname, *resname;
826
1
  struct keylist_context listctx;
827
1
  gpg_error_t listerr = 0;
828
829
1
  memset (&listctx, 0, sizeof (listctx));
830
1
  if (opt.check_sigs)
831
0
    listctx.check_sigs = 1;
832
833
1
  hd = keydb_new (ctrl);
834
1
  if (!hd)
835
0
    rc = gpg_error_from_syserror ();
836
1
  else
837
1
    rc = keydb_search_first (hd);
838
1
  if (rc)
839
1
    {
840
1
      if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
841
1
  log_error ("keydb_search_first failed: %s\n", gpg_strerror (rc));
842
1
      goto leave;
843
1
    }
844
845
0
  lastresname = NULL;
846
0
  do
847
0
    {
848
0
      if (secret)
849
0
        glo_ctrl.silence_parse_warnings++;
850
0
      rc = keydb_get_keyblock (hd, &keyblock);
851
0
      if (secret)
852
0
        glo_ctrl.silence_parse_warnings--;
853
0
      if (rc)
854
0
  {
855
0
          if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY)
856
0
            continue;  /* Skip legacy keys.  */
857
0
    log_error ("keydb_get_keyblock failed: %s\n", gpg_strerror (rc));
858
0
    goto leave;
859
0
  }
860
861
0
      if (secret || mark_secret)
862
0
        any_secret = !agent_probe_any_secret_key (ctrl, keyblock);
863
0
      else
864
0
        any_secret = 0;
865
866
0
      if (secret && !any_secret)
867
0
        ; /* Secret key listing requested but this isn't one.  */
868
0
      else
869
0
        {
870
0
          if (!opt.with_colons && !(opt.list_options & LIST_SHOW_ONLY_FPR_MBOX))
871
0
            {
872
0
              resname = keydb_get_resource_name (hd);
873
0
              if (lastresname != resname)
874
0
                {
875
0
                  int i;
876
877
0
                  es_fprintf (es_stdout, "%s\n", resname);
878
0
                  for (i = strlen (resname); i; i--)
879
0
                    es_putc ('-', es_stdout);
880
0
                  es_putc ('\n', es_stdout);
881
0
                  lastresname = resname;
882
0
                }
883
0
            }
884
0
          merge_keys_and_selfsig (ctrl, keyblock);
885
0
          listerr = list_keyblock (ctrl, keyblock, secret, any_secret,
886
0
                                   opt.fingerprint, &listctx);
887
0
        }
888
0
      release_kbnode (keyblock);
889
0
      keyblock = NULL;
890
0
    }
891
0
  while (!listerr && !(rc = keydb_search_next (hd)));
892
0
  es_fflush (es_stdout);
893
0
  if (rc && gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
894
0
    log_error ("keydb_search_next failed: %s\n", gpg_strerror (rc));
895
0
  if (keydb_get_skipped_counter (hd))
896
0
    log_info (ngettext("Warning: %lu key skipped due to its large size\n",
897
0
                       "Warning: %lu keys skipped due to their large sizes\n",
898
0
                       keydb_get_skipped_counter (hd)),
899
0
              keydb_get_skipped_counter (hd));
900
901
0
  if (opt.check_sigs && !opt.with_colons)
902
0
    print_signature_stats (&listctx);
903
904
1
 leave:
905
1
  keylist_context_release (&listctx);
906
1
  release_kbnode (keyblock);
907
1
  keydb_release (hd);
908
1
}
909
910
911
static void
912
list_one (ctrl_t ctrl, strlist_t names, int secret, int mark_secret)
913
0
{
914
0
  int rc = 0;
915
0
  KBNODE keyblock = NULL;
916
0
  GETKEY_CTX ctx;
917
0
  int any_secret;
918
0
  const char *resname;
919
0
  const char *keyring_str = _("Keyring");
920
0
  int i;
921
0
  struct keylist_context listctx;
922
0
  gpg_error_t listerr = 0;
923
924
0
  memset (&listctx, 0, sizeof (listctx));
925
0
  if (!secret && opt.check_sigs)
926
0
    listctx.check_sigs = 1;
927
928
  /* fixme: using the bynames function has the disadvantage that we
929
   * don't know whether one of the names given was not found.  OTOH,
930
   * this function has the advantage to list the names in the
931
   * sequence as defined by the keyDB and does not duplicate
932
   * outputs.  A solution could be do test whether all given have
933
   * been listed (this needs a way to use the keyDB search
934
   * functions) or to have the search function return indicators for
935
   * found names.  Yet another way is to use the keydb search
936
   * facilities directly. */
937
0
  rc = getkey_bynames (ctrl, &ctx, NULL, names,
938
0
                       (GETKEY_ALLOW_ADSK
939
0
                        | (secret ? GETKEY_WANT_SECRET : 0)),
940
0
                       &keyblock);
941
0
  if (rc)
942
0
    {
943
0
      log_error ("error reading key: %s\n", gpg_strerror (rc));
944
0
      getkey_end (ctrl, ctx);
945
0
      write_status_error ("keylist.getkey", rc);
946
0
      return;
947
0
    }
948
949
0
  do
950
0
    {
951
      /* getkey_bynames makes sure that only secret keys are returned
952
       * if requested, thus we do not need to test again.  With
953
       * MARK_SECRET set (ie. option --with-secret) we have to test
954
       * for a secret key, though.  */
955
0
      if (secret)
956
0
        any_secret = 1;
957
0
      else if (mark_secret)
958
0
        any_secret = !agent_probe_any_secret_key (ctrl, keyblock);
959
0
      else
960
0
        any_secret = 0;
961
962
0
      if (secret && !any_secret)
963
0
        ;/* Secret key listing requested but getkey_bynames failed.  */
964
0
      else
965
0
        {
966
0
          if ((opt.list_options & LIST_SHOW_KEYRING) && !opt.with_colons)
967
0
            {
968
0
              resname = keydb_get_resource_name (get_ctx_handle (ctx));
969
0
              es_fprintf (es_stdout, "%s: %s\n", keyring_str, resname);
970
0
              for (i = strlen (resname) + strlen (keyring_str) + 2; i; i--)
971
0
                es_putc ('-', es_stdout);
972
0
              es_putc ('\n', es_stdout);
973
0
            }
974
0
          listerr = list_keyblock (ctrl, keyblock, secret, any_secret,
975
0
                                   opt.fingerprint, &listctx);
976
0
        }
977
0
      release_kbnode (keyblock);
978
0
    }
979
0
  while (!listerr && !getkey_next (ctrl, ctx, NULL, &keyblock));
980
0
  getkey_end (ctrl, ctx);
981
982
0
  if (opt.check_sigs && !opt.with_colons)
983
0
    print_signature_stats (&listctx);
984
985
0
  keylist_context_release (&listctx);
986
0
}
987
988
989
static void
990
locate_one (ctrl_t ctrl, strlist_t names, int no_local)
991
0
{
992
0
  int rc = 0;
993
0
  strlist_t sl;
994
0
  GETKEY_CTX ctx = NULL;
995
0
  KBNODE keyblock = NULL;
996
0
  struct keylist_context listctx;
997
0
  gpg_error_t listerr = 0;
998
999
0
  memset (&listctx, 0, sizeof (listctx));
1000
0
  if (opt.check_sigs)
1001
0
    listctx.check_sigs = 1;
1002
1003
0
  for (sl = names; sl && !listerr; sl = sl->next)
1004
0
    {
1005
0
      rc = get_best_pubkey_byname (ctrl,
1006
0
                                   no_local? GET_PUBKEY_NO_LOCAL
1007
0
                                   /*    */: GET_PUBKEY_NORMAL,
1008
0
                                   &ctx, NULL, sl->d, &keyblock, 1);
1009
0
      if (rc)
1010
0
  {
1011
0
    if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
1012
0
      log_error ("error reading key: %s\n", gpg_strerror (rc));
1013
0
          else if (opt.verbose)
1014
0
            log_info (_("key \"%s\" not found: %s\n"),
1015
0
                      sl->d, gpg_strerror (rc));
1016
0
  }
1017
0
      else
1018
0
  {
1019
0
    do
1020
0
      {
1021
0
        listerr = list_keyblock (ctrl, keyblock, 0, 0,
1022
0
                                       opt.fingerprint, &listctx);
1023
0
        release_kbnode (keyblock);
1024
0
      }
1025
0
    while (!listerr && ctx && !getkey_next (ctrl, ctx, NULL, &keyblock));
1026
0
    getkey_end (ctrl, ctx);
1027
0
    ctx = NULL;
1028
0
  }
1029
0
    }
1030
1031
0
  if (opt.check_sigs && !opt.with_colons)
1032
0
    print_signature_stats (&listctx);
1033
1034
0
  keylist_context_release (&listctx);
1035
0
}
1036
1037
1038
static void
1039
print_key_data (PKT_public_key * pk)
1040
0
{
1041
0
  int n = pk ? pubkey_get_npkey (pk->pubkey_algo) : 0;
1042
0
  int i;
1043
1044
0
  for (i = 0; i < n; i++)
1045
0
    {
1046
0
      es_fprintf (es_stdout, "pkd:%d:%u:", i, mpi_get_nbits (pk->pkey[i]));
1047
0
      mpi_print (es_stdout, pk->pkey[i], 1);
1048
0
      es_putc (':', es_stdout);
1049
0
      es_putc ('\n', es_stdout);
1050
0
    }
1051
0
}
1052
1053
1054
/* Various public key screenings.  (Right now just ROCA).  With
1055
 * COLON_MODE set the output is formatted for use in the compliance
1056
 * field of a colon listing.
1057
 */
1058
static void
1059
print_pk_screening (PKT_public_key *pk, int colon_mode)
1060
0
{
1061
0
  gpg_error_t err;
1062
1063
0
  if (is_RSA (pk->pubkey_algo) && pubkey_get_npkey (pk->pubkey_algo))
1064
0
    {
1065
0
      err = screen_key_for_roca (pk->pkey[0]);
1066
0
      if (!err)
1067
0
        ;
1068
0
      else if (gpg_err_code (err) == GPG_ERR_TRUE)
1069
0
        {
1070
0
          if (colon_mode)
1071
0
            es_fprintf (es_stdout, colon_mode > 1? " %d":"%d", 6001);
1072
0
          else
1073
0
            es_fprintf (es_stdout,
1074
0
                        "      Screening: ROCA vulnerability detected\n");
1075
0
        }
1076
0
      else if (!colon_mode)
1077
0
        es_fprintf (es_stdout, "      Screening: [ROCA check failed: %s]\n",
1078
0
                    gpg_strerror (err));
1079
0
    }
1080
1081
0
}
1082
1083
1084
static void
1085
print_capabilities (ctrl_t ctrl, PKT_public_key *pk, KBNODE keyblock)
1086
0
{
1087
0
  unsigned int use = pk->pubkey_usage;
1088
0
  int c_printed = 0;
1089
1090
0
  if (use & PUBKEY_USAGE_ENC)
1091
0
    es_putc ('e', es_stdout);
1092
1093
0
  if (use & PUBKEY_USAGE_SIG)
1094
0
    {
1095
0
      es_putc ('s', es_stdout);
1096
0
      if (pk->flags.primary)
1097
0
        {
1098
0
          es_putc ('c', es_stdout);
1099
          /* The PUBKEY_USAGE_CERT flag was introduced later and we
1100
             used to always print 'c' for a primary key.  To avoid any
1101
             regression here we better track whether we printed 'c'
1102
             already.  */
1103
0
          c_printed = 1;
1104
0
        }
1105
0
    }
1106
1107
0
  if ((use & PUBKEY_USAGE_CERT) && !c_printed)
1108
0
    es_putc ('c', es_stdout);
1109
1110
0
  if ((use & PUBKEY_USAGE_AUTH))
1111
0
    es_putc ('a', es_stdout);
1112
1113
0
  if (use & PUBKEY_USAGE_RENC)
1114
0
    es_putc ('r', es_stdout);
1115
0
  if ((use & PUBKEY_USAGE_TIME))
1116
0
    es_putc ('t', es_stdout);
1117
0
  if ((use & PUBKEY_USAGE_GROUP))
1118
0
    es_putc ('g', es_stdout);
1119
1120
0
  if ((use & PUBKEY_USAGE_UNKNOWN))
1121
0
    es_putc ('?', es_stdout);
1122
1123
0
  if (keyblock)
1124
0
    {
1125
      /* Figure out the usable capabilities.  */
1126
0
      KBNODE k;
1127
0
      int enc = 0, sign = 0, cert = 0, auth = 0, disabled = 0;
1128
1129
0
      for (k = keyblock; k; k = k->next)
1130
0
  {
1131
0
    if (k->pkt->pkttype == PKT_PUBLIC_KEY
1132
0
        || k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
1133
0
      {
1134
0
        pk = k->pkt->pkt.public_key;
1135
1136
0
        if (pk->flags.primary)
1137
0
    disabled = pk_is_disabled (pk);
1138
1139
0
        if (pk->flags.valid && !pk->flags.revoked && !pk->has_expired)
1140
0
    {
1141
0
      if (pk->pubkey_usage & PUBKEY_USAGE_ENC)
1142
0
        enc = 1;
1143
0
      if (pk->pubkey_usage & PUBKEY_USAGE_SIG)
1144
0
        {
1145
0
          sign = 1;
1146
0
          if (pk->flags.primary)
1147
0
      cert = 1;
1148
0
        }
1149
0
      if (pk->pubkey_usage & PUBKEY_USAGE_CERT)
1150
0
        cert = 1;
1151
0
      if ((pk->pubkey_usage & PUBKEY_USAGE_AUTH))
1152
0
        auth = 1;
1153
0
    }
1154
0
      }
1155
0
  }
1156
0
      if (enc)
1157
0
  es_putc ('E', es_stdout);
1158
0
      if (sign)
1159
0
  es_putc ('S', es_stdout);
1160
0
      if (cert)
1161
0
  es_putc ('C', es_stdout);
1162
0
      if (auth)
1163
0
  es_putc ('A', es_stdout);
1164
0
      if (disabled)
1165
0
  es_putc ('D', es_stdout);
1166
0
    }
1167
1168
0
  es_putc (':', es_stdout);
1169
0
}
1170
1171
1172
/* FLAGS: 0x01 hashed
1173
          0x02 critical  */
1174
static void
1175
print_one_subpacket (sigsubpkttype_t type, size_t len, int flags,
1176
         const byte * buf)
1177
0
{
1178
0
  size_t i;
1179
1180
0
  es_fprintf (es_stdout, "spk:%d:%u:%u:", type, flags, (unsigned int) len);
1181
1182
0
  for (i = 0; i < len; i++)
1183
0
    {
1184
      /* printable ascii other than : and % */
1185
0
      if (buf[i] >= 32 && buf[i] <= 126 && buf[i] != ':' && buf[i] != '%')
1186
0
  es_fprintf (es_stdout, "%c", buf[i]);
1187
0
      else
1188
0
  es_fprintf (es_stdout, "%%%02X", buf[i]);
1189
0
    }
1190
1191
0
  es_fprintf (es_stdout, "\n");
1192
0
}
1193
1194
1195
void
1196
print_subpackets_colon (PKT_signature * sig)
1197
0
{
1198
0
  byte *i;
1199
1200
0
  log_assert (opt.show_subpackets);
1201
1202
0
  for (i = opt.show_subpackets; *i; i++)
1203
0
    {
1204
0
      const byte *p;
1205
0
      size_t len;
1206
0
      int seq, crit;
1207
1208
0
      seq = 0;
1209
1210
0
      while ((p = enum_sig_subpkt (sig, 1, *i, &len, &seq, &crit)))
1211
0
  print_one_subpacket (*i, len, 0x01 | (crit ? 0x02 : 0), p);
1212
1213
0
      seq = 0;
1214
1215
0
      while ((p = enum_sig_subpkt (sig, 0, *i, &len, &seq, &crit)))
1216
0
  print_one_subpacket (*i, len, 0x00 | (crit ? 0x02 : 0), p);
1217
0
    }
1218
0
}
1219
1220
1221
void
1222
dump_attribs (const PKT_user_id *uid, PKT_public_key *pk)
1223
0
{
1224
0
  int i;
1225
1226
0
  if (!attrib_fp)
1227
0
    return;
1228
1229
0
  for (i = 0; i < uid->numattribs; i++)
1230
0
    {
1231
0
      if (is_status_enabled ())
1232
0
  {
1233
0
    byte array[MAX_FINGERPRINT_LEN], *p;
1234
0
    char buf[(MAX_FINGERPRINT_LEN * 2) + 90];
1235
0
    size_t j, n;
1236
1237
0
          if (!pk)
1238
0
            BUG ();
1239
0
          fingerprint_from_pk (pk, array, &n);
1240
1241
0
    p = array;
1242
0
    for (j = 0; j < n; j++, p++)
1243
0
      sprintf (buf + 2 * j, "%02X", *p);
1244
1245
0
    sprintf (buf + strlen (buf), " %lu %u %u %u %lu %lu %u",
1246
0
       (ulong) uid->attribs[i].len, uid->attribs[i].type, i + 1,
1247
0
       uid->numattribs, (ulong) uid->created,
1248
0
       (ulong) uid->expiredate,
1249
0
       ((uid->flags.primary ? 0x01 : 0) | (uid->flags.revoked ? 0x02 : 0) |
1250
0
        (uid->flags.expired ? 0x04 : 0)));
1251
0
    write_status_text (STATUS_ATTRIBUTE, buf);
1252
0
  }
1253
1254
0
      es_fwrite (uid->attribs[i].data, uid->attribs[i].len, 1, attrib_fp);
1255
0
      es_fflush (attrib_fp);
1256
0
    }
1257
0
}
1258
1259
1260
static void
1261
print_keygrip (const char *keygrip)
1262
0
{
1263
0
  const char *s;
1264
1265
0
  s = strchr (keygrip, ',');
1266
0
  if (s)
1267
0
    es_fprintf (es_stdout, "      Keygrip = %.*s,\n%*s%s\n",
1268
0
                (int)(s-keygrip), keygrip, 16, "", s+1);
1269
0
  else
1270
0
    es_fprintf (es_stdout, "      Keygrip = %s\n", keygrip);
1271
0
}
1272
1273
1274
/* If PK is given the output is written to a new file instead of
1275
 * stdout.  */
1276
static void
1277
print_x509_notations (struct notation *nots, PKT_public_key *pk)
1278
0
{
1279
0
  gpg_error_t err;
1280
0
  gpgrt_b64state_t state = NULL;
1281
0
  char hexfpr[2*4 + 1 + 2*MAX_FINGERPRINT_LEN+4+1];
1282
0
  char sha1[20];
1283
0
  estream_t fp;
1284
1285
0
  for (; nots; nots = nots->next)
1286
0
    {
1287
0
      if (pk)
1288
0
        {
1289
0
          gcry_md_hash_buffer (GCRY_MD_SHA1, sha1, nots->bdat, nots->blen);
1290
0
          bin2hex (sha1+16, 4, hexfpr);
1291
0
          hexfpr[2*4] = '-';
1292
0
          hexfingerprint (pk, hexfpr + 2*4+1, 2*MAX_FINGERPRINT_LEN);
1293
0
          strcat (hexfpr, ".pem");
1294
0
          fp = es_fopen (hexfpr, "w");
1295
0
          if (!fp)
1296
0
            {
1297
0
              err = gpg_err_code_from_syserror ();
1298
0
              goto b64fail;
1299
0
            }
1300
0
        }
1301
0
      else
1302
0
        fp = es_stdout;
1303
0
      state = gpgrt_b64enc_start (fp, "CERTIFICATE");
1304
0
      if (!state)
1305
0
        {
1306
0
          err = gpg_err_code_from_syserror ();
1307
0
          goto b64fail;
1308
0
        }
1309
0
      err = gpgrt_b64enc_write (state, nots->bdat, nots->blen);
1310
0
      if (err)
1311
0
        goto b64fail;
1312
0
      err = gpgrt_b64enc_finish (state);
1313
0
      if (err)
1314
0
        goto b64fail;
1315
0
      if (fp != es_stdout)
1316
0
        {
1317
0
          es_fclose (fp);
1318
0
          fp = NULL;
1319
0
        }
1320
0
    }
1321
0
  return;
1322
1323
0
 b64fail:
1324
0
  log_error ("error writing base64 encoded notation: %s\n", gpg_strerror (err));
1325
0
  gpgrt_b64enc_finish (state);
1326
0
  if (fp && fp != es_stdout)
1327
0
    gpgrt_fcancel (fp);
1328
0
}
1329
1330
1331
/* Order two signatures.  We first order by keyid and then by creation
1332
 * time.  */
1333
int
1334
cmp_signodes (const void *av, const void *bv)
1335
0
{
1336
0
  const kbnode_t an = *(const kbnode_t *)av;
1337
0
  const kbnode_t bn = *(const kbnode_t *)bv;
1338
0
  const PKT_signature *a;
1339
0
  const PKT_signature *b;
1340
0
  int i;
1341
1342
  /* log_assert (an->pkt->pkttype == PKT_SIGNATURE); */
1343
  /* log_assert (bn->pkt->pkttype == PKT_SIGNATURE); */
1344
1345
0
  a = an->pkt->pkt.signature;
1346
0
  b = bn->pkt->pkt.signature;
1347
1348
  /* Self-signatures are ordered first.  */
1349
0
  if ((an->flag & NODFLG_MARK_B) && !(bn->flag & NODFLG_MARK_B))
1350
0
    return -1;
1351
0
  if (!(an->flag & NODFLG_MARK_B) && (bn->flag & NODFLG_MARK_B))
1352
0
    return 1;
1353
1354
  /* then the keyids.  (which are or course the same for self-sigs). */
1355
0
  i = keyid_cmp (a->keyid, b->keyid);
1356
0
  if (i)
1357
0
    return i;
1358
1359
  /* Followed by creation time */
1360
0
  if (a->timestamp > b->timestamp)
1361
0
    return 1;
1362
0
  if (a->timestamp < b->timestamp)
1363
0
    return -1;
1364
1365
  /* followed by the class in a way that a rev comes first.  */
1366
0
  if (a->sig_class > b->sig_class)
1367
0
    return 1;
1368
0
  if (a->sig_class < b->sig_class)
1369
0
    return -1;
1370
1371
  /* To make the sort stable we compare the entire structure as last resort.  */
1372
0
  return memcmp (a, b, sizeof *a);
1373
0
}
1374
1375
1376
/* Given a domain name at NAME with length NAME, check whether this is
1377
 * a valid domain name and in that case return a malloced string ith
1378
 * the name.  Escaped dots are ignored and removed from the result.
1379
 * Example: "example\.org" -> "example.org" Note that the input may
1380
 * not be Nul terminated.  */
1381
static char *
1382
parse_trust_name (const char *name, size_t namelen)
1383
0
{
1384
0
  char *buffer, *p;
1385
1386
0
  p = buffer = xtrymalloc (namelen+1);
1387
0
  if (!buffer)
1388
0
    return NULL; /* Oops - caller needs to use some fallback  */
1389
1390
0
  for (;  namelen; name++, namelen--)
1391
0
    {
1392
0
      if (*name == '\\' && namelen > 1 && name[1] == '.')
1393
0
        ; /* Skip the escape character.  */
1394
0
      else
1395
0
        *p++ = *name;
1396
0
    }
1397
0
  *p = 0;
1398
0
  if (!is_valid_domain_name (buffer))
1399
0
    {
1400
0
      xfree (buffer);
1401
0
      buffer = NULL;
1402
0
    }
1403
0
  return buffer;
1404
0
}
1405
1406
1407
void
1408
print_revocation_reason_comment (const char *comment, size_t comment_len)
1409
0
{
1410
0
  const byte *s, *s_lf;
1411
0
  size_t n, n_lf;
1412
1413
0
  if (!comment || !comment_len)
1414
0
    return;
1415
1416
0
  s = comment;
1417
0
  n = comment_len;
1418
0
  s_lf = NULL;
1419
0
  do
1420
0
    {
1421
      /* We don't want any empty lines, so we skip them.  */
1422
0
      for (;n && *s == '\n'; s++, n--)
1423
0
        ;
1424
0
      if (n)
1425
0
        {
1426
0
          s_lf = memchr (s, '\n', n);
1427
0
          n_lf = s_lf? s_lf - s : n;
1428
0
          es_fprintf (es_stdout, "         %s",
1429
0
                      _("revocation comment: "));
1430
0
          es_write_sanitized (es_stdout, s, n_lf, NULL, NULL);
1431
0
          es_putc ('\n', es_stdout);
1432
0
          s += n_lf; n -= n_lf;
1433
0
        }
1434
0
    } while (s_lf);
1435
0
}
1436
1437
1438
static void
1439
print_revocation_reason (PKT_public_key *pk)
1440
0
{
1441
0
  char *freeme;
1442
0
  const char *codestr;
1443
1444
0
  if (!pk->revoked.got_reason)
1445
0
    return;
1446
1447
0
  if (!pk->revoked.reason_code && !pk->revoked.reason_comment)
1448
0
    return; /* Do not print "revocation reason: No reason specified". */
1449
1450
0
  codestr = revocation_reason_code_to_str (pk->revoked.reason_code, &freeme);
1451
0
  es_fprintf (es_stdout, "      %s%s\n",
1452
0
              _("reason for revocation: "), codestr);
1453
0
  xfree (freeme);
1454
0
  print_revocation_reason_comment (pk->revoked.reason_comment,
1455
0
                                   pk->revoked.reason_comment_len);
1456
0
}
1457
1458
1459
/* Helper for list_keyblock_print.  The caller must have set
1460
 * NODFLG_MARK_B to indicate self-signatures.  */
1461
static void
1462
list_signature_print (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node,
1463
                      struct keylist_context *listctx, PKT_public_key *lastpk)
1464
0
{
1465
0
  PKT_signature *sig = node->pkt->pkt.signature;
1466
0
  int rc, sigrc;
1467
0
  char *sigstr;
1468
0
  char *reason_text = NULL;
1469
0
  char *reason_comment = NULL;
1470
0
  size_t reason_commentlen;
1471
0
  int reason_code = 0;
1472
1473
0
  if (listctx->check_sigs)
1474
0
    {
1475
0
      rc = check_key_signature (ctrl, keyblock, node, NULL);
1476
0
      switch (gpg_err_code (rc))
1477
0
  {
1478
0
  case 0:
1479
0
    listctx->good_sigs++;
1480
0
    sigrc = '!';
1481
0
    break;
1482
0
  case GPG_ERR_BAD_SIGNATURE:
1483
0
    listctx->inv_sigs++;
1484
0
    sigrc = '-';
1485
0
    break;
1486
0
  case GPG_ERR_NO_PUBKEY:
1487
0
  case GPG_ERR_UNUSABLE_PUBKEY:
1488
0
    listctx->no_key++;
1489
0
    return;
1490
0
        case GPG_ERR_DIGEST_ALGO:
1491
0
        case GPG_ERR_PUBKEY_ALGO:
1492
0
          if (!(opt.list_options & LIST_SHOW_UNUSABLE_SIGS))
1493
0
            return;
1494
          /* fallthru. */
1495
0
  default:
1496
0
    listctx->oth_err++;
1497
0
    sigrc = '%';
1498
0
    break;
1499
0
  }
1500
1501
      /* TODO: Make sure a cached sig record here still has
1502
         the pk that issued it.  See also
1503
         keyedit.c:print_and_check_one_sig */
1504
0
    }
1505
0
  else
1506
0
    {
1507
0
      if (!(opt.list_options & LIST_SHOW_UNUSABLE_SIGS)
1508
0
          && (gpg_err_code (openpgp_pk_test_algo (sig->pubkey_algo)
1509
0
                            == GPG_ERR_PUBKEY_ALGO)
1510
0
              || gpg_err_code (openpgp_md_test_algo (sig->digest_algo)
1511
0
                               == GPG_ERR_DIGEST_ALGO)
1512
0
              || (sig->digest_algo == DIGEST_ALGO_SHA1
1513
0
                  && !(node->flag & NODFLG_MARK_B) /*no selfsig*/
1514
0
                  && !opt.flags.allow_weak_key_signatures)))
1515
0
        return;
1516
0
      rc = 0;
1517
0
      sigrc = ' ';
1518
0
    }
1519
1520
0
  if (IS_KEY_REV (sig) || IS_SUBKEY_REV (sig) || IS_UID_REV (sig))
1521
0
    {
1522
0
      sigstr = "rev";
1523
0
      reason_code = get_revocation_reason (sig, &reason_text,
1524
0
                                           &reason_comment,
1525
0
                                           &reason_commentlen);
1526
0
    }
1527
0
  else if (IS_UID_SIG (sig))
1528
0
    sigstr = "sig";
1529
0
  else if (IS_SUBKEY_SIG (sig))
1530
0
    sigstr = "sig";
1531
0
  else if (IS_KEY_SIG (sig))
1532
0
    sigstr = "sig";
1533
0
  else
1534
0
    {
1535
0
      es_fprintf (es_stdout, "sig                             "
1536
0
        "[unexpected signature class 0x%02x]\n",
1537
0
        sig->sig_class);
1538
0
      return;
1539
0
    }
1540
1541
0
  es_fputs (sigstr, es_stdout);
1542
0
  es_fprintf (es_stdout, "%c%c %c%c%c%c%c%c %s %s",
1543
0
    sigrc, (sig->sig_class - 0x10 > 0 &&
1544
0
      sig->sig_class - 0x10 <
1545
0
      4) ? '0' + sig->sig_class - 0x10 : ' ',
1546
0
    sig->flags.exportable ? ' ' : 'L',
1547
0
    sig->flags.revocable ? ' ' : 'R',
1548
0
    sig->flags.policy_url ? 'P' : ' ',
1549
0
    sig->flags.notation ? 'N' : ' ',
1550
0
    sig->flags.expired ? 'X' : ' ',
1551
0
    (sig->trust_depth > 9) ? 'T' : (sig->trust_depth >
1552
0
            0) ? '0' +
1553
0
    sig->trust_depth : ' ', keystr (sig->keyid),
1554
0
    datestr_from_sig (sig));
1555
0
  if (opt.list_options & LIST_SHOW_SIG_EXPIRE)
1556
0
    es_fprintf (es_stdout, " %s", expirestr_from_sig (sig));
1557
0
  es_fprintf (es_stdout, "  ");
1558
0
  if (sigrc == '%')
1559
0
    es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
1560
0
  else if (sigrc == '?')
1561
0
    ;
1562
0
  else if ((node->flag & NODFLG_MARK_B))
1563
0
    es_fputs (_("[self-signature]"), es_stdout);
1564
0
  else if (!opt.fast_list_mode )
1565
0
    {
1566
0
      size_t n;
1567
0
      char *p = get_user_id (ctrl, sig->keyid, &n, NULL);
1568
0
      print_utf8_buffer (es_stdout, p, n);
1569
0
      xfree (p);
1570
0
    }
1571
0
  if ((opt.list_options & LIST_SHOW_TRUSTSIG)
1572
0
      && (sig->trust_depth || sig->trust_value || sig->trust_regexp))
1573
0
    {
1574
0
      es_fprintf (es_stdout, " [T=%d,%d", sig->trust_depth, sig->trust_value);
1575
0
      if (sig->trust_regexp)
1576
0
        {
1577
0
          size_t n = strlen (sig->trust_regexp);
1578
0
          char *tname = NULL;
1579
1580
0
          if (!strncmp (sig->trust_regexp, "<[^>]+[@.]", 10)
1581
0
              && n > 12 && !strcmp (sig->trust_regexp+n-2, ">$")
1582
0
              && (tname=parse_trust_name (sig->trust_regexp+10, n-12)))
1583
0
            {
1584
0
              es_fprintf (es_stdout, ",\"%s", tname);
1585
0
              xfree (tname);
1586
0
            }
1587
0
          else
1588
0
            {
1589
0
              es_fputs (",R\"", es_stdout);
1590
0
              es_write_sanitized (es_stdout, sig->trust_regexp, n, "\"", NULL);
1591
0
            }
1592
0
          es_putc ('\"', es_stdout);
1593
0
        }
1594
0
      es_putc (']', es_stdout);
1595
0
    }
1596
0
  es_putc ('\n', es_stdout);
1597
1598
0
  if (sig->flags.policy_url
1599
0
      && (opt.list_options & LIST_SHOW_POLICY_URLS))
1600
0
    show_policy_url (sig, 3, 0);
1601
1602
0
  if (sig->flags.notation && (opt.list_options & LIST_SHOW_NOTATIONS))
1603
0
    show_notation (sig, 3, 0,
1604
0
                   ((opt.
1605
0
                     list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0) +
1606
0
                   ((opt.
1607
0
                     list_options & LIST_SHOW_USER_NOTATIONS) ? 2 : 0) +
1608
0
                   ((opt.
1609
0
                     list_options & LIST_SHOW_HIDDEN_NOTATIONS) ? 4 : 0));
1610
1611
0
  if (sig->flags.notation
1612
0
      && (opt.list_options
1613
0
          & (LIST_SHOW_X509_NOTATIONS|LIST_STORE_X509_NOTATIONS)))
1614
0
    {
1615
0
      struct notation *nots;
1616
1617
0
      if ((IS_KEY_SIG (sig) || IS_SUBKEY_SIG (sig))
1618
0
          && (nots = search_sig_notations (sig,
1619
0
                                           "x509certificate@pgp.com")))
1620
0
        {
1621
0
          if ((opt.list_options & LIST_STORE_X509_NOTATIONS))
1622
0
            print_x509_notations (nots, lastpk);
1623
0
          else
1624
0
            print_x509_notations (nots, NULL);
1625
0
          free_notation (nots);
1626
0
        }
1627
0
    }
1628
1629
0
  if (sig->flags.pref_ks
1630
0
      && (opt.list_options & LIST_SHOW_KEYSERVER_URLS))
1631
0
    show_keyserver_url (sig, 3, 0);
1632
1633
0
  if (reason_text && (reason_code || reason_comment))
1634
0
    {
1635
0
      es_fprintf (es_stdout, "      %s%s\n",
1636
0
                  _("reason for revocation: "), reason_text);
1637
0
      print_revocation_reason_comment (reason_comment, reason_commentlen);
1638
0
    }
1639
1640
0
  xfree (reason_text);
1641
0
  xfree (reason_comment);
1642
1643
  /* fixme: check or list other sigs here */
1644
0
}
1645
1646
1647
static void
1648
list_keyblock_print (ctrl_t ctrl, kbnode_t keyblock, int secret, int fpr,
1649
                     struct keylist_context *listctx)
1650
0
{
1651
0
  int rc;
1652
0
  kbnode_t node;
1653
0
  PKT_public_key *pk;
1654
0
  PKT_public_key *lastpk;
1655
0
  u32 *mainkid;
1656
0
  int skip_sigs = 0;
1657
0
  char *hexgrip = NULL;
1658
0
  char *serialno = NULL;
1659
1660
  /* Get the keyid from the keyblock.  */
1661
0
  node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
1662
0
  if (!node)
1663
0
    {
1664
0
      log_error ("Oops; key lost!\n");
1665
0
      dump_kbnode (keyblock);
1666
0
      return;
1667
0
    }
1668
1669
0
  pk = node->pkt->pkt.public_key;
1670
0
  mainkid = pk_keyid (pk);
1671
0
  lastpk = pk;
1672
1673
0
  if (secret || opt.with_keygrip)
1674
0
    {
1675
0
      rc = hexkeygrip_from_pk (pk, &hexgrip);
1676
0
      if (rc)
1677
0
        log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
1678
0
    }
1679
1680
0
  if (secret)
1681
0
    {
1682
      /* Encode some info about the secret key in SECRET.  */
1683
0
      if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
1684
0
        secret = serialno? 3 : 1;
1685
0
      else
1686
0
        secret = 2;  /* Key not found.  */
1687
0
    }
1688
1689
0
  if (!listctx->no_validity)
1690
0
    check_trustdb_stale (ctrl);
1691
1692
  /* Print the "pub" line and in KF_NONE mode the fingerprint.  */
1693
0
  print_key_line (ctrl, es_stdout, pk, secret);
1694
1695
0
  if (fpr)
1696
0
    print_fingerprint (ctrl, NULL, pk, 0);
1697
1698
0
  if (opt.with_keygrip && hexgrip)
1699
0
    print_keygrip (hexgrip);
1700
1701
0
  if (serialno)
1702
0
    print_card_serialno (serialno);
1703
1704
0
  if (opt.with_key_data)
1705
0
    print_key_data (pk);
1706
1707
0
  if (opt.with_key_screening)
1708
0
    print_pk_screening (pk, 0);
1709
1710
0
  if (opt.with_key_origin
1711
0
      && (pk->keyorg || pk->keyupdate || pk->updateurl))
1712
0
    {
1713
0
      char updatestr[MK_DATESTR_SIZE];
1714
1715
0
      es_fprintf (es_stdout, "      origin=%s last=%s %s",
1716
0
                  key_origin_string (pk->keyorg),
1717
0
                  mk_datestr (updatestr, sizeof updatestr, pk->keyupdate),
1718
0
                  pk->updateurl? "url=":"");
1719
0
      if (pk->updateurl)
1720
0
        print_utf8_string (es_stdout, pk->updateurl);
1721
0
      es_putc ('\n', es_stdout);
1722
0
    }
1723
1724
0
  print_revokers (es_stdout, 0, pk);
1725
1726
0
  for (node = keyblock; node; node = node->next)
1727
0
    {
1728
0
      if (is_deleted_kbnode (node))
1729
0
        continue;
1730
1731
0
      if (node->pkt->pkttype == PKT_USER_ID)
1732
0
  {
1733
0
    PKT_user_id *uid = node->pkt->pkt.user_id;
1734
0
          int indent;
1735
0
          int kl = opt.keyid_format == KF_NONE? 10 : keystrlen ();
1736
1737
0
    if ((uid->flags.expired || uid->flags.revoked)
1738
0
        && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
1739
0
      {
1740
0
        skip_sigs = 1;
1741
0
        continue;
1742
0
      }
1743
0
    else
1744
0
      skip_sigs = 0;
1745
1746
0
    if (attrib_fp && uid->attrib_data != NULL)
1747
0
      dump_attribs (uid, pk);
1748
1749
0
    if ((uid->flags.revoked || uid->flags.expired)
1750
0
        || ((opt.list_options & LIST_SHOW_UID_VALIDITY)
1751
0
                  && !listctx->no_validity))
1752
0
      {
1753
0
        const char *validity;
1754
1755
0
        validity = uid_trust_string_fixed (ctrl, pk, uid);
1756
0
        indent = ((kl + (opt.legacy_list_mode? 9:11))
1757
0
                        - atoi (uid_trust_string_fixed (ctrl, NULL, NULL)));
1758
0
        if (indent < 0 || indent > 40)
1759
0
    indent = 0;
1760
1761
0
        es_fprintf (es_stdout, "uid%*s%s ", indent, "", validity);
1762
0
      }
1763
0
    else
1764
0
            {
1765
0
              indent = kl + (opt.legacy_list_mode? 10:12);
1766
0
              es_fprintf (es_stdout, "uid%*s", indent, "");
1767
0
            }
1768
1769
0
    print_utf8_buffer (es_stdout, uid->name, uid->len);
1770
0
    es_putc ('\n', es_stdout);
1771
1772
0
          if ((opt.list_options & LIST_SHOW_PREF_VERBOSE))
1773
0
            show_preferences (uid, indent+2, 0, 1);
1774
0
          else if ((opt.list_options & LIST_SHOW_PREF))
1775
0
            show_preferences (uid, indent+2, 0, 0);
1776
1777
0
          if (opt.with_wkd_hash)
1778
0
            {
1779
0
              char *mbox, *hash, *p;
1780
0
              char hashbuf[32];
1781
1782
0
              mbox = mailbox_from_userid (uid->name, 0);
1783
0
              if (mbox && (p = strchr (mbox, '@')))
1784
0
                {
1785
0
                  *p++ = 0;
1786
0
                  gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf,
1787
0
                                       mbox, strlen (mbox));
1788
0
                  hash = zb32_encode (hashbuf, 8*20);
1789
0
                  if (hash)
1790
0
                    {
1791
0
                      es_fprintf (es_stdout, "   %*s%s@%s\n",
1792
0
                                  indent, "", hash, p);
1793
0
                      xfree (hash);
1794
0
                    }
1795
0
                }
1796
0
              xfree (mbox);
1797
0
            }
1798
1799
0
          if (opt.with_key_origin
1800
0
              && (uid->keyorg || uid->keyupdate || uid->updateurl))
1801
0
            {
1802
0
              char updatestr[MK_DATESTR_SIZE];
1803
1804
0
              es_fprintf (es_stdout, "   %*sorigin=%s last=%s %s",
1805
0
                          indent, "",
1806
0
                          key_origin_string (uid->keyorg),
1807
0
                          mk_datestr (updatestr, sizeof updatestr,
1808
0
                                      uid->keyupdate),
1809
0
                          uid->updateurl? "url=":"");
1810
0
              if (uid->updateurl)
1811
0
                print_utf8_string (es_stdout, uid->updateurl);
1812
0
              es_putc ('\n', es_stdout);
1813
0
            }
1814
1815
0
    if ((opt.list_options & LIST_SHOW_PHOTOS) && uid->attribs != NULL)
1816
0
      show_photos (ctrl, uid->attribs, uid->numattribs, pk, uid);
1817
0
  }
1818
0
      else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
1819
0
  {
1820
0
    PKT_public_key *pk2 = node->pkt->pkt.public_key;
1821
1822
0
          lastpk = pk2;
1823
0
    if ((pk2->flags.revoked || pk2->has_expired)
1824
0
        && !(opt.list_options & LIST_SHOW_UNUSABLE_SUBKEYS))
1825
0
      {
1826
0
        skip_sigs = 1;
1827
0
        continue;
1828
0
      }
1829
0
    else
1830
0
      skip_sigs = 0;
1831
1832
0
          xfree (serialno); serialno = NULL;
1833
0
          xfree (hexgrip); hexgrip = NULL;
1834
0
          if (secret || opt.with_keygrip)
1835
0
            {
1836
0
              rc = hexkeygrip_from_pk (pk2, &hexgrip);
1837
0
              if (rc)
1838
0
                log_error ("error computing a keygrip: %s\n",
1839
0
                           gpg_strerror (rc));
1840
0
            }
1841
0
          if (secret)
1842
0
            {
1843
0
              if (!agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
1844
0
                secret = serialno? 3 : 1;
1845
0
              else
1846
0
                secret = 2;  /* Key not found.  */
1847
0
            }
1848
1849
          /* Print the "sub" line.  */
1850
0
          print_key_line (ctrl, es_stdout, pk2, secret);
1851
0
    if (fpr > 1 || opt.with_subkey_fingerprint)
1852
0
            {
1853
0
              print_fingerprint (ctrl, NULL, pk2, 0);
1854
0
              if (serialno)
1855
0
                print_card_serialno (serialno);
1856
0
            }
1857
0
          if (opt.with_keygrip && hexgrip)
1858
0
            print_keygrip (hexgrip);
1859
0
    if (opt.with_key_data)
1860
0
      print_key_data (pk2);
1861
0
          if (opt.with_key_screening)
1862
0
            print_pk_screening (pk2, 0);
1863
0
  }
1864
0
      else if ((opt.list_sigs
1865
0
                || (opt.list_options
1866
0
                    & (LIST_SHOW_X509_NOTATIONS|LIST_STORE_X509_NOTATIONS)))
1867
0
         && node->pkt->pkttype == PKT_SIGNATURE && !skip_sigs)
1868
0
  {
1869
0
          kbnode_t n;
1870
0
          unsigned int sigcount = 0;
1871
0
          kbnode_t *sigarray;
1872
0
          unsigned int idx;
1873
1874
0
          for (n=node; n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
1875
0
            sigcount++;
1876
0
          sigarray = xcalloc (sigcount, sizeof *sigarray);
1877
1878
0
          sigcount = 0;
1879
0
          for (n=node; n && n->pkt->pkttype == PKT_SIGNATURE; n = n->next)
1880
0
            {
1881
0
              if (keyid_eq (mainkid, n->pkt->pkt.signature->keyid))
1882
0
                n->flag |= NODFLG_MARK_B;  /* Is a self-sig.  */
1883
0
              else
1884
0
                n->flag &= ~NODFLG_MARK_B;
1885
1886
0
              sigarray[sigcount++] = node = n;
1887
0
            }
1888
          /* Note that NODE is now at the last signature.  */
1889
1890
0
          if ((opt.list_options & LIST_SORT_SIGS))
1891
0
            qsort (sigarray, sigcount, sizeof *sigarray, cmp_signodes);
1892
1893
0
          for (idx=0; idx < sigcount; idx++)
1894
0
            list_signature_print (ctrl, keyblock, sigarray[idx], listctx,
1895
0
                                  lastpk);
1896
0
          xfree (sigarray);
1897
0
  }
1898
0
    }
1899
0
  es_putc ('\n', es_stdout);
1900
0
  xfree (serialno);
1901
0
  xfree (hexgrip);
1902
0
}
1903
1904
1905
/* Do a simple key listing printing only the fingerprint and the mail
1906
 * address of valid keys.  */
1907
static void
1908
list_keyblock_simple (ctrl_t ctrl, kbnode_t keyblock)
1909
0
{
1910
0
  gpg_err_code_t ec;
1911
0
  kbnode_t kbctx;
1912
0
  kbnode_t node;
1913
0
  char hexfpr[2*MAX_FINGERPRINT_LEN+1];
1914
0
  char *mbox;
1915
1916
0
  (void)ctrl;
1917
1918
0
  node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
1919
0
  if (!node)
1920
0
    {
1921
0
      log_error ("Oops; key lost!\n");
1922
0
      dump_kbnode (keyblock);
1923
0
      return;
1924
0
    }
1925
0
  hexfingerprint (node->pkt->pkt.public_key, hexfpr, sizeof hexfpr);
1926
1927
0
  for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
1928
0
    {
1929
0
      if (node->pkt->pkttype == PKT_USER_ID)
1930
0
  {
1931
0
    PKT_user_id *uid = node->pkt->pkt.user_id;
1932
1933
0
    if (uid->attrib_data)
1934
0
      continue;
1935
1936
0
    if ((uid->flags.expired || uid->flags.revoked)
1937
0
              && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS))
1938
0
            continue;
1939
1940
0
          mbox = mailbox_from_userid (uid->name, 0);
1941
0
          if (!mbox)
1942
0
            {
1943
0
              ec = gpg_err_code_from_syserror ();
1944
0
              if (ec != GPG_ERR_EINVAL)
1945
0
                log_error ("error getting mailbox from user-id: %s\n",
1946
0
                           gpg_strerror (ec));
1947
0
              continue;
1948
0
            }
1949
0
          es_fprintf (es_stdout, "%s %s\n", hexfpr, mbox);
1950
0
          xfree (mbox);
1951
0
  }
1952
0
    }
1953
0
}
1954
1955
1956
/* Print the revoker records. */
1957
void
1958
print_revokers (estream_t fp, int colon_mode, PKT_public_key * pk)
1959
0
{
1960
0
  int i, j;
1961
0
  const byte *p;
1962
1963
0
  if (!pk->revkey && pk->numrevkeys)
1964
0
    BUG ();
1965
1966
0
  for (i = 0; i < pk->numrevkeys; i++)
1967
0
    {
1968
0
      if (colon_mode)
1969
0
        {
1970
0
          es_fprintf (fp, "rvk:::%d::::::", pk->revkey[i].algid);
1971
0
          p = pk->revkey[i].fpr;
1972
0
          for (j = 0; j < pk->revkey[i].fprlen; j++, p++)
1973
0
            es_fprintf (fp, "%02X", *p);
1974
0
          es_fprintf (fp, ":%02x%s:\n",
1975
0
                      pk->revkey[i].class,
1976
0
                      (pk->revkey[i].class & 0x40) ? "s" : "");
1977
0
        }
1978
0
      else
1979
0
        {
1980
0
          es_fprintf (fp, "%*s%s", 6, "", _("Revocable by: "));
1981
0
          p = pk->revkey[i].fpr;
1982
0
          es_write_hexstring (fp, pk->revkey[i].fpr, pk->revkey[i].fprlen,
1983
0
                              0, NULL);
1984
0
          if ((pk->revkey[i].class & 0x40))
1985
0
            es_fprintf (fp, " %s", _("(sensitive)"));
1986
          /* Class bit 7 must always be set, bit 6 indicates sensitive
1987
           * and all others bits are reserved.  */
1988
0
          if (!(pk->revkey[i].class & ~0x40)
1989
0
              || (pk->revkey[i].class & ~(0x40|0x80)))
1990
0
            es_fprintf (fp, " (unknown class %02x)", pk->revkey[i].class);
1991
0
    es_fprintf (fp, "\n");
1992
0
        }
1993
0
    }
1994
0
}
1995
1996
1997
/* Print the compliance flags to field 18.  PK is the public key.
1998
 * KEYLENGTH is the length of the key in bits and CURVENAME is either
1999
 * NULL or the name of the curve.  The latter two args are here
2000
 * merely because the caller has already computed them.  */
2001
static void
2002
print_compliance_flags (PKT_public_key *pk,
2003
                        unsigned int keylength, const char *curvename)
2004
0
{
2005
0
  int any = 0;
2006
2007
0
  if (!keylength)
2008
0
    keylength = nbits_from_pk (pk);
2009
2010
0
  if (pk->version == 5)
2011
0
    {
2012
0
      es_fputs (gnupg_status_compliance_flag (CO_GNUPG), es_stdout);
2013
0
      any++;
2014
0
    }
2015
0
  if (gnupg_pk_is_compliant (CO_DE_VS, pk->pubkey_algo, 0, pk->pkey,
2016
0
           keylength, curvename))
2017
0
    {
2018
0
      es_fprintf (es_stdout, any ? " %s" : "%s",
2019
0
      gnupg_status_compliance_flag (CO_DE_VS));
2020
0
      any++;
2021
0
    }
2022
2023
0
  if (opt.with_key_screening)
2024
0
    print_pk_screening (pk, 1+any);
2025
0
}
2026
2027
2028
/* List a key in colon mode.  If SECRET is true this is a secret key
2029
   record (i.e. requested via --list-secret-key).  If HAS_SECRET a
2030
   secret key is available even if SECRET is not set.  */
2031
static void
2032
list_keyblock_colon (ctrl_t ctrl, kbnode_t keyblock,
2033
                     int secret, int has_secret)
2034
0
{
2035
0
  int rc;
2036
0
  KBNODE kbctx;
2037
0
  KBNODE node;
2038
0
  PKT_public_key *pk;
2039
0
  u32 keyid[2];
2040
0
  int trustletter = 0;
2041
0
  int trustletter_print;
2042
0
  int ownertrust_print;
2043
0
  int ulti_hack = 0;
2044
0
  int i;
2045
0
  char *hexgrip_buffer = NULL;
2046
0
  const char *hexgrip = NULL;
2047
0
  char *serialno = NULL;
2048
0
  int stubkey;
2049
0
  unsigned int keylength;
2050
0
  char *curve = NULL;
2051
0
  const char *curvename = NULL;
2052
0
  char pkstrbuf[PUBKEY_STRING_SIZE];
2053
2054
  /* Get the keyid from the keyblock.  */
2055
0
  node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
2056
0
  if (!node)
2057
0
    {
2058
0
      log_error ("Oops; key lost!\n");
2059
0
      dump_kbnode (keyblock);
2060
0
      return;
2061
0
    }
2062
2063
0
  pk = node->pkt->pkt.public_key;
2064
0
  if (secret || has_secret || opt.with_keygrip || opt.with_key_data)
2065
0
    {
2066
0
      rc = hexkeygrip_from_pk (pk, &hexgrip_buffer);
2067
0
      if (rc)
2068
0
        log_error ("error computing a keygrip: %s\n", gpg_strerror (rc));
2069
      /* In the error case we print an empty string so that we have a
2070
       * "grp" record for each primary and subkey - even if it is
2071
       * empty.  This may help to prevent sync problems.  */
2072
0
      hexgrip = hexgrip_buffer? hexgrip_buffer : "";
2073
0
    }
2074
0
  stubkey = 0;
2075
0
  if ((secret || has_secret)
2076
0
      && agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
2077
0
    stubkey = 1;  /* Key not found.  */
2078
2079
0
  keyid_from_pk (pk, keyid);
2080
0
  if (!pk->flags.valid)
2081
0
    trustletter_print = 'i';
2082
0
  else if (pk->flags.revoked)
2083
0
    trustletter_print = 'r';
2084
0
  else if (pk->has_expired)
2085
0
    trustletter_print = 'e';
2086
0
  else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
2087
0
    trustletter_print = 0;
2088
0
  else
2089
0
    {
2090
0
      trustletter = get_validity_info (ctrl, keyblock, pk, NULL);
2091
0
      if (trustletter == 'u')
2092
0
        ulti_hack = 1;
2093
0
      trustletter_print = trustletter;
2094
0
    }
2095
2096
0
  if (!opt.fast_list_mode && !opt.no_expensive_trust_checks)
2097
0
    ownertrust_print = get_ownertrust_info (ctrl, pk, 0);
2098
0
  else
2099
0
    ownertrust_print = 0;
2100
2101
0
  keylength = nbits_from_pk (pk);
2102
2103
0
  es_fputs (secret? "sec:":"pub:", es_stdout);
2104
0
  if (trustletter_print)
2105
0
    es_putc (trustletter_print, es_stdout);
2106
0
  es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s::",
2107
0
              keylength,
2108
0
              pk->pubkey_algo,
2109
0
              (ulong) keyid[0], (ulong) keyid[1],
2110
0
              colon_datestr_from_pk (pk), colon_strtime (pk->expiredate));
2111
2112
0
  if (ownertrust_print)
2113
0
    es_putc (ownertrust_print, es_stdout);
2114
0
  es_putc (':', es_stdout);
2115
2116
0
  es_putc (':', es_stdout);
2117
0
  es_putc (':', es_stdout);
2118
0
  print_capabilities (ctrl, pk, keyblock);
2119
0
  es_putc (':', es_stdout);   /* End of field 13. */
2120
0
  es_putc (':', es_stdout);   /* End of field 14. */
2121
0
  if (secret || has_secret)
2122
0
    {
2123
0
      if (stubkey)
2124
0
  es_putc ('#', es_stdout);
2125
0
      else if (serialno)
2126
0
        es_fputs (serialno, es_stdout);
2127
0
      else if (has_secret)
2128
0
        es_putc ('+', es_stdout);
2129
0
    }
2130
0
  es_putc (':', es_stdout);   /* End of field 15. */
2131
0
  es_putc (':', es_stdout);   /* End of field 16. */
2132
0
  if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA
2133
0
      || pk->pubkey_algo == PUBKEY_ALGO_EDDSA
2134
0
      || pk->pubkey_algo == PUBKEY_ALGO_ECDH)
2135
0
    {
2136
0
      curve = openpgp_oid_to_str (pk->pkey[0]);
2137
0
      curvename = openpgp_oid_to_curve (curve, 0);
2138
0
      if (!curvename)
2139
0
        curvename = curve;
2140
0
      es_fputs (curvename, es_stdout);
2141
0
    }
2142
0
  else if (pk->pubkey_algo == PUBKEY_ALGO_KYBER)
2143
0
    {
2144
      /* Note that Kyber should actually not appear here because it is
2145
       * the primary key and Kyber is not able to certify.  But we
2146
       * prepare it here for future composite algorithms and in case
2147
       * of faulty packets. */
2148
0
      es_fputs (pubkey_string (pk, pkstrbuf, sizeof pkstrbuf), es_stdout);
2149
0
    }
2150
0
  es_putc (':', es_stdout);   /* End of field 17. */
2151
0
  print_compliance_flags (pk, keylength, curvename);
2152
0
  es_putc (':', es_stdout);   /* End of field 18 (compliance). */
2153
0
  if (pk->keyupdate)
2154
0
    es_fputs (colon_strtime (pk->keyupdate), es_stdout);
2155
0
  es_putc (':', es_stdout);   /* End of field 19 (last_update). */
2156
0
  es_fprintf (es_stdout, "%d%s", pk->keyorg, pk->updateurl? " ":"");
2157
0
  if (pk->updateurl)
2158
0
    es_write_sanitized (es_stdout, pk->updateurl, strlen (pk->updateurl),
2159
0
                        ":", NULL);
2160
0
  es_putc (':', es_stdout);   /* End of field 20 (origin). */
2161
0
  if (pk->flags.revoked && pk->revoked.got_reason
2162
0
      && (pk->revoked.reason_code || pk->revoked.reason_comment))
2163
0
    {
2164
0
      char *freeme;
2165
0
      const char *s;
2166
0
      size_t n;
2167
2168
0
      s = revocation_reason_code_to_str (pk->revoked.reason_code, &freeme);
2169
0
      n = strlen (s);
2170
0
      es_write_sanitized (es_stdout, s, n, ":", NULL);
2171
0
      if (n && s[n-1] != '.')
2172
0
        es_putc ('.', es_stdout);
2173
0
      es_putc ('\\', es_stdout);  /* C-style escaped colon.  */
2174
0
      es_putc ('n', es_stdout);
2175
0
      es_write_sanitized (es_stdout, pk->revoked.reason_comment,
2176
0
                          pk->revoked.reason_comment_len,
2177
0
                          ":", NULL);
2178
0
      xfree (freeme);
2179
0
      es_putc (':', es_stdout);   /* End of field 21 (comment). */
2180
0
    }
2181
0
  es_putc ('\n', es_stdout);
2182
2183
0
  print_revokers (es_stdout, 1, pk);
2184
0
  print_fingerprint (ctrl, NULL, pk, 0);
2185
0
  if (hexgrip)
2186
0
    es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
2187
0
  if (opt.with_key_data)
2188
0
    print_key_data (pk);
2189
2190
0
  for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
2191
0
    {
2192
0
      if (node->pkt->pkttype == PKT_USER_ID)
2193
0
  {
2194
0
    PKT_user_id *uid = node->pkt->pkt.user_id;
2195
0
          int uid_validity;
2196
2197
0
    if (attrib_fp && uid->attrib_data != NULL)
2198
0
      dump_attribs (uid, pk);
2199
2200
0
    if (uid->flags.revoked)
2201
0
      uid_validity = 'r';
2202
0
    else if (uid->flags.expired)
2203
0
      uid_validity = 'e';
2204
0
    else if (opt.no_expensive_trust_checks)
2205
0
      uid_validity = 0;
2206
0
    else if (ulti_hack)
2207
0
            uid_validity = 'u';
2208
0
          else
2209
0
            uid_validity = get_validity_info (ctrl, keyblock, pk, uid);
2210
2211
0
          es_fputs (uid->attrib_data? "uat:":"uid:", es_stdout);
2212
0
          if (uid_validity)
2213
0
            es_putc (uid_validity, es_stdout);
2214
0
          es_fputs ("::::", es_stdout);
2215
2216
0
    es_fprintf (es_stdout, "%s:", colon_strtime (uid->created));
2217
0
    es_fprintf (es_stdout, "%s:", colon_strtime (uid->expiredate));
2218
2219
0
    namehash_from_uid (uid);
2220
2221
0
    for (i = 0; i < 20; i++)
2222
0
      es_fprintf (es_stdout, "%02X", uid->namehash[i]);
2223
2224
0
    es_fprintf (es_stdout, "::");
2225
2226
0
    if (uid->attrib_data)
2227
0
      es_fprintf (es_stdout, "%u %lu", uid->numattribs, uid->attrib_len);
2228
0
    else
2229
0
      es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL);
2230
0
    es_fputs (":::::::::", es_stdout);
2231
0
          if (uid->keyupdate)
2232
0
            es_fputs (colon_strtime (uid->keyupdate), es_stdout);
2233
0
          es_putc (':', es_stdout); /* End of field 19 (last_update). */
2234
0
          es_fprintf (es_stdout, "%d%s", uid->keyorg, uid->updateurl? " ":"");
2235
0
          if (uid->updateurl)
2236
0
            es_write_sanitized (es_stdout,
2237
0
                                uid->updateurl, strlen (uid->updateurl),
2238
0
                                ":", NULL);
2239
0
          es_putc (':', es_stdout); /* End of field 20 (origin). */
2240
0
    es_putc ('\n', es_stdout);
2241
0
          if ((opt.list_options & (LIST_SHOW_PREF|LIST_SHOW_PREF_VERBOSE)))
2242
0
            show_preferences (uid, 0, 2, 0);
2243
#ifdef USE_TOFU
2244
    if (!uid->attrib_data && opt.with_tofu_info
2245
              && (opt.trust_model == TM_TOFU || opt.trust_model == TM_TOFU_PGP))
2246
      {
2247
              /* Print a "tfs" record.  */
2248
              tofu_write_tfs_record (ctrl, es_stdout, pk, uid->name);
2249
      }
2250
#endif /*USE_TOFU*/
2251
0
  }
2252
0
      else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
2253
0
  {
2254
0
    u32 keyid2[2];
2255
0
    PKT_public_key *pk2;
2256
0
          int need_hexgrip = !!hexgrip;
2257
2258
0
          pk2 = node->pkt->pkt.public_key;
2259
0
          xfree (hexgrip_buffer); hexgrip_buffer = NULL; hexgrip = NULL;
2260
0
          xfree (serialno); serialno = NULL;
2261
0
          if (need_hexgrip
2262
0
              || secret || has_secret || opt.with_keygrip || opt.with_key_data)
2263
0
            {
2264
0
              rc = hexkeygrip_from_pk (pk2, &hexgrip_buffer);
2265
0
              if (rc)
2266
0
                log_error ("error computing a keygrip: %s\n",
2267
0
                           gpg_strerror (rc));
2268
0
              hexgrip = hexgrip_buffer? hexgrip_buffer : "";
2269
0
            }
2270
0
          stubkey = 0;
2271
0
          if ((secret||has_secret)
2272
0
              && agent_get_keyinfo (NULL, hexgrip, &serialno, NULL))
2273
0
            stubkey = 1;  /* Key not found.  */
2274
2275
0
    keyid_from_pk (pk2, keyid2);
2276
0
    es_fputs (secret? "ssb:":"sub:", es_stdout);
2277
0
    if (!pk2->flags.valid)
2278
0
      es_putc ('i', es_stdout);
2279
0
    else if (pk2->flags.revoked)
2280
0
      es_putc ('r', es_stdout);
2281
0
    else if (pk2->has_expired)
2282
0
      es_putc ('e', es_stdout);
2283
0
    else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
2284
0
      ;
2285
0
    else
2286
0
      {
2287
        /* TRUSTLETTER should always be defined here. */
2288
0
        if (trustletter)
2289
0
    es_fprintf (es_stdout, "%c", trustletter);
2290
0
      }
2291
0
          keylength = nbits_from_pk (pk2);
2292
0
    es_fprintf (es_stdout, ":%u:%d:%08lX%08lX:%s:%s:::::",
2293
0
                      keylength,
2294
0
                      pk2->pubkey_algo,
2295
0
                      (ulong) keyid2[0], (ulong) keyid2[1],
2296
0
                      colon_datestr_from_pk (pk2),
2297
0
                      colon_strtime (pk2->expiredate));
2298
0
    print_capabilities (ctrl, pk2, NULL);
2299
0
          es_putc (':', es_stdout); /* End of field 13. */
2300
0
          es_putc (':', es_stdout); /* End of field 14. */
2301
0
          if (secret || has_secret)
2302
0
            {
2303
0
              if (stubkey)
2304
0
                es_putc ('#', es_stdout);
2305
0
              else if (serialno)
2306
0
                es_fputs (serialno, es_stdout);
2307
0
              else if (has_secret)
2308
0
                es_putc ('+', es_stdout);
2309
0
            }
2310
0
          es_putc (':', es_stdout); /* End of field 15. */
2311
0
          es_putc (':', es_stdout); /* End of field 16. */
2312
0
          if (pk2->pubkey_algo == PUBKEY_ALGO_ECDSA
2313
0
              || pk2->pubkey_algo == PUBKEY_ALGO_EDDSA
2314
0
              || pk2->pubkey_algo == PUBKEY_ALGO_ECDH)
2315
0
            {
2316
0
              xfree (curve);
2317
0
              curve = openpgp_oid_to_str (pk2->pkey[0]);
2318
0
              curvename = openpgp_oid_to_curve (curve, 0);
2319
0
              if (!curvename)
2320
0
                curvename = curve;
2321
0
              es_fputs (curvename, es_stdout);
2322
0
            }
2323
0
          else if (pk2->pubkey_algo == PUBKEY_ALGO_KYBER)
2324
0
            {
2325
0
              es_fputs (pubkey_string (pk2, pkstrbuf, sizeof pkstrbuf),
2326
0
                        es_stdout);
2327
0
            }
2328
0
          es_putc (':', es_stdout); /* End of field 17. */
2329
0
          print_compliance_flags (pk2, keylength, curvename);
2330
0
          es_putc (':', es_stdout); /* End of field 18. */
2331
0
    es_putc ('\n', es_stdout);
2332
0
          print_fingerprint (ctrl, NULL, pk2, 0);
2333
0
          if (hexgrip)
2334
0
            es_fprintf (es_stdout, "grp:::::::::%s:\n", hexgrip);
2335
0
          if (opt.with_key_data)
2336
0
            print_key_data (pk2);
2337
0
  }
2338
0
      else if (opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE)
2339
0
  {
2340
0
    PKT_signature *sig = node->pkt->pkt.signature;
2341
0
    int sigrc, fprokay = 0;
2342
0
    char *sigstr;
2343
0
    size_t fplen;
2344
0
    byte fparray[MAX_FINGERPRINT_LEN];
2345
0
          char *siguid;
2346
0
          size_t siguidlen;
2347
0
          char *issuer_fpr = NULL;
2348
0
          char *reason_text = NULL;
2349
0
          char *reason_comment = NULL;
2350
0
          size_t reason_commentlen;
2351
0
          int reason_code = 0;  /* Init to silence compiler warning.  */
2352
2353
0
    if (sig->sig_class == 0x20 || sig->sig_class == 0x28
2354
0
        || sig->sig_class == 0x30)
2355
0
            {
2356
0
              sigstr = "rev";
2357
0
              reason_code = get_revocation_reason (sig, &reason_text,
2358
0
                                                   &reason_comment,
2359
0
                                                   &reason_commentlen);
2360
0
            }
2361
0
    else if ((sig->sig_class & ~3) == 0x10)
2362
0
      sigstr = "sig";
2363
0
    else if (sig->sig_class == 0x18)
2364
0
      sigstr = "sig";
2365
0
    else if (sig->sig_class == 0x1F)
2366
0
      sigstr = "sig";
2367
0
    else
2368
0
      {
2369
0
        es_fprintf (es_stdout, "sig::::::::::%02x%c:\n",
2370
0
          sig->sig_class, sig->flags.exportable ? 'x' : 'l');
2371
0
        continue;
2372
0
      }
2373
2374
0
    if (opt.check_sigs)
2375
0
      {
2376
0
        PKT_public_key *signer_pk = NULL;
2377
2378
0
        es_fflush (es_stdout);
2379
0
        if (opt.no_sig_cache)
2380
0
    signer_pk = xmalloc_clear (sizeof (PKT_public_key));
2381
2382
0
        rc = check_key_signature2 (ctrl, keyblock, node, NULL, signer_pk,
2383
0
           NULL, NULL, NULL);
2384
0
        switch (gpg_err_code (rc))
2385
0
    {
2386
0
    case 0:
2387
0
      sigrc = '!';
2388
0
      break;
2389
0
    case GPG_ERR_BAD_SIGNATURE:
2390
0
      sigrc = '-';
2391
0
      break;
2392
0
    case GPG_ERR_NO_PUBKEY:
2393
0
    case GPG_ERR_UNUSABLE_PUBKEY:
2394
0
      sigrc = '?';
2395
0
      break;
2396
0
    default:
2397
0
      sigrc = '%';
2398
0
      break;
2399
0
    }
2400
2401
0
        if (opt.no_sig_cache)
2402
0
    {
2403
0
      if (!rc)
2404
0
        {
2405
0
          fingerprint_from_pk (signer_pk, fparray, &fplen);
2406
0
          fprokay = 1;
2407
0
        }
2408
0
      free_public_key (signer_pk);
2409
0
    }
2410
0
      }
2411
0
    else
2412
0
      {
2413
0
        rc = 0;
2414
0
        sigrc = ' '; /* Note the fix-up below in --list-sigs mode.  */
2415
0
      }
2416
2417
0
    if (sigrc != '%' && sigrc != '?' && !opt.fast_list_mode)
2418
0
            {
2419
0
              int nouid;
2420
0
              siguid = get_user_id (ctrl, sig->keyid, &siguidlen, &nouid);
2421
0
              if (!opt.check_sigs && nouid)
2422
0
                sigrc = '?';  /* No key in local keyring.  */
2423
0
            }
2424
0
          else
2425
0
            {
2426
0
              siguid = NULL;
2427
0
              siguidlen = 0;
2428
0
            }
2429
2430
2431
0
    es_fputs (sigstr, es_stdout);
2432
0
    es_putc (':', es_stdout);
2433
0
    if (sigrc != ' ')
2434
0
      es_putc (sigrc, es_stdout);
2435
0
    es_fprintf (es_stdout, "::%d:%08lX%08lX:%s:%s:", sig->pubkey_algo,
2436
0
      (ulong) sig->keyid[0], (ulong) sig->keyid[1],
2437
0
      colon_datestr_from_sig (sig),
2438
0
      colon_expirestr_from_sig (sig));
2439
2440
0
    if (sig->trust_depth || sig->trust_value)
2441
0
      es_fprintf (es_stdout, "%d %d", sig->trust_depth, sig->trust_value);
2442
0
    es_fprintf (es_stdout, ":");
2443
2444
0
    if (sig->trust_regexp)
2445
0
      es_write_sanitized (es_stdout, sig->trust_regexp,
2446
0
                                strlen (sig->trust_regexp), ":", NULL);
2447
0
    es_fprintf (es_stdout, ":");
2448
2449
0
    if (sigrc == '%')
2450
0
      es_fprintf (es_stdout, "[%s] ", gpg_strerror (rc));
2451
0
    else if (siguid)
2452
0
            es_write_sanitized (es_stdout, siguid, siguidlen, ":", NULL);
2453
2454
0
    es_fprintf (es_stdout, ":%02x%c", sig->sig_class,
2455
0
                      sig->flags.exportable ? 'x' : 'l');
2456
0
          if (reason_text)
2457
0
            es_fprintf (es_stdout, ",%02x", reason_code);
2458
0
          es_fputs ("::", es_stdout);
2459
2460
0
    if (opt.no_sig_cache && opt.check_sigs && fprokay)
2461
0
      {
2462
0
        for (i = 0; i < fplen; i++)
2463
0
    es_fprintf (es_stdout, "%02X", fparray[i]);
2464
0
      }
2465
0
          else if ((issuer_fpr = issuer_fpr_string (sig)))
2466
0
            es_fputs (issuer_fpr, es_stdout);
2467
2468
0
    es_fprintf (es_stdout, ":::%d:", sig->digest_algo);
2469
2470
0
          if (reason_comment)
2471
0
            {
2472
0
              es_fputs ("::::", es_stdout);
2473
0
              es_write_sanitized (es_stdout, reason_comment, reason_commentlen,
2474
0
                                  ":", NULL);
2475
0
              es_putc (':', es_stdout);
2476
0
            }
2477
0
          es_putc ('\n', es_stdout);
2478
2479
0
    if (opt.show_subpackets)
2480
0
      print_subpackets_colon (sig);
2481
2482
    /* fixme: check or list other sigs here */
2483
0
          xfree (reason_text);
2484
0
          xfree (reason_comment);
2485
0
          xfree (siguid);
2486
0
          xfree (issuer_fpr);
2487
0
  }
2488
0
    }
2489
2490
0
  xfree (curve);
2491
0
  xfree (hexgrip_buffer);
2492
0
  xfree (serialno);
2493
0
}
2494
2495
/*
2496
 * Reorder the keyblock so that the primary user ID (and not attribute
2497
 * packet) comes first.  Fixme: Replace this by a generic sort
2498
 * function.  */
2499
static void
2500
do_reorder_keyblock (KBNODE keyblock, int attr)
2501
0
{
2502
0
  KBNODE primary = NULL, primary0 = NULL, primary2 = NULL;
2503
0
  KBNODE last, node;
2504
2505
0
  for (node = keyblock; node; primary0 = node, node = node->next)
2506
0
    {
2507
0
      if (node->pkt->pkttype == PKT_USER_ID &&
2508
0
    ((attr && node->pkt->pkt.user_id->attrib_data) ||
2509
0
     (!attr && !node->pkt->pkt.user_id->attrib_data)) &&
2510
0
    node->pkt->pkt.user_id->flags.primary)
2511
0
  {
2512
0
    primary = primary2 = node;
2513
0
    for (node = node->next; node; primary2 = node, node = node->next)
2514
0
      {
2515
0
        if (node->pkt->pkttype == PKT_USER_ID
2516
0
      || node->pkt->pkttype == PKT_PUBLIC_SUBKEY
2517
0
      || node->pkt->pkttype == PKT_SECRET_SUBKEY)
2518
0
    {
2519
0
      break;
2520
0
    }
2521
0
      }
2522
0
    break;
2523
0
  }
2524
0
    }
2525
0
  if (!primary)
2526
0
    return; /* No primary key flag found (should not happen).  */
2527
2528
0
  for (last = NULL, node = keyblock; node; last = node, node = node->next)
2529
0
    {
2530
0
      if (node->pkt->pkttype == PKT_USER_ID)
2531
0
  break;
2532
0
    }
2533
0
  log_assert (node);
2534
0
  log_assert (last);  /* The user ID is never the first packet.  */
2535
0
  log_assert (primary0); /* Ditto (this is the node before primary).  */
2536
0
  if (node == primary)
2537
0
    return; /* Already the first one.  */
2538
2539
0
  last->next = primary;
2540
0
  primary0->next = primary2->next;
2541
0
  primary2->next = node;
2542
0
}
2543
2544
void
2545
reorder_keyblock (KBNODE keyblock)
2546
0
{
2547
0
  do_reorder_keyblock (keyblock, 1);
2548
0
  do_reorder_keyblock (keyblock, 0);
2549
0
}
2550
2551
2552
/* Note: If this function returns an error the caller is expected to
2553
 * honor this and stop all further processing.  Any error returned
2554
 * will be a write error (to stdout) and a diagnostics is always
2555
 * printed using log_error.  */
2556
static gpg_error_t
2557
list_keyblock (ctrl_t ctrl,
2558
               KBNODE keyblock, int secret, int has_secret, int fpr,
2559
               struct keylist_context *listctx)
2560
0
{
2561
0
  gpg_error_t err = 0;
2562
2563
0
  es_clearerr (es_stdout);
2564
0
  reorder_keyblock (keyblock);
2565
2566
0
  if (list_filter.selkey)
2567
0
    {
2568
0
      int selected = 0;
2569
0
      struct impex_filter_parm_s parm;
2570
0
      parm.ctrl = ctrl;
2571
2572
0
      for (parm.node = keyblock; parm.node; parm.node = parm.node->next)
2573
0
        {
2574
0
          if (recsel_select (list_filter.selkey, impex_filter_getval, &parm))
2575
0
            {
2576
0
              selected = 1;
2577
0
              break;
2578
0
            }
2579
0
        }
2580
0
      if (!selected)
2581
0
        return 0;  /* Skip this one.  */
2582
0
    }
2583
2584
0
  if (opt.with_colons)
2585
0
    list_keyblock_colon (ctrl, keyblock, secret, has_secret);
2586
0
  else if ((opt.list_options & LIST_SHOW_ONLY_FPR_MBOX))
2587
0
    {
2588
0
      if (!listctx->no_validity)
2589
0
        check_trustdb_stale (ctrl);
2590
0
      list_keyblock_simple (ctrl, keyblock);
2591
0
    }
2592
0
  else
2593
0
    list_keyblock_print (ctrl, keyblock, secret, fpr, listctx);
2594
2595
0
  if (es_ferror (es_stdout))
2596
0
    err = gpg_error_from_syserror ();
2597
2598
0
  if (secret && es_fflush (es_stdout) && !err)
2599
0
    err = gpg_error_from_syserror ();
2600
2601
0
  if (err)
2602
0
    log_error (_("error writing to stdout: %s\n"), gpg_strerror (err));
2603
2604
0
  return err;
2605
0
}
2606
2607
2608
/* Public function used by keygen to list a keyblock.  If NO_VALIDITY
2609
 * is set the validity of a key is never shown.  */
2610
gpg_error_t
2611
list_keyblock_direct (ctrl_t ctrl,
2612
                      kbnode_t keyblock, int secret, int has_secret, int fpr,
2613
                      int no_validity)
2614
0
{
2615
0
  struct keylist_context listctx;
2616
0
  gpg_error_t err;
2617
2618
0
  memset (&listctx, 0, sizeof (listctx));
2619
0
  listctx.no_validity = !!no_validity;
2620
0
  if (opt.check_sigs)
2621
0
    listctx.check_sigs = 1;
2622
0
  err = list_keyblock (ctrl, keyblock, secret, has_secret, fpr, &listctx);
2623
0
  keylist_context_release (&listctx);
2624
0
  return err;
2625
0
}
2626
2627
2628
/* Print an hex digit in ICAO spelling.  */
2629
static void
2630
print_icao_hexdigit (estream_t fp, int c)
2631
0
{
2632
0
  static const char *list[16] = {
2633
0
    "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven",
2634
0
    "Eight", "Niner", "Alfa", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"
2635
0
  };
2636
2637
0
  tty_fprintf (fp, "%s", list[c&15]);
2638
0
}
2639
2640
2641
/*
2642
 * Function to print the finperprint.
2643
 * mode 0: as used in key listings, opt.with_colons is honored
2644
 *      1: print using log_info ()
2645
 *      2: direct use of tty
2646
 *      3: direct use of tty but only primary key.
2647
 *      4: direct use of tty but only subkey.
2648
 *     10: Same as 0 but with_colons etc is ignored.
2649
 *     20: Same as 0 but using a compact format.
2650
 *
2651
 * Modes 1 and 2 will try and print both subkey and primary key
2652
 * fingerprints.  A MODE with bit 7 set is used internally.  If
2653
 * OVERRIDE_FP is not NULL that stream will be used in  0 instead
2654
 * of es_stdout or instead of the TTY in modes 2 and 3.
2655
 */
2656
void
2657
print_fingerprint (ctrl_t ctrl, estream_t override_fp,
2658
                   PKT_public_key *pk, int mode)
2659
0
{
2660
0
  char hexfpr[2*MAX_FINGERPRINT_LEN+1];
2661
0
  char *p;
2662
0
  size_t i;
2663
0
  estream_t fp;
2664
0
  const char *text;
2665
0
  int primary = 0;
2666
0
  int with_colons = opt.with_colons;
2667
0
  int with_icao   = opt.with_icao_spelling;
2668
0
  int compact = 0;
2669
2670
0
  if (mode == 10)
2671
0
    {
2672
0
      mode = 0;
2673
0
      with_colons = 0;
2674
0
      with_icao = 0;
2675
0
    }
2676
0
  else if (mode == 20)
2677
0
    {
2678
0
      mode = 0;
2679
0
      with_colons = 0;
2680
0
      compact = 1;
2681
0
    }
2682
2683
0
  if (!opt.fingerprint && !opt.with_fingerprint
2684
0
      && opt.with_subkey_fingerprint)
2685
0
    compact = 1;
2686
2687
0
  if (pk->main_keyid[0] == pk->keyid[0]
2688
0
      && pk->main_keyid[1] == pk->keyid[1])
2689
0
    primary = 1;
2690
2691
  /* Just to be safe */
2692
0
  if ((mode & 0x80) && !primary)
2693
0
    {
2694
0
      log_error ("primary key is not really primary!\n");
2695
0
      return;
2696
0
    }
2697
2698
0
  mode &= ~0x80;
2699
2700
0
  if (!primary && (mode == 1 || mode == 2))
2701
0
    {
2702
0
      PKT_public_key *primary_pk = xmalloc_clear (sizeof (*primary_pk));
2703
0
      get_pubkey (ctrl, primary_pk, pk->main_keyid);
2704
0
      print_fingerprint (ctrl, override_fp, primary_pk, (mode | 0x80));
2705
0
      free_public_key (primary_pk);
2706
0
    }
2707
2708
0
  if (mode == 1)
2709
0
    {
2710
0
      fp = log_get_stream ();
2711
0
      if (primary)
2712
0
  text = _("Primary key fingerprint:");
2713
0
      else
2714
0
  text = _("     Subkey fingerprint:");
2715
0
    }
2716
0
  else if (mode == 2)
2717
0
    {
2718
0
      fp = override_fp; /* Use tty or given stream.  */
2719
0
      if (primary)
2720
  /* TRANSLATORS: this should fit into 24 bytes so that the
2721
   * fingerprint data is properly aligned with the user ID */
2722
0
  text = _(" Primary key fingerprint:");
2723
0
      else
2724
0
  text = _("      Subkey fingerprint:");
2725
0
    }
2726
0
  else if (mode == 3)
2727
0
    {
2728
0
      fp = override_fp; /* Use tty or given stream.  */
2729
0
      text = _("      Key fingerprint =");
2730
0
    }
2731
0
  else if (mode == 4)
2732
0
    {
2733
0
      fp = override_fp; /* Use tty or given stream.  */
2734
0
      text = _("      Subkey fingerprint:");
2735
0
    }
2736
0
  else
2737
0
    {
2738
0
      fp = override_fp? override_fp : es_stdout;
2739
0
      if (opt.keyid_format == KF_NONE)
2740
0
        {
2741
0
          text = "     ";  /* To indent ICAO spelling.  */
2742
0
          compact = 1;
2743
0
        }
2744
0
      else
2745
0
        text = _("      Key fingerprint =");
2746
0
    }
2747
2748
0
  hexfingerprint (pk, hexfpr, sizeof hexfpr);
2749
0
  if (with_colons && !mode)
2750
0
    {
2751
0
      es_fprintf (fp, "fpr:::::::::%s:", hexfpr);
2752
0
      if (opt.with_v5_fingerprint && pk->version == 4)
2753
0
        {
2754
0
          char *v5fpr = v5hexfingerprint (pk, NULL, 0);
2755
0
          es_fprintf (fp, "\nfp2:::::::::%s:", v5fpr);
2756
0
          xfree (v5fpr);
2757
0
        }
2758
0
    }
2759
0
  else if (compact && !opt.fingerprint && !opt.with_fingerprint)
2760
0
    {
2761
0
      tty_fprintf (fp, "%*s%s", 6, "", hexfpr);
2762
0
    }
2763
0
  else
2764
0
    {
2765
0
      char fmtfpr[MAX_FORMATTED_FINGERPRINT_LEN + 1];
2766
0
      format_hexfingerprint (hexfpr, fmtfpr, sizeof fmtfpr);
2767
0
      if (compact)
2768
0
        tty_fprintf (fp, "%*s%s", 6, "", fmtfpr);
2769
0
      else
2770
0
        tty_fprintf (fp, "%s %s", text, fmtfpr);
2771
0
    }
2772
0
  tty_fprintf (fp, "\n");
2773
0
  if (!with_colons && with_icao)
2774
0
    {
2775
0
      ;
2776
0
      tty_fprintf (fp, "%*s\"", (int)strlen(text)+1, "");
2777
0
      for (i = 0, p = hexfpr; *p; i++, p++)
2778
0
        {
2779
0
          if (!i)
2780
0
            ;
2781
0
          else if (!(i%10))
2782
0
            tty_fprintf (fp, "\n%*s ", (int)strlen(text)+1, "");
2783
0
          else if (!(i%5))
2784
0
            tty_fprintf (fp, "  ");
2785
0
          else
2786
0
            tty_fprintf (fp, " ");
2787
0
          print_icao_hexdigit (fp, xtoi_1 (p));
2788
0
        }
2789
0
      tty_fprintf (fp, "\"\n");
2790
0
    }
2791
0
}
2792
2793
/* Print the serial number of an OpenPGP card if available.  */
2794
static void
2795
print_card_serialno (const char *serialno)
2796
0
{
2797
0
  if (!serialno)
2798
0
    return;
2799
0
  if (opt.with_colons)
2800
0
    return; /* Handled elsewhere. */
2801
2802
0
  es_fputs (_("      Card serial no. ="), es_stdout);
2803
0
  es_putc (' ', es_stdout);
2804
0
  if (strlen (serialno) == 32 && !strncmp (serialno, "D27600012401", 12))
2805
0
    {
2806
      /* This is an OpenPGP card.  Print the relevant part.  */
2807
      /* Example: D2760001240101010001000003470000 */
2808
      /*                          xxxxyyyyyyyy     */
2809
0
      es_fprintf (es_stdout, "%.*s %.*s", 4, serialno+16, 8, serialno+20);
2810
0
    }
2811
0
 else
2812
0
   es_fputs (serialno, es_stdout);
2813
0
  es_putc ('\n', es_stdout);
2814
0
}
2815
2816
2817
/* Print a public or secret (sub)key line.  Example:
2818
 *
2819
 * pub   dsa2048 2007-12-31 [SC] [expires: 2018-12-31]
2820
 *       80615870F5BAD690333686D0F2AD85AC1E42B367
2821
 *
2822
 * pub   rsa2048 2017-12-31 [SC] [expires: 2028-12-31]
2823
 *       80615870F5BAD690333686D0F2AD85AC1E42B3671122334455
2824
 *
2825
 * Some global options may result in a different output format.  If
2826
 * SECRET is set, "sec" or "ssb" is used instead of "pub" or "sub" and
2827
 * depending on the value a flag character is shown:
2828
 *
2829
 *    1 := ' ' Regular secret key
2830
 *    2 := '#' Stub secret key
2831
 *    3 := '>' Secret key is on a token.
2832
 */
2833
void
2834
print_key_line (ctrl_t ctrl, estream_t fp, PKT_public_key *pk, int secret)
2835
0
{
2836
0
  char pkstrbuf[PUBKEY_STRING_SIZE];
2837
2838
0
  tty_fprintf (fp, "%s%c  %s",
2839
0
               pk->flags.primary? (secret? "sec":"pub")
2840
0
               /**/             : (secret? "ssb":"sub"),
2841
0
               secret == 2? '#' : secret == 3? '>' : ' ',
2842
0
               pubkey_string (pk, pkstrbuf, sizeof pkstrbuf));
2843
0
  if (opt.keyid_format != KF_NONE)
2844
0
    tty_fprintf (fp, "/%s", keystr_from_pk (pk));
2845
0
  tty_fprintf (fp, " %s", datestr_from_pk (pk));
2846
2847
0
  if (pk->flags.primary
2848
0
      && !(openpgp_pk_algo_usage (pk->pubkey_algo)
2849
0
           & (PUBKEY_USAGE_CERT| PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)))
2850
0
    {
2851
      /* A primary key which is really not capable to sign.  */
2852
0
      tty_fprintf (fp, " [INVALID_ALGO]");
2853
0
    }
2854
0
  else if ((opt.list_options & LIST_SHOW_USAGE))
2855
0
    {
2856
0
      tty_fprintf (fp, " [%s]", usagestr_from_pk (pk, 0));
2857
0
    }
2858
2859
0
  if (pk->flags.primary && (opt.list_options & LIST_SHOW_OWNERTRUST))
2860
0
    {
2861
0
      tty_fprintf (fp, " [%s]", get_ownertrust_string (ctrl, pk, 0));
2862
0
    }
2863
2864
0
  if (pk->flags.revoked)
2865
0
    {
2866
0
      tty_fprintf (fp, " [");
2867
0
      tty_fprintf (fp, _("revoked: %s"), revokestr_from_pk (pk));
2868
0
      tty_fprintf (fp, "]");
2869
0
    }
2870
0
  else if (pk->has_expired)
2871
0
    {
2872
0
      tty_fprintf (fp, " [");
2873
0
      tty_fprintf (fp, _("expired: %s"), expirestr_from_pk (pk));
2874
0
      tty_fprintf (fp, "]");
2875
0
    }
2876
0
  else if (pk->expiredate)
2877
0
    {
2878
0
      tty_fprintf (fp, " [");
2879
0
      tty_fprintf (fp, _("expires: %s"), expirestr_from_pk (pk));
2880
0
      tty_fprintf (fp, "]");
2881
0
    }
2882
2883
0
  if (pk->pubkey_algo >= 100)
2884
0
    tty_fprintf (fp, " [experimental algorithm %d]", pk->pubkey_algo);
2885
2886
0
  tty_fprintf (fp, "\n");
2887
2888
0
  if (pk->flags.primary && pk_is_disabled (pk))
2889
0
    es_fprintf (es_stdout, "      *** %s\n", _("This key has been disabled"));
2890
2891
  /* if the user hasn't explicitly asked for human-readable
2892
     fingerprints, show compact fpr of primary key: */
2893
0
  if (pk->flags.primary &&
2894
0
      !opt.fingerprint && !opt.with_fingerprint)
2895
0
    print_fingerprint (ctrl, fp, pk, 20);
2896
2897
  /* Print the revocation reason.  */
2898
0
  if (pk->flags.revoked)
2899
0
    print_revocation_reason (pk);
2900
0
}
2901
2902
2903
void
2904
set_attrib_fd (int fd)
2905
0
{
2906
0
  static int last_fd = -1;
2907
2908
0
  if (fd != -1 && last_fd == fd)
2909
0
    return;
2910
2911
  /* Fixme: Do we need to check for the log stream here?  */
2912
0
  if (attrib_fp && attrib_fp != log_get_stream ())
2913
0
    es_fclose (attrib_fp);
2914
0
  attrib_fp = NULL;
2915
0
  if (fd == -1)
2916
0
    return;
2917
2918
0
  if (! gnupg_fd_valid (fd))
2919
0
    log_fatal ("attribute-fd is invalid: %s\n", strerror (errno));
2920
2921
#ifdef HAVE_DOSISH_SYSTEM
2922
  setmode (fd, O_BINARY);
2923
#endif
2924
0
  if (fd == 1)
2925
0
    attrib_fp = es_stdout;
2926
0
  else if (fd == 2)
2927
0
    attrib_fp = es_stderr;
2928
0
  else
2929
0
    attrib_fp = es_fdopen (fd, "wb");
2930
0
  if (!attrib_fp)
2931
0
    {
2932
0
      log_fatal ("can't open fd %d for attribute output: %s\n",
2933
0
     fd, strerror (errno));
2934
0
    }
2935
2936
0
  last_fd = fd;
2937
0
}