core: Change the way TOFU information are represented.
[gpgme.git] / src / keylist.c
1 /* keylist.c - Listing keys.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2006, 2007,
4                  2008, 2009  g10 Code GmbH
5
6    This file is part of GPGME.
7
8    GPGME is free software; you can redistribute it and/or modify it
9    under the terms of the GNU Lesser General Public License as
10    published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    GPGME is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #ifdef HAVE_SYS_TYPES_H
29   /* Solaris 8 needs sys/types.h before time.h.  */
30 # include <sys/types.h>
31 #endif
32 #include <time.h>
33 #include <assert.h>
34 #include <ctype.h>
35 #include <errno.h>
36
37 /* Suppress warning for accessing deprecated member "class".  */
38 #define _GPGME_IN_GPGME
39 #include "gpgme.h"
40 #include "util.h"
41 #include "context.h"
42 #include "ops.h"
43 #include "debug.h"
44
45 \f
46 struct key_queue_item_s
47 {
48   struct key_queue_item_s *next;
49   gpgme_key_t key;
50 };
51
52 typedef struct
53 {
54   struct _gpgme_op_keylist_result result;
55
56   gpgme_key_t tmp_key;
57
58   /* This points to the last uid in tmp_key.  */
59   gpgme_user_id_t tmp_uid;
60
61   /* This points to the last sig in tmp_uid.  */
62   gpgme_key_sig_t tmp_keysig;
63
64   /* Something new is available.  */
65   int key_cond;
66   struct key_queue_item_s *key_queue;
67 } *op_data_t;
68
69
70 static void
71 release_op_data (void *hook)
72 {
73   op_data_t opd = (op_data_t) hook;
74   struct key_queue_item_s *key = opd->key_queue;
75
76   if (opd->tmp_key)
77     gpgme_key_unref (opd->tmp_key);
78
79   /* opd->tmp_uid and opd->tmp_keysig are actually part of opd->tmp_key,
80      so we do not need to release them here.  */
81
82   while (key)
83     {
84       struct key_queue_item_s *next = key->next;
85
86       gpgme_key_unref (key->key);
87       key = next;
88     }
89 }
90
91
92 gpgme_keylist_result_t
93 gpgme_op_keylist_result (gpgme_ctx_t ctx)
94 {
95   void *hook;
96   op_data_t opd;
97   gpgme_error_t err;
98
99   TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_result", ctx);
100
101   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
102   opd = hook;
103   if (err || !opd)
104     {
105       TRACE_SUC0 ("result=(null)");
106       return NULL;
107     }
108
109   TRACE_LOG1 ("truncated = %i", opd->result.truncated);
110
111   TRACE_SUC1 ("result=%p", &opd->result);
112   return &opd->result;
113 }
114
115 \f
116 static gpgme_error_t
117 keylist_status_handler (void *priv, gpgme_status_code_t code, char *args)
118 {
119   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
120   gpgme_error_t err;
121   void *hook;
122   op_data_t opd;
123
124   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
125   opd = hook;
126   if (err)
127     return err;
128
129   switch (code)
130     {
131     case GPGME_STATUS_TRUNCATED:
132       opd->result.truncated = 1;
133       break;
134
135     default:
136       break;
137     }
138   return 0;
139 }
140
141 \f
142 static void
143 set_subkey_trust_info (gpgme_subkey_t subkey, const char *src)
144 {
145   while (*src && !isdigit (*src))
146     {
147       switch (*src)
148         {
149         case 'e':
150           subkey->expired = 1;
151           break;
152
153         case 'r':
154           subkey->revoked = 1;
155           break;
156
157         case 'd':
158           /* Note that gpg 1.3 won't print that anymore but only uses
159              the capabilities field. */
160           subkey->disabled = 1;
161           break;
162
163         case 'i':
164           subkey->invalid = 1;
165           break;
166         }
167       src++;
168     }
169 }
170
171
172 static void
173 set_mainkey_trust_info (gpgme_key_t key, const char *src)
174 {
175   /* First set the trust info of the main key (the first subkey).  */
176   set_subkey_trust_info (key->subkeys, src);
177
178   /* Now set the summarized trust info.  */
179   while (*src && !isdigit (*src))
180     {
181       switch (*src)
182         {
183         case 'e':
184           key->expired = 1;
185           break;
186
187         case 'r':
188           key->revoked = 1;
189           break;
190
191         case 'd':
192           /* Note that gpg 1.3 won't print that anymore but only uses
193              the capabilities field.  However, it is still used for
194              external key listings.  */
195           key->disabled = 1;
196           break;
197
198         case 'i':
199           key->invalid = 1;
200           break;
201         }
202       src++;
203     }
204 }
205
206
207 static void
208 set_userid_flags (gpgme_key_t key, const char *src)
209 {
210   gpgme_user_id_t uid = key->_last_uid;
211
212   assert (uid);
213   /* Look at letters and stop at the first digit.  */
214   while (*src && !isdigit (*src))
215     {
216       switch (*src)
217         {
218         case 'r':
219           uid->revoked = 1;
220           break;
221
222         case 'i':
223           uid->invalid = 1;
224           break;
225
226         case 'n':
227           uid->validity = GPGME_VALIDITY_NEVER;
228           break;
229
230         case 'm':
231           uid->validity = GPGME_VALIDITY_MARGINAL;
232           break;
233
234         case 'f':
235           uid->validity = GPGME_VALIDITY_FULL;
236           break;
237
238         case 'u':
239           uid->validity = GPGME_VALIDITY_ULTIMATE;
240           break;
241         }
242       src++;
243     }
244 }
245
246
247 static void
248 set_subkey_capability (gpgme_subkey_t subkey, const char *src)
249 {
250   while (*src)
251     {
252       switch (*src)
253         {
254         case 'e':
255           subkey->can_encrypt = 1;
256           break;
257
258         case 's':
259           subkey->can_sign = 1;
260           break;
261
262         case 'c':
263           subkey->can_certify = 1;
264           break;
265
266         case 'a':
267           subkey->can_authenticate = 1;
268           break;
269
270         case 'q':
271           subkey->is_qualified = 1;
272           break;
273
274         case 'd':
275           subkey->disabled = 1;
276           break;
277         }
278       src++;
279     }
280 }
281
282
283 static void
284 set_mainkey_capability (gpgme_key_t key, const char *src)
285 {
286   /* First set the capabilities of the main key (the first subkey).  */
287   set_subkey_capability (key->subkeys, src);
288
289   while (*src)
290     {
291       switch (*src)
292         {
293         case 'd':
294         case 'D':
295           /* Note, that this flag is also set using the key validity
296              field for backward compatibility with gpg 1.2.  We use d
297              and D, so that a future gpg version will be able to
298              disable certain subkeys. Currently it is expected that
299              gpg sets this for the primary key. */
300           key->disabled = 1;
301           break;
302
303         case 'e':
304         case 'E':
305           key->can_encrypt = 1;
306           break;
307
308         case 's':
309         case 'S':
310           key->can_sign = 1;
311           break;
312
313         case 'c':
314         case 'C':
315           key->can_certify = 1;
316           break;
317
318         case 'a':
319         case 'A':
320           key->can_authenticate = 1;
321           break;
322
323         case 'q':
324         case 'Q':
325           key->is_qualified = 1;
326           break;
327         }
328       src++;
329     }
330 }
331
332
333 static void
334 set_ownertrust (gpgme_key_t key, const char *src)
335 {
336   /* Look at letters and stop at the first digit.  */
337   while (*src && !isdigit (*src))
338     {
339       switch (*src)
340         {
341         case 'n':
342           key->owner_trust = GPGME_VALIDITY_NEVER;
343           break;
344
345         case 'm':
346           key->owner_trust = GPGME_VALIDITY_MARGINAL;
347           break;
348
349         case 'f':
350           key->owner_trust = GPGME_VALIDITY_FULL;
351           break;
352
353         case 'u':
354           key->owner_trust = GPGME_VALIDITY_ULTIMATE;
355           break;
356
357         default:
358           key->owner_trust = GPGME_VALIDITY_UNKNOWN;
359           break;
360         }
361       src++;
362     }
363 }
364
365
366 /* Parse field 15 of a secret key or subkey.  This fields holds a
367    reference to smartcards.  FIELD is the content of the field and we
368    are allowed to modify it.  */
369 static gpg_error_t
370 parse_sec_field15 (gpgme_key_t key, gpgme_subkey_t subkey, char *field)
371 {
372   if (!*field)
373     ; /* Empty.  */
374   else if (*field == '#')
375     {
376       /* This is a stub for an offline key.  We reset the SECRET flag
377          of the subkey here.  Note that the secret flag of the entire
378          key will be true even then.  We even explicitly set
379          key->secret to make it works for GPGME_KEYLIST_MODE_WITH_SECRET. */
380       subkey->secret = 0;
381       key->secret = 1;
382     }
383   else if (strchr ("01234567890ABCDEFabcdef", *field))
384     {
385       /* Fields starts with a hex digit; thus it is a serial number.  */
386       key->secret = 1;
387       subkey->is_cardkey = 1;
388       subkey->card_number = strdup (field);
389       if (!subkey->card_number)
390         return gpg_error_from_syserror ();
391     }
392   else if (*field == '+')
393     {
394       key->secret = 1;
395       subkey->secret = 1;
396     }
397   else
398     {
399       /* RFU.  */
400     }
401
402   return 0;
403 }
404
405
406 /* We have read an entire key into tmp_key and should now finish it.
407    It is assumed that this releases tmp_key.  */
408 static void
409 finish_key (gpgme_ctx_t ctx, op_data_t opd)
410 {
411   gpgme_key_t key = opd->tmp_key;
412
413   opd->tmp_key = NULL;
414   opd->tmp_uid = NULL;
415   opd->tmp_keysig = NULL;
416
417   if (key)
418     _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
419 }
420
421
422 /* Note: We are allowed to modify LINE.  */
423 static gpgme_error_t
424 keylist_colon_handler (void *priv, char *line)
425 {
426   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
427   enum
428     {
429       RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, RT_GRP,
430       RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
431     }
432   rectype = RT_NONE;
433 #define NR_FIELDS 17
434   char *field[NR_FIELDS];
435   int fields = 0;
436   void *hook;
437   op_data_t opd;
438   gpgme_error_t err;
439   gpgme_key_t key;
440   gpgme_subkey_t subkey = NULL;
441   gpgme_key_sig_t keysig = NULL;
442
443   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
444   opd = hook;
445   if (err)
446     return err;
447
448   key = opd->tmp_key;
449
450   TRACE2 (DEBUG_CTX, "gpgme:keylist_colon_handler", ctx,
451           "key = %p, line = %s", key, line ? line : "(null)");
452
453   if (!line)
454     {
455       /* End Of File.  */
456       finish_key (ctx, opd);
457       return 0;
458     }
459
460   while (line && fields < NR_FIELDS)
461     {
462       field[fields++] = line;
463       line = strchr (line, ':');
464       if (line)
465         *(line++) = '\0';
466     }
467
468   if (!strcmp (field[0], "sig"))
469     rectype = RT_SIG;
470   else if (!strcmp (field[0], "rev"))
471     rectype = RT_REV;
472   else if (!strcmp (field[0], "pub"))
473     rectype = RT_PUB;
474   else if (!strcmp (field[0], "sec"))
475     rectype = RT_SEC;
476   else if (!strcmp (field[0], "crt"))
477     rectype = RT_CRT;
478   else if (!strcmp (field[0], "crs"))
479     rectype = RT_CRS;
480   else if (!strcmp (field[0], "fpr") && key)
481     rectype = RT_FPR;
482   else if (!strcmp (field[0], "grp") && key)
483     rectype = RT_GRP;
484   else if (!strcmp (field[0], "uid") && key)
485     rectype = RT_UID;
486   else if (!strcmp (field[0], "sub") && key)
487     rectype = RT_SUB;
488   else if (!strcmp (field[0], "ssb") && key)
489     rectype = RT_SSB;
490   else if (!strcmp (field[0], "spk") && key)
491     rectype = RT_SPK;
492   else
493     rectype = RT_NONE;
494
495   /* Only look at signatures immediately following a user ID.  For
496      this, clear the user ID pointer when encountering anything but a
497      signature.  */
498   if (rectype != RT_SIG && rectype != RT_REV)
499     opd->tmp_uid = NULL;
500
501   /* Only look at subpackets immediately following a signature.  For
502      this, clear the signature pointer when encountering anything but
503      a subpacket.  */
504   if (rectype != RT_SPK)
505     opd->tmp_keysig = NULL;
506
507   switch (rectype)
508     {
509     case RT_PUB:
510     case RT_SEC:
511     case RT_CRT:
512     case RT_CRS:
513       /* Start a new keyblock.  */
514       err = _gpgme_key_new (&key);
515       if (err)
516         return err;
517       key->keylist_mode = ctx->keylist_mode;
518       err = _gpgme_key_add_subkey (key, &subkey);
519       if (err)
520         {
521           gpgme_key_unref (key);
522           return err;
523         }
524
525       if (rectype == RT_SEC || rectype == RT_CRS)
526         key->secret = subkey->secret = 1;
527       if (rectype == RT_CRT || rectype == RT_CRS)
528         key->protocol = GPGME_PROTOCOL_CMS;
529       finish_key (ctx, opd);
530       opd->tmp_key = key;
531
532       /* Field 2 has the trust info.  */
533       if (fields >= 2)
534         set_mainkey_trust_info (key, field[1]);
535
536       /* Field 3 has the key length.  */
537       if (fields >= 3)
538         {
539           int i = atoi (field[2]);
540           /* Ignore invalid values.  */
541           if (i > 1)
542             subkey->length = i;
543         }
544
545       /* Field 4 has the public key algorithm.  */
546       if (fields >= 4)
547         {
548           int i = atoi (field[3]);
549           if (i >= 1 && i < 128)
550             subkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
551         }
552
553       /* Field 5 has the long keyid.  Allow short key IDs for the
554          output of an external keyserver listing.  */
555       if (fields >= 5 && strlen (field[4]) <= DIM(subkey->_keyid) - 1)
556         strcpy (subkey->_keyid, field[4]);
557
558       /* Field 6 has the timestamp (seconds).  */
559       if (fields >= 6)
560         subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
561
562       /* Field 7 has the expiration time (seconds).  */
563       if (fields >= 7)
564         subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
565
566       /* Field 8 has the X.509 serial number.  */
567       if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
568         {
569           key->issuer_serial = strdup (field[7]);
570           if (!key->issuer_serial)
571             return gpg_error_from_syserror ();
572         }
573
574       /* Field 9 has the ownertrust.  */
575       if (fields >= 9)
576         set_ownertrust (key, field[8]);
577
578       /* Field 10 is not used for gpg due to --fixed-list-mode option
579          but GPGSM stores the issuer name.  */
580       if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
581         if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
582           return gpg_error (GPG_ERR_ENOMEM);    /* FIXME */
583
584       /* Field 11 has the signature class.  */
585
586       /* Field 12 has the capabilities.  */
587       if (fields >= 12)
588         set_mainkey_capability (key, field[11]);
589
590       /* Field 15 carries special flags of a secret key.  */
591       if (fields >= 15
592           && (key->secret
593               || (ctx->keylist_mode & GPGME_KEYLIST_MODE_WITH_SECRET)))
594         {
595           err = parse_sec_field15 (key, subkey, field[14]);
596           if (err)
597             return err;
598         }
599
600       /* Field 17 has the curve name for ECC.  */
601       if (fields >= 17 && *field[16])
602         {
603           subkey->curve = strdup (field[16]);
604           if (!subkey->curve)
605             return gpg_error_from_syserror ();
606         }
607
608       break;
609
610     case RT_SUB:
611     case RT_SSB:
612       /* Start a new subkey.  */
613       err = _gpgme_key_add_subkey (key, &subkey);
614       if (err)
615         return err;
616
617       if (rectype == RT_SSB)
618         subkey->secret = 1;
619
620       /* Field 2 has the trust info.  */
621       if (fields >= 2)
622         set_subkey_trust_info (subkey, field[1]);
623
624       /* Field 3 has the key length.  */
625       if (fields >= 3)
626         {
627           int i = atoi (field[2]);
628           /* Ignore invalid values.  */
629           if (i > 1)
630             subkey->length = i;
631         }
632
633       /* Field 4 has the public key algorithm.  */
634       if (fields >= 4)
635         {
636           int i = atoi (field[3]);
637           if (i >= 1 && i < 128)
638             subkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
639         }
640
641       /* Field 5 has the long keyid.  */
642       if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
643         strcpy (subkey->_keyid, field[4]);
644
645       /* Field 6 has the timestamp (seconds).  */
646       if (fields >= 6)
647         subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
648
649       /* Field 7 has the expiration time (seconds).  */
650       if (fields >= 7)
651         subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
652
653       /* Field 8 is reserved (LID).  */
654       /* Field 9 has the ownertrust.  */
655       /* Field 10, the user ID, is n/a for a subkey.  */
656
657       /* Field 11 has the signature class.  */
658
659       /* Field 12 has the capabilities.  */
660       if (fields >= 12)
661         set_subkey_capability (subkey, field[11]);
662
663       /* Field 15 carries special flags of a secret key. */
664       if (fields >= 15
665           && (key->secret
666               || (ctx->keylist_mode & GPGME_KEYLIST_MODE_WITH_SECRET)))
667         {
668           err = parse_sec_field15 (key, subkey, field[14]);
669           if (err)
670             return err;
671         }
672
673       /* Field 17 has the curve name for ECC.  */
674       if (fields >= 17 && *field[16])
675         {
676           subkey->curve = strdup (field[16]);
677           if (!subkey->curve)
678             return gpg_error_from_syserror ();
679         }
680
681       break;
682
683     case RT_UID:
684       /* Field 2 has the trust info, and field 10 has the user ID.  */
685       if (fields >= 10)
686         {
687           if (_gpgme_key_append_name (key, field[9], 1))
688             return gpg_error (GPG_ERR_ENOMEM);  /* FIXME */
689           else
690             {
691               if (field[1])
692                 set_userid_flags (key, field[1]);
693               opd->tmp_uid = key->_last_uid;
694             }
695         }
696       break;
697
698     case RT_FPR:
699       /* Field 10 has the fingerprint (take only the first one).  */
700       if (fields >= 10 && field[9] && *field[9])
701         {
702           /* Need to apply it to the last subkey because all subkeys
703              do have fingerprints. */
704           subkey = key->_last_subkey;
705           if (!subkey->fpr)
706             {
707               subkey->fpr = strdup (field[9]);
708               if (!subkey->fpr)
709                 return gpg_error_from_syserror ();
710             }
711           /* If this is the first subkey, store the fingerprint also
712              in the KEY object.  */
713           if (subkey == key->subkeys)
714             {
715               if (key->fpr && strcmp (key->fpr, subkey->fpr))
716                 {
717                   /* FPR already set but mismatch: Should never happen.  */
718                   return trace_gpg_error (GPG_ERR_INTERNAL);
719                 }
720               if (!key->fpr)
721                 {
722                   key->fpr = strdup (subkey->fpr);
723                   if (!key->fpr)
724                     return gpg_error_from_syserror ();
725                 }
726             }
727         }
728
729       /* Field 13 has the gpgsm chain ID (take only the first one).  */
730       if (fields >= 13 && !key->chain_id && *field[12])
731         {
732           key->chain_id = strdup (field[12]);
733           if (!key->chain_id)
734             return gpg_error_from_syserror ();
735         }
736       break;
737
738     case RT_GRP:
739       /* Field 10 has the keygrip.  */
740       if (fields >= 10 && field[9] && *field[9])
741         {
742           /* Need to apply it to the last subkey because all subkeys
743              have a keygrip. */
744           subkey = key->_last_subkey;
745           if (!subkey->keygrip)
746             {
747               subkey->keygrip = strdup (field[9]);
748               if (!subkey->keygrip)
749                 return gpg_error_from_syserror ();
750             }
751         }
752       break;
753
754     case RT_SIG:
755     case RT_REV:
756       if (!opd->tmp_uid)
757         return 0;
758
759       /* Start a new (revoked) signature.  */
760       assert (opd->tmp_uid == key->_last_uid);
761       keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
762       if (!keysig)
763         return gpg_error (GPG_ERR_ENOMEM);      /* FIXME */
764
765       /* Field 2 has the calculated trust ('!', '-', '?', '%').  */
766       if (fields >= 2)
767         switch (field[1][0])
768           {
769           case '!':
770             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
771             break;
772
773           case '-':
774             keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
775             break;
776
777           case '?':
778             keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
779             break;
780
781           case '%':
782             keysig->status = gpg_error (GPG_ERR_GENERAL);
783             break;
784
785           default:
786             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
787             break;
788           }
789
790       /* Field 4 has the public key algorithm.  */
791       if (fields >= 4)
792         {
793           int i = atoi (field[3]);
794           if (i >= 1 && i < 128)
795             keysig->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
796         }
797
798       /* Field 5 has the long keyid.  */
799       if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
800         strcpy (keysig->_keyid, field[4]);
801
802       /* Field 6 has the timestamp (seconds).  */
803       if (fields >= 6)
804         keysig->timestamp = _gpgme_parse_timestamp (field[5], NULL);
805
806       /* Field 7 has the expiration time (seconds).  */
807       if (fields >= 7)
808         keysig->expires = _gpgme_parse_timestamp (field[6], NULL);
809
810       /* Field 11 has the signature class (eg, 0x30 means revoked).  */
811       if (fields >= 11)
812         if (field[10][0] && field[10][1])
813           {
814             int sig_class = _gpgme_hextobyte (field[10]);
815             if (sig_class >= 0)
816               {
817                 keysig->sig_class = sig_class;
818                 keysig->class = keysig->sig_class;
819                 if (sig_class == 0x30)
820                   keysig->revoked = 1;
821               }
822             if (field[10][2] == 'x')
823               keysig->exportable = 1;
824           }
825
826       opd->tmp_keysig = keysig;
827       break;
828
829     case RT_SPK:
830       if (!opd->tmp_keysig)
831         return 0;
832       assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
833
834       if (fields >= 4)
835         {
836           /* Field 2 has the subpacket type.  */
837           int type = atoi (field[1]);
838
839           /* Field 3 has the flags.  */
840           int flags = atoi (field[2]);
841
842           /* Field 4 has the length.  */
843           int len = atoi (field[3]);
844
845           /* Field 5 has the data.  */
846           char *data = field[4];
847
848           /* Type 20: Notation data.  */
849           /* Type 26: Policy URL.  */
850           if (type == 20 || type == 26)
851             {
852               gpgme_sig_notation_t notation;
853
854               keysig = opd->tmp_keysig;
855
856               /* At this time, any error is serious.  */
857               err = _gpgme_parse_notation (&notation, type, flags, len, data);
858               if (err)
859                 return err;
860
861               /* Add a new notation.  FIXME: Could be factored out.  */
862               if (!keysig->notations)
863                 keysig->notations = notation;
864               if (keysig->_last_notation)
865                 keysig->_last_notation->next = notation;
866               keysig->_last_notation = notation;
867             }
868         }
869
870     case RT_NONE:
871       /* Unknown record.  */
872       break;
873     }
874   return 0;
875 }
876
877
878 void
879 _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
880 {
881   gpgme_error_t err;
882   gpgme_ctx_t ctx = (gpgme_ctx_t) data;
883   gpgme_key_t key = (gpgme_key_t) type_data;
884   void *hook;
885   op_data_t opd;
886   struct key_queue_item_s *q, *q2;
887
888   assert (type == GPGME_EVENT_NEXT_KEY);
889
890   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
891   opd = hook;
892   if (err)
893     return;
894
895   q = malloc (sizeof *q);
896   if (!q)
897     {
898       gpgme_key_unref (key);
899       /* FIXME       return GPGME_Out_Of_Core; */
900       return;
901     }
902   q->key = key;
903   q->next = NULL;
904   /* FIXME: Use a tail pointer?  */
905   if (!(q2 = opd->key_queue))
906     opd->key_queue = q;
907   else
908     {
909       for (; q2->next; q2 = q2->next)
910         ;
911       q2->next = q;
912     }
913   opd->key_cond = 1;
914 }
915
916
917 /* Start a keylist operation within CTX, searching for keys which
918    match PATTERN.  If SECRET_ONLY is true, only secret keys are
919    returned.  */
920 gpgme_error_t
921 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
922 {
923   gpgme_error_t err;
924   void *hook;
925   op_data_t opd;
926   int flags = 0;
927
928   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_start", ctx,
929               "pattern=%s, secret_only=%i", pattern, secret_only);
930
931   if (!ctx)
932     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
933
934   err = _gpgme_op_reset (ctx, 2);
935   if (err)
936     return TRACE_ERR (err);
937
938   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
939                                sizeof (*opd), release_op_data);
940   opd = hook;
941   if (err)
942     return TRACE_ERR (err);
943
944   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
945
946   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
947                                               keylist_colon_handler, ctx);
948   if (err)
949     return TRACE_ERR (err);
950
951   if (ctx->offline)
952     flags |= GPGME_ENGINE_FLAG_OFFLINE;
953
954   err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
955                                   ctx->keylist_mode, flags);
956   return TRACE_ERR (err);
957 }
958
959
960 /* Start a keylist operation within CTX, searching for keys which
961    match PATTERN.  If SECRET_ONLY is true, only secret keys are
962    returned.  */
963 gpgme_error_t
964 gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
965                             int secret_only, int reserved)
966 {
967   gpgme_error_t err;
968   void *hook;
969   op_data_t opd;
970   int flags = 0;
971
972   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_ext_start", ctx,
973               "secret_only=%i, reserved=0x%x", secret_only, reserved);
974
975   if (!ctx)
976     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
977
978   err = _gpgme_op_reset (ctx, 2);
979   if (err)
980     return TRACE_ERR (err);
981
982   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
983                                sizeof (*opd), release_op_data);
984   opd = hook;
985   if (err)
986     return TRACE_ERR (err);
987
988   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
989   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
990                                               keylist_colon_handler, ctx);
991   if (err)
992     return TRACE_ERR (err);
993
994   if (ctx->offline)
995     flags |= GPGME_ENGINE_FLAG_OFFLINE;
996
997   err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
998                                       reserved, ctx->keylist_mode,
999                                       flags);
1000   return TRACE_ERR (err);
1001 }
1002
1003
1004 /* Return the next key from the keylist in R_KEY.  */
1005 gpgme_error_t
1006 gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
1007 {
1008   gpgme_error_t err;
1009   struct key_queue_item_s *queue_item;
1010   void *hook;
1011   op_data_t opd;
1012
1013   TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_next", ctx);
1014
1015   if (!ctx || !r_key)
1016     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1017   *r_key = NULL;
1018   if (!ctx)
1019     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1020
1021   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
1022   opd = hook;
1023   if (err)
1024     return TRACE_ERR (err);
1025   if (opd == NULL)
1026     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1027
1028   if (!opd->key_queue)
1029     {
1030       err = _gpgme_wait_on_condition (ctx, &opd->key_cond, NULL);
1031       if (err)
1032         return TRACE_ERR (err);
1033
1034       if (!opd->key_cond)
1035         return TRACE_ERR (gpg_error (GPG_ERR_EOF));
1036
1037       opd->key_cond = 0;
1038       assert (opd->key_queue);
1039     }
1040   queue_item = opd->key_queue;
1041   opd->key_queue = queue_item->next;
1042   if (!opd->key_queue)
1043     opd->key_cond = 0;
1044
1045   *r_key = queue_item->key;
1046   free (queue_item);
1047
1048   return TRACE_SUC2 ("key=%p (%s)", *r_key,
1049                      ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1050                      (*r_key)->subkeys->fpr : "invalid");
1051 }
1052
1053
1054 /* Terminate a pending keylist operation within CTX.  */
1055 gpgme_error_t
1056 gpgme_op_keylist_end (gpgme_ctx_t ctx)
1057 {
1058   TRACE (DEBUG_CTX, "gpgme_op_keylist_end", ctx);
1059
1060   if (!ctx)
1061     return gpg_error (GPG_ERR_INV_VALUE);
1062
1063   return 0;
1064 }
1065
1066 \f
1067 /* Get the key with the fingerprint FPR from the crypto backend.  If
1068    SECRET is true, get the secret key.  */
1069 gpgme_error_t
1070 gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
1071                int secret)
1072 {
1073   gpgme_ctx_t listctx;
1074   gpgme_error_t err;
1075   gpgme_key_t key;
1076
1077   TRACE_BEG2 (DEBUG_CTX, "gpgme_get_key", ctx,
1078               "fpr=%s, secret=%i", fpr, secret);
1079
1080   if (!ctx || !r_key || !fpr)
1081     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1082
1083   if (strlen (fpr) < 8) /* We have at least a key ID.  */
1084     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1085
1086   /* FIXME: We use our own context because we have to avoid the user's
1087      I/O callback handlers.  */
1088   err = gpgme_new (&listctx);
1089   if (err)
1090     return TRACE_ERR (err);
1091   {
1092     gpgme_protocol_t proto;
1093     gpgme_engine_info_t info;
1094
1095     /* Clone the relevant state.  */
1096     proto = gpgme_get_protocol (ctx);
1097     gpgme_set_protocol (listctx, proto);
1098     gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1099     info = gpgme_ctx_get_engine_info (ctx);
1100     while (info && info->protocol != proto)
1101       info = info->next;
1102     if (info)
1103       gpgme_ctx_set_engine_info (listctx, proto,
1104                                  info->file_name, info->home_dir);
1105   }
1106
1107   err = gpgme_op_keylist_start (listctx, fpr, secret);
1108   if (!err)
1109     err = gpgme_op_keylist_next (listctx, r_key);
1110   if (!err)
1111     {
1112     try_next_key:
1113       err = gpgme_op_keylist_next (listctx, &key);
1114       if (gpgme_err_code (err) == GPG_ERR_EOF)
1115         err = 0;
1116       else
1117         {
1118           if (!err
1119               && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1120               && key && key->subkeys && key->subkeys->fpr
1121               && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1122             {
1123               /* The fingerprint is identical.  We assume that this is
1124                  the same key and don't mark it as an ambiguous.  This
1125                  problem may occur with corrupted keyrings and has
1126                  been noticed often with gpgsm.  In fact gpgsm uses a
1127                  similar hack to sort out such duplicates but it can't
1128                  do that while listing keys.  */
1129               gpgme_key_unref (key);
1130               goto try_next_key;
1131             }
1132           if (!err)
1133             {
1134               gpgme_key_unref (key);
1135               err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1136             }
1137           gpgme_key_unref (*r_key);
1138         }
1139     }
1140   gpgme_release (listctx);
1141   if (! err)
1142     {
1143       TRACE_LOG2 ("key=%p (%s)", *r_key,
1144                   ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1145                   (*r_key)->subkeys->fpr : "invalid");
1146     }
1147   return TRACE_ERR (err);
1148 }