[svn] GnuPG - r4267 - in trunk: . sm

svn author wk cvs at cvs.gnupg.org
Tue Sep 26 12:00:14 CEST 2006


Author: wk
Date: 2006-09-26 12:00:12 +0200 (Tue, 26 Sep 2006)
New Revision: 4267

Modified:
   trunk/NEWS
   trunk/sm/ChangeLog
   trunk/sm/certchain.c
Log:
Finished implementation of the "relax" flag.


Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2006-09-25 18:29:20 UTC (rev 4266)
+++ trunk/NEWS	2006-09-26 10:00:12 UTC (rev 4267)
@@ -1,7 +1,10 @@
 Noteworthy changes in version 1.9.91
 -------------------------------------------------
 
+ * New "relax" flag for trustlist.txt to allow root CA certificates
+   without BasicContraints.
 
+
 Noteworthy changes in version 1.9.90 (2006-09-25)
 -------------------------------------------------
 

Modified: trunk/sm/ChangeLog
===================================================================
--- trunk/sm/ChangeLog	2006-09-25 18:29:20 UTC (rev 4266)
+++ trunk/sm/ChangeLog	2006-09-26 10:00:12 UTC (rev 4267)
@@ -1,3 +1,9 @@
+2006-09-26  Werner Koch  <wk at g10code.com>
+
+	* certchain.c (gpgsm_validate_chain): More changes for the relax
+	feature.  Use certificate reference counting instead of the old
+	explicit tests. Added a missing free. 
+
 2006-09-25  Werner Koch  <wk at g10code.com>
 
 	* gpgsm.h (struct rootca_flags_s): New.

Modified: trunk/sm/certchain.c
===================================================================
--- trunk/sm/certchain.c	2006-09-25 18:29:20 UTC (rev 4266)
+++ trunk/sm/certchain.c	2006-09-26 10:00:12 UTC (rev 4267)
@@ -695,10 +695,15 @@
     gpgsm_dump_cert ("target", cert);
 
   subject_cert = cert;
+  ksba_cert_ref (subject_cert);
   maxdepth = 50;
 
   for (;;)
     {
+      int is_root;
+      gpg_error_t istrusted_rc;
+      struct rootca_flags_s rootca_flags;
+
       xfree (issuer);
       xfree (subject);
       issuer = ksba_cert_get_issuer (subject_cert, 0);
@@ -711,6 +716,20 @@
           goto leave;
         }
 
+      /* Is this a self-issued certificate (i.e. the root certificate)? */
+      is_root = (subject && !strcmp (issuer, subject));
+      if (is_root)
+        {
+          /* Check early whether the certificate is listed as trusted.
+             We used to do this only later but changed it to call the
+             check right here so that we can access special flags
+             associated with that specific root certificate.  */
+          istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert,
+                                                &rootca_flags);
+        }
+      
+
+      /* Check the validity period. */
       {
         ksba_isotime_t not_before, not_after;
 
@@ -762,10 +781,12 @@
           }            
       }
 
+      /* Assert that we understand all critical extensions. */
       rc = unknown_criticals (subject_cert, listmode, fp);
       if (rc)
         goto leave;
 
+      /* Do a policy check. */
       if (!opt.no_policy_check)
         {
           rc = check_cert_policy (subject_cert, listmode, fp);
@@ -780,23 +801,14 @@
 
 
       /* Is this a self-issued certificate? */
-      if (subject && !strcmp (issuer, subject))
-        {  /* Yes. */
-          gpg_error_t istrusted_rc;
-          struct rootca_flags_s rootca_flags;
-
-          /* Check early whether the certificate is listed as trusted.
-             We used to do this only later but changed it to call the
-             check right here so that we can access special flags
-             associated with that specific root certificate.  */
-          istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert,
-                                                &rootca_flags);
-
-          /* Note, that we could save the following signature check
-             because nobody would be so dump to set up a faked chain
-             and fail in creating a valid self-signed certificate. */
-          if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
+      if (is_root)
+        { 
+          if (!istrusted_rc)
+            ; /* No need to check the certificate for a trusted one. */
+          else if (gpgsm_check_cert_sig (subject_cert, subject_cert) )
             {
+              /* We only check the signature if the certificate is not
+                 trusted for better diagnostics. */
               do_list (1, lm, fp,
                        _("self-signed certificate has a BAD signature"));
               if (DBG_X509)
@@ -920,6 +932,7 @@
           break;  /* Okay: a self-signed certicate is an end-point. */
         }
       
+      /* Take care that the chain does not get too long. */
       depth++;
       if (depth > maxdepth)
         {
@@ -928,7 +941,7 @@
           goto leave;
         }
 
-      /* find the next cert up the tree */
+      /* Find the next cert up the tree. */
       keydb_search_reset (kh);
       rc = find_up (kh, subject_cert, issuer, 0);
       if (rc)
@@ -1013,10 +1026,38 @@
           goto leave;
         }
 
+      is_root = 0;
+      istrusted_rc = -1;
+
+      /* Check that a CA is allowed to issue certificates. */
       {
         int chainlen;
+
         rc = allowed_ca (issuer_cert, &chainlen, listmode, fp);
         if (rc)
+          {
+            /* Not allowed.  Check whether this is a trusted root
+               certificate and whether we allow special exceptions.
+               We could carry the result of the test over to the
+               regular root check at the top of the loop but for
+               clarity we won't do that.  Given that the majority of
+               certificates carry proper BasicContraints our way of
+               overriding an error in the way is justified for
+               performance reasons. */
+            if (gpgsm_is_root_cert (issuer_cert))
+              {
+                is_root = 1;
+                istrusted_rc = gpgsm_agent_istrusted (ctrl, issuer_cert,
+                                                      &rootca_flags);
+                if (!istrusted_rc && rootca_flags.relax)
+                  {
+                    /* Ignore the error due to the relax flag.  */
+                    rc = 0;
+                    chainlen = -1;
+                  }
+              }
+          }
+        if (rc)
           goto leave;
         if (chainlen >= 0 && (depth - 1) > chainlen)
           {
@@ -1028,6 +1069,7 @@
           }
       }
 
+      /* Is the certificate allowed to sign other certificates. */
       if (!listmode)
         {
           rc = gpgsm_cert_use_cert_p (issuer_cert);
@@ -1041,9 +1083,14 @@
             }
         }
 
-      /* Check for revocations etc. */
+      /* Check for revocations etc.  Note that for a root certioficate
+         this test is done a second time later. This should eventually
+         be fixed. */
       if ((flags & 1))
         rc = 0;
+      else if (is_root && (opt.no_trusted_cert_crl_check
+                           || (!istrusted_rc && rootca_flags.relax)))
+        ; 
       else
         rc = is_cert_still_valid (ctrl, lm, fp,
                                   subject_cert, issuer_cert,
@@ -1054,8 +1101,10 @@
 
       if (opt.verbose && !listmode)
         log_info ("certificate is good\n");
-      
+
+      /* For the next round the current issuer becomes the new subject.  */
       keydb_search_reset (kh);
+      ksba_cert_release (subject_cert);
       subject_cert = issuer_cert;
       issuer_cert = NULL;
     } /* End chain traversal. */
@@ -1110,10 +1159,10 @@
   if (r_exptime)
     gnupg_copy_time (r_exptime, exptime);
   xfree (issuer);
+  xfree (subject);
   keydb_release (kh); 
   ksba_cert_release (issuer_cert);
-  if (subject_cert != cert)
-    ksba_cert_release (subject_cert);
+  ksba_cert_release (subject_cert);
   return rc;
 }
 




More information about the Gnupg-commits mailing list