core: Add 'is_mime' flags to the verify and decrypt results.
[gpgme.git] / src / verify.c
1 /* verify.c - Signature verification.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2005 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 Lesser General Public License as
9    published by the Free Software Foundation; either version 2.1 of
10    the License, or (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    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <assert.h>
29 #include <limits.h>
30
31 #include "gpgme.h"
32 #include "debug.h"
33 #include "util.h"
34 #include "context.h"
35 #include "ops.h"
36
37 \f
38 typedef struct
39 {
40   struct _gpgme_op_verify_result result;
41
42   /* The error code from a FAILURE status line or 0.  */
43   gpg_error_t failure_code;
44
45   gpgme_signature_t current_sig;
46   int did_prepare_new_sig;
47   int only_newsig_seen;
48   int plaintext_seen;
49   int conflict_user_seen;
50 } *op_data_t;
51
52
53 static void
54 release_op_data (void *hook)
55 {
56   op_data_t opd = (op_data_t) hook;
57   gpgme_signature_t sig = opd->result.signatures;
58
59   while (sig)
60     {
61       gpgme_signature_t next = sig->next;
62       gpgme_sig_notation_t notation = sig->notations;
63
64       while (notation)
65         {
66           gpgme_sig_notation_t next_nota = notation->next;
67
68           _gpgme_sig_notation_free (notation);
69           notation = next_nota;
70         }
71
72       if (sig->fpr)
73         free (sig->fpr);
74       if (sig->pka_address)
75         free (sig->pka_address);
76       if (sig->key)
77         gpgme_key_unref (sig->key);
78       free (sig);
79       sig = next;
80     }
81
82   if (opd->result.file_name)
83     free (opd->result.file_name);
84 }
85
86
87 gpgme_verify_result_t
88 gpgme_op_verify_result (gpgme_ctx_t ctx)
89 {
90   void *hook;
91   op_data_t opd;
92   gpgme_error_t err;
93   gpgme_signature_t sig;
94
95   TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_result", ctx);
96   err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
97   opd = hook;
98   if (err || !opd)
99     {
100       TRACE_SUC0 ("result=(null)");
101       return NULL;
102     }
103
104   /* It is possible that we saw a new signature only followed by an
105      ERROR line for that.  In particular a missing X.509 key triggers
106      this.  In this case it is surprising that the summary field has
107      not been updated.  We fix it here by explicitly looking for this
108      case.  The real fix would be to have GPGME emit ERRSIG.  */
109   for (sig = opd->result.signatures; sig; sig = sig->next)
110     {
111       if (!sig->summary)
112         {
113           switch (gpg_err_code (sig->status))
114             {
115             case GPG_ERR_KEY_EXPIRED:
116               sig->summary |= GPGME_SIGSUM_KEY_EXPIRED;
117               break;
118
119             case GPG_ERR_NO_PUBKEY:
120               sig->summary |= GPGME_SIGSUM_KEY_MISSING;
121               break;
122
123             default:
124               break;
125             }
126         }
127     }
128
129   /* Now for some tracing stuff. */
130   if (_gpgme_debug_trace ())
131     {
132       int i;
133
134       for (sig = opd->result.signatures, i = 0; sig; sig = sig->next, i++)
135         {
136           TRACE_LOG4 ("sig[%i] = fpr %s, summary 0x%x, status %s",
137                       i, sig->fpr, sig->summary, gpg_strerror (sig->status));
138           TRACE_LOG6 ("sig[%i] = timestamps 0x%x/0x%x flags:%s%s%s",
139                       i, sig->timestamp, sig->exp_timestamp,
140                       sig->wrong_key_usage ? "wrong key usage" : "",
141                       sig->pka_trust == 1 ? "pka bad"
142                       : (sig->pka_trust == 2 ? "pka_okay" : "pka RFU"),
143                       sig->chain_model ? "chain model" : "");
144           TRACE_LOG5 ("sig[%i] = validity 0x%x (%s), algos %s/%s",
145                       i, sig->validity, gpg_strerror (sig->validity_reason),
146                       gpgme_pubkey_algo_name (sig->pubkey_algo),
147                       gpgme_hash_algo_name (sig->hash_algo));
148           if (sig->pka_address)
149             {
150               TRACE_LOG2 ("sig[%i] = PKA address %s", i, sig->pka_address);
151             }
152           if (sig->notations)
153             {
154               TRACE_LOG1 ("sig[%i] = has notations (not shown)", i);
155             }
156         }
157     }
158
159   TRACE_SUC1 ("result=%p", &opd->result);
160   return &opd->result;
161 }
162
163 \f
164 /* Build a summary vector from RESULT. */
165 static void
166 calc_sig_summary (gpgme_signature_t sig)
167 {
168   unsigned long sum = 0;
169
170   /* Calculate the red/green flag.  */
171   if (sig->validity == GPGME_VALIDITY_FULL
172       || sig->validity == GPGME_VALIDITY_ULTIMATE)
173     {
174       if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
175           || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
176           || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
177         sum |= GPGME_SIGSUM_GREEN;
178     }
179   else if (sig->validity == GPGME_VALIDITY_NEVER)
180     {
181       if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
182           || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
183           || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
184         sum |= GPGME_SIGSUM_RED;
185     }
186   else if (gpg_err_code (sig->status) == GPG_ERR_BAD_SIGNATURE)
187     sum |= GPGME_SIGSUM_RED;
188
189
190   /* FIXME: handle the case when key and message are expired. */
191   switch (gpg_err_code (sig->status))
192     {
193     case GPG_ERR_SIG_EXPIRED:
194       sum |= GPGME_SIGSUM_SIG_EXPIRED;
195       break;
196
197     case GPG_ERR_KEY_EXPIRED:
198       sum |= GPGME_SIGSUM_KEY_EXPIRED;
199       break;
200
201     case GPG_ERR_NO_PUBKEY:
202       sum |= GPGME_SIGSUM_KEY_MISSING;
203       break;
204
205     case GPG_ERR_CERT_REVOKED:
206       sum |= GPGME_SIGSUM_KEY_REVOKED;
207       break;
208
209     case GPG_ERR_BAD_SIGNATURE:
210     case GPG_ERR_NO_ERROR:
211       break;
212
213     default:
214       sum |= GPGME_SIGSUM_SYS_ERROR;
215       break;
216     }
217
218   /* Now look at the certain reason codes.  */
219   switch (gpg_err_code (sig->validity_reason))
220     {
221     case GPG_ERR_CRL_TOO_OLD:
222       if (sig->validity == GPGME_VALIDITY_UNKNOWN)
223         sum |= GPGME_SIGSUM_CRL_TOO_OLD;
224       break;
225
226     case GPG_ERR_CERT_REVOKED:
227       /* Note that this is a second way to set this flag.  It may also
228          have been set due to a sig->status of STATUS_REVKEYSIG from
229          parse_new_sig.  */
230       sum |= GPGME_SIGSUM_KEY_REVOKED;
231       break;
232
233     default:
234       break;
235     }
236
237   /* Check other flags. */
238   if (sig->wrong_key_usage)
239     sum |= GPGME_SIGSUM_BAD_POLICY;
240
241   /* Set the valid flag when the signature is unquestionable
242      valid.  (The test is identical to if(sum == GPGME_SIGSUM_GREEN)). */
243   if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
244     sum |= GPGME_SIGSUM_VALID;
245
246   sig->summary = sum;
247 }
248
249
250 static gpgme_error_t
251 prepare_new_sig (op_data_t opd)
252 {
253   gpgme_signature_t sig;
254
255   if (opd->only_newsig_seen && opd->current_sig)
256     {
257       /* We have only seen the NEWSIG status and nothing else - we
258          better skip this signature therefore and reuse it for the
259          next possible signature. */
260       sig = opd->current_sig;
261       memset (sig, 0, sizeof *sig);
262       assert (opd->result.signatures == sig);
263     }
264   else
265     {
266       sig = calloc (1, sizeof (*sig));
267       if (!sig)
268         return gpg_error_from_syserror ();
269       if (!opd->result.signatures)
270         opd->result.signatures = sig;
271       if (opd->current_sig)
272         opd->current_sig->next = sig;
273       opd->current_sig = sig;
274     }
275   opd->did_prepare_new_sig = 1;
276   opd->only_newsig_seen = 0;
277   return 0;
278 }
279
280 static gpgme_error_t
281 parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args,
282                gpgme_protocol_t protocol)
283 {
284   gpgme_signature_t sig;
285   char *end = strchr (args, ' ');
286   char *tail;
287   int got_fpr = 0;
288
289   if (end)
290     {
291       *end = '\0';
292       end++;
293     }
294
295   if (!opd->did_prepare_new_sig)
296     {
297       gpg_error_t err;
298
299       err = prepare_new_sig (opd);
300       if (err)
301         return err;
302     }
303   assert (opd->did_prepare_new_sig);
304   opd->did_prepare_new_sig = 0;
305
306   assert (opd->current_sig);
307   sig = opd->current_sig;
308
309   /* FIXME: We should set the source of the state.  */
310   switch (code)
311     {
312     case GPGME_STATUS_GOODSIG:
313       sig->status = gpg_error (GPG_ERR_NO_ERROR);
314       break;
315
316     case GPGME_STATUS_EXPSIG:
317       sig->status = gpg_error (GPG_ERR_SIG_EXPIRED);
318       break;
319
320     case GPGME_STATUS_EXPKEYSIG:
321       sig->status = gpg_error (GPG_ERR_KEY_EXPIRED);
322       break;
323
324     case GPGME_STATUS_BADSIG:
325       sig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
326       break;
327
328     case GPGME_STATUS_REVKEYSIG:
329       sig->status = gpg_error (GPG_ERR_CERT_REVOKED);
330       break;
331
332     case GPGME_STATUS_ERRSIG:
333       /* Parse the pubkey algo.  */
334       if (!end)
335         goto parse_err_sig_fail;
336       gpg_err_set_errno (0);
337       sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0), protocol);
338       if (errno || end == tail || *tail != ' ')
339         goto parse_err_sig_fail;
340       end = tail;
341       while (*end == ' ')
342         end++;
343
344       /* Parse the hash algo.  */
345       if (!*end)
346         goto parse_err_sig_fail;
347       gpg_err_set_errno (0);
348       sig->hash_algo = strtol (end, &tail, 0);
349       if (errno || end == tail || *tail != ' ')
350         goto parse_err_sig_fail;
351       end = tail;
352       while (*end == ' ')
353         end++;
354
355       /* Skip the sig class.  */
356       end = strchr (end, ' ');
357       if (!end)
358         goto parse_err_sig_fail;
359       while (*end == ' ')
360         end++;
361
362       /* Parse the timestamp.  */
363       sig->timestamp = _gpgme_parse_timestamp (end, &tail);
364       if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
365         return trace_gpg_error (GPG_ERR_INV_ENGINE);
366       end = tail;
367       while (*end == ' ')
368         end++;
369
370       /* Parse the return code.  */
371       if (!*end)
372         goto parse_err_sig_fail;
373
374       gpg_err_set_errno (0);
375       sig->status = strtoul (end, &tail, 10);
376       if (errno || end == tail || (*tail && *tail != ' '))
377         goto parse_err_sig_fail;
378       if (!*tail)
379         goto parse_err_sig_ok;
380       end = tail;
381       while (*end == ' ')
382         end++;
383
384       /* Parse the new fingerprint (from the ISSUER_FPR subpacket).  */
385       if (!*end || (*end == '-' && (end[1] == ' ' || !end[1])))
386         goto parse_err_sig_ok;  /* Okay (just trailing spaces).  */
387       sig->fpr = strdup (end);
388       if (!sig->fpr)
389         return gpg_error_from_syserror ();
390       got_fpr = 1;
391       goto parse_err_sig_ok;
392
393     parse_err_sig_fail:
394       sig->status = gpg_error (GPG_ERR_GENERAL);
395     parse_err_sig_ok:
396       break;
397
398     default:
399       return gpg_error (GPG_ERR_GENERAL);
400     }
401
402   if (*args && !got_fpr)
403     {
404       sig->fpr = strdup (args);
405       if (!sig->fpr)
406         return gpg_error_from_syserror ();
407     }
408   return 0;
409 }
410
411
412 static gpgme_error_t
413 parse_valid_sig (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol)
414 {
415   char *end = strchr (args, ' ');
416   if (end)
417     {
418       *end = '\0';
419       end++;
420     }
421
422   if (!*args)
423     /* We require at least the fingerprint.  */
424     return gpg_error (GPG_ERR_GENERAL);
425
426   if (sig->fpr)
427     free (sig->fpr);
428   sig->fpr = strdup (args);
429   if (!sig->fpr)
430     return gpg_error_from_syserror ();
431
432   /* Skip the creation date.  */
433   end = strchr (end, ' ');
434   if (end)
435     {
436       char *tail;
437
438       sig->timestamp = _gpgme_parse_timestamp (end, &tail);
439       if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
440         return trace_gpg_error (GPG_ERR_INV_ENGINE);
441       end = tail;
442
443       sig->exp_timestamp = _gpgme_parse_timestamp (end, &tail);
444       if (sig->exp_timestamp == -1 || end == tail || (*tail && *tail != ' '))
445         return trace_gpg_error (GPG_ERR_INV_ENGINE);
446       end = tail;
447
448       while (*end == ' ')
449         end++;
450       /* Skip the signature version.  */
451       end = strchr (end, ' ');
452       if (end)
453         {
454           while (*end == ' ')
455             end++;
456
457           /* Skip the reserved field.  */
458           end = strchr (end, ' ');
459           if (end)
460             {
461               /* Parse the pubkey algo.  */
462               gpg_err_set_errno (0);
463               sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0),
464                                                      protocol);
465               if (errno || end == tail || *tail != ' ')
466                 return trace_gpg_error (GPG_ERR_INV_ENGINE);
467               end = tail;
468
469               while (*end == ' ')
470                 end++;
471
472               if (*end)
473                 {
474                   /* Parse the hash algo.  */
475
476                   gpg_err_set_errno (0);
477                   sig->hash_algo = strtol (end, &tail, 0);
478                   if (errno || end == tail || *tail != ' ')
479                     return trace_gpg_error (GPG_ERR_INV_ENGINE);
480                   end = tail;
481                 }
482             }
483         }
484     }
485   return 0;
486 }
487
488
489 static gpgme_error_t
490 parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
491 {
492   gpgme_error_t err;
493   gpgme_sig_notation_t *lastp = &sig->notations;
494   gpgme_sig_notation_t notation = sig->notations;
495   char *p;
496
497   if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
498     {
499       p = strchr (args, ' ');
500       if (p)
501         *p = '\0';
502
503       /* FIXME: We could keep a pointer to the last notation in the list.  */
504       while (notation && notation->value)
505         {
506           lastp = &notation->next;
507           notation = notation->next;
508         }
509
510       if (notation)
511         /* There is another notation name without data for the
512            previous one.  The crypto backend misbehaves.  */
513         return trace_gpg_error (GPG_ERR_INV_ENGINE);
514
515       err = _gpgme_sig_notation_create (&notation, NULL, 0, NULL, 0, 0);
516       if (err)
517         return err;
518
519       if (code == GPGME_STATUS_NOTATION_NAME)
520         {
521           err = _gpgme_decode_percent_string (args, &notation->name, 0, 0);
522           if (err)
523             {
524               _gpgme_sig_notation_free (notation);
525               return err;
526             }
527
528           notation->name_len = strlen (notation->name);
529
530           /* Set default flags for use with older gpg versions which
531            * do not emit a NOTATIONS_FLAG line.  */
532           notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE;
533           notation->human_readable = 1;
534         }
535       else
536         {
537           /* This is a policy URL.  */
538
539           err = _gpgme_decode_percent_string (args, &notation->value, 0, 0);
540           if (err)
541             {
542               _gpgme_sig_notation_free (notation);
543               return err;
544             }
545
546           notation->value_len = strlen (notation->value);
547         }
548       *lastp = notation;
549     }
550   else if (code == GPGME_STATUS_NOTATION_FLAGS)
551     {
552       char *field[2];
553
554       while (notation && notation->next)
555         {
556           lastp = &notation->next;
557           notation = notation->next;
558         }
559
560       if (!notation || !notation->name)
561         { /* There are notation flags without a previous notation name.
562            * The crypto backend misbehaves.  */
563           return trace_gpg_error (GPG_ERR_INV_ENGINE);
564         }
565       if (_gpgme_split_fields (args, field, DIM (field)) < 2)
566         { /* Required args missing.  */
567           return trace_gpg_error (GPG_ERR_INV_ENGINE);
568         }
569       notation->flags = 0;
570       if (atoi (field[0]))
571         {
572           notation->flags |= GPGME_SIG_NOTATION_CRITICAL;
573           notation->critical = 1;
574         }
575       if (atoi (field[1]))
576         {
577           notation->flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
578           notation->human_readable = 1;
579         }
580     }
581   else if (code == GPGME_STATUS_NOTATION_DATA)
582     {
583       int len = strlen (args) + 1;
584       char *dest;
585
586       /* FIXME: We could keep a pointer to the last notation in the list.  */
587       while (notation && notation->next)
588         {
589           lastp = &notation->next;
590           notation = notation->next;
591         }
592
593       if (!notation || !notation->name)
594         /* There is notation data without a previous notation
595            name.  The crypto backend misbehaves.  */
596         return trace_gpg_error (GPG_ERR_INV_ENGINE);
597
598       if (!notation->value)
599         {
600           dest = notation->value = malloc (len);
601           if (!dest)
602             return gpg_error_from_syserror ();
603         }
604       else
605         {
606           int cur_len = strlen (notation->value);
607           dest = realloc (notation->value, len + strlen (notation->value));
608           if (!dest)
609             return gpg_error_from_syserror ();
610           notation->value = dest;
611           dest += cur_len;
612         }
613
614       err = _gpgme_decode_percent_string (args, &dest, len, 0);
615       if (err)
616         return err;
617
618       notation->value_len += strlen (dest);
619     }
620   else
621     return trace_gpg_error (GPG_ERR_INV_ENGINE);
622   return 0;
623 }
624
625
626 static gpgme_error_t
627 parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
628 {
629   char *end = strchr (args, ' ');
630
631   if (end)
632     *end = '\0';
633
634   switch (code)
635     {
636     case GPGME_STATUS_TRUST_UNDEFINED:
637     default:
638       sig->validity = GPGME_VALIDITY_UNKNOWN;
639       break;
640
641     case GPGME_STATUS_TRUST_NEVER:
642       sig->validity = GPGME_VALIDITY_NEVER;
643       break;
644
645     case GPGME_STATUS_TRUST_MARGINAL:
646       sig->validity = GPGME_VALIDITY_MARGINAL;
647       break;
648
649     case GPGME_STATUS_TRUST_FULLY:
650     case GPGME_STATUS_TRUST_ULTIMATE:
651       sig->validity = GPGME_VALIDITY_FULL;
652       break;
653     }
654
655   sig->validity_reason = 0;
656   sig->chain_model = 0;
657   if (*args)
658     {
659       sig->validity_reason = atoi (args);
660       while (*args && *args != ' ')
661         args++;
662       if (*args)
663         {
664           while (*args == ' ')
665             args++;
666           if (!strncmp (args, "chain", 2) && (args[2] == ' ' || !args[2]))
667             sig->chain_model = 1;
668         }
669     }
670
671   return 0;
672 }
673
674
675 /* Parse a TOFU_USER line and put the info into SIG.  */
676 static gpgme_error_t
677 parse_tofu_user (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol)
678 {
679   gpg_error_t err;
680   char *tail;
681   gpgme_user_id_t uid;
682   gpgme_tofu_info_t ti;
683   char *fpr = NULL;
684   char *address = NULL;
685
686   tail = strchr (args, ' ');
687   if (!tail || tail == args)
688     {
689       err = trace_gpg_error (GPG_ERR_INV_ENGINE);  /* No fingerprint.  */
690       goto leave;
691     }
692   *tail++ = 0;
693
694   fpr = strdup (args);
695   if (!fpr)
696     {
697       err = gpg_error_from_syserror ();
698       goto leave;
699     }
700
701   if (sig->key && sig->key->fpr && strcmp (sig->key->fpr, fpr))
702     {
703       /* GnuPG since 2.1.17 emits multiple TOFU_USER lines with
704          different fingerprints in case of conflicts for a signature. */
705       err = gpg_error (GPG_ERR_DUP_VALUE);
706       goto leave;
707     }
708
709   args = tail;
710   tail = strchr (args, ' ');
711   if (tail == args)
712     {
713       err = trace_gpg_error (GPG_ERR_INV_ENGINE);  /* No addr-spec.  */
714       goto leave;
715     }
716   if (tail)
717     *tail = 0;
718
719   err = _gpgme_decode_percent_string (args, &address, 0, 0);
720   if (err)
721     goto leave;
722
723   if (!sig->key)
724     {
725       err = _gpgme_key_new (&sig->key);
726       if (err)
727         goto leave;
728       sig->key->fpr = fpr;
729       sig->key->protocol = protocol;
730       fpr = NULL;
731     }
732   else if (!sig->key->fpr)
733     {
734       err = trace_gpg_error (GPG_ERR_INTERNAL);
735       goto leave;
736     }
737
738   err = _gpgme_key_append_name (sig->key, address, 0);
739   if (err)
740     goto leave;
741
742   uid = sig->key->_last_uid;
743   assert (uid);
744
745   ti = calloc (1, sizeof *ti);
746   if (!ti)
747     {
748       err = gpg_error_from_syserror ();
749       goto leave;
750     }
751   uid->tofu = ti;
752
753
754  leave:
755   free (fpr);
756   free (address);
757   return err;
758 }
759
760
761 /* Parse a TOFU_STATS line and store it in the last tofu info of SIG.
762  *
763  *   TOFU_STATS <validity> <sign-count> <encr-count> \
764  *                         [<policy> [<tm1> <tm2> <tm3> <tm4>]]
765  */
766 static gpgme_error_t
767 parse_tofu_stats (gpgme_signature_t sig, char *args)
768 {
769   gpgme_error_t err;
770   gpgme_tofu_info_t ti;
771   char *field[8];
772   int nfields;
773   unsigned long uval;
774
775   if (!sig->key || !sig->key->_last_uid || !(ti = sig->key->_last_uid->tofu))
776     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen.  */
777   if (ti->signfirst || ti->signcount || ti->validity || ti->policy)
778     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already set.  */
779
780   nfields = _gpgme_split_fields (args, field, DIM (field));
781   if (nfields < 3)
782     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required args missing.  */
783
784   /* Note that we allow a value of up to 7 which is what we can store
785    * in the ti->validity.  */
786   err = _gpgme_strtoul_field (field[0], &uval);
787   if (err || uval > 7)
788     return trace_gpg_error (GPG_ERR_INV_ENGINE);
789   ti->validity = uval;
790
791   /* Parse the sign-count.  */
792   err = _gpgme_strtoul_field (field[1], &uval);
793   if (err)
794     return trace_gpg_error (GPG_ERR_INV_ENGINE);
795   if (uval > USHRT_MAX)
796     uval = USHRT_MAX;
797   ti->signcount = uval;
798
799   /* Parse the encr-count.  */
800   err = _gpgme_strtoul_field (field[2], &uval);
801   if (err)
802     return trace_gpg_error (GPG_ERR_INV_ENGINE);
803   if (uval > USHRT_MAX)
804     uval = USHRT_MAX;
805   ti->encrcount = uval;
806
807   if (nfields == 3)
808     return 0; /* All mandatory fields parsed.  */
809
810   /* Parse the policy.  */
811   if (!strcmp (field[3], "none"))
812     ti->policy = GPGME_TOFU_POLICY_NONE;
813   else if (!strcmp (field[3], "auto"))
814     ti->policy = GPGME_TOFU_POLICY_AUTO;
815   else if (!strcmp (field[3], "good"))
816     ti->policy = GPGME_TOFU_POLICY_GOOD;
817   else if (!strcmp (field[3], "bad"))
818     ti->policy = GPGME_TOFU_POLICY_BAD;
819   else if (!strcmp (field[3], "ask"))
820     ti->policy = GPGME_TOFU_POLICY_ASK;
821   else /* "unknown" and invalid policy strings.  */
822     ti->policy = GPGME_TOFU_POLICY_UNKNOWN;
823
824   if (nfields == 4)
825     return 0; /* No more optional fields.  */
826
827   /* Parse first and last seen timestamps (none or both are required).  */
828   if (nfields < 6)
829     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* "tm2" missing.  */
830   err = _gpgme_strtoul_field (field[4], &uval);
831   if (err)
832     return trace_gpg_error (GPG_ERR_INV_ENGINE);
833   ti->signfirst = uval;
834   err = _gpgme_strtoul_field (field[5], &uval);
835   if (err)
836     return trace_gpg_error (GPG_ERR_INV_ENGINE);
837   ti->signlast = uval;
838   if (nfields > 7)
839     {
840       /* This condition is only to allow for gpg 2.1.15 - can
841        * eventually be removed.  */
842       err = _gpgme_strtoul_field (field[6], &uval);
843       if (err)
844         return trace_gpg_error (GPG_ERR_INV_ENGINE);
845       ti->encrfirst = uval;
846       err = _gpgme_strtoul_field (field[7], &uval);
847       if (err)
848         return trace_gpg_error (GPG_ERR_INV_ENGINE);
849       ti->encrlast = uval;
850     }
851
852   return 0;
853 }
854
855
856 /* Parse a TOFU_STATS_LONG line and store it in the last tofu info of SIG.  */
857 static gpgme_error_t
858 parse_tofu_stats_long (gpgme_signature_t sig, char *args, int raw)
859 {
860   gpgme_error_t err;
861   gpgme_tofu_info_t ti;
862   char *p;
863
864   if (!sig->key || !sig->key->_last_uid || !(ti = sig->key->_last_uid->tofu))
865     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen.  */
866   if (ti->description)
867     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already set.  */
868
869   err = _gpgme_decode_percent_string (args, &ti->description, 0, 0);
870   if (err)
871     return err;
872
873   /* Remove the non-breaking spaces.  */
874   if (!raw)
875     {
876       for (p = ti->description; *p; p++)
877         if (*p == '~')
878           *p = ' ';
879     }
880   return 0;
881 }
882
883
884 /* Parse an error status line and if SET_STATUS is true update the
885    result status as appropriate.  With SET_STATUS being false, only
886    check for an error.  */
887 static gpgme_error_t
888 parse_error (gpgme_signature_t sig, char *args, int set_status)
889 {
890   gpgme_error_t err;
891   char *where = strchr (args, ' ');
892   char *which;
893
894   if (where)
895     {
896       *where = '\0';
897       which = where + 1;
898
899       where = strchr (which, ' ');
900       if (where)
901         *where = '\0';
902
903       where = args;
904     }
905   else
906     return trace_gpg_error (GPG_ERR_INV_ENGINE);
907
908   err = atoi (which);
909
910   if (!strcmp (where, "proc_pkt.plaintext")
911       && gpg_err_code (err) == GPG_ERR_BAD_DATA)
912     {
913       /* This indicates a double plaintext.  The only solid way to
914          handle this is by failing the oepration.  */
915       return gpg_error (GPG_ERR_BAD_DATA);
916     }
917   else if (!set_status)
918     ;
919   else if (!strcmp (where, "verify.findkey"))
920     sig->status = err;
921   else if (!strcmp (where, "verify.keyusage")
922            && gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
923     sig->wrong_key_usage = 1;
924
925   return 0;
926 }
927
928
929 gpgme_error_t
930 _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
931 {
932   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
933   gpgme_error_t err;
934   void *hook;
935   op_data_t opd;
936   gpgme_signature_t sig;
937   char *end;
938
939   err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
940   opd = hook;
941   if (err)
942     return err;
943
944   sig = opd->current_sig;
945
946   switch (code)
947     {
948     case GPGME_STATUS_NEWSIG:
949       if (sig)
950         calc_sig_summary (sig);
951       err = prepare_new_sig (opd);
952       opd->only_newsig_seen = 1;
953       opd->conflict_user_seen = 0;
954       return err;
955
956     case GPGME_STATUS_GOODSIG:
957     case GPGME_STATUS_EXPSIG:
958     case GPGME_STATUS_EXPKEYSIG:
959     case GPGME_STATUS_BADSIG:
960     case GPGME_STATUS_ERRSIG:
961     case GPGME_STATUS_REVKEYSIG:
962       if (sig && !opd->did_prepare_new_sig)
963         calc_sig_summary (sig);
964       opd->only_newsig_seen = 0;
965       return parse_new_sig (opd, code, args, ctx->protocol);
966
967     case GPGME_STATUS_VALIDSIG:
968       opd->only_newsig_seen = 0;
969       return sig ? parse_valid_sig (sig, args, ctx->protocol)
970         : trace_gpg_error (GPG_ERR_INV_ENGINE);
971
972     case GPGME_STATUS_NODATA:
973       opd->only_newsig_seen = 0;
974       if (!sig)
975         return gpg_error (GPG_ERR_NO_DATA);
976       sig->status = gpg_error (GPG_ERR_NO_DATA);
977       break;
978
979     case GPGME_STATUS_UNEXPECTED:
980       opd->only_newsig_seen = 0;
981       if (!sig)
982         return gpg_error (GPG_ERR_GENERAL);
983       sig->status = gpg_error (GPG_ERR_NO_DATA);
984       break;
985
986     case GPGME_STATUS_NOTATION_NAME:
987     case GPGME_STATUS_NOTATION_FLAGS:
988     case GPGME_STATUS_NOTATION_DATA:
989     case GPGME_STATUS_POLICY_URL:
990       opd->only_newsig_seen = 0;
991       return sig ? parse_notation (sig, code, args)
992         : trace_gpg_error (GPG_ERR_INV_ENGINE);
993
994     case GPGME_STATUS_TRUST_UNDEFINED:
995     case GPGME_STATUS_TRUST_NEVER:
996     case GPGME_STATUS_TRUST_MARGINAL:
997     case GPGME_STATUS_TRUST_FULLY:
998     case GPGME_STATUS_TRUST_ULTIMATE:
999       opd->only_newsig_seen = 0;
1000       return sig ? parse_trust (sig, code, args)
1001         : trace_gpg_error (GPG_ERR_INV_ENGINE);
1002
1003     case GPGME_STATUS_PKA_TRUST_BAD:
1004     case GPGME_STATUS_PKA_TRUST_GOOD:
1005       opd->only_newsig_seen = 0;
1006       /* Check that we only get one of these status codes per
1007          signature; if not the crypto backend misbehaves.  */
1008       if (!sig || sig->pka_trust || sig->pka_address)
1009         return trace_gpg_error (GPG_ERR_INV_ENGINE);
1010       sig->pka_trust = code == GPGME_STATUS_PKA_TRUST_GOOD? 2 : 1;
1011       end = strchr (args, ' ');
1012       if (end)
1013         *end = 0;
1014       sig->pka_address = strdup (args);
1015       break;
1016
1017     case GPGME_STATUS_TOFU_USER:
1018       opd->only_newsig_seen = 0;
1019       if (!sig)
1020         return trace_gpg_error (GPG_ERR_INV_ENGINE);
1021       err = parse_tofu_user (sig, args, ctx->protocol);
1022       /* gpg emits TOFU User lines for each conflicting key.
1023        * GPGME does not expose this to have a clean API and
1024        * a GPGME user can do a keylisting with the address
1025        * normalisation.
1026        * So when a duplicated TOFU_USER line is encountered
1027        * we ignore the conflicting tofu stats emited afterwards.
1028        */
1029       if (gpg_err_code (err) == GPG_ERR_DUP_VALUE)
1030         {
1031           opd->conflict_user_seen = 1;
1032           break;
1033         }
1034       opd->conflict_user_seen = 0;
1035       return trace_gpg_error (err);
1036
1037     case GPGME_STATUS_TOFU_STATS:
1038       opd->only_newsig_seen = 0;
1039       if (opd->conflict_user_seen)
1040         break;
1041       return sig ? parse_tofu_stats (sig, args)
1042         /*    */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
1043
1044     case GPGME_STATUS_TOFU_STATS_LONG:
1045       opd->only_newsig_seen = 0;
1046       if (opd->conflict_user_seen)
1047         break;
1048       return sig ? parse_tofu_stats_long (sig, args, ctx->raw_description)
1049         /*    */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
1050
1051     case GPGME_STATUS_ERROR:
1052       opd->only_newsig_seen = 0;
1053       /* Some  error stati are informational, so we don't return an
1054          error code if we are not ready to process this status.  */
1055       return parse_error (sig, args, !!sig );
1056
1057     case GPGME_STATUS_FAILURE:
1058       opd->failure_code = _gpgme_parse_failure (args);
1059       break;
1060
1061     case GPGME_STATUS_EOF:
1062       if (sig && !opd->did_prepare_new_sig)
1063         calc_sig_summary (sig);
1064       if (opd->only_newsig_seen && sig)
1065         {
1066           gpgme_signature_t sig2;
1067           /* The last signature has no valid information - remove it
1068              from the list. */
1069           assert (!sig->next);
1070           if (sig == opd->result.signatures)
1071             opd->result.signatures = NULL;
1072           else
1073             {
1074               for (sig2 = opd->result.signatures; sig2; sig2 = sig2->next)
1075                 if (sig2->next == sig)
1076                   {
1077                     sig2->next = NULL;
1078                     break;
1079                   }
1080             }
1081           /* Note that there is no need to release the members of SIG
1082              because we won't be here if they have been set. */
1083           free (sig);
1084           opd->current_sig = NULL;
1085         }
1086       opd->only_newsig_seen = 0;
1087       if (opd->failure_code)
1088         return opd->failure_code;
1089       break;
1090
1091     case GPGME_STATUS_PLAINTEXT:
1092       if (++opd->plaintext_seen > 1)
1093         return gpg_error (GPG_ERR_BAD_DATA);
1094       {
1095         int mime = 0;
1096         err = _gpgme_parse_plaintext (args, &opd->result.file_name, &mime);
1097         if (err)
1098           return err;
1099         gpgrt_log_debug ("verify.c: setting mime to %d\n", mime);
1100         opd->result.is_mime = !!mime;
1101       }
1102       break;
1103
1104     case GPGME_STATUS_VERIFICATION_COMPLIANCE_MODE:
1105       PARSE_COMPLIANCE_FLAGS (args, opd->current_sig);
1106       break;
1107
1108     default:
1109       break;
1110     }
1111   return 0;
1112 }
1113
1114
1115 static gpgme_error_t
1116 verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
1117 {
1118   gpgme_error_t err;
1119
1120   err = _gpgme_progress_status_handler (priv, code, args);
1121   if (!err)
1122     err = _gpgme_verify_status_handler (priv, code, args);
1123   return err;
1124 }
1125
1126
1127 gpgme_error_t
1128 _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
1129 {
1130   void *hook;
1131   op_data_t opd;
1132
1133   return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
1134                                 sizeof (*opd), release_op_data);
1135 }
1136
1137
1138 static gpgme_error_t
1139 verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
1140               gpgme_data_t signed_text, gpgme_data_t plaintext)
1141 {
1142   gpgme_error_t err;
1143
1144   err = _gpgme_op_reset (ctx, synchronous);
1145   if (err)
1146     return err;
1147
1148   err = _gpgme_op_verify_init_result (ctx);
1149   if (err)
1150     return err;
1151
1152   _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
1153
1154   if (!sig)
1155     return gpg_error (GPG_ERR_NO_DATA);
1156
1157   return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext,
1158                                   ctx);
1159 }
1160
1161
1162 /* Decrypt ciphertext CIPHER and make a signature verification within
1163    CTX and store the resulting plaintext in PLAIN.  */
1164 gpgme_error_t
1165 gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
1166                        gpgme_data_t signed_text, gpgme_data_t plaintext)
1167 {
1168   gpg_error_t err;
1169   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify_start", ctx,
1170               "sig=%p, signed_text=%p, plaintext=%p",
1171               sig, signed_text, plaintext);
1172
1173   if (!ctx)
1174     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1175
1176   err = verify_start (ctx, 0, sig, signed_text, plaintext);
1177   return TRACE_ERR (err);
1178 }
1179
1180
1181 /* Decrypt ciphertext CIPHER and make a signature verification within
1182    CTX and store the resulting plaintext in PLAIN.  */
1183 gpgme_error_t
1184 gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
1185                  gpgme_data_t plaintext)
1186 {
1187   gpgme_error_t err;
1188
1189   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify", ctx,
1190               "sig=%p, signed_text=%p, plaintext=%p",
1191               sig, signed_text, plaintext);
1192
1193   if (!ctx)
1194     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1195
1196   err = verify_start (ctx, 1, sig, signed_text, plaintext);
1197   if (!err)
1198     err = _gpgme_wait_one (ctx);
1199   return TRACE_ERR (err);
1200 }
1201
1202 \f
1203 /* Compatibility interfaces.  */
1204
1205 /* Get the key used to create signature IDX in CTX and return it in
1206    R_KEY.  */
1207 gpgme_error_t
1208 gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
1209 {
1210   gpgme_verify_result_t result;
1211   gpgme_signature_t sig;
1212
1213   if (!ctx)
1214     return gpg_error (GPG_ERR_INV_VALUE);
1215
1216   result = gpgme_op_verify_result (ctx);
1217   sig = result->signatures;
1218
1219   while (sig && idx)
1220     {
1221       sig = sig->next;
1222       idx--;
1223     }
1224   if (!sig || idx)
1225     return gpg_error (GPG_ERR_EOF);
1226
1227   return gpgme_get_key (ctx, sig->fpr, r_key, 0);
1228 }
1229
1230
1231 /* Retrieve the signature status of signature IDX in CTX after a
1232    successful verify operation in R_STAT (if non-null).  The creation
1233    time stamp of the signature is returned in R_CREATED (if non-null).
1234    The function returns a string containing the fingerprint.  */
1235 const char *
1236 gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
1237                       _gpgme_sig_stat_t *r_stat, time_t *r_created)
1238 {
1239   gpgme_verify_result_t result;
1240   gpgme_signature_t sig;
1241
1242   result = gpgme_op_verify_result (ctx);
1243   sig = result->signatures;
1244
1245   while (sig && idx)
1246     {
1247       sig = sig->next;
1248       idx--;
1249     }
1250   if (!sig || idx)
1251     return NULL;
1252
1253   if (r_stat)
1254     {
1255       switch (gpg_err_code (sig->status))
1256         {
1257         case GPG_ERR_NO_ERROR:
1258           *r_stat = GPGME_SIG_STAT_GOOD;
1259           break;
1260
1261         case GPG_ERR_BAD_SIGNATURE:
1262           *r_stat = GPGME_SIG_STAT_BAD;
1263           break;
1264
1265         case GPG_ERR_NO_PUBKEY:
1266           *r_stat = GPGME_SIG_STAT_NOKEY;
1267           break;
1268
1269         case GPG_ERR_NO_DATA:
1270           *r_stat = GPGME_SIG_STAT_NOSIG;
1271           break;
1272
1273         case GPG_ERR_SIG_EXPIRED:
1274           *r_stat = GPGME_SIG_STAT_GOOD_EXP;
1275           break;
1276
1277         case GPG_ERR_KEY_EXPIRED:
1278           *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
1279           break;
1280
1281         default:
1282           *r_stat = GPGME_SIG_STAT_ERROR;
1283           break;
1284         }
1285     }
1286   if (r_created)
1287     *r_created = sig->timestamp;
1288   return sig->fpr;
1289 }
1290
1291
1292 /* Retrieve certain attributes of a signature.  IDX is the index
1293    number of the signature after a successful verify operation.  WHAT
1294    is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
1295    one.  WHATIDX is to be passed as 0 for most attributes . */
1296 unsigned long
1297 gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
1298                           _gpgme_attr_t what, int whatidx)
1299 {
1300   gpgme_verify_result_t result;
1301   gpgme_signature_t sig;
1302
1303   (void)whatidx;
1304
1305   result = gpgme_op_verify_result (ctx);
1306   sig = result->signatures;
1307
1308   while (sig && idx)
1309     {
1310       sig = sig->next;
1311       idx--;
1312     }
1313   if (!sig || idx)
1314     return 0;
1315
1316   switch (what)
1317     {
1318     case GPGME_ATTR_CREATED:
1319       return sig->timestamp;
1320
1321     case GPGME_ATTR_EXPIRE:
1322       return sig->exp_timestamp;
1323
1324     case GPGME_ATTR_VALIDITY:
1325       return (unsigned long) sig->validity;
1326
1327     case GPGME_ATTR_SIG_STATUS:
1328       switch (gpg_err_code (sig->status))
1329         {
1330         case GPG_ERR_NO_ERROR:
1331           return GPGME_SIG_STAT_GOOD;
1332
1333         case GPG_ERR_BAD_SIGNATURE:
1334           return GPGME_SIG_STAT_BAD;
1335
1336         case GPG_ERR_NO_PUBKEY:
1337           return GPGME_SIG_STAT_NOKEY;
1338
1339         case GPG_ERR_NO_DATA:
1340           return GPGME_SIG_STAT_NOSIG;
1341
1342         case GPG_ERR_SIG_EXPIRED:
1343           return GPGME_SIG_STAT_GOOD_EXP;
1344
1345         case GPG_ERR_KEY_EXPIRED:
1346           return GPGME_SIG_STAT_GOOD_EXPKEY;
1347
1348         default:
1349           return GPGME_SIG_STAT_ERROR;
1350         }
1351
1352     case GPGME_ATTR_SIG_SUMMARY:
1353       return sig->summary;
1354
1355     default:
1356       break;
1357     }
1358   return 0;
1359 }
1360
1361
1362 const char *
1363 gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
1364                            _gpgme_attr_t what, int whatidx)
1365 {
1366   gpgme_verify_result_t result;
1367   gpgme_signature_t sig;
1368
1369   result = gpgme_op_verify_result (ctx);
1370   sig = result->signatures;
1371
1372   while (sig && idx)
1373     {
1374       sig = sig->next;
1375       idx--;
1376     }
1377   if (!sig || idx)
1378     return NULL;
1379
1380   switch (what)
1381     {
1382     case GPGME_ATTR_FPR:
1383       return sig->fpr;
1384
1385     case GPGME_ATTR_ERRTOK:
1386       if (whatidx == 1)
1387         return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
1388       else
1389         return "";
1390     default:
1391       break;
1392     }
1393
1394   return NULL;
1395 }