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