Add field CURVE to the key info.
[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 17
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 = _gpgme_map_pk_algo (i, ctx->protocol);
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_syserror ();
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
588       /* Field 17 has the curve name for ECC.  */
589       if (fields >= 17 && *field[16])
590         {
591           subkey->curve = strdup (field[16]);
592           if (!subkey->curve)
593             return gpg_error_from_syserror ();
594         }
595
596       break;
597
598     case RT_SUB:
599     case RT_SSB:
600       /* Start a new subkey.  */
601       err = _gpgme_key_add_subkey (key, &subkey);
602       if (err)
603         return err;
604
605       if (rectype == RT_SSB)
606         subkey->secret = 1;
607
608       /* Field 2 has the trust info.  */
609       if (fields >= 2)
610         set_subkey_trust_info (subkey, field[1]);
611
612       /* Field 3 has the key length.  */
613       if (fields >= 3)
614         {
615           int i = atoi (field[2]);
616           /* Ignore invalid values.  */
617           if (i > 1)
618             subkey->length = i;
619         }
620
621       /* Field 4 has the public key algorithm.  */
622       if (fields >= 4)
623         {
624           int i = atoi (field[3]);
625           if (i >= 1 && i < 128)
626             subkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
627         }
628
629       /* Field 5 has the long keyid.  */
630       if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
631         strcpy (subkey->_keyid, field[4]);
632
633       /* Field 6 has the timestamp (seconds).  */
634       if (fields >= 6)
635         subkey->timestamp = _gpgme_parse_timestamp (field[5], NULL);
636
637       /* Field 7 has the expiration time (seconds).  */
638       if (fields >= 7)
639         subkey->expires = _gpgme_parse_timestamp (field[6], NULL);
640
641       /* Field 8 is reserved (LID).  */
642       /* Field 9 has the ownertrust.  */
643       /* Field 10, the user ID, is n/a for a subkey.  */
644
645       /* Field 11 has the signature class.  */
646
647       /* Field 12 has the capabilities.  */
648       if (fields >= 12)
649         set_subkey_capability (subkey, field[11]);
650
651       /* Field 15 carries special flags of a secret key. */
652       if (fields >= 15 && key->secret)
653         {
654           err = parse_sec_field15 (subkey, field[14]);
655           if (err)
656             return err;
657         }
658
659       /* Field 17 has the curve name for ECC.  */
660       if (fields >= 17 && *field[16])
661         {
662           subkey->curve = strdup (field[16]);
663           if (!subkey->curve)
664             return gpg_error_from_syserror ();
665         }
666
667       break;
668
669     case RT_UID:
670       /* Field 2 has the trust info, and field 10 has the user ID.  */
671       if (fields >= 10)
672         {
673           if (_gpgme_key_append_name (key, field[9], 1))
674             return gpg_error (GPG_ERR_ENOMEM);  /* FIXME */
675           else
676             {
677               if (field[1])
678                 set_userid_flags (key, field[1]);
679               opd->tmp_uid = key->_last_uid;
680             }
681         }
682       break;
683
684     case RT_FPR:
685       /* Field 10 has the fingerprint (take only the first one).  */
686       if (fields >= 10 && field[9] && *field[9])
687         {
688           /* Need to apply it to the last subkey because all subkeys
689              do have fingerprints. */
690           subkey = key->_last_subkey;
691           if (!subkey->fpr)
692             {
693               subkey->fpr = strdup (field[9]);
694               if (!subkey->fpr)
695                 return gpg_error_from_syserror ();
696             }
697         }
698
699       /* Field 13 has the gpgsm chain ID (take only the first one).  */
700       if (fields >= 13 && !key->chain_id && *field[12])
701         {
702           key->chain_id = strdup (field[12]);
703           if (!key->chain_id)
704             return gpg_error_from_syserror ();
705         }
706       break;
707
708     case RT_SIG:
709     case RT_REV:
710       if (!opd->tmp_uid)
711         return 0;
712
713       /* Start a new (revoked) signature.  */
714       assert (opd->tmp_uid == key->_last_uid);
715       keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
716       if (!keysig)
717         return gpg_error (GPG_ERR_ENOMEM);      /* FIXME */
718
719       /* Field 2 has the calculated trust ('!', '-', '?', '%').  */
720       if (fields >= 2)
721         switch (field[1][0])
722           {
723           case '!':
724             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
725             break;
726
727           case '-':
728             keysig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
729             break;
730
731           case '?':
732             keysig->status = gpg_error (GPG_ERR_NO_PUBKEY);
733             break;
734
735           case '%':
736             keysig->status = gpg_error (GPG_ERR_GENERAL);
737             break;
738
739           default:
740             keysig->status = gpg_error (GPG_ERR_NO_ERROR);
741             break;
742           }
743
744       /* Field 4 has the public key algorithm.  */
745       if (fields >= 4)
746         {
747           int i = atoi (field[3]);
748           if (i >= 1 && i < 128)
749             keysig->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol);
750         }
751
752       /* Field 5 has the long keyid.  */
753       if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
754         strcpy (keysig->_keyid, field[4]);
755
756       /* Field 6 has the timestamp (seconds).  */
757       if (fields >= 6)
758         keysig->timestamp = _gpgme_parse_timestamp (field[5], NULL);
759
760       /* Field 7 has the expiration time (seconds).  */
761       if (fields >= 7)
762         keysig->expires = _gpgme_parse_timestamp (field[6], NULL);
763
764       /* Field 11 has the signature class (eg, 0x30 means revoked).  */
765       if (fields >= 11)
766         if (field[10][0] && field[10][1])
767           {
768             int sig_class = _gpgme_hextobyte (field[10]);
769             if (sig_class >= 0)
770               {
771                 keysig->sig_class = sig_class;
772                 keysig->class = keysig->sig_class;
773                 if (sig_class == 0x30)
774                   keysig->revoked = 1;
775               }
776             if (field[10][2] == 'x')
777               keysig->exportable = 1;
778           }
779
780       opd->tmp_keysig = keysig;
781       break;
782
783     case RT_SPK:
784       if (!opd->tmp_keysig)
785         return 0;
786       assert (opd->tmp_keysig == key->_last_uid->_last_keysig);
787
788       if (fields >= 4)
789         {
790           /* Field 2 has the subpacket type.  */
791           int type = atoi (field[1]);
792
793           /* Field 3 has the flags.  */
794           int flags = atoi (field[2]);
795
796           /* Field 4 has the length.  */
797           int len = atoi (field[3]);
798
799           /* Field 5 has the data.  */
800           char *data = field[4];
801
802           /* Type 20: Notation data.  */
803           /* Type 26: Policy URL.  */
804           if (type == 20 || type == 26)
805             {
806               gpgme_sig_notation_t notation;
807
808               keysig = opd->tmp_keysig;
809
810               /* At this time, any error is serious.  */
811               err = _gpgme_parse_notation (&notation, type, flags, len, data);
812               if (err)
813                 return err;
814
815               /* Add a new notation.  FIXME: Could be factored out.  */
816               if (!keysig->notations)
817                 keysig->notations = notation;
818               if (keysig->_last_notation)
819                 keysig->_last_notation->next = notation;
820               keysig->_last_notation = notation;
821             }
822         }
823
824     case RT_NONE:
825       /* Unknown record.  */
826       break;
827     }
828   return 0;
829 }
830
831
832 void
833 _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type, void *type_data)
834 {
835   gpgme_error_t err;
836   gpgme_ctx_t ctx = (gpgme_ctx_t) data;
837   gpgme_key_t key = (gpgme_key_t) type_data;
838   void *hook;
839   op_data_t opd;
840   struct key_queue_item_s *q, *q2;
841
842   assert (type == GPGME_EVENT_NEXT_KEY);
843
844   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
845   opd = hook;
846   if (err)
847     return;
848
849   q = malloc (sizeof *q);
850   if (!q)
851     {
852       gpgme_key_unref (key);
853       /* FIXME       return GPGME_Out_Of_Core; */
854       return;
855     }
856   q->key = key;
857   q->next = NULL;
858   /* FIXME: Use a tail pointer?  */
859   if (!(q2 = opd->key_queue))
860     opd->key_queue = q;
861   else
862     {
863       for (; q2->next; q2 = q2->next)
864         ;
865       q2->next = q;
866     }
867   opd->key_cond = 1;
868 }
869
870
871 /* Start a keylist operation within CTX, searching for keys which
872    match PATTERN.  If SECRET_ONLY is true, only secret keys are
873    returned.  */
874 gpgme_error_t
875 gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
876 {
877   gpgme_error_t err;
878   void *hook;
879   op_data_t opd;
880
881   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_start", ctx,
882               "pattern=%s, secret_only=%i", pattern, secret_only);
883
884   if (!ctx)
885     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
886
887   err = _gpgme_op_reset (ctx, 2);
888   if (err)
889     return TRACE_ERR (err);
890
891   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
892                                sizeof (*opd), release_op_data);
893   opd = hook;
894   if (err)
895     return TRACE_ERR (err);
896
897   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
898
899   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
900                                               keylist_colon_handler, ctx);
901   if (err)
902     return TRACE_ERR (err);
903
904   err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
905                                   ctx->keylist_mode);
906   return TRACE_ERR (err);
907 }
908
909
910 /* Start a keylist operation within CTX, searching for keys which
911    match PATTERN.  If SECRET_ONLY is true, only secret keys are
912    returned.  */
913 gpgme_error_t
914 gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
915                             int secret_only, int reserved)
916 {
917   gpgme_error_t err;
918   void *hook;
919   op_data_t opd;
920
921   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_ext_start", ctx,
922               "secret_only=%i, reserved=0x%x", secret_only, reserved);
923
924   if (!ctx)
925     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
926
927   err = _gpgme_op_reset (ctx, 2);
928   if (err)
929     return TRACE_ERR (err);
930
931   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
932                                sizeof (*opd), release_op_data);
933   opd = hook;
934   if (err)
935     return TRACE_ERR (err);
936
937   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
938   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
939                                               keylist_colon_handler, ctx);
940   if (err)
941     return TRACE_ERR (err);
942
943   err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
944                                       reserved, ctx->keylist_mode);
945   return TRACE_ERR (err);
946 }
947
948
949 /* Return the next key from the keylist in R_KEY.  */
950 gpgme_error_t
951 gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
952 {
953   gpgme_error_t err;
954   struct key_queue_item_s *queue_item;
955   void *hook;
956   op_data_t opd;
957
958   TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_next", ctx);
959
960   if (!ctx || !r_key)
961     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
962   *r_key = NULL;
963   if (!ctx)
964     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
965
966   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
967   opd = hook;
968   if (err)
969     return TRACE_ERR (err);
970   if (opd == NULL)
971     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
972
973   if (!opd->key_queue)
974     {
975       err = _gpgme_wait_on_condition (ctx, &opd->key_cond, NULL);
976       if (err)
977         return TRACE_ERR (err);
978
979       if (!opd->key_cond)
980         return TRACE_ERR (gpg_error (GPG_ERR_EOF));
981
982       opd->key_cond = 0;
983       assert (opd->key_queue);
984     }
985   queue_item = opd->key_queue;
986   opd->key_queue = queue_item->next;
987   if (!opd->key_queue)
988     opd->key_cond = 0;
989
990   *r_key = queue_item->key;
991   free (queue_item);
992
993   return TRACE_SUC2 ("key=%p (%s)", *r_key,
994                      ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
995                      (*r_key)->subkeys->fpr : "invalid");
996 }
997
998
999 /* Terminate a pending keylist operation within CTX.  */
1000 gpgme_error_t
1001 gpgme_op_keylist_end (gpgme_ctx_t ctx)
1002 {
1003   TRACE (DEBUG_CTX, "gpgme_op_keylist_end", ctx);
1004
1005   if (!ctx)
1006     return gpg_error (GPG_ERR_INV_VALUE);
1007
1008   return 0;
1009 }
1010
1011 \f
1012 /* Get the key with the fingerprint FPR from the crypto backend.  If
1013    SECRET is true, get the secret key.  */
1014 gpgme_error_t
1015 gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
1016                int secret)
1017 {
1018   gpgme_ctx_t listctx;
1019   gpgme_error_t err;
1020   gpgme_key_t key;
1021
1022   TRACE_BEG2 (DEBUG_CTX, "gpgme_get_key", ctx,
1023               "fpr=%s, secret=%i", fpr, secret);
1024
1025   if (!ctx || !r_key || !fpr)
1026     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1027
1028   if (strlen (fpr) < 8) /* We have at least a key ID.  */
1029     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1030
1031   /* FIXME: We use our own context because we have to avoid the user's
1032      I/O callback handlers.  */
1033   err = gpgme_new (&listctx);
1034   if (err)
1035     return TRACE_ERR (err);
1036   {
1037     gpgme_protocol_t proto;
1038     gpgme_engine_info_t info;
1039
1040     /* Clone the relevant state.  */
1041     proto = gpgme_get_protocol (ctx);
1042     gpgme_set_protocol (listctx, proto);
1043     gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1044     info = gpgme_ctx_get_engine_info (ctx);
1045     while (info && info->protocol != proto)
1046       info = info->next;
1047     if (info)
1048       gpgme_ctx_set_engine_info (listctx, proto,
1049                                  info->file_name, info->home_dir);
1050   }
1051
1052   err = gpgme_op_keylist_start (listctx, fpr, secret);
1053   if (!err)
1054     err = gpgme_op_keylist_next (listctx, r_key);
1055   if (!err)
1056     {
1057     try_next_key:
1058       err = gpgme_op_keylist_next (listctx, &key);
1059       if (gpgme_err_code (err) == GPG_ERR_EOF)
1060         err = 0;
1061       else
1062         {
1063           if (!err
1064               && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1065               && key && key->subkeys && key->subkeys->fpr
1066               && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1067             {
1068               /* The fingerprint is identical.  We assume that this is
1069                  the same key and don't mark it as an ambiguous.  This
1070                  problem may occur with corrupted keyrings and has
1071                  been noticed often with gpgsm.  In fact gpgsm uses a
1072                  similar hack to sort out such duplicates but it can't
1073                  do that while listing keys.  */
1074               gpgme_key_unref (key);
1075               goto try_next_key;
1076             }
1077           if (!err)
1078             {
1079               gpgme_key_unref (key);
1080               err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1081             }
1082           gpgme_key_unref (*r_key);
1083         }
1084     }
1085   gpgme_release (listctx);
1086   if (! err)
1087     {
1088       TRACE_LOG2 ("key=%p (%s)", *r_key,
1089                   ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1090                   (*r_key)->subkeys->fpr : "invalid");
1091     }
1092   return TRACE_ERR (err);
1093 }