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             {
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   gpgme_error_t err;
536
537   err = _gpgme_progress_status_handler (priv, code, args);
538   if (!err)
539     err = _gpgme_verify_status_handler (priv, code, args);
540   return err;
541 }
542
543
544 gpgme_error_t
545 _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
546 {  
547   void *hook;
548   op_data_t opd;
549
550   return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
551                                 sizeof (*opd), release_op_data);
552 }
553
554
555 static gpgme_error_t
556 verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
557               gpgme_data_t signed_text, gpgme_data_t plaintext)
558 {
559   gpgme_error_t err;
560
561   err = _gpgme_op_reset (ctx, synchronous);
562   if (err)
563     return err;
564
565   err = _gpgme_op_verify_init_result (ctx);
566   if (err)
567     return err;
568
569   _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
570
571   if (!sig)
572     return gpg_error (GPG_ERR_NO_DATA);
573   if (!signed_text && !plaintext)
574     return gpg_error (GPG_ERR_INV_VALUE);
575
576   return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
577 }
578
579
580 /* Decrypt ciphertext CIPHER and make a signature verification within
581    CTX and store the resulting plaintext in PLAIN.  */
582 gpgme_error_t
583 gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
584                        gpgme_data_t signed_text, gpgme_data_t plaintext)
585 {
586   return verify_start (ctx, 0, sig, signed_text, plaintext);
587 }
588
589
590 /* Decrypt ciphertext CIPHER and make a signature verification within
591    CTX and store the resulting plaintext in PLAIN.  */
592 gpgme_error_t
593 gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
594                  gpgme_data_t plaintext)
595 {
596   gpgme_error_t err;
597
598   err = verify_start (ctx, 1, sig, signed_text, plaintext);
599   if (!err)
600     err = _gpgme_wait_one (ctx);
601   return err;
602 }
603
604 \f
605 /* Compatibility interfaces.  */
606
607 /* Get the key used to create signature IDX in CTX and return it in
608    R_KEY.  */
609 gpgme_error_t
610 gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
611 {
612   gpgme_verify_result_t result;
613   gpgme_signature_t sig;
614
615   result = gpgme_op_verify_result (ctx);
616   sig = result->signatures;
617
618   while (sig && idx)
619     {
620       sig = sig->next;
621       idx--;
622     }
623   if (!sig || idx)
624     return gpg_error (GPG_ERR_EOF);
625
626   return gpgme_get_key (ctx, sig->fpr, r_key, 0);
627 }
628
629
630 /* Retrieve the signature status of signature IDX in CTX after a
631    successful verify operation in R_STAT (if non-null).  The creation
632    time stamp of the signature is returned in R_CREATED (if non-null).
633    The function returns a string containing the fingerprint.  */
634 const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
635                                   _gpgme_sig_stat_t *r_stat, time_t *r_created)
636 {
637   gpgme_verify_result_t result;
638   gpgme_signature_t sig;
639
640   result = gpgme_op_verify_result (ctx);
641   sig = result->signatures;
642
643   while (sig && idx)
644     {
645       sig = sig->next;
646       idx--;
647     }
648   if (!sig || idx)
649     return NULL;
650
651   if (r_stat)
652     {
653       switch (gpg_err_code (sig->status))
654         {
655         case GPG_ERR_NO_ERROR:
656           *r_stat = GPGME_SIG_STAT_GOOD;
657           break;
658           
659         case GPG_ERR_BAD_SIGNATURE:
660           *r_stat = GPGME_SIG_STAT_BAD;
661           break;
662           
663         case GPG_ERR_NO_PUBKEY:
664           *r_stat = GPGME_SIG_STAT_NOKEY;
665           break;
666           
667         case GPG_ERR_NO_DATA:
668           *r_stat = GPGME_SIG_STAT_NOSIG;
669           break;
670           
671         case GPG_ERR_SIG_EXPIRED:
672           *r_stat = GPGME_SIG_STAT_GOOD_EXP;
673           break;
674           
675         case GPG_ERR_KEY_EXPIRED:
676           *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
677           break;
678           
679         default:
680           *r_stat = GPGME_SIG_STAT_ERROR;
681           break;
682         }
683     }
684   if (r_created)
685     *r_created = sig->timestamp;
686   return sig->fpr;
687 }
688
689
690 /* Retrieve certain attributes of a signature.  IDX is the index
691    number of the signature after a successful verify operation.  WHAT
692    is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
693    one.  WHATIDX is to be passed as 0 for most attributes . */
694 unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
695                                         _gpgme_attr_t what, int whatidx)
696 {
697   gpgme_verify_result_t result;
698   gpgme_signature_t sig;
699
700   result = gpgme_op_verify_result (ctx);
701   sig = result->signatures;
702
703   while (sig && idx)
704     {
705       sig = sig->next;
706       idx--;
707     }
708   if (!sig || idx)
709     return 0;
710
711   switch (what)
712     {
713     case GPGME_ATTR_CREATED:
714       return sig->timestamp;
715
716     case GPGME_ATTR_EXPIRE:
717       return sig->exp_timestamp;
718
719     case GPGME_ATTR_VALIDITY:
720       return (unsigned long) sig->validity;
721
722     case GPGME_ATTR_SIG_STATUS:
723       switch (gpg_err_code (sig->status))
724         {
725         case GPG_ERR_NO_ERROR:
726           return GPGME_SIG_STAT_GOOD;
727           
728         case GPG_ERR_BAD_SIGNATURE:
729           return GPGME_SIG_STAT_BAD;
730           
731         case GPG_ERR_NO_PUBKEY:
732           return GPGME_SIG_STAT_NOKEY;
733           
734         case GPG_ERR_NO_DATA:
735           return GPGME_SIG_STAT_NOSIG;
736           
737         case GPG_ERR_SIG_EXPIRED:
738           return GPGME_SIG_STAT_GOOD_EXP;
739           
740         case GPG_ERR_KEY_EXPIRED:
741           return GPGME_SIG_STAT_GOOD_EXPKEY;
742           
743         default:
744           return GPGME_SIG_STAT_ERROR;
745         }
746
747     case GPGME_ATTR_SIG_SUMMARY:
748       return sig->summary;
749
750     default:
751       break;
752     }
753   return 0;
754 }
755
756
757 const char *gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
758                                       _gpgme_attr_t what, int whatidx)
759 {
760   gpgme_verify_result_t result;
761   gpgme_signature_t sig;
762
763   result = gpgme_op_verify_result (ctx);
764   sig = result->signatures;
765
766   while (sig && idx)
767     {
768       sig = sig->next;
769       idx--;
770     }
771   if (!sig || idx)
772     return NULL;
773
774   switch (what)
775     {
776     case GPGME_ATTR_FPR:
777       return sig->fpr;
778
779     case GPGME_ATTR_ERRTOK:
780       if (whatidx == 1)
781         return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
782       else
783         return "";
784     default:
785       break;
786     }
787
788   return NULL;
789 }