Fix last change.
[gpgme.git] / gpgme / verify.c
1 /* verify.c - Signature verification.
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 <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27
28 #include "gpgme.h"
29 #include "util.h"
30 #include "context.h"
31 #include "ops.h"
32
33 \f
34 typedef struct
35 {
36   struct _gpgme_op_verify_result result;
37
38   gpgme_signature_t current_sig;
39 } *op_data_t;
40
41
42 static void
43 release_op_data (void *hook)
44 {
45   op_data_t opd = (op_data_t) hook;
46   gpgme_signature_t sig = opd->result.signatures;
47
48   while (sig)
49     {
50       gpgme_signature_t next = sig->next;
51       gpgme_sig_notation_t notation = sig->notations;
52
53       while (notation)
54         {
55           gpgme_sig_notation_t next_nota = notation->next;
56
57           if (notation->name)
58             free (notation->name);
59           if (notation->value)
60             free (notation->value);
61           notation = next_nota;
62         }
63
64       if (sig->fpr)
65         free (sig->fpr);
66       free (sig);
67       sig = next;
68     }
69 }
70
71
72 gpgme_verify_result_t
73 gpgme_op_verify_result (gpgme_ctx_t ctx)
74 {
75   void *hook;
76   op_data_t opd;
77   gpgme_error_t err;
78
79   err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
80   opd = hook;
81   if (err || !opd)
82     return NULL;
83
84   return &opd->result;
85 }
86
87 \f
88 /* Build a summary vector from RESULT. */
89 static void
90 calc_sig_summary (gpgme_signature_t sig)
91 {
92   unsigned long sum = 0;
93
94   if (sig->validity == GPGME_VALIDITY_FULL
95       || sig->validity == GPGME_VALIDITY_ULTIMATE)
96     {
97       if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
98           || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
99           || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
100         sum |= GPGME_SIGSUM_GREEN;
101     }
102   else if (sig->validity == GPGME_VALIDITY_NEVER)
103     {
104       if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
105           || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
106           || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
107         sum |= GPGME_SIGSUM_RED;
108     }
109   else if (gpg_err_code (sig->status) == GPG_ERR_BAD_SIGNATURE)
110     sum |= GPGME_SIGSUM_RED;
111   
112   /* FIXME: handle the case when key and message are expired. */
113   switch (gpg_err_code (sig->status))
114     {
115     case GPG_ERR_SIG_EXPIRED:
116       sum |= GPGME_SIGSUM_SIG_EXPIRED;
117       break;
118
119     case GPG_ERR_KEY_EXPIRED:
120       sum |= GPGME_SIGSUM_KEY_EXPIRED;
121       break;
122
123     case GPG_ERR_NO_PUBKEY:
124       sum |= GPGME_SIGSUM_KEY_MISSING;
125       break;
126
127     case GPG_ERR_BAD_SIGNATURE:
128     case GPG_ERR_NO_ERROR:
129       break;
130
131     default:
132       sum |= GPGME_SIGSUM_SYS_ERROR;
133       break;
134     }
135   
136   if (sig->wrong_key_usage)
137     sum |= GPGME_SIGSUM_BAD_POLICY;
138   
139   /* Set the valid flag when the signature is unquestionable
140      valid. */
141   if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
142     sum |= GPGME_SIGSUM_VALID;
143   
144   sig->summary = sum;
145 }
146   
147
148 static gpgme_error_t
149 parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args)
150 {
151   gpgme_signature_t sig;
152   char *end = strchr (args, ' ');
153
154   if (end)
155     {
156       *end = '\0';
157       end++;
158     }
159
160   sig = calloc (1, sizeof (*sig));
161   if (!sig)
162     return gpg_error_from_errno (errno);
163   if (!opd->result.signatures)
164     opd->result.signatures = sig;
165   if (opd->current_sig)
166     opd->current_sig->next = sig;
167   opd->current_sig = sig;
168
169   /* FIXME: We should set the source of the state.  */
170   switch (code)
171     {
172     case GPGME_STATUS_GOODSIG:
173       sig->status = gpg_error (GPG_ERR_NO_ERROR);
174       break;
175
176     case GPGME_STATUS_EXPSIG:
177       sig->status = gpg_error (GPG_ERR_SIG_EXPIRED);
178       break;
179
180     case GPGME_STATUS_EXPKEYSIG:
181       sig->status = gpg_error (GPG_ERR_KEY_EXPIRED);
182       break;
183
184     case GPGME_STATUS_BADSIG:
185       sig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
186       break;
187
188     case GPGME_STATUS_ERRSIG:
189       if (end)
190         {
191           int i = 0;
192           /* The return code is the 6th argument, if it is 9, the
193              problem is a missing key.  */
194           while (end && i < 4)
195             {
196               end = strchr (end, ' ');
197               if (end)
198                 end++;
199               i++;
200             }
201           if (end && end[0] && (!end[1] || !end[1] == ' '))
202             {
203               switch (end[0])
204                 {
205                 case '4':
206                   sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
207                   break;
208                   
209                 case 9:
210                   sig->status = gpg_error (GPG_ERR_NO_PUBKEY);
211                   break;
212                   
213                 default:
214                   sig->status = gpg_error (GPG_ERR_GENERAL);
215                 }
216             }
217         }
218       else
219         sig->status = gpg_error (GPG_ERR_GENERAL);
220       break;
221
222     default:
223       return gpg_error (GPG_ERR_GENERAL);
224     }
225
226   if (*args)
227     {
228       sig->fpr = strdup (args);
229       if (!sig->fpr)
230         return gpg_error_from_errno (errno);
231     }
232   return 0;
233 }
234
235
236 static gpgme_error_t
237 parse_valid_sig (gpgme_signature_t sig, char *args)
238 {
239   char *end = strchr (args, ' ');
240
241   if (end)
242     {
243       *end = '\0';
244       end++;
245     }
246
247   if (!*args)
248     /* We require at least the fingerprint.  */
249     return gpg_error (GPG_ERR_GENERAL);
250
251   if (sig->fpr)
252     free (sig->fpr);
253   sig->fpr = strdup (args);
254   if (!sig->fpr)
255     return gpg_error_from_errno (errno);
256
257   end = strchr (end, ' ');
258   if (end)
259     {
260       char *tail;
261       errno = 0;
262       sig->timestamp = strtol (end, &tail, 0);
263       if (errno || end == tail || (*tail && *tail != ' '))
264         return gpg_error (GPG_ERR_INV_ENGINE);
265       end = tail;
266      
267       sig->exp_timestamp = strtol (end, &tail, 0);
268       if (errno || end == tail || (*tail && *tail != ' '))
269         return gpg_error (GPG_ERR_INV_ENGINE);
270     }
271   return 0;
272 }
273
274
275 static gpgme_error_t
276 parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
277 {
278   gpgme_error_t err;
279   gpgme_sig_notation_t *lastp = &sig->notations;
280   gpgme_sig_notation_t notation = sig->notations;
281   char *end = strchr (args, ' ');
282
283   if (end)
284     *end = '\0';
285
286   if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
287     {
288       /* FIXME: We could keep a pointer to the last notation in the list.  */
289       while (notation && notation->value)
290         {
291           lastp = &notation->next;
292           notation = notation->next;
293         }
294
295       if (notation)
296         /* There is another notation name without data for the
297            previous one.  The crypto backend misbehaves.  */
298         return gpg_error (GPG_ERR_INV_ENGINE);
299
300       notation = malloc (sizeof (*sig));
301       if (!notation)
302         return gpg_error_from_errno (errno);
303       notation->next = NULL;
304
305       if (code == GPGME_STATUS_NOTATION_NAME)
306         {
307           int len = strlen (args) + 1;
308
309           notation->name = malloc (len);
310           if (!notation->name)
311             {
312               int saved_errno = errno;
313               free (notation);
314               return gpg_error_from_errno (saved_errno);
315             }
316           err = _gpgme_decode_percent_string (args, &notation->name, len);
317           if (err)
318             {
319               free (notation->name);
320               free (notation);
321               return err;
322             }
323
324           notation->value = NULL;
325         }
326       else
327         {
328           int len = strlen (args) + 1;
329
330           notation->name = NULL;
331           notation->value = malloc (len);
332           if (!notation->value)
333             {
334               int saved_errno = errno;
335               free (notation);
336               return gpg_error_from_errno (saved_errno);
337             }
338           err = _gpgme_decode_percent_string (args, &notation->value, len);
339           if (err)
340             {
341               free (notation->value);
342               free (notation);
343               return err;
344             }
345         }
346       *lastp = notation;
347     }
348   else if (code == GPGME_STATUS_NOTATION_DATA)
349     {
350       int len = strlen (args) + 1;
351       char *dest;
352
353       /* FIXME: We could keep a pointer to the last notation in the list.  */
354       while (notation && notation->next)
355         {
356           lastp = &notation->next;
357           notation = notation->next;
358         }
359
360       if (!notation || !notation->name)
361         /* There is notation data without a previous notation
362            name.  The crypto backend misbehaves.  */
363         return gpg_error (GPG_ERR_INV_ENGINE);
364       
365       if (!notation->value)
366         {
367           dest = notation->value = malloc (len);
368           if (!dest)
369             return gpg_error_from_errno (errno);
370         }
371       else
372         {
373           int cur_len = strlen (notation->value);
374           dest = realloc (notation->value, len + strlen (notation->value));
375           if (!dest)
376             return gpg_error_from_errno (errno);
377           notation->value = dest;
378           dest += cur_len;
379         }
380       
381       err = _gpgme_decode_percent_string (args, &dest, len);
382       if (err)
383         return err;
384     }
385   else
386     return gpg_error (GPG_ERR_INV_ENGINE);
387   return 0;
388 }
389
390
391 static gpgme_error_t
392 parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
393 {
394   char *end = strchr (args, ' ');
395
396   if (end)
397     *end = '\0';
398
399   switch (code)
400     {
401     case GPGME_STATUS_TRUST_UNDEFINED:
402     default:
403       sig->validity = GPGME_VALIDITY_UNKNOWN;
404       break;
405
406     case GPGME_STATUS_TRUST_NEVER:
407       sig->validity = GPGME_VALIDITY_NEVER;
408       break;
409
410     case GPGME_STATUS_TRUST_MARGINAL:
411       sig->validity = GPGME_VALIDITY_MARGINAL;
412       break;
413
414     case GPGME_STATUS_TRUST_FULLY:
415     case GPGME_STATUS_TRUST_ULTIMATE:
416       sig->validity = GPGME_VALIDITY_FULL;
417       break;
418     }
419
420   if (*args)
421     sig->validity_reason = _gpgme_map_gnupg_error (args);
422
423   return 0;
424 }
425
426
427 static gpgme_error_t
428 parse_error (gpgme_signature_t sig, char *args)
429 {
430   gpgme_error_t err;
431   char *where = strchr (args, ' ');
432   char *which;
433
434   if (where)
435     {
436       *where = '\0';
437       which = where + 1;
438
439       where = strchr (which, ' ');
440       if (where)
441         *where = '\0';
442
443       where = args;      
444     }
445   else
446     return gpg_error (GPG_ERR_INV_ENGINE);
447
448   err = _gpgme_map_gnupg_error (which);
449
450   if (!strcmp (where, "verify.findkey"))
451     sig->status = err;
452   else if (!strcmp (where, "verify.keyusage")
453            && gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
454     sig->wrong_key_usage = 1;
455
456   return 0;
457 }
458
459
460 gpgme_error_t
461 _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
462 {
463   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
464   gpgme_error_t err;
465   void *hook;
466   op_data_t opd;
467   gpgme_signature_t sig;
468
469   err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
470   opd = hook;
471   if (err)
472     return err;
473
474   sig = opd->current_sig;
475
476   switch (code)
477     {
478     case GPGME_STATUS_GOODSIG:
479     case GPGME_STATUS_EXPSIG:
480     case GPGME_STATUS_EXPKEYSIG:
481     case GPGME_STATUS_BADSIG:
482     case GPGME_STATUS_ERRSIG:
483       if (sig)
484         calc_sig_summary (sig);
485       return parse_new_sig (opd, code, args);
486
487     case GPGME_STATUS_VALIDSIG:
488       return sig ? parse_valid_sig (sig, args)
489         : gpg_error (GPG_ERR_INV_ENGINE);
490
491     case GPGME_STATUS_NODATA:
492       if (!sig)
493         return gpg_error (GPG_ERR_NO_DATA);
494       sig->status = gpg_error (GPG_ERR_NO_DATA);
495       break;
496
497     case GPGME_STATUS_UNEXPECTED:
498       if (!sig)
499         return gpg_error (GPG_ERR_GENERAL);
500       sig->status = gpg_error (GPG_ERR_NO_DATA);
501       break;
502
503     case GPGME_STATUS_NOTATION_NAME:
504     case GPGME_STATUS_NOTATION_DATA:
505     case GPGME_STATUS_POLICY_URL:
506       return sig ? parse_notation (sig, code, args)
507         : gpg_error (GPG_ERR_INV_ENGINE);
508
509     case GPGME_STATUS_TRUST_UNDEFINED:
510     case GPGME_STATUS_TRUST_NEVER:
511     case GPGME_STATUS_TRUST_MARGINAL:
512     case GPGME_STATUS_TRUST_FULLY:
513     case GPGME_STATUS_TRUST_ULTIMATE:
514       return sig ? parse_trust (sig, code, args)
515         : gpg_error (GPG_ERR_INV_ENGINE);
516
517     case GPGME_STATUS_ERROR:
518       return sig ? parse_error (sig, args) : gpg_error (GPG_ERR_INV_ENGINE);
519
520     case GPGME_STATUS_EOF:
521       if (sig)
522         calc_sig_summary (sig);
523       break;
524
525     default:
526       break;
527     }
528   return 0;
529 }
530
531
532 static gpgme_error_t
533 verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
534 {
535   return _gpgme_progress_status_handler (priv, code, args)
536     || _gpgme_verify_status_handler (priv, code, args);
537 }
538
539
540 gpgme_error_t
541 _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
542 {  
543   void *hook;
544   op_data_t opd;
545
546   return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
547                                 sizeof (*opd), release_op_data);
548 }
549
550
551 static gpgme_error_t
552 verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
553               gpgme_data_t signed_text, gpgme_data_t plaintext)
554 {
555   gpgme_error_t err;
556
557   err = _gpgme_op_reset (ctx, synchronous);
558   if (err)
559     return err;
560
561   err = _gpgme_op_verify_init_result (ctx);
562   if (err)
563     return err;
564
565   _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
566
567   if (!sig)
568     return gpg_error (GPG_ERR_NO_DATA);
569   if (!signed_text && !plaintext)
570     return gpg_error (GPG_ERR_INV_VALUE);
571
572   return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
573 }
574
575
576 /* Decrypt ciphertext CIPHER and make a signature verification within
577    CTX and store the resulting plaintext in PLAIN.  */
578 gpgme_error_t
579 gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
580                        gpgme_data_t signed_text, gpgme_data_t plaintext)
581 {
582   return verify_start (ctx, 0, sig, signed_text, plaintext);
583 }
584
585
586 /* Decrypt ciphertext CIPHER and make a signature verification within
587    CTX and store the resulting plaintext in PLAIN.  */
588 gpgme_error_t
589 gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
590                  gpgme_data_t plaintext)
591 {
592   gpgme_error_t err;
593
594   err = verify_start (ctx, 1, sig, signed_text, plaintext);
595   if (!err)
596     err = _gpgme_wait_one (ctx);
597   return err;
598 }
599
600 \f
601 /* Compatibility interfaces.  */
602
603 /* Get the key used to create signature IDX in CTX and return it in
604    R_KEY.  */
605 gpgme_error_t
606 gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
607 {
608   gpgme_verify_result_t result;
609   gpgme_signature_t sig;
610
611   result = gpgme_op_verify_result (ctx);
612   sig = result->signatures;
613
614   while (sig && idx)
615     {
616       sig = sig->next;
617       idx--;
618     }
619   if (!sig || idx)
620     return gpg_error (GPG_ERR_EOF);
621
622   return gpgme_get_key (ctx, sig->fpr, r_key, 0);
623 }
624
625
626 /* Retrieve the signature status of signature IDX in CTX after a
627    successful verify operation in R_STAT (if non-null).  The creation
628    time stamp of the signature is returned in R_CREATED (if non-null).
629    The function returns a string containing the fingerprint.  */
630 const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
631                                   _gpgme_sig_stat_t *r_stat, time_t *r_created)
632 {
633   gpgme_verify_result_t result;
634   gpgme_signature_t sig;
635
636   result = gpgme_op_verify_result (ctx);
637   sig = result->signatures;
638
639   while (sig && idx)
640     {
641       sig = sig->next;
642       idx--;
643     }
644   if (!sig || idx)
645     return NULL;
646
647   if (r_stat)
648     {
649       switch (gpg_err_code (sig->status))
650         {
651         case GPG_ERR_NO_ERROR:
652           *r_stat = GPGME_SIG_STAT_GOOD;
653           break;
654           
655         case GPG_ERR_BAD_SIGNATURE:
656           *r_stat = GPGME_SIG_STAT_BAD;
657           break;
658           
659         case GPG_ERR_NO_PUBKEY:
660           *r_stat = GPGME_SIG_STAT_NOKEY;
661           break;
662           
663         case GPG_ERR_NO_DATA:
664           *r_stat = GPGME_SIG_STAT_NOSIG;
665           break;
666           
667         case GPG_ERR_SIG_EXPIRED:
668           *r_stat = GPGME_SIG_STAT_GOOD_EXP;
669           break;
670           
671         case GPG_ERR_KEY_EXPIRED:
672           *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
673           break;
674           
675         default:
676           *r_stat = GPGME_SIG_STAT_ERROR;
677           break;
678         }
679     }
680   if (r_created)
681     *r_created = sig->timestamp;
682   return sig->fpr;
683 }
684
685
686 /* Retrieve certain attributes of a signature.  IDX is the index
687    number of the signature after a successful verify operation.  WHAT
688    is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
689    one.  WHATIDX is to be passed as 0 for most attributes . */
690 unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
691                                         _gpgme_attr_t what, int whatidx)
692 {
693   gpgme_verify_result_t result;
694   gpgme_signature_t sig;
695
696   result = gpgme_op_verify_result (ctx);
697   sig = result->signatures;
698
699   while (sig && idx)
700     {
701       sig = sig->next;
702       idx--;
703     }
704   if (!sig || idx)
705     return 0;
706
707   switch (what)
708     {
709     case GPGME_ATTR_CREATED:
710       return sig->timestamp;
711
712     case GPGME_ATTR_EXPIRE:
713       return sig->exp_timestamp;
714
715     case GPGME_ATTR_VALIDITY:
716       return (unsigned long) sig->validity;
717
718     case GPGME_ATTR_SIG_STATUS:
719       switch (gpg_err_code (sig->status))
720         {
721         case GPG_ERR_NO_ERROR:
722           return GPGME_SIG_STAT_GOOD;
723           
724         case GPG_ERR_BAD_SIGNATURE:
725           return GPGME_SIG_STAT_BAD;
726           
727         case GPG_ERR_NO_PUBKEY:
728           return GPGME_SIG_STAT_NOKEY;
729           
730         case GPG_ERR_NO_DATA:
731           return GPGME_SIG_STAT_NOSIG;
732           
733         case GPG_ERR_SIG_EXPIRED:
734           return GPGME_SIG_STAT_GOOD_EXP;
735           
736         case GPG_ERR_KEY_EXPIRED:
737           return GPGME_SIG_STAT_GOOD_EXPKEY;
738           
739         default:
740           return GPGME_SIG_STAT_ERROR;
741         }
742
743     case GPGME_ATTR_SIG_SUMMARY:
744       return sig->summary;
745
746     default:
747       break;
748     }
749   return 0;
750 }
751
752
753 const char *gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
754                                       _gpgme_attr_t what, int whatidx)
755 {
756   gpgme_verify_result_t result;
757   gpgme_signature_t sig;
758
759   result = gpgme_op_verify_result (ctx);
760   sig = result->signatures;
761
762   while (sig && idx)
763     {
764       sig = sig->next;
765       idx--;
766     }
767   if (!sig || idx)
768     return NULL;
769
770   switch (what)
771     {
772     case GPGME_ATTR_FPR:
773       return sig->fpr;
774
775     case GPGME_ATTR_ERRTOK:
776       if (whatidx == 1)
777         return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
778       else
779         return "";
780     default:
781       break;
782     }
783
784   return NULL;
785 }