A whole bunch of changes to allow building for W32.
[gnupg.git] / sm / certchain.c
1 /* certchain.c - certificate chain validation
2  * Copyright (C) 2001, 2002, 2003, 2004 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 <stdarg.h>
29 #include <assert.h>
30
31 #define JNLIB_NEED_LOG_LOGV /* We need log_logv. */
32
33 #include "gpgsm.h"
34 #include <gcrypt.h>
35 #include <ksba.h>
36
37 #include "keydb.h"
38 #include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
39 #include "i18n.h"
40
41
42 /* If LISTMODE is true, print FORMAT using LISTMODE to FP.  If
43    LISTMODE is false, use the string to print an log_info or, if
44    IS_ERROR is true, and log_error. */
45 static void
46 do_list (int is_error, int listmode, FILE *fp, const char *format, ...)
47 {
48   va_list arg_ptr;
49
50   va_start (arg_ptr, format) ;
51   if (listmode)
52     {
53       if (fp)
54         {
55           fputs ("  [", fp);
56           vfprintf (fp, format, arg_ptr);
57           fputs ("]\n", fp);
58         }
59     }
60   else
61     {
62       log_logv (is_error? JNLIB_LOG_ERROR: JNLIB_LOG_INFO, format, arg_ptr);
63       log_printf ("\n");
64     }
65   va_end (arg_ptr);
66 }
67
68 /* Return 0 if A and B are equal. */
69 static int
70 compare_certs (ksba_cert_t a, ksba_cert_t b)
71 {
72   const unsigned char *img_a, *img_b;
73   size_t len_a, len_b;
74
75   img_a = ksba_cert_get_image (a, &len_a);
76   if (!img_a)
77     return 1;
78   img_b = ksba_cert_get_image (b, &len_b);
79   if (!img_b)
80     return 1;
81   return !(len_a == len_b && !memcmp (img_a, img_b, len_a));
82 }
83
84
85 static int
86 unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp)
87 {
88   static const char *known[] = {
89     "2.5.29.15", /* keyUsage */
90     "2.5.29.19", /* basic Constraints */
91     "2.5.29.32", /* certificatePolicies */
92     "2.5.29.37", /* extendedKeyUsage - handled by certlist.c */
93     NULL
94   };
95   int rc = 0, i, idx, crit;
96   const char *oid;
97   gpg_error_t err;
98
99   for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
100                                              &oid, &crit, NULL, NULL));idx++)
101     {
102       if (!crit)
103         continue;
104       for (i=0; known[i] && strcmp (known[i],oid); i++)
105         ;
106       if (!known[i])
107         {
108           do_list (1, listmode, fp,
109                    _("critical certificate extension %s is not supported"),
110                    oid);
111           rc = gpg_error (GPG_ERR_UNSUPPORTED_CERT);
112         }
113     }
114   if (err && gpg_err_code (err) != GPG_ERR_EOF)
115     rc = err;
116
117   return rc;
118 }
119
120 static int
121 allowed_ca (ksba_cert_t cert, int *chainlen, int listmode, FILE *fp)
122 {
123   gpg_error_t err;
124   int flag;
125
126   err = ksba_cert_is_ca (cert, &flag, chainlen);
127   if (err)
128     return err;
129   if (!flag)
130     {
131       do_list (1, listmode, fp,_("issuer certificate is not marked as a CA"));
132       return gpg_error (GPG_ERR_BAD_CA_CERT);
133     }
134   return 0;
135 }
136
137
138 static int
139 check_cert_policy (ksba_cert_t cert, int listmode, FILE *fplist)
140 {
141   gpg_error_t err;
142   char *policies;
143   FILE *fp;
144   int any_critical;
145
146   err = ksba_cert_get_cert_policies (cert, &policies);
147   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
148     return 0; /* no policy given */
149   if (err)
150     return err;
151
152   /* STRING is a line delimited list of certifiate policies as stored
153      in the certificate.  The line itself is colon delimited where the
154      first field is the OID of the policy and the second field either
155      N or C for normal or critical extension */
156
157   if (opt.verbose > 1 && !listmode)
158     log_info ("certificate's policy list: %s\n", policies);
159
160   /* The check is very minimal but won't give false positives */
161   any_critical = !!strstr (policies, ":C");
162
163   if (!opt.policy_file)
164     { 
165       xfree (policies);
166       if (any_critical)
167         {
168           do_list (1, listmode, fplist,
169                    _("critical marked policy without configured policies"));
170           return gpg_error (GPG_ERR_NO_POLICY_MATCH);
171         }
172       return 0;
173     }
174
175   fp = fopen (opt.policy_file, "r");
176   if (!fp)
177     {
178       log_error ("failed to open `%s': %s\n",
179                  opt.policy_file, strerror (errno));
180       xfree (policies);
181       /* With no critical policies this is only a warning */
182       if (!any_critical)
183         {
184           do_list (0, listmode, fplist,
185                    _("note: non-critical certificate policy not allowed"));
186           return 0;
187         }
188       do_list (1, listmode, fplist,
189                _("certificate policy not allowed"));
190       return gpg_error (GPG_ERR_NO_POLICY_MATCH);
191     }
192
193   for (;;) 
194     {
195       int c;
196       char *p, line[256];
197       char *haystack, *allowed;
198
199       /* read line */
200       do
201         {
202           if (!fgets (line, DIM(line)-1, fp) )
203             {
204               gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
205
206               xfree (policies);
207               if (feof (fp))
208                 {
209                   fclose (fp);
210                   /* With no critical policies this is only a warning */
211                   if (!any_critical)
212                     {
213                       do_list (0, listmode, fplist,
214                      _("note: non-critical certificate policy not allowed"));
215                       return 0;
216                     }
217                   do_list (1, listmode, fplist,
218                            _("certificate policy not allowed"));
219                   return gpg_error (GPG_ERR_NO_POLICY_MATCH);
220                 }
221               fclose (fp);
222               return tmperr;
223             }
224       
225           if (!*line || line[strlen(line)-1] != '\n')
226             {
227               /* eat until end of line */
228               while ( (c=getc (fp)) != EOF && c != '\n')
229                 ;
230               fclose (fp);
231               xfree (policies);
232               return gpg_error (*line? GPG_ERR_LINE_TOO_LONG
233                                      : GPG_ERR_INCOMPLETE_LINE);
234             }
235           
236           /* Allow for empty lines and spaces */
237           for (p=line; spacep (p); p++)
238             ;
239         }
240       while (!*p || *p == '\n' || *p == '#');
241   
242       /* parse line */
243       for (allowed=line; spacep (allowed); allowed++)
244         ;
245       p = strpbrk (allowed, " :\n");
246       if (!*p || p == allowed)
247         {
248           fclose (fp);
249           xfree (policies);
250           return gpg_error (GPG_ERR_CONFIGURATION);
251         }
252       *p = 0; /* strip the rest of the line */
253       /* See whether we find ALLOWED (which is an OID) in POLICIES */
254       for (haystack=policies; (p=strstr (haystack, allowed)); haystack = p+1)
255         {
256           if ( !(p == policies || p[-1] == '\n') )
257             continue; /* Does not match the begin of a line. */
258           if (p[strlen (allowed)] != ':')
259             continue; /* The length does not match. */
260           /* Yep - it does match so return okay. */
261           fclose (fp);
262           xfree (policies);
263           return 0;
264         }
265     }
266 }
267
268
269 static void
270 find_up_store_certs_cb (void *cb_value, ksba_cert_t cert)
271 {
272   if (keydb_store_cert (cert, 1, NULL))
273     log_error ("error storing issuer certificate as ephemeral\n");
274   ++*(int*)cb_value;
275 }
276
277
278 static int
279 find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
280 {
281   ksba_name_t authid;
282   ksba_sexp_t authidno;
283   int rc = -1;
284
285   if (!ksba_cert_get_auth_key_id (cert, NULL, &authid, &authidno))
286     {
287       const char *s = ksba_name_enum (authid, 0);
288       if (s && *authidno)
289         {
290           rc = keydb_search_issuer_sn (kh, s, authidno);
291           if (rc)
292               keydb_search_reset (kh);
293           
294           /* In case of an error try the ephemeral DB.  We can't do
295              that in find-next mode because we can't keep the search
296              state then. */
297           if (rc == -1 && !find_next)
298             { 
299               int old = keydb_set_ephemeral (kh, 1);
300               if (!old)
301                 {
302                   rc = keydb_search_issuer_sn (kh, s, authidno);
303                   if (rc)
304                     keydb_search_reset (kh);
305                 }
306               keydb_set_ephemeral (kh, old);
307             }
308         }
309       /* Print a note so that the user does not feel too helpless when
310          an issuer certificate was found and gpgsm prints BAD
311          signature because it is not the correct one. */
312       if (rc == -1)
313         {
314           log_info ("%sissuer certificate (#", find_next?"next ":"");
315           gpgsm_dump_serial (authidno);
316           log_printf ("/");
317           gpgsm_dump_string (s);
318           log_printf (") not found\n");
319         }
320       else if (rc)
321         log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc);
322       ksba_name_release (authid);
323       xfree (authidno);
324       /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
325     }
326   
327   if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
328     rc = keydb_search_subject (kh, issuer);
329   if (rc == -1 && !find_next)
330     {
331       /* Not found, lets see whether we have one in the ephemeral key DB. */
332       int old = keydb_set_ephemeral (kh, 1);
333       if (!old)
334         {
335           keydb_search_reset (kh);
336           rc = keydb_search_subject (kh, issuer);
337         }
338       keydb_set_ephemeral (kh, old);
339     }
340
341   if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
342     {
343       STRLIST names = NULL;
344       int count = 0;
345       char *pattern;
346       const char *s;
347       
348       if (opt.verbose)
349         log_info (_("looking up issuer at external location\n"));
350       /* dirmngr is confused about unknown attributes so as a quick
351          and ugly hack we locate the CN and use this and the
352          following.  Fixme: we should have far better parsing in the
353          dirmngr. */
354       s = strstr (issuer, "CN=");
355       if (!s || s == issuer || s[-1] != ',')
356         s = issuer;
357
358       pattern = xtrymalloc (strlen (s)+2);
359       if (!pattern)
360         return OUT_OF_CORE (errno);
361       strcpy (stpcpy (pattern, "/"), s);
362       add_to_strlist (&names, pattern);
363       xfree (pattern);
364       rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
365       free_strlist (names);
366       if (opt.verbose)
367         log_info (_("number of issuers matching: %d\n"), count);
368       if (rc) 
369         {
370           log_error ("external key lookup failed: %s\n", gpg_strerror (rc));
371           rc = -1;
372         }
373       else if (!count)
374         rc = -1;
375       else
376         {
377           int old;
378           /* The issuers are currently stored in the ephemeral key
379              DB, so we temporary switch to ephemeral mode. */
380           old = keydb_set_ephemeral (kh, 1);
381           keydb_search_reset (kh);
382           rc = keydb_search_subject (kh, issuer);
383           keydb_set_ephemeral (kh, old);
384         }
385     }
386   return rc;
387 }
388
389
390 /* Return the next certificate up in the chain starting at START.
391    Returns -1 when there are no more certificates. */
392 int
393 gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next)
394 {
395   int rc = 0; 
396   char *issuer = NULL;
397   char *subject = NULL;
398   KEYDB_HANDLE kh = keydb_new (0);
399
400   *r_next = NULL;
401   if (!kh)
402     {
403       log_error (_("failed to allocated keyDB handle\n"));
404       rc = gpg_error (GPG_ERR_GENERAL);
405       goto leave;
406     }
407
408   issuer = ksba_cert_get_issuer (start, 0);
409   subject = ksba_cert_get_subject (start, 0);
410   if (!issuer)
411     {
412       log_error ("no issuer found in certificate\n");
413       rc = gpg_error (GPG_ERR_BAD_CERT);
414       goto leave;
415     }
416   if (!subject)
417     {
418       log_error ("no subject found in certificate\n");
419       rc = gpg_error (GPG_ERR_BAD_CERT);
420       goto leave;
421     }
422
423   if (!strcmp (issuer, subject))
424     {
425       rc = -1; /* we are at the root */
426       goto leave; 
427     }
428
429   rc = find_up (kh, start, issuer, 0);
430   if (rc)
431     {
432       /* it is quite common not to have a certificate, so better don't
433          print an error here */
434       if (rc != -1 && opt.verbose > 1)
435         log_error ("failed to find issuer's certificate: rc=%d\n", rc);
436       rc = gpg_error (GPG_ERR_MISSING_CERT);
437       goto leave;
438     }
439
440   rc = keydb_get_cert (kh, r_next);
441   if (rc)
442     {
443       log_error ("failed to get cert: rc=%d\n", rc);
444       rc = gpg_error (GPG_ERR_GENERAL);
445     }
446
447  leave:
448   xfree (issuer);
449   xfree (subject);
450   keydb_release (kh); 
451   return rc;
452 }
453
454
455 /* Check whether the CERT is a root certificate.  Returns True if this
456    is the case. */
457 int
458 gpgsm_is_root_cert (ksba_cert_t cert)
459 {
460   char *issuer;
461   char *subject;
462   int yes;
463
464   issuer = ksba_cert_get_issuer (cert, 0);
465   subject = ksba_cert_get_subject (cert, 0);
466   yes = (issuer && subject && !strcmp (issuer, subject));
467   xfree (issuer);
468   xfree (subject);
469   return yes;
470 }
471
472
473 /* This is a helper for gpgsm_validate_chain. */
474 static gpg_error_t 
475 is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp,
476                      ksba_cert_t subject_cert, ksba_cert_t issuer_cert,
477                      int *any_revoked, int *any_no_crl, int *any_crl_too_old)
478 {
479   if (!opt.no_crl_check || ctrl->use_ocsp)
480     {
481       gpg_error_t err;
482
483       err = gpgsm_dirmngr_isvalid (ctrl,
484                                    subject_cert, issuer_cert, ctrl->use_ocsp);
485       if (err)
486         {
487           /* Fixme: We should change the wording because we may
488              have used OCSP. */
489           switch (gpg_err_code (err))
490             {
491             case GPG_ERR_CERT_REVOKED:
492               do_list (1, lm, fp, _("certificate has been revoked"));
493               *any_revoked = 1;
494               /* Store that in the keybox so that key listings are
495                  able to return the revoked flag.  We don't care
496                  about error, though. */
497               keydb_set_cert_flags (subject_cert, KEYBOX_FLAG_VALIDITY, 0,
498                                     VALIDITY_REVOKED);
499               break;
500             case GPG_ERR_NO_CRL_KNOWN:
501               do_list (1, lm, fp, _("no CRL found for certificate"));
502               *any_no_crl = 1;
503               break;
504             case GPG_ERR_CRL_TOO_OLD:
505               do_list (1, lm, fp, _("the available CRL is too old"));
506               if (!lm)
507                 log_info (_("please make sure that the "
508                             "\"dirmngr\" is properly installed\n"));
509               *any_crl_too_old = 1;
510               break;
511             default:
512               do_list (1, lm, fp, _("checking the CRL failed: %s"),
513                        gpg_strerror (err));
514               return err;
515             }
516         }
517     }
518   return 0;
519 }
520
521
522 \f
523 /* Validate a chain and optionally return the nearest expiration time
524    in R_EXPTIME. With LISTMODE set to 1 a special listmode is
525    activated where only information about the certificate is printed
526    to FP and no output is send to the usual log stream. 
527
528    Defined flag bits: 0 - do not do any dirmngr isvalid checks.
529 */
530 int
531 gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
532                       int listmode, FILE *fp, unsigned int flags)
533 {
534   int rc = 0, depth = 0, maxdepth;
535   char *issuer = NULL;
536   char *subject = NULL;
537   KEYDB_HANDLE kh = NULL;
538   ksba_cert_t subject_cert = NULL, issuer_cert = NULL;
539   ksba_isotime_t current_time;
540   ksba_isotime_t exptime;
541   int any_expired = 0;
542   int any_revoked = 0;
543   int any_no_crl = 0;
544   int any_crl_too_old = 0;
545   int any_no_policy_match = 0;
546   int lm = listmode;
547
548   gnupg_get_isotime (current_time);
549   if (r_exptime)
550     *r_exptime = 0;
551   *exptime = 0;
552
553   if (opt.no_chain_validation && !listmode)
554     {
555       log_info ("WARNING: bypassing certificate chain validation\n");
556       return 0;
557     }
558
559   kh = keydb_new (0);
560   if (!kh)
561     {
562       log_error (_("failed to allocated keyDB handle\n"));
563       rc = gpg_error (GPG_ERR_GENERAL);
564       goto leave;
565     }
566
567   if (DBG_X509 && !listmode)
568     gpgsm_dump_cert ("target", cert);
569
570   subject_cert = cert;
571   maxdepth = 50;
572
573   for (;;)
574     {
575       xfree (issuer);
576       xfree (subject);
577       issuer = ksba_cert_get_issuer (subject_cert, 0);
578       subject = ksba_cert_get_subject (subject_cert, 0);
579
580       if (!issuer)
581         {
582           do_list (1, lm, fp,  _("no issuer found in certificate"));
583           rc = gpg_error (GPG_ERR_BAD_CERT);
584           goto leave;
585         }
586
587       {
588         ksba_isotime_t not_before, not_after;
589
590         rc = ksba_cert_get_validity (subject_cert, 0, not_before);
591         if (!rc)
592           rc = ksba_cert_get_validity (subject_cert, 1, not_after);
593         if (rc)
594           {
595             do_list (1, lm, fp, _("certificate with invalid validity: %s"),
596                      gpg_strerror (rc));
597             rc = gpg_error (GPG_ERR_BAD_CERT);
598             goto leave;
599           }
600
601         if (*not_after)
602           {
603             if (!*exptime)
604               gnupg_copy_time (exptime, not_after);
605             else if (strcmp (not_after, exptime) < 0 )
606               gnupg_copy_time (exptime, not_after);
607           }
608
609         if (*not_before && strcmp (current_time, not_before) < 0 )
610           {
611             do_list (1, lm, fp, _("certificate not yet valid"));
612             if (!lm)
613               {
614                 log_info ("(valid from ");
615                 gpgsm_dump_time (not_before);
616                 log_printf (")\n");
617               }
618             rc = gpg_error (GPG_ERR_CERT_TOO_YOUNG);
619             goto leave;
620           }            
621         if (*not_after && strcmp (current_time, not_after) > 0 )
622           {
623             do_list (opt.ignore_expiration?0:1, lm, fp,
624                      _("certificate has expired"));
625             if (!lm)
626               {
627                 log_info ("(expired at ");
628                 gpgsm_dump_time (not_after);
629                 log_printf (")\n");
630               }
631             if (opt.ignore_expiration)
632                 log_info ("WARNING: ignoring expiration\n");
633             else
634               any_expired = 1;
635           }            
636       }
637
638       rc = unknown_criticals (subject_cert, listmode, fp);
639       if (rc)
640         goto leave;
641
642       if (!opt.no_policy_check)
643         {
644           rc = check_cert_policy (subject_cert, listmode, fp);
645           if (gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH)
646             {
647               any_no_policy_match = 1;
648               rc = 1;
649             }
650           else if (rc)
651             goto leave;
652         }
653
654
655       /* Is this a self-signed certificate? */
656       if (subject && !strcmp (issuer, subject))
657         {  /* Yes. */
658           if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
659             {
660               do_list (1, lm, fp,
661                        _("selfsigned certificate has a BAD signature"));
662               if (DBG_X509)
663                 {
664                   gpgsm_dump_cert ("self-signing cert", subject_cert);
665                 }
666               rc = gpg_error (depth? GPG_ERR_BAD_CERT_CHAIN
667                                    : GPG_ERR_BAD_CERT);
668               goto leave;
669             }
670           rc = allowed_ca (subject_cert, NULL, listmode, fp);
671           if (rc)
672             goto leave;
673
674           rc = gpgsm_agent_istrusted (ctrl, subject_cert);
675           if (!rc)
676             ;
677           else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
678             {
679               do_list (0, lm, fp, _("root certificate is not marked trusted"));
680               /* If we already figured out that the certificate is
681                  expired it does not make much sense to ask the user
682                  whether we wants to trust the root certificate.  He
683                  should do this only if the certificate under question
684                  will then be usable. */
685               if (!lm && !any_expired)
686                 {
687                   int rc2;
688                   char *fpr = gpgsm_get_fingerprint_string (subject_cert,
689                                                             GCRY_MD_SHA1);
690                   log_info (_("fingerprint=%s\n"), fpr? fpr : "?");
691                   xfree (fpr);
692                   rc2 = gpgsm_agent_marktrusted (ctrl, subject_cert);
693                   if (!rc2)
694                     {
695                       log_info (_("root certificate has now"
696                                   " been marked as trusted\n"));
697                       rc = 0;
698                     }
699                   else 
700                     {
701                       gpgsm_dump_cert ("issuer", subject_cert);
702                       log_info ("after checking the fingerprint, you may want "
703                                 "to add it manually to the list of trusted "
704                                 "certificates.\n");
705                     }
706                 }
707             }
708           else 
709             {
710               log_error (_("checking the trust list failed: %s\n"),
711                          gpg_strerror (rc));
712             }
713           
714           if (rc)
715             goto leave;
716
717           /* Check for revocations etc. */
718           if ((flags & 1))
719             rc = 0;
720           else if (any_expired)
721             ; /* Don't bother to run the expensive CRL check then. */
722           else
723             rc = is_cert_still_valid (ctrl, lm, fp,
724                                       subject_cert, subject_cert,
725                                       &any_revoked, &any_no_crl,
726                                       &any_crl_too_old);
727           if (rc)
728             goto leave;
729
730           break;  /* Okay: a self-signed certicate is an end-point. */
731         }
732       
733       depth++;
734       if (depth > maxdepth)
735         {
736           do_list (1, lm, fp, _("certificate chain too long\n"));
737           rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
738           goto leave;
739         }
740
741       /* find the next cert up the tree */
742       keydb_search_reset (kh);
743       rc = find_up (kh, subject_cert, issuer, 0);
744       if (rc)
745         {
746           if (rc == -1)
747             {
748               do_list (0, lm, fp, _("issuer certificate not found"));
749               if (!lm)
750                 {
751                   log_info ("issuer certificate: #/");
752                   gpgsm_dump_string (issuer);
753                   log_printf ("\n");
754                 }
755             }
756           else
757             log_error ("failed to find issuer's certificate: rc=%d\n", rc);
758           rc = gpg_error (GPG_ERR_MISSING_CERT);
759           goto leave;
760         }
761
762       ksba_cert_release (issuer_cert); issuer_cert = NULL;
763       rc = keydb_get_cert (kh, &issuer_cert);
764       if (rc)
765         {
766           log_error ("failed to get cert: rc=%d\n", rc);
767           rc = gpg_error (GPG_ERR_GENERAL);
768           goto leave;
769         }
770
771     try_another_cert:
772       if (DBG_X509)
773         {
774           log_debug ("got issuer's certificate:\n");
775           gpgsm_dump_cert ("issuer", issuer_cert);
776         }
777
778       rc = gpgsm_check_cert_sig (issuer_cert, subject_cert);
779       if (rc)
780         {
781           do_list (0, lm, fp, _("certificate has a BAD signature"));
782           if (DBG_X509)
783             {
784               gpgsm_dump_cert ("signing issuer", issuer_cert);
785               gpgsm_dump_cert ("signed subject", subject_cert);
786             }
787           if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE)
788             {
789               /* We now try to find other issuer certificates which
790                  might have been used.  This is required because some
791                  CAs are reusing the issuer and subject DN for new
792                  root certificates. */
793               rc = find_up (kh, subject_cert, issuer, 1);
794               if (!rc)
795                 {
796                   ksba_cert_t tmp_cert;
797
798                   rc = keydb_get_cert (kh, &tmp_cert);
799                   if (rc || !compare_certs (issuer_cert, tmp_cert))
800                     {
801                       /* The find next did not work or returned an
802                          identical certificate.  We better stop here
803                          to avoid infinite checks. */
804                       rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
805                       ksba_cert_release (tmp_cert);
806                     }
807                   else
808                     {
809                       do_list (0, lm, fp, _("found another possible matching "
810                                             "CA certificate - trying again"));
811                       ksba_cert_release (issuer_cert); 
812                       issuer_cert = tmp_cert;
813                       goto try_another_cert;
814                     }
815                 }
816             }
817
818           /* We give a more descriptive error code than the one
819              returned from the signature checking. */
820           rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
821           goto leave;
822         }
823
824       {
825         int chainlen;
826         rc = allowed_ca (issuer_cert, &chainlen, listmode, fp);
827         if (rc)
828           goto leave;
829         if (chainlen >= 0 && (depth - 1) > chainlen)
830           {
831             do_list (1, lm, fp,
832                      _("certificate chain longer than allowed by CA (%d)"),
833                      chainlen);
834             rc = gpg_error (GPG_ERR_BAD_CERT_CHAIN);
835             goto leave;
836           }
837       }
838
839       if (!listmode)
840         {
841           rc = gpgsm_cert_use_cert_p (issuer_cert);
842           if (rc)
843             {
844               char numbuf[50];
845               sprintf (numbuf, "%d", rc);
846               gpgsm_status2 (ctrl, STATUS_ERROR, "certcert.issuer.keyusage",
847                              numbuf, NULL);
848               goto leave;
849             }
850         }
851
852       /* Check for revocations etc. */
853       if ((flags & 1))
854         rc = 0;
855       else if (any_expired)
856         ; /* Don't bother to run the expensive CRL check then. */
857       else
858         rc = is_cert_still_valid (ctrl, lm, fp,
859                                   subject_cert, issuer_cert,
860                                   &any_revoked, &any_no_crl, &any_crl_too_old);
861       if (rc)
862         goto leave;
863
864
865       if (opt.verbose && !listmode)
866         log_info ("certificate is good\n");
867       
868       keydb_search_reset (kh);
869       subject_cert = issuer_cert;
870       issuer_cert = NULL;
871     }
872
873   if (!listmode)
874     {
875       if (opt.no_policy_check)
876         log_info ("policies not checked due to %s option\n",
877                   "--disable-policy-checks");
878       if (opt.no_crl_check && !ctrl->use_ocsp)
879         log_info ("CRLs not checked due to %s option\n",
880                   "--disable-crl-checks");
881     }
882
883   if (!rc)
884     { /* If we encountered an error somewhere during the checks, set
885          the error code to the most critical one */
886       if (any_revoked)
887         rc = gpg_error (GPG_ERR_CERT_REVOKED);
888       else if (any_expired)
889         rc = gpg_error (GPG_ERR_CERT_EXPIRED);
890       else if (any_no_crl)
891         rc = gpg_error (GPG_ERR_NO_CRL_KNOWN);
892       else if (any_crl_too_old)
893         rc = gpg_error (GPG_ERR_CRL_TOO_OLD);
894       else if (any_no_policy_match)
895         rc = gpg_error (GPG_ERR_NO_POLICY_MATCH);
896     }
897   
898  leave:
899   if (r_exptime)
900     gnupg_copy_time (r_exptime, exptime);
901   xfree (issuer);
902   keydb_release (kh); 
903   ksba_cert_release (issuer_cert);
904   if (subject_cert != cert)
905     ksba_cert_release (subject_cert);
906   return rc;
907 }
908
909
910 /* Check that the given certificate is valid but DO NOT check any
911    constraints.  We assume that the issuers certificate is already in
912    the DB and that this one is valid; which it should be because it
913    has been checked using this function. */
914 int
915 gpgsm_basic_cert_check (ksba_cert_t cert)
916 {
917   int rc = 0;
918   char *issuer = NULL;
919   char *subject = NULL;
920   KEYDB_HANDLE kh = keydb_new (0);
921   ksba_cert_t issuer_cert = NULL;
922   
923   if (opt.no_chain_validation)
924     {
925       log_info ("WARNING: bypassing basic certificate checks\n");
926       return 0;
927     }
928
929   if (!kh)
930     {
931       log_error (_("failed to allocated keyDB handle\n"));
932       rc = gpg_error (GPG_ERR_GENERAL);
933       goto leave;
934     }
935
936   issuer = ksba_cert_get_issuer (cert, 0);
937   subject = ksba_cert_get_subject (cert, 0);
938   if (!issuer)
939     {
940       log_error ("no issuer found in certificate\n");
941       rc = gpg_error (GPG_ERR_BAD_CERT);
942       goto leave;
943     }
944
945   if (subject && !strcmp (issuer, subject))
946     {
947       rc = gpgsm_check_cert_sig (cert, cert);
948       if (rc)
949         {
950           log_error ("selfsigned certificate has a BAD signature: %s\n",
951                      gpg_strerror (rc));
952           if (DBG_X509)
953             {
954               gpgsm_dump_cert ("self-signing cert", cert);
955             }
956           rc = gpg_error (GPG_ERR_BAD_CERT);
957           goto leave;
958         }
959     }
960   else
961     {
962       /* find the next cert up the tree */
963       keydb_search_reset (kh);
964       rc = find_up (kh, cert, issuer, 0);
965       if (rc)
966         {
967           if (rc == -1)
968             {
969               log_info ("issuer certificate (#/");
970               gpgsm_dump_string (issuer);
971               log_printf (") not found\n");
972             }
973           else
974             log_error ("failed to find issuer's certificate: rc=%d\n", rc);
975           rc = gpg_error (GPG_ERR_MISSING_CERT);
976           goto leave;
977         }
978       
979       ksba_cert_release (issuer_cert); issuer_cert = NULL;
980       rc = keydb_get_cert (kh, &issuer_cert);
981       if (rc)
982         {
983           log_error ("failed to get cert: rc=%d\n", rc);
984           rc = gpg_error (GPG_ERR_GENERAL);
985           goto leave;
986         }
987
988       rc = gpgsm_check_cert_sig (issuer_cert, cert);
989       if (rc)
990         {
991           log_error ("certificate has a BAD signature: %s\n",
992                      gpg_strerror (rc));
993           rc = gpg_error (GPG_ERR_BAD_CERT);
994           goto leave;
995         }
996       if (opt.verbose)
997         log_info ("certificate is good\n");
998     }
999
1000  leave:
1001   xfree (issuer);
1002   keydb_release (kh); 
1003   ksba_cert_release (issuer_cert);
1004   return rc;
1005 }
1006