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