Merge commit 'a2b9adafe46c55a2c26dd46163055bbdf3526835'
[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_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.  */
379       subkey->secret = 0;
380     }
381   else if (strchr ("01234567890ABCDEFabcdef", *field))
382     {
383       /* Fields starts with a hex digit; thus it is a serial number.  */
384       subkey->is_cardkey = 1;
385       subkey->card_number = strdup (field);
386       if (!subkey->card_number)
387         return gpg_error_from_syserror ();
388     }
389   else
390     {
391       /* RFU.  */
392     }
393
394   return 0;
395 }
396
397
398 /* We have read an entire key into tmp_key and should now finish it.
399    It is assumed that this releases tmp_key.  */
400 static void
401 finish_key (gpgme_ctx_t ctx, op_data_t opd)
402 {
403   gpgme_key_t key = opd->tmp_key;
404
405   opd->tmp_key = NULL;
406   opd->tmp_uid = NULL;
407   opd->tmp_keysig = NULL;
408
409   if (key)
410     _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
411 }
412
413
414 /* Note: We are allowed to modify LINE.  */
415 static gpgme_error_t
416 keylist_colon_handler (void *priv, char *line)
417 {
418   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
419   enum
420     {
421       RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
422       RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
423     }
424   rectype = RT_NONE;
425 #define NR_FIELDS 16
426   char *field[NR_FIELDS];
427   int fields = 0;
428   void *hook;
429   op_data_t opd;
430   gpgme_error_t err;
431   gpgme_key_t key;
432   gpgme_subkey_t subkey = NULL;
433   gpgme_key_sig_t keysig = NULL;
434
435   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
436   opd = hook;
437   if (err)
438     return err;
439
440   key = opd->tmp_key;
441
442   TRACE2 (DEBUG_CTX, "gpgme:keylist_colon_handler", ctx,
443           "key = %p, line = %s", key, line ? line : "(null)");
444
445   if (!line)
446     {
447       /* End Of File.  */
448       finish_key (ctx, opd);
449       return 0;
450     }
451
452   while (line && fields < NR_FIELDS)
453     {
454       field[fields++] = line;
455       line = strchr (line, ':');
456       if (line)
457         *(line++) = '\0';
458     }
459
460   if (!strcmp (field[0], "sig"))
461     rectype = RT_SIG;
462   else if (!strcmp (field[0], "rev"))
463     rectype = RT_REV;
464   else if (!strcmp (field[0], "pub"))
465     rectype = RT_PUB;
466   else if (!strcmp (field[0], "sec"))
467     rectype = RT_SEC;
468   else if (!strcmp (field[0], "crt"))
469     rectype = RT_CRT;
470   else if (!strcmp (field[0], "crs"))
471     rectype = RT_CRS;
472   else if (!strcmp (field[0], "fpr") && key) 
473     rectype = RT_FPR;
474   else if (!strcmp (field[0], "uid") && key)
475     rectype = RT_UID;
476   else if (!strcmp (field[0], "sub") && key)
477     rectype = RT_SUB; 
478   else if (!strcmp (field[0], "ssb") && key)
479     rectype = RT_SSB;
480   else if (!strcmp (field[0], "spk") && key)
481     rectype = RT_SPK;
482   else 
483     rectype = RT_NONE;
484
485   /* Only look at signatures immediately following a user ID.  For
486      this, clear the user ID pointer when encountering anything but a
487      signature.  */
488   if (rectype != RT_SIG && rectype != RT_REV)
489     opd->tmp_uid = NULL;
490
491   /* Only look at subpackets immediately following a signature.  For
492      this, clear the signature pointer when encountering anything but
493      a subpacket.  */
494   if (rectype != RT_SPK)
495     opd->tmp_keysig = NULL;
496
497   switch (rectype)
498     {
499     case RT_PUB:
500     case RT_SEC:
501     case RT_CRT:
502     case RT_CRS:
503       /* Start a new keyblock.  */
504       err = _gpgme_key_new (&key);
505       if (err)
506         return err;
507       key->keylist_mode = ctx->keylist_mode;
508       err = _gpgme_key_add_subkey (key, &subkey);
509       if (err)
510         {
511           gpgme_key_unref (key);
512           return err;
513         }
514
515       if (rectype == RT_SEC || rectype == RT_CRS)
516         key->secret = subkey->secret = 1;
517       if (rectype == RT_CRT || rectype == RT_CRS)
518         key->protocol = GPGME_PROTOCOL_CMS;
519       finish_key (ctx, opd);
520       opd->tmp_key = key;
521
522       /* Field 2 has the trust info.  */
523       if (fields >= 2)
524         set_mainkey_trust_info (key, field[1]);
525
526       /* Field 3 has the key length.  */
527       if (fields >= 3)
528         {
529           int i = atoi (field[2]);
530           /* Ignore invalid values.  */
531           if (i > 1)
532             subkey->length = i; 
533         }
534
535       /* Field 4 has the public key algorithm.  */
536       if (fields >= 4)
537         {
538           int i = atoi (field[3]);
539           if (i >= 1 && i < 128)
540             subkey->pubkey_algo = i;
541         }
542
543       /* Field 5 has the long keyid.  Allow short key IDs for the
544          output of an external keyserver listing.  */
545       if (fields >= 5 && strlen (field[4]) <= DIM(subkey->_keyid) - 1)
546         strcpy (subkey->_keyid, field[4]);
547
548       /* Field 6 has the timestamp (seconds).  */
549       if (fields >= 6)
550         subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
551
552       /* Field 7 has the expiration time (seconds).  */
553       if (fields >= 7)
554         subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
555
556       /* Field 8 has the X.509 serial number.  */
557       if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
558         {
559           key->issuer_serial = strdup (field[7]);
560           if (!key->issuer_serial)
561             return gpg_error_from_errno (errno);
562         }
563           
564       /* Field 9 has the ownertrust.  */
565       if (fields >= 9)
566         set_ownertrust (key, field[8]);
567
568       /* Field 10 is not used for gpg due to --fixed-list-mode option
569          but GPGSM stores the issuer name.  */
570       if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
571         if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
572           return gpg_error (GPG_ERR_ENOMEM);    /* FIXME */
573
574       /* Field 11 has the signature class.  */
575
576       /* Field 12 has the capabilities.  */
577       if (fields >= 12)
578         set_mainkey_capability (key, field[11]);
579
580       /* Field 15 carries special flags of a secret key.  */
581       if (fields >= 15 && key->secret)
582         {
583           err = parse_sec_field15 (subkey, field[14]);
584           if (err)
585             return err;
586         }
587       break;
588
589     case RT_SUB:
590     case RT_SSB:
591       /* Start a new subkey.  */
592       err = _gpgme_key_add_subkey (key, &subkey);
593       if (err)
594         return err;
595
596       if (rectype == RT_SSB)
597         subkey->secret = 1;
598
599       /* Field 2 has the trust info.  */
600       if (fields >= 2)
601         set_subkey_trust_info (subkey, field[1]);
602
603       /* Field 3 has the key length.  */
604       if (fields >= 3)
605         {
606           int i = atoi (field[2]);
607           /* Ignore invalid values.  */
608           if (i > 1)
609             subkey->length = i;
610         }
611
612       /* Field 4 has the public key algorithm.  */
613       if (fields >= 4)
614         {
615           int i = atoi (field[3]);
616           if (i >= 1 && i < 128)
617             subkey->pubkey_algo = i;
618         }
619
620       /* Field 5 has the long keyid.  */
621       if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
622         strcpy (subkey->_keyid, field[4]);
623
624       /* Field 6 has the timestamp (seconds).  */
625       if (fields >= 6)
626         subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
627
628       /* Field 7 has the expiration time (seconds).  */
629       if (fields >= 7)
630         subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
631
632       /* Field 8 is reserved (LID).  */
633       /* Field 9 has the ownertrust.  */
634       /* Field 10, the user ID, is n/a for a subkey.  */
635       
636       /* Field 11 has the signature class.  */
637
638       /* Field 12 has the capabilities.  */
639       if (fields >= 12)
640         set_subkey_capability (subkey, field[11]);
641
642       /* Field 15 carries special flags of a secret key. */
643       if (fields >= 15 && key->secret)
644         {
645           err = parse_sec_field15 (subkey, field[14]);
646           if (err)
647             return err;
648         }
649       break;
650
651     case RT_UID:
652       /* Field 2 has the trust info, and field 10 has the user ID.  */
653       if (fields >= 10)
654         {
655           if (_gpgme_key_append_name (key, field[9], 1))
656             return gpg_error_from_errno (GPG_ERR_ENOMEM);       /* FIXME */
657           else
658             {
659               if (field[1])
660                 set_userid_flags (key, field[1]);
661               opd->tmp_uid = key->_last_uid;
662             }
663         }
664       break;
665
666     case RT_FPR:
667       /* Field 10 has the fingerprint (take only the first one).  */
668       if (fields >= 10 && field[9] && *field[9])
669         {
670           /* Need to apply it to the last subkey because all subkeys
671              do have fingerprints. */
672           subkey = key->_last_subkey;
673           if (!subkey->fpr)
674             {
675               subkey->fpr = strdup (field[9]);
676               if (!subkey->fpr)
677                 return gpg_error_from_errno (errno);
678             }
679         }
680
681       /* Field 13 has the gpgsm chain ID (take only the first one).  */
682       if (fields >= 13 && !key->chain_id && *field[12])
683         {
684           key->chain_id = strdup (field[12]);
685           if (!key->chain_id)
686             return gpg_error_from_errno (errno);
687         }
688       break;
689
690     case RT_SIG:
691     case RT_REV:
692       if (!opd->tmp_uid)
693         return 0;
694
695       /* Start a new (revoked) signature.  */
696       assert (opd->tmp_uid == key->_last_uid);
697       keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
698       if (!keysig)
699         return gpg_error (GPG_ERR_ENOMEM);      /* FIXME */
700
701       /* Field 2 has the calculated trust ('!', '-', '?', '%').  */
702       if (fields >= 2)
703         switch (field[1][0])
704           {
705           case '!':
706             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
707             break;
708
709           case '-':
710             keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
711             break;
712
713           case '?':
714             keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
715             break;
716
717           case '%':
718             keysig->status = gpg_error (GPG_ERR_GENERAL);
719             break;
720
721           default:
722             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
723             break;
724           }
725
726       /* Field 4 has the public key algorithm.  */
727       if (fields >= 4)
728         {
729           int i = atoi (field[3]);
730           if (i >= 1 && i < 128)
731             keysig->pubkey_algo = i;
732         }
733       
734       /* Field 5 has the long keyid.  */
735       if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
736         strcpy (keysig->_keyid, field[4]);
737       
738       /* Field 6 has the timestamp (seconds).  */
739       if (fields >= 6)
740         keysig->timestamp = _gpgme_parse_timestamp (field[5], NULL);
741
742       /* Field 7 has the expiration time (seconds).  */
743       if (fields >= 7)
744         keysig->expires = _gpgme_parse_timestamp (field[6], NULL);
745
746       /* Field 11 has the signature class (eg, 0x30 means revoked).  */
747       if (fields >= 11)
748         if (field[10][0] && field[10][1])
749           {
750             int sig_class = _gpgme_hextobyte (field[10]);
751             if (sig_class >= 0)
752               {
753                 keysig->sig_class = sig_class;
754                 keysig->class = keysig->sig_class;
755                 if (sig_class == 0x30)
756                   keysig->revoked = 1;
757               }
758             if (field[10][2] == 'x')
759               keysig->exportable = 1;
760           }
761
762       opd->tmp_keysig = keysig;
763       break;
764
765     case RT_SPK:
766       if (!opd->tmp_keysig)
767         return 0;
768       assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
769
770       if (fields >= 4)
771         {
772           /* Field 2 has the subpacket type.  */
773           int type = atoi (field[1]);
774
775           /* Field 3 has the flags.  */
776           int flags = atoi (field[2]);
777
778           /* Field 4 has the length.  */
779           int len = atoi (field[3]);
780
781           /* Field 5 has the data.  */
782           char *data = field[4];
783
784           /* Type 20: Notation data.  */
785           /* Type 26: Policy URL.  */
786           if (type == 20 || type == 26)
787             {
788               gpgme_sig_notation_t notation;
789
790               keysig = opd->tmp_keysig;
791
792               /* At this time, any error is serious.  */
793               err = _gpgme_parse_notation (&notation, type, flags, len, data);
794               if (err)
795                 return err;
796
797               /* Add a new notation.  FIXME: Could be factored out.  */
798               if (!keysig->notations)
799                 keysig->notations = notation;
800               if (keysig->_last_notation)
801                 keysig->_last_notation->next = notation;
802               keysig->_last_notation = notation;
803             }
804         }
805     
806     case RT_NONE:
807       /* Unknown record.  */
808       break;
809     }
810   return 0;
811 }
812
813
814 void
815 _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
816 {
817   gpgme_error_t err;
818   gpgme_ctx_t ctx = (gpgme_ctx_t) data;
819   gpgme_key_t key = (gpgme_key_t) type_data;
820   void *hook;
821   op_data_t opd;
822   struct key_queue_item_s *q, *q2;
823
824   assert (type == GPGME_EVENT_NEXT_KEY);
825
826   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
827   opd = hook;
828   if (err)
829     return;
830
831   q = malloc (sizeof *q);
832   if (!q)
833     {
834       gpgme_key_unref (key);
835       /* FIXME       return GPGME_Out_Of_Core; */
836       return;
837     }
838   q->key = key;
839   q->next = NULL;
840   /* FIXME: Use a tail pointer?  */
841   if (!(q2 = opd->key_queue))
842     opd->key_queue = q;
843   else
844     {
845       for (; q2->next; q2 = q2->next)
846         ;
847       q2->next = q;
848     }
849   opd->key_cond = 1;
850 }
851
852
853 /* Start a keylist operation within CTX, searching for keys which
854    match PATTERN.  If SECRET_ONLY is true, only secret keys are
855    returned.  */
856 gpgme_error_t
857 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
858 {
859   gpgme_error_t err;
860   void *hook;
861   op_data_t opd;
862
863   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_start", ctx,
864               "pattern=%s, secret_only=%i", pattern, secret_only);
865
866   err = _gpgme_op_reset (ctx, 2);
867   if (err)
868     return TRACE_ERR (err);
869
870   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
871                                sizeof (*opd), release_op_data);
872   opd = hook;
873   if (err)
874     return TRACE_ERR (err);
875
876   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
877
878   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
879                                               keylist_colon_handler, ctx);
880   if (err)
881     return TRACE_ERR (err);
882
883   err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
884                                   ctx->keylist_mode);
885   return TRACE_ERR (err);
886 }
887
888
889 /* Start a keylist operation within CTX, searching for keys which
890    match PATTERN.  If SECRET_ONLY is true, only secret keys are
891    returned.  */
892 gpgme_error_t
893 gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
894                             int secret_only, int reserved)
895 {
896   gpgme_error_t err;
897   void *hook;
898   op_data_t opd;
899
900   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_ext_start", ctx,
901               "secret_only=%i, reserved=0x%x", secret_only, reserved);
902
903   err = _gpgme_op_reset (ctx, 2);
904   if (err)
905     return TRACE_ERR (err);
906
907   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
908                                sizeof (*opd), release_op_data);
909   opd = hook;
910   if (err)
911     return TRACE_ERR (err);
912
913   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
914   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
915                                               keylist_colon_handler, ctx);
916   if (err)
917     return TRACE_ERR (err);
918
919   err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
920                                       reserved, ctx->keylist_mode);
921   return TRACE_ERR (err);
922 }
923
924
925 /* Return the next key from the keylist in R_KEY.  */
926 gpgme_error_t
927 gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
928 {
929   gpgme_error_t err;
930   struct key_queue_item_s *queue_item;
931   void *hook;
932   op_data_t opd;
933
934   TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_next", ctx);
935
936   if (!ctx || !r_key)
937     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
938   *r_key = NULL;
939   if (!ctx)
940     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
941
942   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
943   opd = hook;
944   if (err)
945     return TRACE_ERR (err);
946   if (opd == NULL)
947     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
948
949   if (!opd->key_queue)
950     {
951       err = _gpgme_wait_on_condition (ctx, &opd->key_cond, NULL);
952       if (err)
953         return TRACE_ERR (err);
954
955       if (!opd->key_cond)
956         return TRACE_ERR (gpg_error (GPG_ERR_EOF));
957
958       opd->key_cond = 0; 
959       assert (opd->key_queue);
960     }
961   queue_item = opd->key_queue;
962   opd->key_queue = queue_item->next;
963   if (!opd->key_queue)
964     opd->key_cond = 0;
965   
966   *r_key = queue_item->key;
967   free (queue_item);
968
969   return TRACE_SUC2 ("key=%p (%s)", *r_key,
970                      ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ? 
971                      (*r_key)->subkeys->fpr : "invalid");
972 }
973
974
975 /* Terminate a pending keylist operation within CTX.  */
976 gpgme_error_t
977 gpgme_op_keylist_end (gpgme_ctx_t ctx)
978 {
979   TRACE (DEBUG_CTX, "gpgme_op_keylist_end", ctx);
980   
981   if (!ctx)
982     return gpg_error (GPG_ERR_INV_VALUE);
983
984   return 0;
985 }
986
987 \f
988 /* Get the key with the fingerprint FPR from the crypto backend.  If
989    SECRET is true, get the secret key.  */
990 gpgme_error_t
991 gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
992                int secret)
993 {
994   gpgme_ctx_t listctx;
995   gpgme_error_t err;
996   gpgme_key_t key;
997
998   TRACE_BEG2 (DEBUG_CTX, "gpgme_get_key", ctx,
999               "fpr=%s, secret=%i", fpr, secret);
1000
1001   if (!ctx || !r_key || !fpr)
1002     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1003   
1004   if (strlen (fpr) < 8) /* We have at least a key ID.  */
1005     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1006
1007   /* FIXME: We use our own context because we have to avoid the user's
1008      I/O callback handlers.  */
1009   err = gpgme_new (&listctx);
1010   if (err)
1011     return TRACE_ERR (err);
1012   {
1013     gpgme_protocol_t proto;
1014     gpgme_engine_info_t info;
1015
1016     /* Clone the relevant state.  */
1017     proto = gpgme_get_protocol (ctx);
1018     gpgme_set_protocol (listctx, proto);
1019     gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1020     info = gpgme_ctx_get_engine_info (ctx);
1021     while (info && info->protocol != proto)
1022       info = info->next;
1023     if (info)
1024       gpgme_ctx_set_engine_info (listctx, proto,
1025                                  info->file_name, info->home_dir);
1026   }
1027
1028   err = gpgme_op_keylist_start (listctx, fpr, secret);
1029   if (!err)
1030     err = gpgme_op_keylist_next (listctx, r_key);
1031   if (!err)
1032     {
1033     try_next_key:
1034       err = gpgme_op_keylist_next (listctx, &key);
1035       if (gpgme_err_code (err) == GPG_ERR_EOF)
1036         err = 0;
1037       else
1038         {
1039           if (!err
1040               && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1041               && key && key->subkeys && key->subkeys->fpr
1042               && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1043             {
1044               /* The fingerprint is identical.  We assume that this is
1045                  the same key and don't mark it as an ambiguous.  This
1046                  problem may occur with corrupted keyrings and has
1047                  been noticed often with gpgsm.  In fact gpgsm uses a
1048                  similar hack to sort out such duplicates but it can't
1049                  do that while listing keys.  */
1050               gpgme_key_unref (key);
1051               goto try_next_key;
1052             }
1053           if (!err)
1054             {
1055               gpgme_key_unref (key);
1056               err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1057             }
1058           gpgme_key_unref (*r_key);
1059         }
1060     }
1061   gpgme_release (listctx);
1062   if (! err)
1063     {
1064       TRACE_LOG2 ("key=%p (%s)", *r_key,
1065                   ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ? 
1066                   (*r_key)->subkeys->fpr : "invalid");
1067     }
1068   return TRACE_ERR (err);
1069 }