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