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