Author: mturk
Date: Fri Feb 24 07:43:44 2012
New Revision: 1293119

URL: http://svn.apache.org/viewvc?rev=1293119&view=rev
Log:
BZ45392 Apply modified patch. OCSP is enabled is explicitly configure with 
--enable-ocsp at build time
Modified:
    tomcat/native/branches/1.1.x/native/configure.in
    tomcat/native/branches/1.1.x/native/include/ssl_private.h
    tomcat/native/branches/1.1.x/native/src/sslutils.c
    tomcat/native/branches/1.1.x/xdocs/miscellaneous/changelog.xml

Modified: tomcat/native/branches/1.1.x/native/configure.in
URL: 
http://svn.apache.org/viewvc/tomcat/native/branches/1.1.x/native/configure.in?rev=1293119&r1=1293118&r2=1293119&view=diff
==============================================================================
--- tomcat/native/branches/1.1.x/native/configure.in (original)
+++ tomcat/native/branches/1.1.x/native/configure.in Fri Feb 24 07:43:44 2012
@@ -151,6 +151,17 @@ AC_ARG_ENABLE(openssl, 
   esac
 ])
 
+AC_ARG_ENABLE(ocsp,
+[AS_HELP_STRING([--enable-openssl],[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/branches/1.1.x/native/include/ssl_private.h
URL: 
http://svn.apache.org/viewvc/tomcat/native/branches/1.1.x/native/include/ssl_private.h?rev=1293119&r1=1293118&r2=1293119&view=diff
==============================================================================
--- tomcat/native/branches/1.1.x/native/include/ssl_private.h (original)
+++ tomcat/native/branches/1.1.x/native/include/ssl_private.h Fri Feb 24 
07:43:44 2012
@@ -204,6 +204,11 @@
                                 "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
+
+
 extern void *SSL_temp_keys[SSL_TMP_KEY_MAX];
 
 typedef struct {
@@ -308,4 +313,7 @@ void        SSL_vhost_algo_id(const unsi
 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);
+int         SSL_ocsp_request(X509 *cert, X509 *issuer);
+
+
 #endif /* SSL_PRIVATE_H */

Modified: tomcat/native/branches/1.1.x/native/src/sslutils.c
URL: 
http://svn.apache.org/viewvc/tomcat/native/branches/1.1.x/native/src/sslutils.c?rev=1293119&r1=1293118&r2=1293119&view=diff
==============================================================================
--- tomcat/native/branches/1.1.x/native/src/sslutils.c (original)
+++ tomcat/native/branches/1.1.x/native/src/sslutils.c Fri Feb 24 07:43:44 2012
@@ -21,16 +21,31 @@
  */
 
 #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
 
+#if defined(HAVE_SSL_OCSP) && defined(HAVE_OPENSSL_OCSP)
+#define HAS_OCSP_ENABLED 1
+#else
+#define HAS_OCSP_ENABLED 0
+#endif
+#if HAS_OCSP_ENABLED
+#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
+
+static int ssl_verify_OCSP(int ok, X509_STORE_CTX *ctx);
+#endif
+
 /*  _________________________________________________________________
 **
 **  Additional High-Level Functions for OpenSSL
@@ -621,6 +636,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 */
@@ -632,6 +649,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)
@@ -642,10 +660,28 @@ int SSL_callback_SSL_verify(int ok, X509
         ok = 1;
         SSL_set_verify_result(ssl, X509_V_OK);
     }
+
+#if HAS_OCSP_ENABLED
+    /* First perform OCSP validation if possible */
+    if(ok) {
+        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 */
@@ -693,8 +729,8 @@ void SSL_callback_handshake(const SSL *s
      * read. */
     if ((where & SSL_CB_ACCEPT_LOOP) && con->reneg_state == RENEG_REJECT) {
         int state = SSL_get_state(ssl);
-        
-        if (state == SSL3_ST_SR_CLNT_HELLO_A 
+
+        if (state == SSL3_ST_SR_CLNT_HELLO_A
             || state == SSL23_ST_SR_CLNT_HELLO_A) {
             con->reneg_state = RENEG_ABORT;
             /* XXX: rejecting client initiated renegotiation
@@ -708,5 +744,511 @@ void SSL_callback_handshake(const SSL *s
     }
 
 }
- 
-#endif
+
+#if HAS_OCSP_ENABLED
+
+/* 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 developped 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 i, 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;
+    return OCSP_request_add0_id(*req, id);
+}
+
+
+/* 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)
+{
+    int r = 0;
+    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 = 0, 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;
+}
+
+
+int SSL_ocsp_request(X509 *cert, X509 *issuer)
+{
+    char **ocsp_urls = NULL;
+    int nid, i;
+    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]);
+
+        apr_pool_destroy(p);
+        if (resp != NULL)
+            return process_ocsp_response(resp);
+    }
+    apr_pool_destroy(p);
+    return OCSP_STATUS_UNKNOWN;
+}
+
+#endif /* HAS_OCSP_ENABLED */
+#endif /* HAVE_OPENSSL  */

Modified: tomcat/native/branches/1.1.x/xdocs/miscellaneous/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/native/branches/1.1.x/xdocs/miscellaneous/changelog.xml?rev=1293119&r1=1293118&r2=1293119&view=diff
==============================================================================
--- tomcat/native/branches/1.1.x/xdocs/miscellaneous/changelog.xml (original)
+++ tomcat/native/branches/1.1.x/xdocs/miscellaneous/changelog.xml Fri Feb 24 
07:43:44 2012
@@ -38,6 +38,10 @@
 </section>
 <section name="Changes between 1.1.22 and 1.1.23">
   <changelog>
+    <update>
+      <bug>45392</bug>: Add support for OCSP verification. Based upon a patch
+      from Aristotelis. (mturk)
+    </update>
     <fix>
       <bug>52119</bug>: Autodetect Diablo JDK on FreeBSD and Java7+. Based 
upon a patch
       from Michael Osipov. (mturk)



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

Reply via email to