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