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