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