Author: rjung
Date: Fri May 22 12:39:51 2015
New Revision: 1681092

URL: http://svn.apache.org/r1681092
Log:
Sync trunk with 1.1.x branch for ssl.

1.1 has several additions trunk never got, e.g.
OCSP support, pkcs12 support and others.

Below is a list of revisions added to 1.1.x which are part
of the forward port. The only remaining changes that have not been
forward ported all concern sslnetwork.c:

r1456353 | mturk | 2013-03-14 08:35:56 +0100 (Thu, 14 Mar 2013) | 1 line
Prevent infinite loop for SSL_ERROR_SSL

r1409681 | mturk | 2012-11-15 08:59:36 +0100 (Thu, 15 Nov 2012) | 1 line
Clean up SSL network layer. Ensure the behavior is similar to standard APR layer

They have not (yet) been forward ported, because it is not clear
(to me) how well they apply and whether they conflict with the following
change in trunk, which is not part of 1.1:

r1299312 | costin | 2012-03-11 00:59:25 +0100 (Sun, 11 Mar 2012) | 5 lines
Small fix for ssl_read/ssl_write if the socket is not blocking. Tomcat is not 
currently using apr
in non blocking mode, so it shouldn't be affected. Without the fix read would 
block.
Also added/fixed methods in sslext to set the mode - needed for non-blocking 
write.

It would be nice if we could clean up this remaining difference.
Apart from that the only things in trunk ssl that are now not in 1.1
are the recent additions concerning ALPN and SNI support.

An addition to forward ports, this commit also removes all code
with #if or #ifdef checks which only apply to OpenSSL 1.0.1 or
earlier and removes all code only active when OPENSSL_USE_DEPRECATED
is defined. As a consequence support for custom DHE params is gone
but this will re-intgrated from mod_ssl in a more appropriate form
to trunk and 1.1 next.

List of forward ports contained in this commit:

r1680456 | billbarker | 2015-05-20 06:22:58 +0200 (Wed, 20 May 2015) | 1 line
Fix errors when compiling against openssl master

r1673617 | billbarker | 2015-04-15 04:08:02 +0200 (Wed, 15 Apr 2015) | 1 line
More cleanup of thread ID handling for openssl master plus remove compile 
warning that doesn't make any difference. Still no change if compiling against 
any currently released v
ersion of openssl

r1673333 | billbarker | 2015-04-14 03:41:49 +0200 (Tue, 14 Apr 2015) | 1 line
openssl master handles thread id itself (and better than we do).  No change if 
compiling against any currently released version of openssl

r1649733 | billbarker | 2015-01-06 05:42:24 +0100 (Tue, 06 Jan 2015) | 1 line
More fixes to help Gump build. No change if compiling against any currently 
released version of openssl
Plus removing all code that is only used for older OpenSSL versions than 1.0.2
plus remove all code that only runs for OPENSSL_USE_DEPRECATED.

r1649278 | billbarker | 2015-01-04 02:06:53 +0100 (Sun, 04 Jan 2015) | 1 line
Fix compilation error for Gump. There is no change if compiling against any 
currently released version of openssl.

r1586221 | mturk | 2014-04-10 07:44:09 +0200 (Thu, 10 Apr 2014) | 1 line
Revert NO_SSL_INTERN define. We need direct struct access for sslinfo

r1585957 | mturk | 2014-04-09 14:54:25 +0200 (Wed, 09 Apr 2014) | 1 line
Ensure we have the needed ECDH with the OpenSSL used

r1585923 | mturk | 2014-04-09 11:52:40 +0200 (Wed, 09 Apr 2014) | 1 line
As per Tom's suggestion. Set SSL_OP_SINGLE_ECDH_USE to context

r1585898 | mturk | 2014-04-09 09:32:29 +0200 (Wed, 09 Apr 2014) | 1 line
Apply Ognjen's patch for bz55915

r1507125 | schultz | 2013-07-25 23:01:25 +0200 (Thu, 25 Jul 2013) | 5 lines
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=53937
Eliminate double-call to apr_pool_destroy.

r1409079 | mturk | 2012-11-14 06:21:53 +0100 (Wed, 14 Nov 2012) | 1 line
Trim trailing spaces - No functional change

r1350270 | rjung | 2012-06-14 16:38:33 +0200 (Thu, 14 Jun 2012) | 4 lines
Return error if BIO_flush() didn't work.
Fixes compiler warning about unused return
value.

r1294171 | mturk | 2012-02-27 15:56:07 +0100 (Mon, 27 Feb 2012) | 1 line
Ensure that cert_file is present. Key can be null in which case it'll get the 
cert_file value, but cer must be provided

r1293368 | mturk | 2012-02-24 19:07:07 +0100 (Fri, 24 Feb 2012) | 1 line
Fix typo. Thanks Felix :)

r1293187 | mturk | 2012-02-24 12:29:35 +0100 (Fri, 24 Feb 2012) | 1 line
Use correct variable types to suppress compile time warning

r1293144 | mturk | 2012-02-24 10:26:28 +0100 (Fri, 24 Feb 2012) | 1 line
Fix few remaining issues in OCSP patch

r1293123 | mturk | 2012-02-24 09:01:52 +0100 (Fri, 24 Feb 2012) | 1 line
Fix code style. No functional change

r1293122 | mturk | 2012-02-24 08:58:26 +0100 (Fri, 24 Feb 2012) | 1 line
Apply additional security check from mod_ssl

r1293120 | mturk | 2012-02-24 08:46:39 +0100 (Fri, 24 Feb 2012) | 1 line
No need for public function

r1293119 | mturk | 2012-02-24 08:43:44 +0100 (Fri, 24 Feb 2012) | 1 line
BZ45392 Apply modified patch. OCSP is enabled is explicitly configure with 
--enable-ocsp at build time

r1292859 | mturk | 2012-02-23 18:21:50 +0100 (Thu, 23 Feb 2012) | 1 line
Add support for loading pkcs12 certificates. Certificate must have .pkcs12 
extension

Modified:
    tomcat/native/trunk/native/configure.in
    tomcat/native/trunk/native/include/ssl_private.h
    tomcat/native/trunk/native/src/ssl.c
    tomcat/native/trunk/native/src/sslcontext.c
    tomcat/native/trunk/native/src/sslnetwork.c
    tomcat/native/trunk/native/src/sslutils.c

