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