* encrypt.c (init_dek): Check for too weak algorithms.
[gnupg.git] / sm / certchain.c
1 /* certchain.c - certificate chain validation
2  *      Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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 "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
36 #include "i18n.h"
37
38 static int
39 unknown_criticals (ksba_cert_t cert)
40 {
41   static const char *known[] = {
42     "2.5.29.15", /* keyUsage */
43     "2.5.29.19", /* basic Constraints */
44     "2.5.29.32", /* certificatePolicies */
45     NULL
46   };
47   int rc = 0, i, idx, crit;
48   const char *oid;
49   gpg_error_t err;
50
51   for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
52                                              &oid, &crit, NULL, NULL));idx++)
53     {
54       if (!crit)
55         continue;
56       for (i=0; known[i] && strcmp (known[i],oid); i++)
57         ;
58       if (!known[i])
59         {
60           log_error (_("critical certificate extension %s is not supported\n"),
61                      oid);
62           rc = gpg_error (GPG_ERR_UNSUPPORTED_CERT);
63         }
64     }
65   if (err && gpg_err_code (err) != GPG_ERR_EOF)
66     rc = err;
67
68   return rc;
69 }
70
71 static int
72 allowed_ca (ksba_cert_t cert, int *chainlen)
73 {
74   gpg_error_t err;
75   int flag;
76
77   err = ksba_cert_is_ca (cert, &flag, chainlen);
78   if (err)
79     return err;
80   if (!flag)
81     {
82       log_error (_("issuer certificate is not marked as a CA\n"));
83       return gpg_error (GPG_ERR_BAD_CA_CERT);
84     }
85   return 0;
86 }
87
88
89 static int
90 check_cert_policy (ksba_cert_t cert)
91 {
92   gpg_error_t err;
93   char *policies;
94   FILE *fp;
95   int any_critical;
96
97   err = ksba_cert_get_cert_policies (cert, &policies);
98   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
99     return 0; /* no policy given */
100   if (err)
101     return err;
102
103   /* STRING is a line delimited list of certifiate policies as stored
104      in the certificate.  The line itself is colon delimited where the
105      first field is the OID of the policy and the second field either
106      N or C for normal or critical extension */
107
108   if (opt.verbose > 1)
109     log_info ("certificate's policy list: %s\n", policies);
110
111   /* The check is very minimal but won't give false positives */
112   any_critical = !!strstr (policies, ":C");
113
114   if (!opt.policy_file)
115     { 
116       xfree (policies);
117       if (any_critical)
118         {
119           log_error ("critical marked policy without configured policies\n");
120           return gpg_error (GPG_ERR_NO_POLICY_MATCH);
121         }
122       return 0;
123     }
124
125   fp = fopen (opt.policy_file, "r");
126   if (!fp)
127     {
128       log_error ("failed to open `%s': %s\n",
129                  opt.policy_file, strerror (errno));
130       xfree (policies);
131       /* With no critical policies this is only a warning */
132       if (!any_critical)
133         {
134           log_info (_("note: certificate policy not allowed\n"));
135           return 0;
136         }
137       log_error (_("certificate policy not allowed\n"));
138       return gpg_error (GPG_ERR_NO_POLICY_MATCH);
139     }
140
141   for (;;) 
142     {
143       int c;
144       char *p, line[256];
145       char *haystack, *allowed;
146
147       /* read line */
148       do
149         {
150           if (!fgets (line, DIM(line)-1, fp) )
151             {
152               gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
153
154               xfree (policies);
155               if (feof (fp))
156                 {
157                   fclose (fp);
158                   /* With no critical policies this is only a warning */
159                   if (!any_critical)
160                     {
161                       log_info (_("note: certificate policy not allowed\n"));
162                       return 0;
163                     }
164                   log_error (_("certificate policy not allowed\n"));
165                   return gpg_error (GPG_ERR_NO_POLICY_MATCH);
166                 }
167               fclose (fp);
168               return tmperr;
169             }
170       
171           if (!*line || line[strlen(line)-1] != '\n')
172             {
173               /* eat until end of line */
174               while ( (c=getc (fp)) != EOF && c != '\n')
175                 ;
176               fclose (fp);
177               xfree (policies);
178               return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
179                                      : GPG_ERR_INCOMPLETE_LINE);
180             }
181           
182           /* Allow for empty lines and spaces */
183           for (p=line; spacep (p); p++)
184             ;
185         }
186       while (!*p || *p == '\n' || *p == '#');
187   
188       /* parse line */
189       for (allowed=line; spacep (allowed); allowed++)
190         ;
191       p = strpbrk (allowed, " :\n");
192       if (!*p || p == allowed)
193         {
194           fclose (fp);
195           xfree (policies);
196           return gpg_error (GPG_ERR_CONFIGURATION);
197         }
198       *p = 0; /* strip the rest of the line */
199       /* See whether we find ALLOWED (which is an OID) in POLICIES */
200       for (haystack=policies; (p=strstr (haystack, allowed)); haystack = p+1)
201         {
202           if ( !(p == policies || p[-1] == '\n') )
203             continue; /* Does not match the begin of a line. */
204           if (p[strlen (allowed)] != ':')
205             continue; /* The length does not match. */
206           /* Yep - it does match so return okay. */
207           fclose (fp);
208           xfree (policies);
209           return 0;
210         }
211     }
212 }
213
214
215 static void
216 find_up_store_certs_cb (void *cb_value, ksba_cert_t cert)
217 {
218   if (keydb_store_cert (cert, 1, NULL))
219     log_error ("error storing issuer certificate as ephemeral\n");
220   ++*(int*)cb_value;
221 }
222
223
224 static int
225 find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer)
226 {
227   ksba_name_t authid;
228   ksba_sexp_t authidno;
229   int rc = -1;
230
231   if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno))
232     {
233       const char *s = ksba_name_enum (authid, 0);
234       if (s && *authidno)
235         {
236           rc = keydb_search_issuer_sn (kh, s, authidno);
237           if (rc)
238               keydb_search_reset (kh);
239           if (rc == -1)
240             { /* And try the ephemeral DB. */
241               int old = keydb_set_ephemeral (kh, 1);
242               if (!old)
243                 {
244                   rc = keydb_search_issuer_sn (kh, s, authidno);
245                   if (rc)
246                     keydb_search_reset (kh);
247                 }
248               keydb_set_ephemeral (kh, old);
249             }
250         }
251       /* print a note so that the user does not feel too helpless when
252          an issuer certificate was found and gpgsm prints BAD
253          signature becuase it is not the correct one. */
254       if (rc == -1)
255         {
256           log_info ("issuer certificate (#");
257           gpgsm_dump_serial (authidno);
258           log_printf ("/");
259           gpgsm_dump_string (s);
260           log_printf (") not found\n");
261         }
262       else if (rc)
263         log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc);
264       ksba_name_release (authid);
265       xfree (authidno);
266       /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
267     }
268   
269   if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
270       rc = keydb_search_subject (kh, issuer);
271   if (rc == -1)
272     {
273       /* Not found, lets see whether we have one in the ephemeral key DB. */
274       int old = keydb_set_ephemeral (kh, 1);
275       if (!old)
276         {
277           keydb_search_reset (kh);
278           rc = keydb_search_subject (kh, issuer);
279         }
280       keydb_set_ephemeral (kh, old);
281     }
282
283   if (rc == -1 && opt.auto_issuer_key_retrieve)
284     {
285       STRLIST names = NULL;
286       int count = 0;
287       char *pattern;
288       const char *s;
289       
290       if (opt.verbose)
291         log_info (_("looking up issuer at external location\n"));
292       /* dirmngr is confused about unknown attributes so has a quick
293          and ugly hack we locate the CN and use this and the
294          following.  Fixme: we should have far better parsing in the
295          dirmngr. */
296       s = strstr (issuer, "CN=");
297       if (!s || s == issuer || s[-1] != ',')
298         s = issuer;
299
300       pattern = xtrymalloc (strlen (s)+2);
301       if (!pattern)
302         return OUT_OF_CORE (errno);
303       strcpy (stpcpy (pattern, "/"), s);
304       add_to_strlist (&names, pattern);
305       xfree (pattern);
306       rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
307       free_strlist (names);
308       if (opt.verbose)
309         log_info (_("number of issuers matching: %d\n"), count);
310       if (rc) 
311         {
312           log_error ("external key lookup failed: %s\n", gpg_strerror (rc));
313           rc = -1;
314         }
315       else if (!count)
316         rc = -1;
317       else
318         {
319           int old;
320           /* The issuers are currently stored in the ephemeral key
321              DB, so we temporary switch to ephemeral mode. */
322           old = keydb_set_ephemeral (kh, 1);
323           keydb_search_reset (kh);
324           rc = keydb_search_subject (kh, issuer);
325           keydb_set_ephemeral (kh, old);
326         }
327     }
328   return rc;
329 }
330
331
332 /* Return the next certificate up in the chain starting at START.
333    Returns -1 when there are no more certificates. */
334 int
335 gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next)
336 {
337   int rc = 0; 
338   char *issuer = NULL;
339   char *subject = NULL;
340   KEYDB_HANDLE kh = keydb_new (0);
341
342   *r_next = NULL;
343   if (!kh)
344     {
345       log_error (_("failed to allocated keyDB handle\n"));
346       rc = gpg_error (GPG_ERR_GENERAL);
347       goto leave;
348     }
349
350   issuer = ksba_cert_get_issuer (start, 0);
351   subject = ksba_cert_get_subject (start, 0);
352   if (!issuer)
353     {
354       log_error ("no issuer found in certificate\n");
355       rc = gpg_error (GPG_ERR_BAD_CERT);
356       goto leave;
357     }
358   if (!subject)
359     {
360       log_error ("no subject found in certificate\n");
361       rc = gpg_error (GPG_ERR_BAD_CERT);
362       goto leave;
363     }
364
365   if (!strcmp (issuer, subject))
366     {
367       rc = -1; /* we are at the root */
368       goto leave; 
369     }
370
371   rc = find_up (kh, start, issuer);
372   if (rc)
373     {
374       /* it is quite common not to have a certificate, so better don't
375          print an error here */
376       if (rc != -1 && opt.verbose > 1)
377         log_error ("failed to find issuer's certificate: rc=%d\n", rc);
378       rc = gpg_error (GPG_ERR_MISSING_CERT);
379       goto leave;
380     }
381
382   rc = keydb_get_cert (kh, r_next);
383   if (rc)
384     {
385       log_error ("failed to get cert: rc=%d\n", rc);
386       rc = gpg_error (GPG_ERR_GENERAL);
387     }
388
389  leave:
390   xfree (issuer);
391   xfree (subject);
392   keydb_release (kh); 
393   return rc;
394 }
395
396
397 /* Check whether the CERT is a root certificate.  Returns True if this
398    is the case. */
399 int
400 gpgsm_is_root_cert (ksba_cert_t cert)
401 {
402   char *issuer;
403   char *subject;
404   int yes;
405
406   issuer = ksba_cert_get_issuer (cert, 0);
407   subject = ksba_cert_get_subject (cert, 0);
408   yes = (issuer && subject && !strcmp (issuer, subject));
409   xfree (issuer);
410   xfree (subject);
411   return yes;
412 }
413
414 \f
415 /* Validate a chain and optionally return the nearest expiration time
416    in R_EXPTIME */
417 int
418 gpgsm_validate_chain (CTRL ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime)
419 {
420   int rc = 0, depth = 0, maxdepth;
421   char *issuer = NULL;
422   char *subject = NULL;
423   KEYDB_HANDLE kh = keydb_new (0);
424   ksba_cert_t subject_cert = NULL, issuer_cert = NULL;
425   ksba_isotime_t current_time;
426   ksba_isotime_t exptime;
427   int any_expired = 0;
428   int any_revoked = 0;
429   int any_no_crl = 0;
430   int any_crl_too_old = 0;
431   int any_no_policy_match = 0;
432
433
434   gnupg_get_isotime (current_time);
435   if (r_exptime)
436     *r_exptime = 0;
437   *exptime = 0;
438
439   if (opt.no_chain_validation)
440     {
441       log_info ("WARNING: bypassing certificate chain validation\n");
442       return 0;
443     }
444   
445   if (!kh)
446     {
447       log_error (_("failed to allocated keyDB handle\n"));
448       rc = gpg_error (GPG_ERR_GENERAL);
449       goto leave;
450     }
451
452   if (DBG_X509)
453     gpgsm_dump_cert ("subject", cert);
454
455   subject_cert = cert;
456   maxdepth = 50;
457
458   for (;;)
459     {
460       xfree (issuer);
461       xfree (subject);
462       issuer = ksba_cert_get_issuer (subject_cert, 0);
463       subject = ksba_cert_get_subject (subject_cert, 0);
464
465       if (!issuer)
466         {
467           log_error ("no issuer found in certificate\n");
468           rc = gpg_error (GPG_ERR_BAD_CERT);
469           goto leave;
470         }
471
472       {
473         ksba_isotime_t not_before, not_after;
474
475         rc = ksba_cert_get_validity (subject_cert, 0, not_before);
476         if (!rc)
477           rc = ksba_cert_get_validity (subject_cert, 1, not_after);
478         if (rc)
479           {
480             log_error (_("certificate with invalid validity: %s\n"),
481                        gpg_strerror (rc));
482             rc = gpg_error (GPG_ERR_BAD_CERT);
483             goto leave;
484           }
485
486         if (*not_after)
487           {
488             if (!*exptime)
489               gnupg_copy_time (exptime, not_after);
490             else if (strcmp (not_after, exptime) < 0 )
491               gnupg_copy_time (exptime, not_after);
492           }
493
494         if (*not_before && strcmp (current_time, not_before) < 0 )
495           {
496             log_error ("certificate too young; valid from ");
497             gpgsm_dump_time (not_before);
498             log_printf ("\n");
499             rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG);
500             goto leave;
501           }            
502         if (not_after && strcmp (current_time, not_after) > 0 )
503           {
504             log_error ("certificate has expired at ");
505             gpgsm_dump_time (not_after);
506             log_printf ("\n");
507             any_expired = 1;
508           }            
509       }
510
511       rc = unknown_criticals (subject_cert);
512       if (rc)
513         goto leave;
514
515       if (!opt.no_policy_check)
516         {
517           rc = check_cert_policy (subject_cert);
518           if (gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH)
519             {
520               any_no_policy_match = 1;
521               rc = 1;
522             }
523           else if (rc)
524             goto leave;
525         }
526
527       if (!opt.no_crl_check || ctrl->use_ocsp)
528         {
529           rc = gpgsm_dirmngr_isvalid (subject_cert, ctrl->use_ocsp);
530           if (rc)
531             {
532               /* Fixme: We should change the wording because we may
533                  have used OCSP. */
534               switch (gpg_err_code (rc))
535                 {
536                 case GPG_ERR_CERT_REVOKED:
537                   log_error (_("the certificate has been revoked\n"));
538                   any_revoked = 1;
539                   /* Store that in the keybox so that key listings are
540                      able to return the revoked flag.  We don't care
541                      about error, though. */
542                   keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0,
543                                         VALIDITY_REVOKED);
544                   break;
545                 case GPG_ERR_NO_CRL_KNOWN:
546                   log_error (_("no CRL found for certificate\n"));
547                   any_no_crl = 1;
548                   break;
549                 case GPG_ERR_CRL_TOO_OLD:
550                   log_error (_("the available CRL is too old\n"));
551                   log_info (_("please make sure that the "
552                               "\"dirmngr\" is properly installed\n"));
553                   any_crl_too_old = 1;
554                   break;
555                 default:
556                   log_error (_("checking the CRL failed: %s\n"),
557                              gpg_strerror (rc));
558                   goto leave;
559                 }
560               rc = 0;
561             }
562         }
563
564       if (subject && !strcmp (issuer, subject))
565         {
566           if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
567             {
568               log_error ("selfsigned certificate has a BAD signatures\n");
569               rc = gpg_error (depth? GPG_ERR_BAD_CERT_CHAIN
570                                    : GPG_ERR_BAD_CERT);
571               goto leave;
572             }
573           rc = allowed_ca (subject_cert, NULL);
574           if (rc)
575             goto leave;
576
577           rc = gpgsm_agent_istrusted (subject_cert);
578           if (!rc)
579             ;
580           else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
581             {
582               int rc2;
583
584               char *fpr = gpgsm_get_fingerprint_string (subject_cert,
585                                                         GCRY_MD_SHA1);
586               log_info (_("root certificate is not marked trusted\n"));
587               log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
588               xfree (fpr);
589               rc2 = gpgsm_agent_marktrusted (subject_cert);
590               if (!rc2)
591                 {
592                   log_info (_("root certificate has now"
593                               " been marked as trusted\n"));
594                   rc = 0;
595                 }
596               else 
597                 {
598                   gpgsm_dump_cert ("issuer", subject_cert);
599                   log_info ("after checking the fingerprint, you may want "
600                             "to add it manually to the list of trusted "
601                             "certificates.\n");
602                 }
603             }
604           else 
605             {
606               log_error (_("checking the trust list failed: %s\n"),
607                          gpg_strerror (rc));
608             }
609           
610           break;  /* okay, a self-signed certicate is an end-point */
611         }
612       
613       depth++;
614       if (depth > maxdepth)
615         {
616           log_error (_("certificate chain too long\n"));
617           rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
618           goto leave;
619         }
620
621       /* find the next cert up the tree */
622       keydb_search_reset (kh);
623       rc = find_up (kh, subject_cert, issuer);
624       if (rc)
625         {
626           if (rc == -1)
627             {
628               log_info ("issuer certificate (#/");
629               gpgsm_dump_string (issuer);
630               log_printf (") not found\n");
631             }
632           else
633             log_error ("failed to find issuer's certificate: rc=%d\n", rc);
634           rc = gpg_error (GPG_ERR_MISSING_CERT);
635           goto leave;
636         }
637
638       ksba_cert_release (issuer_cert); issuer_cert = NULL;
639       rc = keydb_get_cert (kh, &issuer_cert);
640       if (rc)
641         {
642           log_error ("failed to get cert: rc=%d\n", rc);
643           rc = gpg_error (GPG_ERR_GENERAL);
644           goto leave;
645         }
646
647       if (DBG_X509)
648         {
649           log_debug ("got issuer's certificate:\n");
650           gpgsm_dump_cert ("issuer", issuer_cert);
651         }
652
653       if (gpgsm_check_cert_sig (issuer_cert, subject_cert) )
654         {
655           log_error ("certificate has a BAD signatures\n");
656           rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
657           goto leave;
658         }
659
660       {
661         int chainlen;
662         rc = allowed_ca (issuer_cert, &chainlen);
663         if (rc)
664           goto leave;
665         if (chainlen >= 0 && (depth - 1) > chainlen)
666           {
667             log_error (_("certificate chain longer than allowed by CA (%d)\n"),
668                        chainlen);
669             rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
670             goto leave;
671           }
672       }
673
674       rc = gpgsm_cert_use_cert_p (issuer_cert);
675       if (rc)
676         {
677           char numbuf[50];
678           sprintf (numbuf, "%d", rc);
679           gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage",
680                          numbuf, NULL);
681           rc = 0;
682         }
683
684       if (opt.verbose)
685         log_info ("certificate is good\n");
686       
687       keydb_search_reset (kh);
688       subject_cert = issuer_cert;
689       issuer_cert = NULL;
690     }
691
692   if (opt.no_policy_check)
693     log_info ("policies not checked due to --disable-policy-checks option\n");
694   if (opt.no_crl_check && !ctrl->use_ocsp)
695     log_info ("CRLs not checked due to --disable-crl-checks option\n");
696
697   if (!rc)
698     { /* If we encountered an error somewhere during the checks, set
699          the error code to the most critical one */
700       if (any_revoked)
701         rc = gpg_error (GPG_ERR_CERT_REVOKED);
702       else if (any_no_crl)
703         rc = gpg_error (GPG_ERR_NO_CRL_KNOWN);
704       else if (any_crl_too_old)
705         rc = gpg_error (GPG_ERR_CRL_TOO_OLD);
706       else if (any_no_policy_match)
707         rc = gpg_error (GPG_ERR_NO_POLICY_MATCH);
708       else if (any_expired)
709         rc = gpg_error (GPG_ERR_CERT_EXPIRED);
710     }
711   
712  leave:
713   if (r_exptime)
714     gnupg_copy_time (r_exptime, exptime);
715   xfree (issuer);
716   keydb_release (kh); 
717   ksba_cert_release (issuer_cert);
718   if (subject_cert != cert)
719     ksba_cert_release (subject_cert);
720   return rc;
721 }
722
723
724 /* Check that the given certificate is valid but DO NOT check any
725    constraints.  We assume that the issuers certificate is already in
726    the DB and that this one is valid; which it should be because it
727    has been checked using this function. */
728 int
729 gpgsm_basic_cert_check (ksba_cert_t cert)
730 {
731   int rc = 0;
732   char *issuer = NULL;
733   char *subject = NULL;
734   KEYDB_HANDLE kh = keydb_new (0);
735   ksba_cert_t issuer_cert = NULL;
736
737   if (opt.no_chain_validation)
738     {
739       log_info ("WARNING: bypassing basic certificate checks\n");
740       return 0;
741     }
742
743   if (!kh)
744     {
745       log_error (_("failed to allocated keyDB handle\n"));
746       rc = gpg_error (GPG_ERR_GENERAL);
747       goto leave;
748     }
749
750   issuer = ksba_cert_get_issuer (cert, 0);
751   subject = ksba_cert_get_subject (cert, 0);
752   if (!issuer)
753     {
754       log_error ("no issuer found in certificate\n");
755       rc = gpg_error (GPG_ERR_BAD_CERT);
756       goto leave;
757     }
758
759   if (subject && !strcmp (issuer, subject))
760     {
761       if (gpgsm_check_cert_sig (cert, cert) )
762         {
763           log_error ("selfsigned certificate has a BAD signatures\n");
764           rc = gpg_error (GPG_ERR_BAD_CERT);
765           goto leave;
766         }
767     }
768   else
769     {
770       /* find the next cert up the tree */
771       keydb_search_reset (kh);
772       rc = find_up (kh, cert, issuer);
773       if (rc)
774         {
775           if (rc == -1)
776             {
777               log_info ("issuer certificate (#/");
778               gpgsm_dump_string (issuer);
779               log_printf (") not found\n");
780             }
781           else
782             log_error ("failed to find issuer's certificate: rc=%d\n", rc);
783           rc = gpg_error (GPG_ERR_MISSING_CERT);
784           goto leave;
785         }
786       
787       ksba_cert_release (issuer_cert); issuer_cert = NULL;
788       rc = keydb_get_cert (kh, &issuer_cert);
789       if (rc)
790         {
791           log_error ("failed to get cert: rc=%d\n", rc);
792           rc = gpg_error (GPG_ERR_GENERAL);
793           goto leave;
794         }
795
796       if (gpgsm_check_cert_sig (issuer_cert, cert) )
797         {
798           log_error ("certificate has a BAD signatures\n");
799           rc = gpg_error (GPG_ERR_BAD_CERT);
800           goto leave;
801         }
802       if (opt.verbose)
803         log_info ("certificate is good\n");
804     }
805
806  leave:
807   xfree (issuer);
808   keydb_release (kh); 
809   ksba_cert_release (issuer_cert);
810   return rc;
811 }
812