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