Sync gridsite-core_R_1_5_9
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 26 Jun 2008 14:28:28 +0000 (14:28 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Thu, 26 Jun 2008 14:28:28 +0000 (14:28 +0000)
org.gridsite.core/src/mod_gridsite.c
org.gridsite.core/src/mod_ssl-private.h

index b6d28d8..6a04c54 100644 (file)
@@ -132,6 +132,12 @@ char                       *ocspmodes = NULL;
 struct sitecast_group  sitecastgroups[GRST_SITECAST_GROUPS+1];
 struct sitecast_alias  sitecastaliases[GRST_SITECAST_ALIASES];
 
+#if AP_MODULE_MAGIC_AT_LEAST(20051115,0)
+/* SSL_app_data2_idx is private in Apache 2.2 mod_ssl but can be
+   determined at init time, and then recorded here */
+int GRST_SSL_app_data2_idx = -1;
+#endif
+
 typedef struct
 {
    int                 auth;
@@ -3418,6 +3424,210 @@ int GRST_verify_cert_wrapper(X509_STORE_CTX *ctx, void *p)
    return X509_verify_cert(ctx);
 }
 
+#if AP_MODULE_MAGIC_AT_LEAST(20051115,0)
+/*
+    Include this here until libgridsite functions can be used
+*/
+int GRST_ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx, conn_rec *c)
+{
+    server_rec *s       = c->base_server;
+    SSLSrvConfigRec *sc = (SSLSrvConfigRec *) ap_get_module_config(s->module_config, &ssl_module);
+    SSLConnRec *sslconn = (SSLConnRec *) ap_get_module_config(c->conn_config, &ssl_module);
+    modssl_ctx_t *mctx  = sslconn->is_proxy ? sc->proxy : sc->server;
+    X509_OBJECT obj;
+    X509_NAME *subject, *issuer;
+    X509 *cert;
+    X509_CRL *crl;
+    EVP_PKEY *pubkey;
+    int i, n, rc;
+
+    /*
+     * Unless a revocation store for CRLs was created we
+     * cannot do any CRL-based verification, of course.
+     */
+    if (!mctx->crl) {
+        return ok;
+    }
+
+    /*
+     * Determine certificate ingredients in advance
+     */
+    cert    = X509_STORE_CTX_get_current_cert(ctx);
+    subject = X509_get_subject_name(cert);
+    issuer  = X509_get_issuer_name(cert);
+
+    /*
+     * OpenSSL provides the general mechanism to deal with CRLs but does not
+     * use them automatically when verifying certificates, so we do it
+     * explicitly here. We will check the CRL for the currently checked
+     * certificate, if there is such a CRL in the store.
+     *
+     * We come through this procedure for each certificate in the certificate
+     * chain, starting with the root-CA's certificate. At each step we've to
+     * both verify the signature on the CRL (to make sure it's a valid CRL)
+     * and it's revocation list (to make sure the current certificate isn't
+     * revoked).  But because to check the signature on the CRL we need the
+     * public key of the issuing CA certificate (which was already processed
+     * one round before), we've a little problem. But we can both solve it and
+     * at the same time optimize the processing by using the following
+     * verification scheme (idea and code snippets borrowed from the GLOBUS
+     * project):
+     *
+     * 1. We'll check the signature of a CRL in each step when we find a CRL
+     *    through the _subject_ name of the current certificate. This CRL
+     *    itself will be needed the first time in the next round, of course.
+     *    But we do the signature processing one round before this where the
+     *    public key of the CA is available.
+     *
+     * 2. We'll check the revocation list of a CRL in each step when
+     *    we find a CRL through the _issuer_ name of the current certificate.
+     *    This CRLs signature was then already verified one round before.
+     *
+     * This verification scheme allows a CA to revoke its own certificate as
+     * well, of course.
+     */
+
+    /*
+     * Try to retrieve a CRL corresponding to the _subject_ of
+     * the current certificate in order to verify it's integrity.
+     */
+    memset((char *)&obj, 0, sizeof(obj));
+    {
+      X509_STORE_CTX pStoreCtx;
+      X509_STORE_CTX_init(&pStoreCtx, mctx->crl, NULL, NULL);
+      rc = X509_STORE_get_by_subject(&pStoreCtx, X509_LU_CRL, subject, &obj);
+      X509_STORE_CTX_cleanup(&pStoreCtx);
+    }
+
+    crl = obj.data.crl;
+
+    if ((rc > 0) && crl) {
+        /*
+         * Log information about CRL
+         * (A little bit complicated because of ASN.1 and BIOs...)
+         */
+        if (s->loglevel >= APLOG_DEBUG) {
+            char buff[512]; /* should be plenty */
+            BIO *bio = BIO_new(BIO_s_mem());
+
+            BIO_printf(bio, "CA CRL: Issuer: ");
+            X509_NAME_print(bio, issuer, 0);
+
+            BIO_printf(bio, ", lastUpdate: ");
+            ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(crl));
+
+            BIO_printf(bio, ", nextUpdate: ");
+            ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(crl));
+
+            n = BIO_read(bio, buff, sizeof(buff) - 1);
+            buff[n] = '\0';
+
+            BIO_free(bio);
+
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "%s", buff);
+        }
+
+        /*
+         * Verify the signature on this CRL
+         */
+        pubkey = X509_get_pubkey(cert);
+        rc = X509_CRL_verify(crl, pubkey);
+#ifdef OPENSSL_VERSION_NUMBER
+        /* Only refcounted in OpenSSL */
+        if (pubkey)
+            EVP_PKEY_free(pubkey);
+#endif
+        if (rc <= 0) {
+            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
+                         "Invalid signature on CRL");
+
+            X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE);
+            X509_OBJECT_free_contents(&obj);
+            return FALSE;
+        }
+
+        /*
+         * Check date of CRL to make sure it's not expired
+         */
+        i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl));
+
+        if (i == 0) {
+            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
+                         "Found CRL has invalid nextUpdate field");
+
+            X509_STORE_CTX_set_error(ctx,
+                                     X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
+            X509_OBJECT_free_contents(&obj);
+
+            return FALSE;
+        }
+
+        if (i < 0) {
+            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
+                         "Found CRL is expired - "
+                         "revoking all certificates until you get updated CRL");
+
+            X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED);
+            X509_OBJECT_free_contents(&obj);
+
+            return FALSE;
+        }
+
+        X509_OBJECT_free_contents(&obj);
+    }
+
+    /*
+     * Try to retrieve a CRL corresponding to the _issuer_ of
+     * the current certificate in order to check for revocation.
+     */
+    memset((char *)&obj, 0, sizeof(obj));
+    {
+      X509_STORE_CTX pStoreCtx;
+      X509_STORE_CTX_init(&pStoreCtx, mctx->crl, NULL, NULL);
+      rc = X509_STORE_get_by_subject(&pStoreCtx, X509_LU_CRL, issuer, &obj);
+      X509_STORE_CTX_cleanup(&pStoreCtx);
+    }
+
+    crl = obj.data.crl;
+    if ((rc > 0) && crl) {
+        /*
+         * Check if the current certificate is revoked by this CRL
+         */
+        n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
+
+        for (i = 0; i < n; i++) {
+            X509_REVOKED *revoked =
+                sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
+
+//            ASN1_INTEGER *sn = X509_REVOKED_get_serialNumber(revoked);
+            ASN1_INTEGER *sn = revoked->serialNumber;
+
+            if (!ASN1_INTEGER_cmp(sn, X509_get_serialNumber(cert))) {
+                if (s->loglevel >= APLOG_DEBUG) {
+                    char *cp = X509_NAME_oneline(issuer, NULL, 0);
+                    long serial = ASN1_INTEGER_get(sn);
+
+                    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+                                 "Certificate with serial %ld (0x%lX) "
+                                 "revoked per CRL from issuer %s",
+                                 serial, serial, cp);
+                    OPENSSL_free(cp);
+                }
+
+                X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
+                X509_OBJECT_free_contents(&obj);
+
+                return FALSE;
+            }
+        }
+
+        X509_OBJECT_free_contents(&obj);
+    }
+
+    return ok;
+}
+#endif
+
 int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
 {
    SSL *ssl            = (SSL *) X509_STORE_CTX_get_app_data(ctx);
@@ -3430,7 +3640,7 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
    int returned_ok;
    int first_non_ca;
 #if AP_MODULE_MAGIC_AT_LEAST(20051115,0)
-   request_rec *r      = (request_rec *)SSL_get_app_data2(ssl);
+   request_rec *r      = (request_rec *) SSL_get_ex_data(ssl, GRST_SSL_app_data2_idx);
    SSLSrvConfigRec *sc = (SSLSrvConfigRec *) ap_get_module_config(s->module_config, &ssl_module);
    SSLDirConfigRec *dc = r ? (SSLDirConfigRec *) ap_get_module_config(r->per_dir_config, &ssl_module) : NULL;
    modssl_ctx_t *mctx  = sslconn->is_proxy ? sc->proxy : sc->server;
@@ -3456,9 +3666,9 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
                      sname ? sname : "-unknown-",
                      iname ? iname : "-unknown-");
 
