core: Extend gpgme_subkey_t to carry the keygrip.
[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         }
712
713       /* Field 13 has the gpgsm chain ID (take only the first one).  */
714       if (fields >= 13 && !key->chain_id && *field[12])
715         {
716           key->chain_id = strdup (field[12]);
717           if (!key->chain_id)
718             return gpg_error_from_syserror ();
719         }
720       break;
721
722     case RT_GRP:
723       /* Field 10 has the keygrip.  */
724       if (fields >= 10 && field[9] && *field[9])
725         {
726           /* Need to apply it to the last subkey because all subkeys
727              have a keygrip. */
728           subkey = key->_last_subkey;
729           if (!subkey->keygrip)
730             {
731               subkey->keygrip = strdup (field[9]);
732               if (!subkey->keygrip)
733                 return gpg_error_from_syserror ();
734             }
735         }
736       break;
737
738     case RT_SIG:
739     case RT_REV:
740       if (!opd->tmp_uid)
741         return 0;
742
743       /* Start a new (revoked) signature.  */
744       assert (opd->tmp_uid == key->_last_uid);
745       keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
746       if (!keysig)
747         return gpg_error (GPG_ERR_ENOMEM);      /* FIXME */
748
749       /* Field 2 has the calculated trust ('!', '-', '?', '%').  */
750       if (fields >= 2)
751         switch (field[1][0])
752           {
753           case '!':
754             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
755             break;
756
757           case '-':
758             keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
759             break;
760
761           case '?':
762             keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
763             break;
764
765           case '%':
766             keysig->status = gpg_error (GPG_ERR_GENERAL);
767             break;
768
769           default:
770             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
771             break;
772           }
773
774       /* Field 4 has the public key algorithm.  */
775       if (fields >= 4)
776         {
777           int i = atoi (field[3]);
778           if (i >= 1 && i < 128)
779             keysig->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
780         }
781
782       /* Field 5 has the long keyid.  */
783       if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
784         strcpy (keysig->_keyid, field[4]);
785
786       /* Field 6 has the timestamp (seconds).  */
787       if (fields >= 6)
788         keysig->timestamp = _gpgme_parse_timestamp (field[5], NULL);
789
790       /* Field 7 has the expiration time (seconds).  */
791       if (fields >= 7)
792         keysig->expires = _gpgme_parse_timestamp (field[6], NULL);
793
794       /* Field 11 has the signature class (eg, 0x30 means revoked).  */
795       if (fields >= 11)
796         if (field[10][0] && field[10][1])
797           {
798             int sig_class = _gpgme_hextobyte (field[10]);
799             if (sig_class >= 0)
800               {
801                 keysig->sig_class = sig_class;
802                 keysig->class = keysig->sig_class;
803                 if (sig_class == 0x30)
804                   keysig->revoked = 1;
805               }
806             if (field[10][2] == 'x')
807               keysig->exportable = 1;
808           }
809
810       opd->tmp_keysig = keysig;
811       break;
812
813     case RT_SPK:
814       if (!opd->tmp_keysig)
815         return 0;
816       assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
817
818       if (fields >= 4)
819         {
820           /* Field 2 has the subpacket type.  */
821           int type = atoi (field[1]);
822
823           /* Field 3 has the flags.  */
824           int flags = atoi (field[2]);
825
826           /* Field 4 has the length.  */
827           int len = atoi (field[3]);
828
829           /* Field 5 has the data.  */
830           char *data = field[4];
831
832           /* Type 20: Notation data.  */
833           /* Type 26: Policy URL.  */
834           if (type == 20 || type == 26)
835             {
836               gpgme_sig_notation_t notation;
837
838               keysig = opd->tmp_keysig;
839
840               /* At this time, any error is serious.  */
841               err = _gpgme_parse_notation (&notation, type, flags, len, data);
842               if (err)
843                 return err;
844
845               /* Add a new notation.  FIXME: Could be factored out.  */
846               if (!keysig->notations)
847                 keysig->notations = notation;
848               if (keysig->_last_notation)
849                 keysig->_last_notation->next = notation;
850               keysig->_last_notation = notation;
851             }
852         }
853
854     case RT_NONE:
855       /* Unknown record.  */
856       break;
857     }
858   return 0;
859 }
860
861
862 void
863 _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
864 {
865   gpgme_error_t err;
866   gpgme_ctx_t ctx = (gpgme_ctx_t) data;
867   gpgme_key_t key = (gpgme_key_t) type_data;
868   void *hook;
869   op_data_t opd;
870   struct key_queue_item_s *q, *q2;
871
872   assert (type == GPGME_EVENT_NEXT_KEY);
873
874   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
875   opd = hook;
876   if (err)
877     return;
878
879   q = malloc (sizeof *q);
880   if (!q)
881     {
882       gpgme_key_unref (key);
883       /* FIXME       return GPGME_Out_Of_Core; */
884       return;
885     }
886   q->key = key;
887   q->next = NULL;
888   /* FIXME: Use a tail pointer?  */
889   if (!(q2 = opd->key_queue))
890     opd->key_queue = q;
891   else
892     {
893       for (; q2->next; q2 = q2->next)
894         ;
895       q2->next = q;
896     }
897   opd->key_cond = 1;
898 }
899
900
901 /* Start a keylist operation within CTX, searching for keys which
902    match PATTERN.  If SECRET_ONLY is true, only secret keys are
903    returned.  */
904 gpgme_error_t
905 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
906 {
907   gpgme_error_t err;
908   void *hook;
909   op_data_t opd;
910   int flags = 0;
911
912   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_start", ctx,
913               "pattern=%s, secret_only=%i", pattern, secret_only);
914
915   if (!ctx)
916     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
917
918   err = _gpgme_op_reset (ctx, 2);
919   if (err)
920     return TRACE_ERR (err);
921
922   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
923                                sizeof (*opd), release_op_data);
924   opd = hook;
925   if (err)
926     return TRACE_ERR (err);
927
928   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
929
930   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
931                                               keylist_colon_handler, ctx);
932   if (err)
933     return TRACE_ERR (err);
934
935   if (ctx->offline)
936     flags |= GPGME_ENGINE_FLAG_OFFLINE;
937
938   err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
939                                   ctx->keylist_mode, flags);
940   return TRACE_ERR (err);
941 }
942
943
944 /* Start a keylist operation within CTX, searching for keys which
945    match PATTERN.  If SECRET_ONLY is true, only secret keys are
946    returned.  */
947 gpgme_error_t
948 gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
949                             int secret_only, int reserved)
950 {
951   gpgme_error_t err;
952   void *hook;
953   op_data_t opd;
954   int flags = 0;
955
956   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_ext_start", ctx,
957               "secret_only=%i, reserved=0x%x", secret_only, reserved);
958
959   if (!ctx)
960     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
961
962   err = _gpgme_op_reset (ctx, 2);
963   if (err)
964     return TRACE_ERR (err);
965
966   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
967                                sizeof (*opd), release_op_data);
968   opd = hook;
969   if (err)
970     return TRACE_ERR (err);
971
972   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
973   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
974                                               keylist_colon_handler, ctx);
975   if (err)
976     return TRACE_ERR (err);
977
978   if (ctx->offline)
979     flags |= GPGME_ENGINE_FLAG_OFFLINE;
980
981   err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
982                                       reserved, ctx->keylist_mode,
983                                       flags);
984   return TRACE_ERR (err);
985 }
986
987
988 /* Return the next key from the keylist in R_KEY.  */
989 gpgme_error_t
990 gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
991 {
992   gpgme_error_t err;
993   struct key_queue_item_s *queue_item;
994   void *hook;
995   op_data_t opd;
996
997   TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_next", ctx);
998
999   if (!ctx || !r_key)
1000     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1001   *r_key = NULL;
1002   if (!ctx)
1003     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1004
1005   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
1006   opd = hook;
1007   if (err)
1008     return TRACE_ERR (err);
1009   if (opd == NULL)
1010     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1011
1012   if (!opd->key_queue)
1013     {
1014       err = _gpgme_wait_on_condition (ctx, &opd->key_cond, NULL);
1015       if (err)
1016         return TRACE_ERR (err);
1017
1018       if (!opd->key_cond)
1019         return TRACE_ERR (gpg_error (GPG_ERR_EOF));
1020
1021       opd->key_cond = 0;
1022       assert (opd->key_queue);
1023     }
1024   queue_item = opd->key_queue;
1025   opd->key_queue = queue_item->next;
1026   if (!opd->key_queue)
1027     opd->key_cond = 0;
1028
1029   *r_key = queue_item->key;
1030   free (queue_item);
1031
1032   return TRACE_SUC2 ("key=%p (%s)", *r_key,
1033                      ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1034                      (*r_key)->subkeys->fpr : "invalid");
1035 }
1036
1037
1038 /* Terminate a pending keylist operation within CTX.  */
1039 gpgme_error_t
1040 gpgme_op_keylist_end (gpgme_ctx_t ctx)
1041 {
1042   TRACE (DEBUG_CTX, "gpgme_op_keylist_end", ctx);
1043
1044   if (!ctx)
1045     return gpg_error (GPG_ERR_INV_VALUE);
1046
1047   return 0;
1048 }
1049
1050 \f
1051 /* Get the key with the fingerprint FPR from the crypto backend.  If
1052    SECRET is true, get the secret key.  */
1053 gpgme_error_t
1054 gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
1055                int secret)
1056 {
1057   gpgme_ctx_t listctx;
1058   gpgme_error_t err;
1059   gpgme_key_t key;
1060
1061   TRACE_BEG2 (DEBUG_CTX, "gpgme_get_key", ctx,
1062               "fpr=%s, secret=%i", fpr, secret);
1063
1064   if (!ctx || !r_key || !fpr)
1065     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1066
1067   if (strlen (fpr) < 8) /* We have at least a key ID.  */
1068     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1069
1070   /* FIXME: We use our own context because we have to avoid the user's
1071      I/O callback handlers.  */
1072   err = gpgme_new (&listctx);
1073   if (err)
1074     return TRACE_ERR (err);
1075   {
1076     gpgme_protocol_t proto;
1077     gpgme_engine_info_t info;
1078
1079     /* Clone the relevant state.  */
1080     proto = gpgme_get_protocol (ctx);
1081     gpgme_set_protocol (listctx, proto);
1082     gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1083     info = gpgme_ctx_get_engine_info (ctx);
1084     while (info && info->protocol != proto)
1085       info = info->next;
1086     if (info)
1087       gpgme_ctx_set_engine_info (listctx, proto,
1088                                  info->file_name, info->home_dir);
1089   }
1090
1091   err = gpgme_op_keylist_start (listctx, fpr, secret);
1092   if (!err)
1093     err = gpgme_op_keylist_next (listctx, r_key);
1094   if (!err)
1095     {
1096     try_next_key:
1097       err = gpgme_op_keylist_next (listctx, &key);
1098       if (gpgme_err_code (err) == GPG_ERR_EOF)
1099         err = 0;
1100       else
1101         {
1102           if (!err
1103               && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1104               && key && key->subkeys && key->subkeys->fpr
1105               && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1106             {
1107               /* The fingerprint is identical.  We assume that this is
1108                  the same key and don't mark it as an ambiguous.  This
1109                  problem may occur with corrupted keyrings and has
1110                  been noticed often with gpgsm.  In fact gpgsm uses a
1111                  similar hack to sort out such duplicates but it can't
1112                  do that while listing keys.  */
1113               gpgme_key_unref (key);
1114               goto try_next_key;
1115             }
1116           if (!err)
1117             {
1118               gpgme_key_unref (key);
1119               err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1120             }
1121           gpgme_key_unref (*r_key);
1122         }
1123     }
1124   gpgme_release (listctx);
1125   if (! err)
1126     {
1127       TRACE_LOG2 ("key=%p (%s)", *r_key,
1128                   ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1129                   (*r_key)->subkeys->fpr : "invalid");
1130     }
1131   return TRACE_ERR (err);
1132 }