Modified: tomcat/native/trunk/native/configure.in
URL: 
http://svn.apache.org/viewvc/tomcat/native/trunk/native/configure.in?rev=1681092&r1=1681091&r2=1681092&view=diff
==============================================================================
--- tomcat/native/trunk/native/configure.in (original)
+++ tomcat/native/trunk/native/configure.in Fri May 22 12:39:51 2015
@@ -149,6 +149,17 @@ AC_ARG_ENABLE(openssl,
   esac
 ])
 
+AC_ARG_ENABLE(ocsp,
+[AS_HELP_STRING([--enable-ocsp],[Turn on OpenSSL OCSP verification support])],
+[
+  case "${enableval}" in
+    yes )
+       APR_ADDTO(CFLAGS, [-DHAVE_OPENSSL_OCSP])
+       AC_MSG_RESULT([Enabling OCSP verification support...])
+       ;;
+  esac
+])
+
 if $use_openssl ; then
   TCN_CHECK_SSL_TOOLKIT
 fi

Modified: tomcat/native/trunk/native/include/ssl_private.h
URL: 
http://svn.apache.org/viewvc/tomcat/native/trunk/native/include/ssl_private.h?rev=1681092&r1=1681091&r2=1681092&view=diff
==============================================================================
--- tomcat/native/trunk/native/include/ssl_private.h (original)
+++ tomcat/native/trunk/native/include/ssl_private.h Fri May 22 12:39:51 2015
@@ -40,10 +40,12 @@
 #endif
 
 /* OpenSSL headers */
+#include <openssl/opensslv.h>
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include <openssl/x509.h>
 #include <openssl/pem.h>
+#include <openssl/pkcs12.h>
 #include <openssl/crypto.h>
 #include <openssl/evp.h>
 #include <openssl/rand.h>
@@ -200,12 +202,20 @@
     || (errnum == X509_V_ERR_CERT_UNTRUSTED) \
     || (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE))
 
-
-
 #define SSL_DEFAULT_PASS_PROMPT "Some of your private key files are encrypted 
for security reasons.\n"  \
                                 "In order to read them you have to provide the 
pass phrases.\n"         \
                                 "Enter password :"
 
+#define OCSP_STATUS_OK        0
+#define OCSP_STATUS_REVOKED   1
+#define OCSP_STATUS_UNKNOWN   2
+
+
+/* ECC: make sure we have at least 1.0.0 */
+#if !defined(OPENSSL_NO_EC) && defined(TLSEXT_ECPOINTFORMAT_uncompressed)
+#define HAVE_ECC              1
+#endif
+
 extern void *SSL_temp_keys[SSL_TMP_KEY_MAX];
 
 typedef struct {
@@ -317,4 +327,5 @@ void        SSL_callback_handshake(const
 int         SSL_CTX_use_certificate_chain(SSL_CTX *, const char *, int);
 int         SSL_callback_SSL_verify(int, X509_STORE_CTX *);
 int         SSL_rand_seed(const char *file);
+
 #endif /* SSL_PRIVATE_H */

Modified: tomcat/native/trunk/native/src/ssl.c
URL: 
http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/ssl.c?rev=1681092&r1=1681091&r2=1681092&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/ssl.c (original)
+++ tomcat/native/trunk/native/src/ssl.c Fri May 22 12:39:51 2015
@@ -53,11 +53,15 @@ struct CRYPTO_dynlock_value {
  * Handle the Temporary RSA Keys and DH Params
  */
 
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED)
 #define SSL_TMP_KEY_FREE(type, idx)                     \
     if (SSL_temp_keys[idx]) {                           \
         type##_free((type *)SSL_temp_keys[idx]);        \
         SSL_temp_keys[idx] = NULL;                      \
     } else (void)(0)
+#else
+#define SSL_TMP_KEY_FREE(type, idx)    SSL_temp_keys[idx] = NULL
+#endif
 
 #define SSL_TMP_KEYS_FREE(type) \
     SSL_TMP_KEY_FREE(type, SSL_TMP_KEY_##type##_512);   \
@@ -229,20 +233,39 @@ static const jint supported_ssl_opts = 0
 
 static int ssl_tmp_key_init_rsa(int bits, int idx)
 {
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED)
     if (!(SSL_temp_keys[idx] =
-          RSA_generate_key(bits, RSA_F4, NULL, NULL)))
+          RSA_generate_key(bits, RSA_F4, NULL, NULL))) {
+#ifdef OPENSSL_FIPS
+        /**
+         * With FIPS mode short RSA keys cannot be
+         * generated.
+         */
+        if (bits < 1024)
+            return 0;
+        else
+#endif
         return 1;
-    else
+    }
+    else {
         return 0;
+    }
+#else
+    return 0;
+#endif
 }
 
 static int ssl_tmp_key_init_dh(int bits, int idx)
 {
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED)
     if (!(SSL_temp_keys[idx] =
           SSL_dh_get_tmp_param(bits)))
         return 1;
     else
         return 0;
+#else
+    return 0;
+#endif
 }
 
 
@@ -292,7 +315,11 @@ static apr_status_t ssl_init_cleanup(voi
     ENGINE_cleanup();
 #endif
     CRYPTO_cleanup_all_ex_data();
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED)
     ERR_remove_state(0);