-        if (sname) modssl_free(sname);
+        if (sname) OPENSSL_free(sname);
 
-        if (iname) modssl_free(iname);
+        if (iname) OPENSSL_free(iname);
       } 
 
     /*
@@ -3500,7 +3710,7 @@ int GRST_callback_SSLVerify_wrapper(int ok, X509_STORE_CTX *ctx)
      */
    if (ok) 
      {
-        if (!(ok = ssl_callback_SSLVerify_CRL(ok, ctx, conn))) 
+        if (!(ok = GRST_ssl_callback_SSLVerify_CRL(ok, ctx, conn))) 
           {
             errnum = X509_STORE_CTX_get_error(ctx);
           }
@@ -4017,6 +4227,16 @@ static int mod_gridsite_server_post_config(apr_pool_t *pPool,
    ap_add_version_component(pPool,
                             apr_psprintf(pPool, "mod_gridsite/%s", VERSION));
 
+#if AP_MODULE_MAGIC_AT_LEAST(20051115,0)
+   /* establish value of SSL_app_data2_idx and record it */
+   GRST_SSL_app_data2_idx = SSL_get_ex_new_index(0,
+                                  "Dummy Application Data for mod_gridsite",
+                                   NULL, NULL, NULL) - 1;
+   ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, main_server,
+              "mod_gridsite: GRST_SSL_app_data2_idx=%d", 
+              GRST_SSL_app_data2_idx);
+#endif
+
    for (this_server = main_server; 
         this_server != NULL; 
         this_server = this_server->next)
index 4a7bd52..f4d3582 100644 (file)
@@ -93,6 +93,14 @@ typedef enum {
     SSL_CVERIFY_REQUIRE         = 2,
     SSL_CVERIFY_OPTIONAL_NO_CA  = 3
 } ssl_verify_t;
+
+#define ssl_verify_error_is_optional(errnum) \
+   ((errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) \
+    || (errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) \
+    || (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) \
+    || (errnum == X509_V_ERR_CERT_UNTRUSTED) \
+    || (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE))
+
 #endif
 
 typedef struct {
@@ -172,4 +180,5 @@ typedef struct {
 } SSLDirConfigRec;
 #endif
 
+
 extern module AP_MODULE_DECLARE_DATA ssl_module;