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