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