w32: Remove all support for WindowsCE
[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         opd->result.is_mime = !!mime;
1100       }
1101       break;
1102
1103     case GPGME_STATUS_VERIFICATION_COMPLIANCE_MODE:
1104       PARSE_COMPLIANCE_FLAGS (args, opd->current_sig);
1105       break;
1106
1107     default:
1108       break;
1109     }
1110   return 0;
1111 }
1112
1113
1114 static gpgme_error_t
1115 verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
1116 {
1117   gpgme_error_t err;
1118
1119   err = _gpgme_progress_status_handler (priv, code, args);
1120   if (!err)
1121     err = _gpgme_verify_status_handler (priv, code, args);
1122   return err;
1123 }
1124
1125
1126 gpgme_error_t
1127 _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
1128 {
1129   void *hook;
1130   op_data_t opd;
1131
1132   return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
1133                                 sizeof (*opd), release_op_data);
1134 }
1135
1136
1137 static gpgme_error_t
1138 verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
1139               gpgme_data_t signed_text, gpgme_data_t plaintext)
1140 {
1141   gpgme_error_t err;
1142
1143   err = _gpgme_op_reset (ctx, synchronous);
1144   if (err)
1145     return err;
1146
1147   err = _gpgme_op_verify_init_result (ctx);
1148   if (err)
1149     return err;
1150
1151   _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
1152
1153   if (!sig)
1154     return gpg_error (GPG_ERR_NO_DATA);
1155
1156   return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext,
1157                                   ctx);
1158 }
1159
1160
1161 /* Decrypt ciphertext CIPHER and make a signature verification within
1162    CTX and store the resulting plaintext in PLAIN.  */
1163 gpgme_error_t
1164 gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
1165                        gpgme_data_t signed_text, gpgme_data_t plaintext)
1166 {
1167   gpg_error_t err;
1168   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify_start", ctx,
1169               "sig=%p, signed_text=%p, plaintext=%p",
1170               sig, signed_text, plaintext);
1171
1172   if (!ctx)
1173     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1174
1175   err = verify_start (ctx, 0, sig, signed_text, plaintext);
1176   return TRACE_ERR (err);
1177 }
1178
1179
1180 /* Decrypt ciphertext CIPHER and make a signature verification within
1181    CTX and store the resulting plaintext in PLAIN.  */
1182 gpgme_error_t
1183 gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
1184                  gpgme_data_t plaintext)
1185 {
1186   gpgme_error_t err;
1187
1188   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify", ctx,
1189               "sig=%p, signed_text=%p, plaintext=%p",
1190               sig, signed_text, plaintext);
1191
1192   if (!ctx)
1193     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1194
1195   err = verify_start (ctx, 1, sig, signed_text, plaintext);
1196   if (!err)
1197     err = _gpgme_wait_one (ctx);
1198   return TRACE_ERR (err);
1199 }
1200
1201 \f
1202 /* Compatibility interfaces.  */
1203
1204 /* Get the key used to create signature IDX in CTX and return it in
1205    R_KEY.  */
1206 gpgme_error_t
1207 gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
1208 {
1209   gpgme_verify_result_t result;
1210   gpgme_signature_t sig;
1211
1212   if (!ctx)
1213     return gpg_error (GPG_ERR_INV_VALUE);
1214
1215   result = gpgme_op_verify_result (ctx);
1216   sig = result->signatures;
1217
1218   while (sig && idx)
1219     {
1220       sig = sig->next;
1221       idx--;
1222     }
1223   if (!sig || idx)
1224     return gpg_error (GPG_ERR_EOF);
1225
1226   return gpgme_get_key (ctx, sig->fpr, r_key, 0);
1227 }
1228
1229
1230 /* Retrieve the signature status of signature IDX in CTX after a
1231    successful verify operation in R_STAT (if non-null).  The creation
1232    time stamp of the signature is returned in R_CREATED (if non-null).
1233    The function returns a string containing the fingerprint.  */
1234 const char *
1235 gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
1236                       _gpgme_sig_stat_t *r_stat, time_t *r_created)
1237 {
1238   gpgme_verify_result_t result;
1239   gpgme_signature_t sig;
1240
1241   result = gpgme_op_verify_result (ctx);
1242   sig = result->signatures;
1243
1244   while (sig && idx)
1245     {
1246       sig = sig->next;
1247       idx--;
1248     }
1249   if (!sig || idx)
1250     return NULL;
1251
1252   if (r_stat)
1253     {
1254       switch (gpg_err_code (sig->status))
1255         {
1256         case GPG_ERR_NO_ERROR:
1257           *r_stat = GPGME_SIG_STAT_GOOD;
1258           break;
1259
1260         case GPG_ERR_BAD_SIGNATURE:
1261           *r_stat = GPGME_SIG_STAT_BAD;
1262           break;
1263
1264         case GPG_ERR_NO_PUBKEY:
1265           *r_stat = GPGME_SIG_STAT_NOKEY;
1266           break;
1267
1268         case GPG_ERR_NO_DATA:
1269           *r_stat = GPGME_SIG_STAT_NOSIG;
1270           break;
1271
1272         case GPG_ERR_SIG_EXPIRED:
1273           *r_stat = GPGME_SIG_STAT_GOOD_EXP;
1274           break;
1275
1276         case GPG_ERR_KEY_EXPIRED:
1277           *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
1278           break;
1279
1280         default:
1281           *r_stat = GPGME_SIG_STAT_ERROR;
1282           break;
1283         }
1284     }
1285   if (r_created)
1286     *r_created = sig->timestamp;
1287   return sig->fpr;
1288 }
1289
1290
1291 /* Retrieve certain attributes of a signature.  IDX is the index
1292    number of the signature after a successful verify operation.  WHAT
1293    is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
1294    one.  WHATIDX is to be passed as 0 for most attributes . */
1295 unsigned long
1296 gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
1297                           _gpgme_attr_t what, int whatidx)
1298 {
1299   gpgme_verify_result_t result;
1300   gpgme_signature_t sig;
1301
1302   (void)whatidx;
1303
1304   result = gpgme_op_verify_result (ctx);
1305   sig = result->signatures;
1306
1307   while (sig && idx)
1308     {
1309       sig = sig->next;
1310       idx--;
1311     }
1312   if (!sig || idx)
1313     return 0;
1314
1315   switch (what)
1316     {
1317     case GPGME_ATTR_CREATED:
1318       return sig->timestamp;
1319
1320     case GPGME_ATTR_EXPIRE:
1321       return sig->exp_timestamp;
1322
1323     case GPGME_ATTR_VALIDITY:
1324       return (unsigned long) sig->validity;
1325
1326     case GPGME_ATTR_SIG_STATUS:
1327       switch (gpg_err_code (sig->status))
1328         {
1329         case GPG_ERR_NO_ERROR:
1330           return GPGME_SIG_STAT_GOOD;
1331
1332         case GPG_ERR_BAD_SIGNATURE:
1333           return GPGME_SIG_STAT_BAD;
1334
1335         case GPG_ERR_NO_PUBKEY:
1336           return GPGME_SIG_STAT_NOKEY;
1337
1338         case GPG_ERR_NO_DATA:
1339           return GPGME_SIG_STAT_NOSIG;
1340
1341         case GPG_ERR_SIG_EXPIRED:
1342           return GPGME_SIG_STAT_GOOD_EXP;
1343
1344         case GPG_ERR_KEY_EXPIRED:
1345           return GPGME_SIG_STAT_GOOD_EXPKEY;
1346
1347         default:
1348           return GPGME_SIG_STAT_ERROR;
1349         }
1350
1351     case GPGME_ATTR_SIG_SUMMARY:
1352       return sig->summary;
1353
1354     default:
1355       break;
1356     }
1357   return 0;
1358 }
1359
1360
1361 const char *
1362 gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
1363                            _gpgme_attr_t what, int whatidx)
1364 {
1365   gpgme_verify_result_t result;
1366   gpgme_signature_t sig;
1367
1368   result = gpgme_op_verify_result (ctx);
1369   sig = result->signatures;
1370
1371   while (sig && idx)
1372     {
1373       sig = sig->next;
1374       idx--;
1375     }
1376   if (!sig || idx)
1377     return NULL;
1378
1379   switch (what)
1380     {
1381     case GPGME_ATTR_FPR:
1382       return sig->fpr;
1383
1384     case GPGME_ATTR_ERRTOK:
1385       if (whatidx == 1)
1386         return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
1387       else
1388         return "";
1389     default:
1390       break;
1391     }
1392
1393   return NULL;
1394 }