+#else
+    ERR_remove_thread_state(NULL);
+#endif
 
     /* Don't call ERR_free_strings here; ERR_load_*_strings only
      * actually load the error strings once per process due to static
@@ -368,7 +395,9 @@ static apr_status_t ssl_thread_cleanup(v
 {
     UNREFERENCED(data);
     CRYPTO_set_locking_callback(NULL);
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED)
     CRYPTO_set_id_callback(NULL);
+#endif
     CRYPTO_set_dynlock_create_callback(NULL);
     CRYPTO_set_dynlock_lock_callback(NULL);
     CRYPTO_set_dynlock_destroy_callback(NULL);
@@ -430,6 +459,8 @@ static struct CRYPTO_dynlock_value *ssl_
 static void ssl_dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l,
                            const char *file, int line)
 {
+
+
     if (mode & CRYPTO_LOCK) {
         apr_thread_mutex_lock(l->mutex);
     }
@@ -467,7 +498,9 @@ static void ssl_thread_setup(apr_pool_t
                                 APR_THREAD_MUTEX_DEFAULT, p);
     }
 
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED)
     CRYPTO_set_id_callback(ssl_thread_id);
+#endif
     CRYPTO_set_locking_callback(ssl_thread_lock);
 
     /* Set up dynamic locking scaffolding for OpenSSL to use at its
@@ -606,9 +639,9 @@ static int ssl_rand_make(const char *fil
         BIO_write(out, buf, len);
         num -= len;
     }
-    BIO_flush(out);
+    r = BIO_flush(out);
     BIO_free_all(out);
-    return 1;
+    return r > 0 ? 1 : 0;
 }
 
 TCN_IMPLEMENT_CALL(jint, SSL, initialize)(TCN_STDARGS, jstring engine)

Modified: tomcat/native/trunk/native/src/sslcontext.c
URL: 
http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/sslcontext.c?rev=1681092&r1=1681091&r2=1681092&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/sslcontext.c (original)
+++ tomcat/native/trunk/native/src/sslcontext.c Fri May 22 12:39:51 2015
@@ -71,7 +71,7 @@ static jmethodID sni_java_callback;
 int ssl_callback_ServerNameIndication(SSL *ssl, int *al, tcn_ssl_ctxt_t *c)
 {
     // TODO: Is it better to cache the JNIEnv* during the call to handshake?
-    
+
     // Get the JNI environment for this callback
     JavaVM *javavm = tcn_get_java_vm();
     JNIEnv *env;
@@ -79,14 +79,14 @@ int ssl_callback_ServerNameIndication(SS
     jstring hostname;
     jlong original_ssl_context, new_ssl_context;
     (*javavm)->AttachCurrentThread(javavm, (void **)&env, NULL);
-    
+
     // Get the host name presented by the client
     servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
-    
+
     // Convert parameters ready for the method call
     hostname = (*env)->NewStringUTF(env, servername);
     original_ssl_context = P2J(c->ctx);
- 
+
     // Make the call
     new_ssl_context = (*env)->CallStaticLongMethod(env,
                                                             ssl_context_class,
@@ -97,10 +97,10 @@ int ssl_callback_ServerNameIndication(SS
     if (original_ssl_context != new_ssl_context) {
         SSL_set_SSL_CTX(ssl, J2P(new_ssl_context, SSL_CTX *));
     }
- 
+
     return SSL_TLSEXT_ERR_OK;
 }
- 
+
 /* Initialize server context */
 TCN_IMPLEMENT_CALL(jlong, SSLContext, make)(TCN_STDARGS, jlong pool,
                                             jint protocol, jint mode)
@@ -141,6 +141,15 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, ma
             ctx = SSL_CTX_new(SSLv3_server_method());
         else
             ctx = SSL_CTX_new(SSLv3_method());
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) && !defined(OPENSSL_NO_SSL2)
+    } else if (protocol == SSL_PROTOCOL_SSLV2) {
+        if (mode == SSL_MODE_CLIENT)
+            ctx = SSL_CTX_new(SSLv2_client_method());
+        else if (mode == SSL_MODE_SERVER)
+            ctx = SSL_CTX_new(SSLv2_server_method());
+        else
+            ctx = SSL_CTX_new(SSLv2_method());
+#endif
 #ifndef OPENSSL_NO_SSL2
     } else if (protocol == SSL_PROTOCOL_SSLV2) {
         if (mode == SSL_MODE_CLIENT)
@@ -159,12 +168,21 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, ma
         /* requested but not supported */
 #endif
     } else {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
         if (mode == SSL_MODE_CLIENT)
-            ctx = SSL_CTX_new(SSLv23_client_method());
+                ctx = SSL_CTX_new(SSLv23_client_method());
         else if (mode == SSL_MODE_SERVER)
-            ctx = SSL_CTX_new(SSLv23_server_method());
+                ctx = SSL_CTX_new(SSLv23_server_method());
         else
-            ctx = SSL_CTX_new(SSLv23_method());
+                ctx = SSL_CTX_new(SSLv23_method());
+#else
+        if (mode == SSL_MODE_CLIENT)
+                ctx = SSL_CTX_new(TLS_client_method());
+        else if (mode == SSL_MODE_SERVER)
+                ctx = SSL_CTX_new(TLS_server_method());
+        else
+                ctx = SSL_CTX_new(TLS_method());
+#endif
     }
 
     if (!ctx) {
@@ -204,6 +222,9 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, ma
      * Configure additional context ingredients
      */
     SSL_CTX_set_options(c->ctx, SSL_OP_SINGLE_DH_USE);
+#ifdef HAVE_ECC
+    SSL_CTX_set_options(c->ctx, SSL_OP_SINGLE_ECDH_USE);
+#endif
 
     /** To get back the tomcat wrapper from CTX */
     SSL_CTX_set_app_data(c->ctx, (char *)c);
@@ -221,6 +242,12 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, ma
                (unsigned long)((sizeof SSL_DEFAULT_VHOST_NAME) - 1),
                &(c->context_id[0]), NULL, EVP_sha1(), NULL);
     if (mode) {
+#ifdef HAVE_ECC
+        /* Set default (nistp256) elliptic curve for ephemeral ECDH keys */
+        EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+        SSL_CTX_set_tmp_ecdh(c->ctx, ecdh);
+        EC_KEY_free(ecdh);
+#endif
         SSL_CTX_set_tmp_rsa_callback(c->ctx, SSL_callback_tmp_RSA);
         SSL_CTX_set_tmp_dh_callback(c->ctx,  SSL_callback_tmp_DH);
     }
