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