Line data Source code
1 : /* verify.c - Verify a messages signature
2 : * Copyright (C) 2001, 2002, 2003, 2007,
3 : * 2010 Free Software Foundation, Inc.
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * GnuPG is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <errno.h>
26 : #include <unistd.h>
27 : #include <time.h>
28 : #include <assert.h>
29 :
30 : #include "gpgsm.h"
31 : #include <gcrypt.h>
32 : #include <ksba.h>
33 :
34 : #include "keydb.h"
35 : #include "i18n.h"
36 :
37 : static char *
38 0 : strtimestamp_r (ksba_isotime_t atime)
39 : {
40 0 : char *buffer = xmalloc (15);
41 :
42 0 : if (!atime || !*atime)
43 0 : strcpy (buffer, "none");
44 : else
45 0 : sprintf (buffer, "%.4s-%.2s-%.2s", atime, atime+4, atime+6);
46 0 : return buffer;
47 : }
48 :
49 :
50 :
51 : /* Hash the data for a detached signature. Returns 0 on success. */
52 : static gpg_error_t
53 0 : hash_data (int fd, gcry_md_hd_t md)
54 : {
55 0 : gpg_error_t err = 0;
56 : estream_t fp;
57 : char buffer[4096];
58 : int nread;
59 :
60 0 : fp = es_fdopen_nc (fd, "rb");
61 0 : if (!fp)
62 : {
63 0 : err = gpg_error_from_syserror ();
64 0 : log_error ("fdopen(%d) failed: %s\n", fd, gpg_strerror (err));
65 0 : return err;
66 : }
67 :
68 : do
69 : {
70 0 : nread = es_fread (buffer, 1, DIM(buffer), fp);
71 0 : gcry_md_write (md, buffer, nread);
72 : }
73 0 : while (nread);
74 0 : if (es_ferror (fp))
75 : {
76 0 : err = gpg_error_from_syserror ();
77 0 : log_error ("read error on fd %d: %s\n", fd, gpg_strerror (err));
78 : }
79 0 : es_fclose (fp);
80 0 : return err;
81 : }
82 :
83 :
84 :
85 :
86 : /* Perform a verify operation. To verify detached signatures, DATA_FD
87 : must be different than -1. With OUT_FP given and a non-detached
88 : signature, the signed material is written to that stream. */
89 : int
90 0 : gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, estream_t out_fp)
91 : {
92 : int i, rc;
93 0 : Base64Context b64reader = NULL;
94 0 : Base64Context b64writer = NULL;
95 : ksba_reader_t reader;
96 0 : ksba_writer_t writer = NULL;
97 0 : ksba_cms_t cms = NULL;
98 : ksba_stop_reason_t stopreason;
99 : ksba_cert_t cert;
100 : KEYDB_HANDLE kh;
101 0 : gcry_md_hd_t data_md = NULL;
102 : int signer;
103 : const char *algoid;
104 : int algo;
105 : int is_detached;
106 0 : estream_t in_fp = NULL;
107 : char *p;
108 :
109 0 : audit_set_type (ctrl->audit, AUDIT_TYPE_VERIFY);
110 :
111 0 : kh = keydb_new ();
112 0 : if (!kh)
113 : {
114 0 : log_error (_("failed to allocate keyDB handle\n"));
115 0 : rc = gpg_error (GPG_ERR_GENERAL);
116 0 : goto leave;
117 : }
118 :
119 :
120 0 : in_fp = es_fdopen_nc (in_fd, "rb");
121 0 : if (!in_fp)
122 : {
123 0 : rc = gpg_error_from_syserror ();
124 0 : log_error ("fdopen() failed: %s\n", strerror (errno));
125 0 : goto leave;
126 : }
127 :
128 0 : rc = gpgsm_create_reader (&b64reader, ctrl, in_fp, 0, &reader);
129 0 : if (rc)
130 : {
131 0 : log_error ("can't create reader: %s\n", gpg_strerror (rc));
132 0 : goto leave;
133 : }
134 :
135 0 : if (out_fp)
136 : {
137 0 : rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
138 0 : if (rc)
139 : {
140 0 : log_error ("can't create writer: %s\n", gpg_strerror (rc));
141 0 : goto leave;
142 : }
143 : }
144 :
145 0 : rc = ksba_cms_new (&cms);
146 0 : if (rc)
147 0 : goto leave;
148 :
149 0 : rc = ksba_cms_set_reader_writer (cms, reader, writer);
150 0 : if (rc)
151 : {
152 0 : log_error ("ksba_cms_set_reader_writer failed: %s\n",
153 : gpg_strerror (rc));
154 0 : goto leave;
155 : }
156 :
157 0 : rc = gcry_md_open (&data_md, 0, 0);
158 0 : if (rc)
159 : {
160 0 : log_error ("md_open failed: %s\n", gpg_strerror (rc));
161 0 : goto leave;
162 : }
163 0 : if (DBG_HASHING)
164 0 : gcry_md_debug (data_md, "vrfy.data");
165 :
166 0 : audit_log (ctrl->audit, AUDIT_SETUP_READY);
167 :
168 0 : is_detached = 0;
169 : do
170 : {
171 0 : rc = ksba_cms_parse (cms, &stopreason);
172 0 : if (rc)
173 : {
174 0 : log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc));
175 0 : goto leave;
176 : }
177 :
178 0 : if (stopreason == KSBA_SR_NEED_HASH)
179 : {
180 0 : is_detached = 1;
181 0 : audit_log (ctrl->audit, AUDIT_DETACHED_SIGNATURE);
182 0 : if (opt.verbose)
183 0 : log_info ("detached signature\n");
184 : }
185 :
186 0 : if (stopreason == KSBA_SR_NEED_HASH
187 0 : || stopreason == KSBA_SR_BEGIN_DATA)
188 : {
189 0 : audit_log (ctrl->audit, AUDIT_GOT_DATA);
190 :
191 : /* We are now able to enable the hash algorithms */
192 0 : for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
193 : {
194 0 : algo = gcry_md_map_name (algoid);
195 0 : if (!algo)
196 : {
197 0 : log_error ("unknown hash algorithm '%s'\n",
198 : algoid? algoid:"?");
199 0 : if (algoid
200 0 : && ( !strcmp (algoid, "1.2.840.113549.1.1.2")
201 0 : ||!strcmp (algoid, "1.2.840.113549.2.2")))
202 0 : log_info (_("(this is the MD2 algorithm)\n"));
203 0 : audit_log_s (ctrl->audit, AUDIT_BAD_DATA_HASH_ALGO, algoid);
204 : }
205 : else
206 : {
207 0 : if (DBG_X509)
208 0 : log_debug ("enabling hash algorithm %d (%s)\n",
209 : algo, algoid? algoid:"");
210 0 : gcry_md_enable (data_md, algo);
211 0 : audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
212 : }
213 : }
214 0 : if (opt.extra_digest_algo)
215 : {
216 0 : if (DBG_X509)
217 0 : log_debug ("enabling extra hash algorithm %d\n",
218 : opt.extra_digest_algo);
219 0 : gcry_md_enable (data_md, opt.extra_digest_algo);
220 0 : audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO,
221 : opt.extra_digest_algo);
222 : }
223 0 : if (is_detached)
224 : {
225 0 : if (data_fd == -1)
226 : {
227 0 : log_info ("detached signature w/o data "
228 : "- assuming certs-only\n");
229 0 : audit_log (ctrl->audit, AUDIT_CERT_ONLY_SIG);
230 : }
231 : else
232 0 : audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING,
233 : hash_data (data_fd, data_md));
234 : }
235 : else
236 : {
237 0 : ksba_cms_set_hash_function (cms, HASH_FNC, data_md);
238 : }
239 : }
240 0 : else if (stopreason == KSBA_SR_END_DATA)
241 : { /* The data bas been hashed */
242 0 : audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, 0);
243 : }
244 : }
245 0 : while (stopreason != KSBA_SR_READY);
246 :
247 0 : if (b64writer)
248 : {
249 0 : rc = gpgsm_finish_writer (b64writer);
250 0 : if (rc)
251 : {
252 0 : log_error ("write failed: %s\n", gpg_strerror (rc));
253 0 : audit_log_ok (ctrl->audit, AUDIT_WRITE_ERROR, rc);
254 0 : goto leave;
255 : }
256 : }
257 :
258 0 : if (data_fd != -1 && !is_detached)
259 : {
260 0 : log_error ("data given for a non-detached signature\n");
261 0 : rc = gpg_error (GPG_ERR_CONFLICT);
262 0 : audit_log (ctrl->audit, AUDIT_USAGE_ERROR);
263 0 : goto leave;
264 : }
265 :
266 0 : for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
267 : {
268 : /* Fixme: it might be better to check the validity of the
269 : certificate first before entering it into the DB. This way
270 : we would avoid cluttering the DB with invalid
271 : certificates. */
272 0 : audit_log_cert (ctrl->audit, AUDIT_SAVE_CERT, cert,
273 0 : keydb_store_cert (ctrl, cert, 0, NULL));
274 0 : ksba_cert_release (cert);
275 : }
276 :
277 0 : cert = NULL;
278 0 : for (signer=0; ; signer++)
279 : {
280 0 : char *issuer = NULL;
281 0 : ksba_sexp_t sigval = NULL;
282 : ksba_isotime_t sigtime, keyexptime;
283 : ksba_sexp_t serial;
284 0 : char *msgdigest = NULL;
285 : size_t msgdigestlen;
286 : char *ctattr;
287 : int sigval_hash_algo;
288 : int info_pkalgo;
289 : unsigned int verifyflags;
290 :
291 0 : rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
292 0 : if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA
293 0 : && data_fd == -1 && is_detached)
294 : {
295 0 : log_info ("certs-only message accepted\n");
296 0 : rc = 0;
297 0 : break;
298 : }
299 0 : if (rc)
300 : {
301 0 : if (signer && rc == -1)
302 0 : rc = 0;
303 0 : break;
304 : }
305 :
306 0 : gpgsm_status (ctrl, STATUS_NEWSIG, NULL);
307 0 : audit_log_i (ctrl->audit, AUDIT_NEW_SIG, signer);
308 :
309 0 : if (DBG_X509)
310 : {
311 0 : log_debug ("signer %d - issuer: '%s'\n",
312 0 : signer, issuer? issuer:"[NONE]");
313 0 : log_debug ("signer %d - serial: ", signer);
314 0 : gpgsm_dump_serial (serial);
315 0 : log_printf ("\n");
316 : }
317 0 : if (ctrl->audit)
318 : {
319 0 : char *tmpstr = gpgsm_format_sn_issuer (serial, issuer);
320 0 : audit_log_s (ctrl->audit, AUDIT_SIG_NAME, tmpstr);
321 0 : xfree (tmpstr);
322 : }
323 :
324 0 : rc = ksba_cms_get_signing_time (cms, signer, sigtime);
325 0 : if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
326 0 : *sigtime = 0;
327 0 : else if (rc)
328 : {
329 0 : log_error ("error getting signing time: %s\n", gpg_strerror (rc));
330 0 : *sigtime = 0; /* (we can't encode an error in the time string.) */
331 : }
332 :
333 0 : rc = ksba_cms_get_message_digest (cms, signer,
334 : &msgdigest, &msgdigestlen);
335 0 : if (!rc)
336 : {
337 : size_t is_enabled;
338 :
339 0 : algoid = ksba_cms_get_digest_algo (cms, signer);
340 0 : algo = gcry_md_map_name (algoid);
341 0 : if (DBG_X509)
342 0 : log_debug ("signer %d - digest algo: %d\n", signer, algo);
343 0 : is_enabled = sizeof algo;
344 0 : if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED,
345 : &algo, &is_enabled)
346 0 : || !is_enabled)
347 : {
348 0 : log_error ("digest algo %d (%s) has not been enabled\n",
349 : algo, algoid?algoid:"");
350 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "unsupported");
351 0 : goto next_signer;
352 : }
353 : }
354 0 : else if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
355 : {
356 0 : assert (!msgdigest);
357 0 : rc = 0;
358 0 : algoid = NULL;
359 0 : algo = 0;
360 : }
361 : else /* real error */
362 : {
363 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
364 0 : break;
365 : }
366 :
367 0 : rc = ksba_cms_get_sigattr_oids (cms, signer,
368 : "1.2.840.113549.1.9.3", &ctattr);
369 0 : if (!rc)
370 : {
371 : const char *s;
372 :
373 0 : if (DBG_X509)
374 0 : log_debug ("signer %d - content-type attribute: %s",
375 : signer, ctattr);
376 :
377 0 : s = ksba_cms_get_content_oid (cms, 1);
378 0 : if (!s || strcmp (ctattr, s))
379 : {
380 0 : log_error ("content-type attribute does not match "
381 : "actual content-type\n");
382 0 : ksba_free (ctattr);
383 0 : ctattr = NULL;
384 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
385 0 : goto next_signer;
386 : }
387 0 : ksba_free (ctattr);
388 0 : ctattr = NULL;
389 : }
390 0 : else if (rc != -1)
391 : {
392 0 : log_error ("error getting content-type attribute: %s\n",
393 : gpg_strerror (rc));
394 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
395 0 : goto next_signer;
396 : }
397 0 : rc = 0;
398 :
399 :
400 0 : sigval = ksba_cms_get_sig_val (cms, signer);
401 0 : if (!sigval)
402 : {
403 0 : log_error ("no signature value available\n");
404 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
405 0 : goto next_signer;
406 : }
407 0 : sigval_hash_algo = hash_algo_from_sigval (sigval);
408 0 : if (DBG_X509)
409 : {
410 0 : log_debug ("signer %d - signature available (sigval hash=%d)",
411 : signer, sigval_hash_algo);
412 : /* log_printhex ("sigval ", sigval, */
413 : /* gcry_sexp_canon_len (sigval, 0, NULL, NULL)); */
414 : }
415 0 : if (!sigval_hash_algo)
416 0 : sigval_hash_algo = algo; /* Fallback used e.g. with old libksba. */
417 :
418 : /* Find the certificate of the signer */
419 0 : keydb_search_reset (kh);
420 0 : rc = keydb_search_issuer_sn (ctrl, kh, issuer, serial);
421 0 : if (rc)
422 : {
423 0 : if (rc == -1)
424 : {
425 0 : log_error ("certificate not found\n");
426 0 : rc = gpg_error (GPG_ERR_NO_PUBKEY);
427 : }
428 : else
429 0 : log_error ("failed to find the certificate: %s\n",
430 : gpg_strerror(rc));
431 : {
432 : char numbuf[50];
433 0 : sprintf (numbuf, "%d", rc);
434 :
435 0 : gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey",
436 : numbuf, NULL);
437 : }
438 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "no-cert");
439 0 : goto next_signer;
440 : }
441 :
442 0 : rc = keydb_get_cert (kh, &cert);
443 0 : if (rc)
444 : {
445 0 : log_error ("failed to get cert: %s\n", gpg_strerror (rc));
446 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
447 0 : goto next_signer;
448 : }
449 :
450 0 : log_info (_("Signature made "));
451 0 : if (*sigtime)
452 0 : dump_isotime (sigtime);
453 : else
454 0 : log_printf (_("[date not given]"));
455 0 : log_printf (_(" using certificate ID 0x%08lX\n"),
456 : gpgsm_get_short_fingerprint (cert, NULL));
457 :
458 0 : audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo);
459 :
460 0 : if (msgdigest)
461 : { /* Signed attributes are available. */
462 : gcry_md_hd_t md;
463 : unsigned char *s;
464 :
465 : /* Check that the message digest in the signed attributes
466 : matches the one we calculated on the data. */
467 0 : s = gcry_md_read (data_md, algo);
468 0 : if ( !s || !msgdigestlen
469 0 : || gcry_md_get_algo_dlen (algo) != msgdigestlen
470 0 : || memcmp (s, msgdigest, msgdigestlen) )
471 : {
472 : char *fpr;
473 :
474 0 : log_error (_("invalid signature: message digest attribute "
475 : "does not match computed one\n"));
476 0 : if (DBG_X509)
477 : {
478 0 : if (msgdigest)
479 0 : log_printhex ("message: ", msgdigest, msgdigestlen);
480 0 : if (s)
481 0 : log_printhex ("computed: ",
482 0 : s, gcry_md_get_algo_dlen (algo));
483 : }
484 0 : fpr = gpgsm_fpr_and_name_for_status (cert);
485 0 : gpgsm_status (ctrl, STATUS_BADSIG, fpr);
486 0 : xfree (fpr);
487 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
488 0 : goto next_signer;
489 : }
490 :
491 0 : audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, sigval_hash_algo);
492 0 : rc = gcry_md_open (&md, sigval_hash_algo, 0);
493 0 : if (rc)
494 : {
495 0 : log_error ("md_open failed: %s\n", gpg_strerror (rc));
496 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
497 0 : goto next_signer;
498 : }
499 0 : if (DBG_HASHING)
500 0 : gcry_md_debug (md, "vrfy.attr");
501 :
502 0 : ksba_cms_set_hash_function (cms, HASH_FNC, md);
503 0 : rc = ksba_cms_hash_signed_attrs (cms, signer);
504 0 : if (rc)
505 : {
506 0 : log_error ("hashing signed attrs failed: %s\n",
507 : gpg_strerror (rc));
508 0 : gcry_md_close (md);
509 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error");
510 0 : goto next_signer;
511 : }
512 0 : rc = gpgsm_check_cms_signature (cert, sigval, md,
513 : sigval_hash_algo, &info_pkalgo);
514 0 : gcry_md_close (md);
515 : }
516 : else
517 : {
518 0 : rc = gpgsm_check_cms_signature (cert, sigval, data_md,
519 : algo, &info_pkalgo);
520 : }
521 :
522 0 : if (rc)
523 : {
524 : char *fpr;
525 :
526 0 : log_error ("invalid signature: %s\n", gpg_strerror (rc));
527 0 : fpr = gpgsm_fpr_and_name_for_status (cert);
528 0 : gpgsm_status (ctrl, STATUS_BADSIG, fpr);
529 0 : xfree (fpr);
530 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
531 0 : goto next_signer;
532 : }
533 0 : rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/
534 0 : if (rc)
535 : {
536 0 : gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage",
537 : gpg_err_code (rc));
538 0 : rc = 0;
539 : }
540 :
541 0 : if (DBG_X509)
542 0 : log_debug ("signature okay - checking certs\n");
543 0 : audit_log (ctrl->audit, AUDIT_VALIDATE_CHAIN);
544 0 : rc = gpgsm_validate_chain (ctrl, cert,
545 0 : *sigtime? sigtime : "19700101T000000",
546 : keyexptime, 0,
547 : NULL, 0, &verifyflags);
548 : {
549 : char *fpr, *buf, *tstr;
550 :
551 0 : fpr = gpgsm_fpr_and_name_for_status (cert);
552 0 : if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED)
553 : {
554 0 : gpgsm_status (ctrl, STATUS_EXPKEYSIG, fpr);
555 0 : rc = 0;
556 : }
557 : else
558 0 : gpgsm_status (ctrl, STATUS_GOODSIG, fpr);
559 :
560 0 : xfree (fpr);
561 :
562 0 : fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
563 0 : tstr = strtimestamp_r (sigtime);
564 0 : buf = xasprintf ("%s %s %s %s 0 0 %d %d 00", fpr, tstr,
565 0 : *sigtime? sigtime : "0",
566 0 : *keyexptime? keyexptime : "0",
567 : info_pkalgo, algo);
568 0 : xfree (tstr);
569 0 : xfree (fpr);
570 0 : gpgsm_status (ctrl, STATUS_VALIDSIG, buf);
571 0 : xfree (buf);
572 : }
573 :
574 0 : audit_log_ok (ctrl->audit, AUDIT_CHAIN_STATUS, rc);
575 0 : if (rc) /* of validate_chain */
576 : {
577 0 : log_error ("invalid certification chain: %s\n", gpg_strerror (rc));
578 0 : if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN
579 0 : || gpg_err_code (rc) == GPG_ERR_BAD_CERT
580 0 : || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT
581 0 : || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED)
582 0 : gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL,
583 : gpg_err_code (rc));
584 : else
585 0 : gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL,
586 : gpg_err_code (rc));
587 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad");
588 0 : goto next_signer;
589 : }
590 :
591 0 : audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "good");
592 :
593 0 : for (i=0; (p = ksba_cert_get_subject (cert, i)); i++)
594 : {
595 0 : log_info (!i? _("Good signature from")
596 : : _(" aka"));
597 0 : log_printf (" \"");
598 0 : gpgsm_es_print_name (log_get_stream (), p);
599 0 : log_printf ("\"\n");
600 0 : ksba_free (p);
601 : }
602 :
603 : /* Print a note if this is a qualified signature. */
604 : {
605 : size_t qualbuflen;
606 : char qualbuffer[1];
607 :
608 0 : rc = ksba_cert_get_user_data (cert, "is_qualified", &qualbuffer,
609 : sizeof (qualbuffer), &qualbuflen);
610 0 : if (!rc && qualbuflen)
611 : {
612 0 : if (*qualbuffer)
613 : {
614 0 : log_info (_("This is a qualified signature\n"));
615 0 : if (!opt.qualsig_approval)
616 0 : log_info
617 0 : (_("Note, that this software is not officially approved "
618 : "to create or verify such signatures.\n"));
619 : }
620 : }
621 0 : else if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
622 0 : log_error ("get_user_data(is_qualified) failed: %s\n",
623 : gpg_strerror (rc));
624 : }
625 :
626 0 : gpgsm_status (ctrl, STATUS_TRUST_FULLY,
627 0 : (verifyflags & VALIDATE_FLAG_STEED)?
628 : "0 steed":
629 0 : (verifyflags & VALIDATE_FLAG_CHAIN_MODEL)?
630 : "0 chain": "0 shell");
631 :
632 :
633 : next_signer:
634 0 : rc = 0;
635 0 : xfree (issuer);
636 0 : xfree (serial);
637 0 : xfree (sigval);
638 0 : xfree (msgdigest);
639 0 : ksba_cert_release (cert);
640 0 : cert = NULL;
641 0 : }
642 0 : rc = 0;
643 :
644 : leave:
645 0 : ksba_cms_release (cms);
646 0 : gpgsm_destroy_reader (b64reader);
647 0 : gpgsm_destroy_writer (b64writer);
648 0 : keydb_release (kh);
649 0 : gcry_md_close (data_md);
650 0 : es_fclose (in_fp);
651 :
652 0 : if (rc)
653 : {
654 : char numbuf[50];
655 0 : sprintf (numbuf, "%d", rc );
656 0 : gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave",
657 : numbuf, NULL);
658 : }
659 :
660 0 : return rc;
661 : }
|