@@ -235,7 +262,7 @@ TCN_IMPLEMENT_CALL(jlong, SSLContext, ma
     SSL_CTX_set_default_passwd_cb(c->ctx, (pem_password_cb 
*)SSL_password_callback);
     SSL_CTX_set_default_passwd_cb_userdata(c->ctx, (void 
*)(&tcn_password_callback));
     SSL_CTX_set_info_callback(c->ctx, SSL_callback_handshake);
-    
+
     /* Cache Java side SNI callback if not already cached */
     if (ssl_context_class == NULL) {
         ssl_context_class = (*e)->NewGlobalRef(e, o);
@@ -591,6 +618,53 @@ static X509 *load_pem_cert(tcn_ssl_ctxt_
     return cert;
 }
 
+static int ssl_load_pkcs12(tcn_ssl_ctxt_t *c, const char *file,
+                           EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
+{
+    const char *pass;
+    char        buff[PEM_BUFSIZE];
+    int         len, rc = 0;
+    PKCS12     *p12;
+    BIO        *in;
+    tcn_pass_cb_t *cb_data = c->cb_data;
+
+    if ((in = BIO_new(BIO_s_file())) == 0)
+        return 0;
+    if (BIO_read_filename(in, file) <= 0) {
+        BIO_free(in);
+        return 0;
+    }
+    p12 = d2i_PKCS12_bio(in, 0);
+    if (p12 == 0) {
+        /* Error loading PKCS12 file */
+        goto cleanup;
+    }
+    /* See if an empty password will do */
+    if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, 0, 0)) {
+        pass = "";
+    }
+    else {
+        if (!cb_data)
+            cb_data = &tcn_password_callback;
+        len = SSL_password_callback(buff, PEM_BUFSIZE, 0, cb_data);
+        if (len < 0) {
+            /* Passpharse callback error */
+            goto cleanup;
+        }
+        if (!PKCS12_verify_mac(p12, buff, len)) {
+            /* Mac verify error (wrong password?) in PKCS12 file */
+            goto cleanup;
+        }
+        pass = buff;
+    }
+    rc = PKCS12_parse(p12, pass, pkey, cert, ca);
+cleanup:
+    if (p12 != 0)
+        PKCS12_free(p12);
+    BIO_free(in);
+    return rc;
+}
+
 TCN_IMPLEMENT_CALL(void, SSLContext, setRandom)(TCN_STDARGS, jlong ctx,
                                                 jstring file)
 {
@@ -614,6 +688,7 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     TCN_ALLOC_CSTRING(key);
     TCN_ALLOC_CSTRING(password);
     const char *key_file, *cert_file;
+    const char *p;
     char err[256];
 
     UNREFERENCED(o);
@@ -634,24 +709,35 @@ TCN_IMPLEMENT_CALL(jboolean, SSLContext,
     cert_file = J2S(cert);
     if (!key_file)
         key_file = cert_file;
-    if (!key_file) {
+    if (!key_file || !cert_file) {
         tcn_Throw(e, "No Certificate file specified or invalid file format");
         rv = JNI_FALSE;
         goto cleanup;
     }
-    if ((c->keys[idx] = load_pem_key(c, key_file)) == NULL) {
-        ERR_error_string(ERR_get_error(), err);
-        tcn_Throw(e, "Unable to load certificate key %s (%s)",
-                  key_file, err);
-        rv = JNI_FALSE;
-        goto cleanup;
+    if ((p = strrchr(cert_file, '.')) != NULL && strcmp(p, ".pkcs12") == 0) {
+        if (!ssl_load_pkcs12(c, cert_file, &c->keys[idx], &c->certs[idx], 0)) {
+            ERR_error_string(ERR_get_error(), err);
+            tcn_Throw(e, "Unable to load certificate %s (%s)",
+                      cert_file, err);
+            rv = JNI_FALSE;
+            goto cleanup;
+        }
     }
-    if ((c->certs[idx] = load_pem_cert(c, cert_file)) == NULL) {
-        ERR_error_string(ERR_get_error(), err);
-        tcn_Throw(e, "Unable to load certificate %s (%s)",
-                  cert_file, err);
-        rv = JNI_FALSE;
-        goto cleanup;
+    else {
+        if ((c->keys[idx] = load_pem_key(c, key_file)) == NULL) {
+            ERR_error_string(ERR_get_error(), err);
+            tcn_Throw(e, "Unable to load certificate key %s (%s)",
+                      key_file, err);
+            rv = JNI_FALSE;
+            goto cleanup;
+        }
+        if ((c->certs[idx] = load_pem_cert(c, cert_file)) == NULL) {
+            ERR_error_string(ERR_get_error(), err);
+            tcn_Throw(e, "Unable to load certificate %s (%s)",
+                      cert_file, err);
+            rv = JNI_FALSE;
+            goto cleanup;
+        }
     }
     if (SSL_CTX_use_certificate(c->ctx, c->certs[idx]) <= 0) {
         ERR_error_string(ERR_get_error(), err);
@@ -739,7 +825,7 @@ int cb_server_alpn(SSL *ssl,
         // Client specified an empty protocol list. Nothing to negotiate.
         return SSL_TLSEXT_ERR_ALERT_FATAL;
     }
-    
+
     client_protos = apr_array_make(con->pool , 0, sizeof(char *));
     for (i = 0; i < inlen; /**/) {
         unsigned int plen = in[i++];
@@ -756,12 +842,12 @@ int cb_server_alpn(SSL *ssl,
         // Server supported protocol names not set.
         return SSL_TLSEXT_ERR_ALERT_FATAL;
     }
-    
+
     if (tcsslctx->alpnlen == 0) {
         // Server supported protocols is an empty list
         return SSL_TLSEXT_ERR_ALERT_FATAL;
     }
-    
+
     proposed_protos = apr_array_make(con->pool, 0, sizeof(char *));
     for (i = 0; i < tcsslctx->alpnlen; /**/) {
         unsigned int plen = tcsslctx->alpn[i++];
@@ -773,12 +859,12 @@ int cb_server_alpn(SSL *ssl,
         APR_ARRAY_PUSH(proposed_protos, char*) = apr_pstrndup(con->pool, 
(const char *)tcsslctx->alpn+i, plen);
         i += plen;
     }
-    
+
     if (proposed_protos->nelts <= 0) {
         // Should never happen. The server did not specify any protocols.
         return SSL_TLSEXT_ERR_ALERT_FATAL;
     }
-    
+
     /* Now select the most preferred protocol from the proposals. */
     *out = APR_ARRAY_IDX(proposed_protos, 0, const unsigned char *);
     for (i = 1; i < proposed_protos->nelts; ++i) {
@@ -794,7 +880,7 @@ int cb_server_alpn(SSL *ssl,
         // Agreed protocol name too long
         return SSL_TLSEXT_ERR_ALERT_FATAL;
     }
-    
+
     *outlen = (unsigned char)len;
 
     return SSL_TLSEXT_ERR_OK;
@@ -804,11 +890,11 @@ TCN_IMPLEMENT_CALL(jint, SSLContext, set
                                           jbyteArray buf, jint len)
 {
     tcn_ssl_ctxt_t *sslctx = J2P(ctx, tcn_ssl_ctxt_t *);
-    
+
     sslctx->alpn = apr_pcalloc(sslctx->pool, len);
     (*e)->GetByteArrayRegion(e, buf, 0, len, &sslctx->alpn[0]);
     sslctx->alpnlen = len;
-    
+
     if (sslctx->mode == SSL_MODE_SERVER) {
         SSL_CTX_set_alpn_select_cb(sslctx->ctx, cb_server_alpn, sslctx);
     } else {

Modified: tomcat/native/trunk/native/src/sslnetwork.c
URL: 
http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/sslnetwork.c?rev=1681092&r1=1681091&r2=1681092&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/sslnetwork.c (original)
+++ tomcat/native/trunk/native/src/sslnetwork.c Fri May 22 12:39:51 2015
@@ -693,15 +693,15 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, getA
     tcn_socket_t *s = J2P(sock, tcn_socket_t *);
     tcn_ssl_conn_t *tcssl = (tcn_ssl_conn_t *)s->opaque;
     int bufLen = (*e)->GetArrayLength(e, buf);
-    
+
     SSL_get0_alpn_selected(tcssl->ssl, &alpn, &alpn_len);
-    
+
     if (alpn_len == 0 || bufLen < alpn_len) {
         return 0;
     }
     int len = alpn_len;
     (*e)->SetByteArrayRegion(e, buf, 0, len, alpn);
-    
+
     return len;
 }
 

Modified: tomcat/native/trunk/native/src/sslutils.c
URL: 
http://svn.apache.org/viewvc/tomcat/native/trunk/native/src/sslutils.c?rev=1681092&r1=1681091&r2=1681092&view=diff
==============================================================================
--- tomcat/native/trunk/native/src/sslutils.c (original)
+++ tomcat/native/trunk/native/src/sslutils.c Fri May 22 12:39:51 2015
@@ -21,16 +21,27 @@
  */
 
 #include "tcn.h"
-#include "apr_thread_mutex.h"
-#include "apr_poll.h"
 
 #ifdef HAVE_OPENSSL
+#include "apr_poll.h"
 #include "ssl_private.h"
 
 #ifdef WIN32
 extern int WIN32_SSL_password_prompt(tcn_pass_cb_t *data);
 #endif
 
+#ifdef HAVE_OPENSSL_OCSP
+#include <openssl/bio.h>
+#include <openssl/ocsp.h>
+/* defines with the values as seen by the asn1parse -dump openssl command */
+#define ASN1_SEQUENCE 0x30
+#define ASN1_OID      0x06
+#define ASN1_STRING   0x86
+#pragma message("Using OCSP")
+static int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx);
+static int ssl_ocsp_request(X509 *cert, X509 *issuer);
+#endif
+
 /*  _________________________________________________________________
 **
 **  Additional High-Level Functions for OpenSSL
@@ -243,6 +254,7 @@ static unsigned char dhxxx2_g[]={
 
 static DH *get_dh(int idx)
 {
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(OPENSSL_USE_DEPRECATED)
     DH *dh;
 
     if ((dh = DH_new()) == NULL)
@@ -268,6 +280,9 @@ static DH *get_dh(int idx)
     }
     else
         return dh;
+#else
+    return NULL;
+#endif
 }
 
 DH *SSL_dh_get_tmp_param(int key_len)
@@ -599,6 +614,8 @@ static int ssl_verify_CRL(int ok, X509_S
  * This OpenSSL callback function is called when OpenSSL
  * does client authentication and verifies the certificate chain.
  */
+
+
 int SSL_callback_SSL_verify(int ok, X509_STORE_CTX *ctx)
 {
    /* Get Apache context back through OpenSSL context */
@@ -610,6 +627,7 @@ int SSL_callback_SSL_verify(int ok, X509
     int errdepth = X509_STORE_CTX_get_error_depth(ctx);
     int verify   = con->ctx->verify_mode;
     int depth    = con->ctx->verify_depth;
+    int skip_crl = 0;
 
     if (verify == SSL_CVERIFY_UNSET ||
         verify == SSL_CVERIFY_NONE)
@@ -620,10 +638,39 @@ int SSL_callback_SSL_verify(int ok, X509
         ok = 1;
         SSL_set_verify_result(ssl, X509_V_OK);
     }
+
+#ifdef HAVE_OPENSSL_OCSP
+    /* First perform OCSP validation if possible */
+    if (ok) {
+        /* If there was an optional verification error, it's not
+         * possible to perform OCSP validation since the issuer may be
+         * missing/untrusted.  Fail in that case.
+         */
+        if (SSL_VERIFY_ERROR_IS_OPTIONAL(errnum)) {
+            X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
+            errnum = X509_V_ERR_APPLICATION_VERIFICATION;
+            ok = 0;
+        }
+        else {
+            int ocsp_response = ssl_verify_OCSP(ok, ctx);
+            if (ocsp_response == OCSP_STATUS_OK) {
+                skip_crl = 1; /* we know it is valid we skip crl evaluation */
+            }
+            else if (ocsp_response == OCSP_STATUS_REVOKED) {
+                ok = 0 ;
+                errnum = X509_STORE_CTX_get_error(ctx);
+            }
+            else if (ocsp_response == OCSP_STATUS_UNKNOWN) {
+                /* TODO: do nothing for time being, continue with CRL */
+                ;
+            }
+        }
+    }
+#endif
     /*
      * Additionally perform CRL-based revocation checks
      */
-    if (ok && con->ctx->crl) {
+    if (ok && con->ctx->crl && !skip_crl) {
         if (!(ok = ssl_verify_CRL(ok, ctx, con))) {
             errnum = X509_STORE_CTX_get_error(ctx);
             /* TODO: Log something */
@@ -673,7 +720,10 @@ void SSL_callback_handshake(const SSL *s
         int state = SSL_get_state(ssl);
 
         if (state == SSL3_ST_SR_CLNT_HELLO_A
-            || state == SSL23_ST_SR_CLNT_HELLO_A) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+            || state == SSL23_ST_SR_CLNT_HELLO_A
+#endif
+            ) {
             con->reneg_state = RENEG_ABORT;
             /* XXX: rejecting client initiated renegotiation
              */
@@ -687,4 +737,512 @@ void SSL_callback_handshake(const SSL *s
 
 }
 
-#endif
+#ifdef HAVE_OPENSSL_OCSP
+
+/* Function that is used to do the OCSP verification */
+static int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx)
+{
+    X509 *cert, *issuer;
+    int r = OCSP_STATUS_UNKNOWN;
+
+    cert = X509_STORE_CTX_get_current_cert(ctx);
+    /* if we can't get the issuer, we cannot perform OCSP verification */
+    if (X509_STORE_CTX_get1_issuer(&issuer, ctx, cert) == 1 ) {
+        r = ssl_ocsp_request(cert, issuer);
+        if (r == OCSP_STATUS_REVOKED) {
+            /* we set the error if we know that it is revoked */
+            X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
+        }
+        else {
+            /* else we return unknown, so that we can continue with the crl */
+            r = OCSP_STATUS_UNKNOWN;
+        }
+        X509_free(issuer); /* It appears that we  should free issuer since
+                            * X509_STORE_CTX_get1_issuer() calls 
X509_OBJECT_up_ref_count()
+                            * on the issuer object (unline 
X509_STORE_CTX_get_current_cert()
+                            * that just returns the pointer
+                            */
+    }
+    return r;
+}
+
+
+/* Helps with error handling or realloc */
+static void *apr_xrealloc(void *buf, size_t oldlen, size_t len, apr_pool_t *p)
+{
+    void *newp = apr_palloc(p, len);
+
+    if(newp)
+        memcpy(newp, buf, oldlen);
+    return newp;
+}
+
+/* parses the ocsp url and updates the ocsp_urls and nocsp_urls variables
+   returns 0 on success, 1 on failure */
+static int parse_ocsp_url(unsigned char *asn1, char ***ocsp_urls,
+                          int *nocsp_urls, apr_pool_t *p)
+{
+    char **new_ocsp_urls, *ocsp_url;
+    int len, err = 0, new_nocsp_urls;
+
+    if (*asn1 == ASN1_STRING) {
+        len = *++asn1;
+        asn1++;
+        new_nocsp_urls = *nocsp_urls+1;
+        if ((new_ocsp_urls = apr_xrealloc(*ocsp_urls,*nocsp_urls, 
new_nocsp_urls, p)) == NULL)
+            err = 1;
+        if (!err) {
+            *ocsp_urls  = new_ocsp_urls;
+            *nocsp_urls = new_nocsp_urls;
+            *(*ocsp_urls + *nocsp_urls) = NULL;
+            if ((ocsp_url = apr_palloc(p, len + 1)) == NULL) {
+                err = 1;
+            }
+            else {
+                memcpy(ocsp_url, asn1, len);
+                ocsp_url[len] = '\0';
+                *(*ocsp_urls + *nocsp_urls - 1) = ocsp_url;
+            }
+        }
+    }
+    return err;
+
+}
+
+/* parses the ANS1 OID and if it is an OCSP OID then calls the parse_ocsp_url 
function */
+static int parse_ASN1_OID(unsigned char *asn1, char ***ocsp_urls, int 
*nocsp_urls, apr_pool_t *p)
+{
+    int len, err = 0 ;
+    const unsigned char OCSP_OID[] = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 
0x30, 0x01};
+
+    len = *++asn1;
+    asn1++;
+    if (memcmp(asn1, OCSP_OID, len) == 0) {
+        asn1+=len;
+        err = parse_ocsp_url(asn1, ocsp_urls, nocsp_urls, p);
+    }
+    return err;
+}
+
+
+/* Parses an ASN1 Sequence. It is a recursive function, since if it finds a  
sequence
+   within the sequence it calls recursively itself. This function stops when 
it finds
+   the end of the ASN1 sequence (marked by '\0'), so if there are other 
sequences within
+   the same sequence the while loop parses the sequences */
+
+/* This algo was developed with AIA in mind so it was tested only with this 
extension */
+static int parse_ASN1_Sequence(unsigned char *asn1, char ***ocsp_urls,
+                               int *nocsp_urls, apr_pool_t *p)
+{
+    int len = 0 , err = 0;
+
+    while (!err && *asn1 != '\0') {
+        switch(*asn1) {
+            case ASN1_SEQUENCE:
+                len = *++asn1;
+                asn1++;
+                err = parse_ASN1_Sequence(asn1, ocsp_urls, nocsp_urls, p);
+            break;
+            case ASN1_OID:
+                err = parse_ASN1_OID(asn1,ocsp_urls,nocsp_urls, p);
+                return 0;
+            break;
+            default:
+                err = 1; /* we shouldn't have any errors */
+            break;
+        }
+        asn1+=len;
+    }
+    return err;
+}
+
+/* the main function that gets the ASN1 encoding string and returns
+   a pointer to a NULL terminated "array" of char *, that contains
+   the ocsp_urls */
+static char **decode_OCSP_url(ASN1_OCTET_STRING *os, apr_pool_t *p)
+{
+    char **response = NULL;
+    unsigned char *ocsp_urls;
+    int len, numofresponses = 0 ;
+
+    len = ASN1_STRING_length(os);
+
+    ocsp_urls = apr_palloc(p,  len + 1);
+    memcpy(ocsp_urls,os->data, len);
+    ocsp_urls[len] = '\0';
+
+    if ((response = apr_pcalloc(p, sizeof(char *))) == NULL)
+        return NULL;
+    if (parse_ASN1_Sequence(ocsp_urls, &response, &numofresponses, p))
+        response = NULL;
+    return response;
+}
+
+
+/* stolen from openssl ocsp command */
+static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, X509 *issuer,
+                         STACK_OF(OCSP_CERTID) *ids)
+{
+    OCSP_CERTID *id;
+
+    if (!issuer)
+        return 0;
+    if (!*req)
+        *req = OCSP_REQUEST_new();
+    if (!*req)
+        return 0;
+    id = OCSP_cert_to_id(NULL, cert, issuer);
+    if (!id || !sk_OCSP_CERTID_push(ids, id))
+        return 0;
+    if (!OCSP_request_add0_id(*req, id))
+        return 0;
+    else
+        return 1;
+}
+
+
+/* Creates the APR socket and connect to the hostname. Returns the
+   socket or NULL if there is an error.
+*/
+static apr_socket_t *make_socket(char *hostname, int port, apr_pool_t *mp)
+{
+    apr_sockaddr_t *sa_in;
+    apr_status_t status;
+    apr_socket_t *sock = NULL;
+
+
+    status = apr_sockaddr_info_get(&sa_in, hostname, APR_INET, port, 0, mp);
+
+    if (status == APR_SUCCESS)
+        status = apr_socket_create(&sock, sa_in->family, SOCK_STREAM, 
APR_PROTO_TCP, mp);
+    if (status == APR_SUCCESS)
+        status = apr_socket_connect(sock, sa_in);
+
+    if (status == APR_SUCCESS)
+        return sock;
+    return NULL;
+}
+
+
+/* Creates the request in a memory BIO in order to send it to the OCSP server.
+   Most parts of this function are taken from mod_ssl support for OCSP (with 
some
+   minor modifications
+*/
+static BIO *serialize_request(OCSP_REQUEST *req, char *host, int port, char 
*path)
+{
+    BIO *bio;
+    int len;
+
+    len = i2d_OCSP_REQUEST(req, NULL);
+
+    bio = BIO_new(BIO_s_mem());
+
+    BIO_printf(bio, "POST %s HTTP/1.0\r\n"
+      "Host: %s:%d\r\n"
+      "Content-Type: application/ocsp-request\r\n"
+      "Content-Length: %d\r\n"
+      "\r\n",
+      path, host, port, len);
+
+    if (i2d_OCSP_REQUEST_bio(bio, req) != 1) {
+        BIO_free(bio);
+        return NULL;
+    }
+
+    return bio;
+}
+
+
+/* Send the OCSP request to the OCSP server. Taken from mod_ssl OCSP support */
+static int ocsp_send_req(apr_socket_t *sock, BIO *req)
+{
+    int len;
+    char buf[TCN_BUFFER_SZ];
+    apr_status_t rv;
+    int ok = 1;
+
+    while ((len = BIO_read(req, buf, sizeof buf)) > 0) {
+        char *wbuf = buf;
+        apr_size_t remain = len;
+
+        do {
+            apr_size_t wlen = remain;
+            rv = apr_socket_send(sock, wbuf, &wlen);
+            wbuf += remain;
+            remain -= wlen;
+        } while (rv == APR_SUCCESS && remain > 0);
+
+        if (rv != APR_SUCCESS) {
+            apr_socket_close(sock);
+            ok = 0;
+        }
+    }
+
+    return ok;
+}
+
+
+
+/* Parses the buffer from the response and extracts the OCSP response.
+   Taken from openssl library */
+static OCSP_RESPONSE *parse_ocsp_resp(char *buf, int len)
+{
+    BIO *mem = NULL;
+    char tmpbuf[1024];
+    OCSP_RESPONSE *resp = NULL;
+    char *p, *q, *r;
+    int retcode;
+
+    mem = BIO_new(BIO_s_mem());
+    if(mem == NULL)
+        return NULL;
+
+    BIO_write(mem, buf, len);  /* write the buffer to the bio */
+    if (BIO_gets(mem, tmpbuf, 512) <= 0) {
+        OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+        goto err;
+    }
+    /* Parse the HTTP response. This will look like this:
+     * "HTTP/1.0 200 OK". We need to obtain the numeric code and
+     * (optional) informational message.
+     */
+
+    /* Skip to first white space (passed protocol info) */
+    for (p = tmpbuf; *p && !apr_isspace(*p); p++)
+        continue;
+    if (!*p) {
+        goto err;
+    }
+    /* Skip past white space to start of response code */
+    while (apr_isspace(*p))
+        p++;
+    if (!*p) {
+        goto err;
+    }
+    /* Find end of response code: first whitespace after start of code */
+    for (q = p; *q && !apr_isspace(*q); q++)
+        continue;
+    if (!*q) {
+        goto err;
+    }
+    /* Set end of response code and start of message */
+    *q++ = 0;
+    /* Attempt to parse numeric code */
+    retcode = strtoul(p, &r, 10);
+    if (*r)
+        goto err;
+    /* Skip over any leading white space in message */
+    while (apr_isspace(*q))
+        q++;
+    if (*q) {
+        /* Finally zap any trailing white space in message (include CRLF) */
+        /* We know q has a non white space character so this is OK */
+        for(r = q + strlen(q) - 1; apr_isspace(*r); r--) *r = 0;
+    }
+    if (retcode != 200) {
+        goto err;
+    }
+    /* Find blank line marking beginning of content */
+    while (BIO_gets(mem, tmpbuf, 512) > 0) {
+        for (p = tmpbuf; apr_isspace(*p); p++)
+            continue;
+        if (!*p)
+            break;
+    }
+    if (*p) {
+        goto err;
+    }
+    if (!(resp = d2i_OCSP_RESPONSE_bio(mem, NULL))) {
+        goto err;
+    }
+err:
+    BIO_free(mem);
+    return resp;
+}
+
+
+/* Reads the respnse from the APR socket to a buffer, and parses the buffer to
+   return the OCSP response  */
+#define ADDLEN 512
+static OCSP_RESPONSE *ocsp_get_resp(apr_socket_t *sock)
+{
+    int buflen;
+    apr_size_t totalread = 0;
+    apr_size_t readlen;
+    char *buf, tmpbuf[ADDLEN];
+    apr_status_t rv = APR_SUCCESS;
+    apr_pool_t *p;
+    OCSP_RESPONSE *resp;
+
+    apr_pool_create(&p, NULL);
+    buflen = ADDLEN;
+    buf = apr_palloc(p, buflen);
+    if (buf == NULL) {
+        apr_pool_destroy(p);
+        return NULL;
+    }
+
+    while (rv == APR_SUCCESS ) {
+        readlen = sizeof(tmpbuf);
+        rv = apr_socket_recv(sock, tmpbuf, &readlen);
+        if (rv == APR_SUCCESS) { /* if we have read something .. we can put it 
in the buffer*/
+            if ((totalread + readlen) >= buflen) {
+                buf = apr_xrealloc(buf, buflen, buflen + ADDLEN, p);
+                if (buf == NULL) {
+                    apr_pool_destroy(p);
+                    return NULL;
+                }
+                buflen += ADDLEN; /* if needed we enlarge the buffer */
+            }
+            memcpy(buf + totalread, tmpbuf, readlen); /* the copy to the 
buffer */
+            totalread += readlen; /* update the total bytes read */
+        }
+        else {
+            if (rv == APR_EOF && readlen == 0)
+                ; /* EOF, normal situation */
+            else if (readlen == 0) {
+                /* Not success, and readlen == 0 .. some error */
+                apr_pool_destroy(p);
+                return NULL;
+            }
+        }
+    }
+
+    resp = parse_ocsp_resp(buf, buflen);
+    apr_pool_destroy(p);
+    return resp;
+}
+
+/* Creates and OCSP request and returns the OCSP_RESPONSE */
+static OCSP_RESPONSE *get_ocsp_response(X509 *cert, X509 *issuer, char *url)
+{
+    OCSP_RESPONSE *ocsp_resp = NULL;
+    OCSP_REQUEST *ocsp_req = NULL;
+    BIO *bio_req;
+    char *hostname, *path, *c_port;
+    int port, use_ssl;
+    STACK_OF(OCSP_CERTID) *ids = NULL;
+    int ok = 0;
+    apr_socket_t *apr_sock = NULL;
+    apr_pool_t *mp;
+
+    apr_pool_create(&mp, NULL);
+    ids = sk_OCSP_CERTID_new_null();
+
+    /* problem parsing the URL */
+    if (OCSP_parse_url(url,&hostname, &c_port, &path, &use_ssl) == 0 ) {
+        sk_OCSP_CERTID_free(ids);
+        return NULL;
+    }
+
+    /* Create the OCSP request */
+    if (sscanf(c_port, "%d", &port) != 1)
+        goto end;
+    ocsp_req = OCSP_REQUEST_new();
+    if (ocsp_req == NULL)
+        return NULL;
+    if (add_ocsp_cert(&ocsp_req,cert,issuer,ids) == 0 )
+        goto free_req;
+
+    /* create the BIO with the request to send */
+    bio_req = serialize_request(ocsp_req, hostname, port, path);
+    if (bio_req == NULL) {
+        goto free_req;
+    }
+
+    apr_sock = make_socket(hostname, port, mp);
+    if (apr_sock == NULL) {
+        ocsp_resp = NULL;
+        goto free_bio;
+    }
+
+    ok = ocsp_send_req(apr_sock, bio_req);
+    if (ok)
+        ocsp_resp = ocsp_get_resp(apr_sock);
+
+free_bio:
+    BIO_free(bio_req);
+
+free_req:
+    if(apr_sock && ok) /* if ok == 0 we have already closed the socket */
+        apr_socket_close(apr_sock);
+
+    apr_pool_destroy(mp);
+
+    sk_OCSP_CERTID_free(ids);
+    OCSP_REQUEST_free(ocsp_req);
+
+end:
+    return ocsp_resp;
+}
+
+/* Process the OCSP_RESPONSE and returns the corresponding
+   answert according to the status.
+*/
+static int process_ocsp_response(OCSP_RESPONSE *ocsp_resp)
+{
+    int r, o = V_OCSP_CERTSTATUS_UNKNOWN, i;
+    OCSP_BASICRESP *bs;
+    OCSP_SINGLERESP *ss;
+
+    r = OCSP_response_status(ocsp_resp);
+
+    if (r != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+        OCSP_RESPONSE_free(ocsp_resp);
+        return OCSP_STATUS_UNKNOWN;
+    }
+    bs = OCSP_response_get1_basic(ocsp_resp);
+
+    ss = OCSP_resp_get0(bs,0); /* we know we have only 1 request */
+
+    i = OCSP_single_get0_status(ss, NULL, NULL, NULL, NULL);
+    if (i == V_OCSP_CERTSTATUS_GOOD)
+        o =  OCSP_STATUS_OK;
+    else if (i == V_OCSP_CERTSTATUS_REVOKED)
+        o = OCSP_STATUS_REVOKED;
+    else if (i == V_OCSP_CERTSTATUS_UNKNOWN)
+        o = OCSP_STATUS_UNKNOWN;
+
+    /* we clean up */
+    OCSP_RESPONSE_free(ocsp_resp);
+    return o;
+}
+
+static int ssl_ocsp_request(X509 *cert, X509 *issuer)
+{
+    char **ocsp_urls = NULL;
+    int nid;
+    X509_EXTENSION *ext;
+    ASN1_OCTET_STRING *os;
+    apr_pool_t *p;
+
+    apr_pool_create(&p, NULL);
+
+    /* Get the proper extension */
+    nid = X509_get_ext_by_NID(cert,NID_info_access,-1);
+    if (nid >= 0 ) {
+        ext = X509_get_ext(cert,nid);
+        os = X509_EXTENSION_get_data(ext);
+
+        ocsp_urls = decode_OCSP_url(os, p);
+    }
+
+    /* if we find the extensions and we can parse it check
+       the ocsp status. Otherwise, return OCSP_STATUS_UNKNOWN */
+    if (ocsp_urls != NULL) {
+        OCSP_RESPONSE *resp;
+        /* for the time being just check for the fist response .. a better
+           approach is to iterate for all the possible ocsp urls */
+        resp = get_ocsp_response(cert, issuer, ocsp_urls[0]);
+
+        if (resp != NULL) {
+            apr_pool_destroy(p);
+            return process_ocsp_response(resp);
+        }
+    }
+    apr_pool_destroy(p);
+    return OCSP_STATUS_UNKNOWN;
+}
+
+#endif /* HAS_OCSP_ENABLED */
+#endif /* HAVE_OPENSSL  */



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to