GRSTx509CheckChain() now uses caNl to verify cert chain
authorMarcel Poul <marcel.poul@cern.ch>
Mon, 15 Oct 2012 12:51:16 +0000 (12:51 +0000)
committerMarcel Poul <marcel.poul@cern.ch>
Mon, 15 Oct 2012 12:51:16 +0000 (12:51 +0000)
org.gridsite.core/src/grst_canl_x509.c

index c5028ef..54d1f38 100644 (file)
@@ -1139,168 +1139,28 @@ int GRSTx509ChainLoadCheck(GRSTx509Chain **chain,
    return GRST_RET_OK;
 }
 
-/// Check certificate chain for GSI proxy acceptability.
-int GRSTx509CheckChain(int *first_non_ca, X509_STORE_CTX *ctx)
-///
-/// Returns X509_V_OK/GRST_RET_OK if valid; OpenSSL X509 errors otherwise.
-///
-/// Inspired by GSIcheck written by Mike Jones, SVE, Manchester Computing,
-/// The University of Manchester.
-///
-/// The GridSite version handles old and new style Globus proxies, and
-/// proxies derived from user certificates issued with "X509v3 Basic
-/// Constraints: CA:FALSE" (eg UK e-Science CA)
-///
-/// We do not check chain links between certs here: this is done by
-/// GRST_check_issued/X509_check_issued in mod_ssl's ssl_engine_init.c
-///
-/// TODO: we do not yet check ProxyCertInfo and ProxyCertPolicy extensions
-///       (although via GRSTx509KnownCriticalExts() we can accept them.)
+/* Check certificate chain for GSI proxy acceptability. */
+int GRSTx509CheckChain(int *first_non_ca, X509_STORE_CTX *store_ctx)
+/* Returns X509_V_OK/GRST_RET_OK if valid; OpenSSL X509 errors otherwise.
+   We do not check chain links between certs here: this is done by
+   GRST_check_issued/X509_check_issued in mod_ssl's ssl_engine_init.c */
 {
-   STACK_OF(X509) *certstack;   /* Points to the client's cert chain */
-   X509 *cert;                  /* Points to the client's cert */
-   int depth;                   /* Depth of cert chain */
-   size_t len,len2;             /* Lengths of issuer and cert DN */
-   int IsCA;                    /* Holds whether cert is allowed to sign */
-   int prevIsCA;                /* Holds whether previous cert in chain is 
-                                   allowed to sign */
-   int prevIsLimited;          /* previous cert was proxy and limited */
-   int i;                       /* Iteration variables */
-   char *cert_DN;               /* Pointer to current-certificate-in-chain's 
-                                   DN */
-   char *issuer_DN;             /* Pointer to 
-                                   issuer-of-current-cert-in-chain's DN */
-   char *proxy_part_DN;         /* Pointer to end part of current-cert-in-chain
-                                   maybe eg "/CN=proxy" */
-   time_t now;
+   canl_err_code  ret = 0;      /* Canl error code */
    
-   time(&now);
-
-   *first_non_ca = 0; /* set to something predictable if things fail */
+   canl_ctx cctx = NULL;
+   cctx = canl_create_ctx();
+   if (cctx == NULL)
+       return GRST_RET_FAILED;
 
    /* Check for context */
-   if (!ctx) return X509_V_ERR_INVALID_CA; 
-     /* Can't GSI-verify if there is no context. Here and throughout this
-        function we report all errors as X509_V_ERR_INVALID_CA. */
-   /* Set necessary preliminary values */
-   IsCA          = TRUE;           /* =prevIsCA - start from a CA */
-   prevIsLimited = 0;
-   /* Get the client cert chain */
-   certstack = X509_STORE_CTX_get_chain(ctx);     /* Get the client's chain  */
-   depth     = sk_X509_num(certstack);            /* How deep is that chain? */
+   if (!store_ctx)
+       return X509_V_ERR_INVALID_CA; /* TODO really not clever*/
  
-   /* Check the client chain */
-   for (i=depth-1; i >= 0; --i) 
-      /* loop through client-presented chain starting at CA end */
-      {
-        prevIsCA=IsCA;
+   /* Verify chain using caNl, without openssl part */
+   ret = canl_verify_chain_wo_ossl(cctx, NULL, store_ctx);
+   if (ret)
+       return X509_V_ERR_INVALID_CA;
 
-        /* Check for X509 certificate and point to it with 'cert' */
-        if ((cert = sk_X509_value(certstack, i)))
-          {
-            /* we check times and reject immediately if invalid */
-          
-            if (now <
-           GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notBefore(cert)),0))
-                  return X509_V_ERR_INVALID_CA;
-                
-            if (now > 
-           GRSTasn1TimeToTimeT(ASN1_STRING_data(X509_get_notAfter(cert)),0))
-                  return X509_V_ERR_INVALID_CA;
-
-            /* If any forebear certificate is not allowed to sign we must 
-               assume all decendents are proxies and cannot sign either */
-            if (prevIsCA)
-              {
-                /* always treat the first cert (from the CA files) as a CA */
-                if (i == depth-1) IsCA = TRUE;
-                /* check if this cert is valid CA for signing certs */
-                else IsCA = (GRSTx509IsCA(cert) == GRST_RET_OK);
-                
-                if (!IsCA) *first_non_ca = i;
-              } 
-            else 
-              {
-                IsCA = FALSE; 
-                /* Force proxy check next iteration. Important because I can
-                   sign any CA I create! */
-              }
-            cert_DN   = X509_NAME_oneline(X509_get_subject_name(cert),NULL,0);
-            issuer_DN = X509_NAME_oneline(X509_get_issuer_name(cert),NULL,0);
-            len       = strlen(cert_DN);
-            len2      = strlen(issuer_DN);
-
-            /* issuer didn't have CA status, so this is (at best) a proxy:
-               check for bad proxy extension*/
-
-            if (!prevIsCA)
-              {
-                if (prevIsLimited) /* we reject proxies of limited proxies! */
-                                return X509_V_ERR_INVALID_CA;
-              
-                /* User not allowed to sign shortened DN */
-                if (len2 > len) return X509_V_ERR_INVALID_CA;                           
-                  
-                /* Proxy subject must begin with issuer. */
-                if (strncmp(cert_DN, issuer_DN, len2) != 0) 
-                              return X509_V_ERR_INVALID_CA;
-
-                /* Set pointer to end of base DN in cert_DN */
-                proxy_part_DN = &cert_DN[len2];
-
-                /* First attempt at support for Old and New style GSI
-                   proxies: /CN=anything is ok for now */
-                if (strncmp(proxy_part_DN, "/CN=", 4) != 0)
-                                         return X509_V_ERR_INVALID_CA;
-                                         
-                if ((strncmp(proxy_part_DN, "/CN=limited proxy", 17) == 0) &&
-                    (i > 0)) prevIsLimited = 1; /* ready for next cert ... */
-              } 
-          }
-      }
-
-   /* Check cert whose private key is being used by client. If previous in 
-      chain is not allowed to be a CA then need to check this final cert for 
-      valid proxy-icity too */
-   if (!prevIsCA) 
-     { 
-       if (prevIsLimited) return X509_V_ERR_INVALID_CA;
-        /* we do not accept proxies signed by limited proxies */
-     
-       if ((cert = sk_X509_value(certstack, 0))) 
-         {
-           /* Load DN & length of DN and either its issuer or the
-              first-bad-issuer-in-chain */
-           cert_DN = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
-           issuer_DN = X509_NAME_oneline(X509_get_issuer_name(cert),  NULL, 0);
-           len = strlen(cert_DN);
-           len2 = strlen(issuer_DN);
-           /* issuer didn't have CA status, check for bad proxy extension */
-
-           if (len2 > len) return X509_V_ERR_INVALID_CA;
-             /* User not allowed to sign shortened DN */
-
-           if (strncmp(cert_DN, issuer_DN, len2) != 0) 
-                           return X509_V_ERR_INVALID_CA;
-             /* Proxy subject must begin with issuer. */
-
-           proxy_part_DN = &cert_DN[len2];                         
-             /* Set pointer to end of DN base in cert_DN */
-             
-           /* Remander of subject must be either "/CN=proxy" or 
-              "/CN=limited proxy" (or /CN=XYZ for New style GSI) */
-              
-           /* First attempt at support for Old and New style GSI
-              proxies: /CN=anything is ok for now. */
-           if (strncmp(proxy_part_DN, "/CN=", 4) != 0)
-                                   return X509_V_ERR_INVALID_CA;
-         }
-     }
    return X509_V_OK; /* this is also GRST_RET_OK, of course - by choice */
 }