doc/
[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             return err;
319
320           notation->value = NULL;
321         }
322       else
323         {
324           int len = strlen (args) + 1;
325
326           notation->name = NULL;
327           notation->value = malloc (len);
328           if (!notation->value)
329             {
330               int saved_errno = errno;
331               free (notation);
332               return gpg_error_from_errno (saved_errno);
333             }
334           err = _gpgme_decode_percent_string (args, &notation->value, len);
335           if (err)
336             return err;
337         }
338       *lastp = notation;
339     }
340   else if (code == GPGME_STATUS_NOTATION_DATA)
341     {
342       int len = strlen (args) + 1;
343       char *dest;
344
345       /* FIXME: We could keep a pointer to the last notation in the list.  */
346       while (notation && notation->next)
347         {
348           lastp = &notation->next;
349           notation = notation->next;
350         }
351
352       if (!notation || !notation->name)
353         /* There is notation data without a previous notation
354            name.  The crypto backend misbehaves.  */
355         return gpg_error (GPG_ERR_INV_ENGINE);
356       
357       if (!notation->value)
358         {
359           dest = notation->value = malloc (len);
360           if (!dest)
361             return gpg_error_from_errno (errno);
362         }
363       else
364         {
365           int cur_len = strlen (notation->value);
366           dest = realloc (notation->value, len + strlen (notation->value));
367           if (!dest)
368             return gpg_error_from_errno (errno);
369           notation->value = dest;
370           dest += cur_len;
371         }
372       
373       err = _gpgme_decode_percent_string (args, &dest, len);
374       if (err)
375         return err;
376     }
377   else
378     return gpg_error (GPG_ERR_INV_ENGINE);
379   return 0;
380 }
381
382
383 static gpgme_error_t
384 parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
385 {
386   char *end = strchr (args, ' ');
387
388   if (end)
389     *end = '\0';
390
391   switch (code)
392     {
393     case GPGME_STATUS_TRUST_UNDEFINED:
394     default:
395       sig->validity = GPGME_VALIDITY_UNKNOWN;
396       break;
397
398     case GPGME_STATUS_TRUST_NEVER:
399       sig->validity = GPGME_VALIDITY_NEVER;
400       break;
401
402     case GPGME_STATUS_TRUST_MARGINAL:
403       sig->validity = GPGME_VALIDITY_MARGINAL;
404       break;
405
406     case GPGME_STATUS_TRUST_FULLY:
407     case GPGME_STATUS_TRUST_ULTIMATE:
408       sig->validity = GPGME_VALIDITY_FULL;
409       break;
410     }
411
412   if (*args)
413     sig->validity_reason = _gpgme_map_gnupg_error (args);
414
415   return 0;
416 }
417
418
419 static gpgme_error_t
420 parse_error (gpgme_signature_t sig, char *args)
421 {
422   gpgme_error_t err;
423   char *where = strchr (args, ' ');
424   char *which;
425
426   if (where)
427     {
428       *where = '\0';
429       which = where + 1;
430
431       where = strchr (which, ' ');
432       if (where)
433         *where = '\0';
434
435       where = args;      
436     }
437   else
438     return gpg_error (GPG_ERR_INV_ENGINE);
439
440   err = _gpgme_map_gnupg_error (which);
441
442   if (!strcmp (where, "verify.findkey"))
443     sig->status = err;
444   else if (!strcmp (where, "verify.keyusage")
445            && gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
446     sig->wrong_key_usage = 1;
447
448   return 0;
449 }
450
451
452 gpgme_error_t
453 _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
454 {
455   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
456   gpgme_error_t err;
457   void *hook;
458   op_data_t opd;
459   gpgme_signature_t sig;
460
461   err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
462   opd = hook;
463   if (err)
464     return err;
465
466   sig = opd->current_sig;
467
468   switch (code)
469     {
470     case GPGME_STATUS_GOODSIG:
471     case GPGME_STATUS_EXPSIG:
472     case GPGME_STATUS_EXPKEYSIG:
473     case GPGME_STATUS_BADSIG:
474     case GPGME_STATUS_ERRSIG:
475       if (sig)
476         calc_sig_summary (sig);
477       return parse_new_sig (opd, code, args);
478
479     case GPGME_STATUS_VALIDSIG:
480       return sig ? parse_valid_sig (sig, args)
481         : gpg_error (GPG_ERR_INV_ENGINE);
482
483     case GPGME_STATUS_NODATA:
484       if (!sig)
485         return gpg_error (GPG_ERR_NO_DATA);
486       sig->status = gpg_error (GPG_ERR_NO_DATA);
487       break;
488
489     case GPGME_STATUS_UNEXPECTED:
490       if (!sig)
491         return gpg_error (GPG_ERR_GENERAL);
492       sig->status = gpg_error (GPG_ERR_NO_DATA);
493       break;
494
495     case GPGME_STATUS_NOTATION_NAME:
496     case GPGME_STATUS_NOTATION_DATA:
497     case GPGME_STATUS_POLICY_URL:
498       return sig ? parse_notation (sig, code, args)
499         : gpg_error (GPG_ERR_INV_ENGINE);
500
501     case GPGME_STATUS_TRUST_UNDEFINED:
502     case GPGME_STATUS_TRUST_NEVER:
503     case GPGME_STATUS_TRUST_MARGINAL:
504     case GPGME_STATUS_TRUST_FULLY:
505     case GPGME_STATUS_TRUST_ULTIMATE:
506       return sig ? parse_trust (sig, code, args)
507         : gpg_error (GPG_ERR_INV_ENGINE);
508
509     case GPGME_STATUS_ERROR:
510       return sig ? parse_error (sig, args) : gpg_error (GPG_ERR_INV_ENGINE);
511
512     case GPGME_STATUS_EOF:
513       if (sig)
514         calc_sig_summary (sig);
515       break;
516
517     default:
518       break;
519     }
520   return 0;
521 }
522
523
524 static gpgme_error_t
525 verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
526 {
527   return _gpgme_progress_status_handler (priv, code, args)
528     || _gpgme_verify_status_handler (priv, code, args);
529 }
530
531
532 gpgme_error_t
533 _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
534 {  
535   void *hook;
536   op_data_t opd;
537
538   return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
539                                 sizeof (*opd), release_op_data);
540 }
541
542
543 static gpgme_error_t
544 verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
545               gpgme_data_t signed_text, gpgme_data_t plaintext)
546 {
547   gpgme_error_t err;
548
549   err = _gpgme_op_reset (ctx, synchronous);
550   if (err)
551     return err;
552
553   err = _gpgme_op_verify_init_result (ctx);
554   if (err)
555     return err;
556
557   _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
558
559   if (!sig)
560     return gpg_error (GPG_ERR_NO_DATA);
561   if (!signed_text && !plaintext)
562     return gpg_error (GPG_ERR_INV_VALUE);
563
564   return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
565 }
566
567
568 /* Decrypt ciphertext CIPHER and make a signature verification within
569    CTX and store the resulting plaintext in PLAIN.  */
570 gpgme_error_t
571 gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
572                        gpgme_data_t signed_text, gpgme_data_t plaintext)
573 {
574   return verify_start (ctx, 0, sig, signed_text, plaintext);
575 }
576
577
578 /* Decrypt ciphertext CIPHER and make a signature verification within
579    CTX and store the resulting plaintext in PLAIN.  */
580 gpgme_error_t
581 gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
582                  gpgme_data_t plaintext)
583 {
584   gpgme_error_t err;
585
586   err = verify_start (ctx, 1, sig, signed_text, plaintext);
587   if (!err)
588     err = _gpgme_wait_one (ctx);
589   return err;
590 }
591
592 \f
593 /* Compatibility interfaces.  */
594
595 /* Get the key used to create signature IDX in CTX and return it in
596    R_KEY.  */
597 gpgme_error_t
598 gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
599 {
600   gpgme_verify_result_t result;
601   gpgme_signature_t sig;
602
603   result = gpgme_op_verify_result (ctx);
604   sig = result->signatures;
605
606   while (sig && idx)
607     {
608       sig = sig->next;
609       idx--;
610     }
611   if (!sig || idx)
612     return gpg_error (GPG_ERR_EOF);
613
614   return gpgme_get_key (ctx, sig->fpr, r_key, 0);
615 }
616
617
618 /* Retrieve the signature status of signature IDX in CTX after a
619    successful verify operation in R_STAT (if non-null).  The creation
620    time stamp of the signature is returned in R_CREATED (if non-null).
621    The function returns a string containing the fingerprint.  */
622 const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
623                                   _gpgme_sig_stat_t *r_stat, time_t *r_created)
624 {
625   gpgme_verify_result_t result;
626   gpgme_signature_t sig;
627
628   result = gpgme_op_verify_result (ctx);
629   sig = result->signatures;
630
631   while (sig && idx)
632     {
633       sig = sig->next;
634       idx--;
635     }
636   if (!sig || idx)
637     return NULL;
638
639   if (r_stat)
640     {
641       switch (gpg_err_code (sig->status))
642         {
643         case GPG_ERR_NO_ERROR:
644           *r_stat = GPGME_SIG_STAT_GOOD;
645           break;
646           
647         case GPG_ERR_BAD_SIGNATURE:
648           *r_stat = GPGME_SIG_STAT_BAD;
649           break;
650           
651         case GPG_ERR_NO_PUBKEY:
652           *r_stat = GPGME_SIG_STAT_NOKEY;
653           break;
654           
655         case GPG_ERR_NO_DATA:
656           *r_stat = GPGME_SIG_STAT_NOSIG;
657           break;
658           
659         case GPG_ERR_SIG_EXPIRED:
660           *r_stat = GPGME_SIG_STAT_GOOD_EXP;
661           break;
662           
663         case GPG_ERR_KEY_EXPIRED:
664           *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
665           break;
666           
667         default:
668           *r_stat = GPGME_SIG_STAT_ERROR;
669           break;
670         }
671     }
672   if (r_created)
673     *r_created = sig->timestamp;
674   return sig->fpr;
675 }
676
677
678 /* Retrieve certain attributes of a signature.  IDX is the index
679    number of the signature after a successful verify operation.  WHAT
680    is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
681    one.  WHATIDX is to be passed as 0 for most attributes . */
682 unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
683                                         _gpgme_attr_t what, int whatidx)
684 {
685   gpgme_verify_result_t result;
686   gpgme_signature_t sig;
687
688   result = gpgme_op_verify_result (ctx);
689   sig = result->signatures;
690
691   while (sig && idx)
692     {
693       sig = sig->next;
694       idx--;
695     }
696   if (!sig || idx)
697     return 0;
698
699   switch (what)
700     {
701     case GPGME_ATTR_CREATED:
702       return sig->timestamp;
703
704     case GPGME_ATTR_EXPIRE:
705       return sig->exp_timestamp;
706
707     case GPGME_ATTR_VALIDITY:
708       return (unsigned long) sig->validity;
709
710     case GPGME_ATTR_SIG_STATUS:
711       switch (gpg_err_code (sig->status))
712         {
713         case GPG_ERR_NO_ERROR:
714           return GPGME_SIG_STAT_GOOD;
715           
716         case GPG_ERR_BAD_SIGNATURE:
717           return GPGME_SIG_STAT_BAD;
718           
719         case GPG_ERR_NO_PUBKEY:
720           return GPGME_SIG_STAT_NOKEY;
721           
722         case GPG_ERR_NO_DATA:
723           return GPGME_SIG_STAT_NOSIG;
724           
725         case GPG_ERR_SIG_EXPIRED:
726           return GPGME_SIG_STAT_GOOD_EXP;
727           
728         case GPG_ERR_KEY_EXPIRED:
729           return GPGME_SIG_STAT_GOOD_EXPKEY;
730           
731         default:
732           return GPGME_SIG_STAT_ERROR;
733         }
734
735     case GPGME_ATTR_SIG_SUMMARY:
736       return sig->summary;
737
738     default:
739       break;
740     }
741   return 0;
742 }
743
744
745 const char *gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
746                                       _gpgme_attr_t what, int whatidx)
747 {
748   gpgme_verify_result_t result;
749   gpgme_signature_t sig;
750
751   result = gpgme_op_verify_result (ctx);
752   sig = result->signatures;
753
754   while (sig && idx)
755     {
756       sig = sig->next;
757       idx--;
758     }
759   if (!sig || idx)
760     return NULL;
761
762   switch (what)
763     {
764     case GPGME_ATTR_FPR:
765       return sig->fpr;
766
767     case GPGME_ATTR_ERRTOK:
768       if (whatidx == 1)
769         return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
770       else
771         return "";
772     default:
773       break;
774     }
775
776   return NULL;
777 }