Use gpg_error_from_syserror instead of directly accessing errno.
[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_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       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 (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_syserror ();
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_syserror ();
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   if (!ctx)
867     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
868
869   err = _gpgme_op_reset (ctx, 2);
870   if (err)
871     return TRACE_ERR (err);
872
873   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
874                                sizeof (*opd), release_op_data);
875   opd = hook;
876   if (err)
877     return TRACE_ERR (err);
878
879   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
880
881   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
882                                               keylist_colon_handler, ctx);
883   if (err)
884     return TRACE_ERR (err);
885
886   err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
887                                   ctx->keylist_mode);
888   return TRACE_ERR (err);
889 }
890
891
892 /* Start a keylist operation within CTX, searching for keys which
893    match PATTERN.  If SECRET_ONLY is true, only secret keys are
894    returned.  */
895 gpgme_error_t
896 gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
897                             int secret_only, int reserved)
898 {
899   gpgme_error_t err;
900   void *hook;
901   op_data_t opd;
902
903   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_ext_start", ctx,
904               "secret_only=%i, reserved=0x%x", secret_only, reserved);
905
906   if (!ctx)
907     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
908
909   err = _gpgme_op_reset (ctx, 2);
910   if (err)
911     return TRACE_ERR (err);
912
913   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook,
914                                sizeof (*opd), release_op_data);
915   opd = hook;
916   if (err)
917     return TRACE_ERR (err);
918
919   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
920   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
921                                               keylist_colon_handler, ctx);
922   if (err)
923     return TRACE_ERR (err);
924
925   err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
926                                       reserved, ctx->keylist_mode);
927   return TRACE_ERR (err);
928 }
929
930
931 /* Return the next key from the keylist in R_KEY.  */
932 gpgme_error_t
933 gpgme_op_keylist_next (gpgme_ctx_t ctx, gpgme_key_t *r_key)
934 {
935   gpgme_error_t err;
936   struct key_queue_item_s *queue_item;
937   void *hook;
938   op_data_t opd;
939
940   TRACE_BEG (DEBUG_CTX, "gpgme_op_keylist_next", ctx);
941
942   if (!ctx || !r_key)
943     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
944   *r_key = NULL;
945   if (!ctx)
946     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
947
948   err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
949   opd = hook;
950   if (err)
951     return TRACE_ERR (err);
952   if (opd == NULL)
953     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
954
955   if (!opd->key_queue)
956     {
957       err = _gpgme_wait_on_condition (ctx, &opd->key_cond, NULL);
958       if (err)
959         return TRACE_ERR (err);
960
961       if (!opd->key_cond)
962         return TRACE_ERR (gpg_error (GPG_ERR_EOF));
963
964       opd->key_cond = 0;
965       assert (opd->key_queue);
966     }
967   queue_item = opd->key_queue;
968   opd->key_queue = queue_item->next;
969   if (!opd->key_queue)
970     opd->key_cond = 0;
971
972   *r_key = queue_item->key;
973   free (queue_item);
974
975   return TRACE_SUC2 ("key=%p (%s)", *r_key,
976                      ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
977                      (*r_key)->subkeys->fpr : "invalid");
978 }
979
980
981 /* Terminate a pending keylist operation within CTX.  */
982 gpgme_error_t
983 gpgme_op_keylist_end (gpgme_ctx_t ctx)
984 {
985   TRACE (DEBUG_CTX, "gpgme_op_keylist_end", ctx);
986
987   if (!ctx)
988     return gpg_error (GPG_ERR_INV_VALUE);
989
990   return 0;
991 }
992
993 \f
994 /* Get the key with the fingerprint FPR from the crypto backend.  If
995    SECRET is true, get the secret key.  */
996 gpgme_error_t
997 gpgme_get_key (gpgme_ctx_t ctx, const char *fpr, gpgme_key_t *r_key,
998                int secret)
999 {
1000   gpgme_ctx_t listctx;
1001   gpgme_error_t err;
1002   gpgme_key_t key;
1003
1004   TRACE_BEG2 (DEBUG_CTX, "gpgme_get_key", ctx,
1005               "fpr=%s, secret=%i", fpr, secret);
1006
1007   if (!ctx || !r_key || !fpr)
1008     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1009
1010   if (strlen (fpr) < 8) /* We have at least a key ID.  */
1011     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1012
1013   /* FIXME: We use our own context because we have to avoid the user's
1014      I/O callback handlers.  */
1015   err = gpgme_new (&listctx);
1016   if (err)
1017     return TRACE_ERR (err);
1018   {
1019     gpgme_protocol_t proto;
1020     gpgme_engine_info_t info;
1021
1022     /* Clone the relevant state.  */
1023     proto = gpgme_get_protocol (ctx);
1024     gpgme_set_protocol (listctx, proto);
1025     gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx));
1026     info = gpgme_ctx_get_engine_info (ctx);
1027     while (info && info->protocol != proto)
1028       info = info->next;
1029     if (info)
1030       gpgme_ctx_set_engine_info (listctx, proto,
1031                                  info->file_name, info->home_dir);
1032   }
1033
1034   err = gpgme_op_keylist_start (listctx, fpr, secret);
1035   if (!err)
1036     err = gpgme_op_keylist_next (listctx, r_key);
1037   if (!err)
1038     {
1039     try_next_key:
1040       err = gpgme_op_keylist_next (listctx, &key);
1041       if (gpgme_err_code (err) == GPG_ERR_EOF)
1042         err = 0;
1043       else
1044         {
1045           if (!err
1046               && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr
1047               && key && key->subkeys && key->subkeys->fpr
1048               && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr))
1049             {
1050               /* The fingerprint is identical.  We assume that this is
1051                  the same key and don't mark it as an ambiguous.  This
1052                  problem may occur with corrupted keyrings and has
1053                  been noticed often with gpgsm.  In fact gpgsm uses a
1054                  similar hack to sort out such duplicates but it can't
1055                  do that while listing keys.  */
1056               gpgme_key_unref (key);
1057               goto try_next_key;
1058             }
1059           if (!err)
1060             {
1061               gpgme_key_unref (key);
1062               err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
1063             }
1064           gpgme_key_unref (*r_key);
1065         }
1066     }
1067   gpgme_release (listctx);
1068   if (! err)
1069     {
1070       TRACE_LOG2 ("key=%p (%s)", *r_key,
1071                   ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ?
1072                   (*r_key)->subkeys->fpr : "invalid");
1073     }
1074   return TRACE_ERR (err);
1075 }