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;
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);
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;
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);
}
/*
*/
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);
}
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)