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