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