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