DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=41123>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND·
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=41123


[EMAIL PROTECTED] changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
  Attachment #20958|Small corrections in error  |Small corrections in error
        description|handling and OCSP response  |handling, OCSP response
                   |logging                     |logging, and memory leaks
                   |                            |corrections (remarks from
                   |                            |OpenSSL developers)




------- Additional Comments From [EMAIL PROTECTED]  2007-10-12 06:22 -------
(From update of attachment 20958)
diff -uaEbwNp orig/ssl_ocsp.c ./ssl_ocsp.c
--- orig/ssl_ocsp.c     1970-01-01 01:00:00.000000000 +0100
+++ ./ssl_ocsp.c        2007-10-11 16:37:20.866178500 +0200
@@ -0,0 +1,441 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+    
+/*                      _             _
+ *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
+ * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
+ * | | | | | | (_) | (_| |   \__ \__ \ |
+ * |_| |_| |_|\___/ \__,_|___|___/___/_|
+ *                      |_____|
+ *  ssl_ocsp.c
+ *  The SSL OCSP checking
+ *
+ *  Developed by Marc Stern, for Approach Belgium / CSC / Belgian Government
+ *           based on code developed by Zetes Pass
+ *
+ *  This code was added to support the Belgian Electronic Identity Card
+ *
+ *  The OCSP responder URL is read from the certificate itself
+ *
+ */ 
+    /* ``When the only tool you own is a hammer,
+         every problem begins to resemble a nail.´´
+     */ 
+    
+#include "mod_ssl.h"
+#include "ssl_private.h"
+#include "apr_base64.h"
+
+#define X509_NAME2STR(name_)        X509_NAME_oneline(name_, NULL, 0)
+#define X509_SUBJ_NAME(cert_)      
X509_NAME2STR(X509_get_subject_name(cert_))
+#define X509_ISSUER_NAME(cert_)     X509_NAME2STR(X509_get_issuer_name(cert_))
+
+
+static char *ap_ocsp_ASN1_Int2Str(ASN1_INTEGER *data, apr_pool_t *pool)
+{
+    char *result = (char *)apr_palloc(pool, 100); /* 100 should be enough */
+    char *buf = NULL;
+    BIGNUM *bn = ASN1_INTEGER_to_BN(data, NULL);
+
+    *result = 0;
+    if (bn && !BN_is_zero(bn)) {
+        buf = BN_bn2hex(bn);
+        if (buf) {
+            strncpy(result, buf, sizeof(result) - 1);
+            result[sizeof(result) - 1 ] = 0;
+        }
+    }
+
+    if (bn) BN_free(bn);
+    if (buf) OPENSSL_free(buf);
+    return result;
+}
+
+static char *ap_ocsp_get_ocsp_uri(X509 *cert, apr_pool_t *pool)
+{
+    int crit, j;
+    STACK_OF(ACCESS_DESCRIPTION) *values =
+        (STACK_OF(ACCESS_DESCRIPTION) *)
+               X509_get_ext_d2i(cert, NID_info_access, &crit, NULL);
+    if (! values) return NULL;
+
+    for (j = 0; j < sk_ACCESS_DESCRIPTION_num(values); j++) {
+        ACCESS_DESCRIPTION *value = sk_ACCESS_DESCRIPTION_value(values, j);
+        if(OBJ_obj2nid(value->method) == NID_ad_OCSP) {
+            /* Name found in extension */
+                       char *result;
+                       
+                       /* Check that it is a URI */
+                       if (value->location->type != GEN_URI)
+                               continue;
+
+            result = apr_pstrdup(pool,
+                             (char
*)value->location->d.uniformResourceIdentifier->data);
+                        AUTHORITY_INFO_ACCESS_free(values);
+            return result;
+        }
+    }
+
+       sk_ACCESS_DESCRIPTION_free(values);
+       //AUTHORITY_INFO_ACCESS_free(values);
+    return NULL;
+}
+
+
+static BIO *ap_ocsp_connect(const char *host, int port) 
+{
+    BIO *connection = BIO_new_connect((char *)host);
+    if (!connection) return 0;
+
+    BIO_set_conn_int_port(connection, &port);
+    if (BIO_do_connect(connection) <= 0) {
+        /* Not needed - default: BIO_set_close(connection, BIO_CLOSE); */
+        BIO_free_all(connection);
+        return NULL;
+    }
+
+    return connection;
+
+}
+
+
+static OCSP_RESPONSE *ap_ocsp_sendreq(const char *ocspHost, const char
*ocspPort, const char *ocspPath, OCSP_REQUEST *request, server_rec *s) 
+{
+    BIO *bio = NULL;
+    OCSP_RESPONSE *response = NULL;
+
+    /* establish a connection to the OCSP responder */ 
+    ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+        "Connect to OCSP responder '%s:%s'", ocspHost, ocspPort);
+    bio = ap_ocsp_connect(ocspHost, atoi(ocspPort));
+    if (!bio) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                "Cannot connect to OCSP responder '%s:%s'", ocspHost,
ocspPort);
+        return NULL;
+    }
+    
+    /* send the request and get a response */ 
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                "sending request to OCSP responder");
+    response = OCSP_sendreq_bio(bio, (char *)ocspPath, request);
+    if (!response) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                        "Cannot send request to OCSP responder '%s'",
ocspHost);
+        }
+
+    BIO_free_all(bio);
+
+    return response;
+}
+
+
+static int ap_ocsp_verify_ocsp(X509 *cert, X509_STORE_CTX *ctx, server_rec *s,
+                               int *ocspStatus, apr_pool_t *pool) 
+{
+    int rc = SSL_OCSP_OK;
+    X509 *issuer = NULL;
+    char *ocspUrl = NULL, *ocspHost = NULL, *ocspPort = NULL, *ocspPath =
NULL;
+    BIO * bio = NULL;
+    OCSP_RESPONSE * response = NULL;
+    OCSP_BASICRESP * basicResponse = NULL;
+    OCSP_REQUEST * request = NULL;
+    OCSP_CERTID * certID = NULL;
+    int ssl = 0;
+    SSLSrvConfigRec *sc = mySrvConfig(s);
+       char *subj_name = X509_SUBJ_NAME(cert);
+       char *issuer_name = X509_ISSUER_NAME(cert);
+
+    *ocspStatus = V_OCSP_CERTSTATUS_UNKNOWN;
+    X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
+    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+        "OCSP check - cert='%s', issuer='%s'", subj_name, issuer_name);
+   
+    
+    /* First look if we force the responder url*/
+    if (sc->server->OCSPForceResponderURL) {
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                "Force the url of responder to: %s",
sc->server->OCSPForceResponderURL);
+        ocspUrl = sc->server->OCSPForceResponderURL;
+    }
+    /* if not, look inside the certificate if we have one */
+    else {
+         /* Get OCSP Responder URI (only first one) */
+        ocspUrl = ap_ocsp_get_ocsp_uri(cert, pool); 
+        if (ocspUrl)
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                "OCSP responder from certificate: %s", ocspUrl);
+    }
+
+    if (!ocspUrl && sc->server->OCSPDefaultResponderURL) {
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+            "No Responder URL in certificate - using default: %s",
+            sc->server->OCSPDefaultResponderURL);
+        ocspUrl = sc->server->OCSPDefaultResponderURL;
+    }
+
+    if (!ocspUrl) {
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
+         "Cannot get OCSP responder URL from '%s' and no default URL
Responder",
+         subj_name);
+        rc = SSL_OCSP_ERROR_PARSE_URL;
+    }
+    
+    if (rc == SSL_OCSP_OK) {
+        if (!OCSP_parse_url(ocspUrl, &ocspHost, &ocspPort, &ocspPath, &ssl)) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                "Cannot parse OCSP responder URL from '%s'",
+                               subj_name);
+            rc = SSL_OCSP_ERROR_PARSE_URL;
+        }
+    }
+    
+
+    if (rc == SSL_OCSP_OK) {
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Create new OCSP
request");
+        request = OCSP_REQUEST_new();
+        if (!request) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                        "Cannot create new OCSP request");
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+    
+    if (rc == SSL_OCSP_OK) {
+        /* Get issuer */
+               int r;
+               /* Enhancement: ctx->chain is already ordered -> extract 2nd ?
*/
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Get Issuer");
+        r = X509_STORE_CTX_get1_issuer(&issuer, ctx, cert);
+        if (r != 1) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                        "Cannot get issuer of '%s'. rc=%d", subj_name, rc);
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+
+    if (rc == SSL_OCSP_OK) {
+        certID = OCSP_cert_to_id(0, cert, issuer);
+        if (!certID || !OCSP_request_add0_id(request, certID)) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s
+                       , "Cannot get certificate id from '%s'", subj_name);
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+
+    if (rc == SSL_OCSP_OK) {
+        OCSP_request_add1_nonce(request, 0, -1);
+
+        /*  To use a proxy, do the following
+              - ocspHost = proxyHost;
+              - ocspPort = proxyPort;
+              - ocspPath = ocspUrl;
+         */
+    
+        /* establish a connection to the OCSP responder */ 
+        response = ap_ocsp_sendreq(ocspHost, ocspPort, ocspPath, request, s);
+        if (!response) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                    "Cannot send request to OCSP responder '%s'", ocspHost);
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+
+
+    if ( (rc == SSL_OCSP_OK) && (s->loglevel >= APLOG_DEBUG) ) {
+        /* Log OCSP answer (complete OpenSSL buffer) */
+        char *buf = apr_palloc(pool,
+               
apr_base64_encode_len(response->responseBytes->response->length) + 1);
+        if (buf) {
+            apr_base64_encode(buf,
+                        (const char*)response->responseBytes->response->data,
+                        response->responseBytes->response->length);
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                        "OCSP response (OpenSSL bufer): serial=%s | dn=%s |
%s",
+                         ap_ocsp_ASN1_Int2Str(X509_get_serialNumber(cert),
pool),
+                          X509_SUBJ_NAME(cert), buf);
+        }
+        else {
+           ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Cannot allocate
buffer");
+        }
+    }
+
+    if (rc == SSL_OCSP_OK) {
+               int r;
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                "Analyse OCSP request answer");
+        r = OCSP_response_status(response);
+        if (r != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                        "Bad OCSP responder answer. rc=%d", rc);
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+    
+    if ( (rc == SSL_OCSP_OK) && (s->loglevel >= APLOG_DEBUG) ) {
+        /* Log OCSP answer (only the "bare" response) */
+        int len = i2d_OCSP_RESPONSE(response, NULL);
+        if (len <= 0)
+           rc = SSL_OCSP_ERROR_INTERNAL;
+        else {
+                       unsigned char *buf1, *buf2;
+            buf1 = buf2 = (unsigned char *)apr_palloc(pool, len);
+            if (!buf1) {
+                               ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Out
of memory");
+                rc = SSL_OCSP_ERROR_INTERNAL;
+            }
+            else {
+               if (i2d_OCSP_RESPONSE(response, &buf1) != len) 
+                              rc = SSL_OCSP_ERROR_INTERNAL;
+               else {
+                    /* contents is in buf2, because buf1 is now pointing
+                       to the end of the structure */
+                    char h[] = "OCSP response : ";
+                    int len64 = apr_base64_encode_len(len);
+                    char *msg = (char *)apr_palloc(pool, len64 + strlen(h) +
1);
+                    if (msg) {
+                        strcpy(msg, h);
+                        apr_base64_encode(msg + strlen(h), buf2, len);
+                        msg[strlen(h) + len64 + 1] = 0;
+                        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, msg);
+                    }
+               }
+           }
+       }
+    }
+
+    if (rc == SSL_OCSP_OK) {
+        basicResponse = OCSP_response_get1_basic(response);
+        if (!basicResponse) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                        "Bad OCSP responder answer");
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+
+    if (rc == SSL_OCSP_OK) {
+        if (OCSP_check_nonce(request, basicResponse) <= 0) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                        "Bad OCSP responder answer (bad nonce)");
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+        
+    if (rc == SSL_OCSP_OK) {
+        if (OCSP_basic_verify(basicResponse, 0, ctx->ctx,
+                sc->server->OCSPResponderVerifyFlag) <= 0) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                        "Error verifying OCSP responder answer");
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+    
+    if (rc == SSL_OCSP_OK) {
+        int ocspReason = -1;
+        ASN1_GENERALIZEDTIME * ocspProducedAt, *ocspThisUpdate,
+            *ocspNextUpdate;
+        rc = OCSP_resp_find_status(basicResponse, certID, ocspStatus,
+                      &ocspReason, &ocspProducedAt,
+                      &ocspThisUpdate, &ocspNextUpdate);
+        if (rc == 0) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Bad OCSP status");
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+        "OCSP validation completed: status=%d", *ocspStatus);
+    rc = SSL_OCSP_OK;
+    }
+
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Cleanup OCSP code");
+       if (issuer) X509_free(issuer);
+       if (subj_name)   OPENSSL_free(subj_name);
+       if (issuer_name) OPENSSL_free(issuer_name);
+    if (request)  OCSP_REQUEST_free(request);
+    if (response) OCSP_RESPONSE_free(response);
+    if (basicResponse) OCSP_BASICRESP_free(basicResponse);
+       if (ocspHost) OPENSSL_free(ocspHost);
+       if (ocspPort) OPENSSL_free(ocspPort);
+       if (ocspPath) OPENSSL_free(ocspPath);
+    /* certID is just a pointer, nothing to free */ 
+
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Ending cleanup OCSP code");
+    return rc;
+}
+
+int ssl_cmd_VerifyOCSP(X509_STORE_CTX *ctx, server_rec *s, int *ocspStatus,
+ apr_pool_t *pool) 
+{
+    int rc = SSL_OCSP_OK, i;
+    X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
+    X509_STORE_CTX *ocspCtx = NULL;
+    X509_STORE *store = NULL;
+    SSLSrvConfigRec *sc = mySrvConfig(s);
+       char *subj_name = X509_SUBJ_NAME(cert);
+       char *issuer_name = X509_ISSUER_NAME(cert);
+
+    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+        "Validating certificate '%s', issuer: '%s'",
+           subj_name, issuer_name);
+    
+    /* Store certif chain in a store */ 
+    if (!ctx->chain) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "No certificate chain");
+        return SSL_OCSP_ERROR_INTERNAL;
+    }
+
+    /*
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+        "certificates chain length: %d", ctx->chain->num);
+    */ 
+
+    store = X509_STORE_new();
+    if (!store) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                "Cannot create a new X509 store");
+        return SSL_OCSP_ERROR_INTERNAL;
+    }
+    
+    for (i = 0; i < ctx->chain->num; i++)
+    if (!X509_STORE_add_cert(store, sk_X509_value(ctx->chain, i))) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                "Cannot add certificate to X509 store");
+        rc = SSL_OCSP_ERROR_INTERNAL;
+    }
+
+    if (rc == SSL_OCSP_OK) {
+        ocspCtx = X509_STORE_CTX_new();
+        if (!ocspCtx) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                    "Cannot create a new X509 context");
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+    if (rc == SSL_OCSP_OK) {
+        if (X509_STORE_CTX_init(ocspCtx, store, cert, 0) != 1) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                        "Cannot initialise the new X509 context");
+            rc = SSL_OCSP_ERROR_INTERNAL;
+        }
+    }
+
+    if (rc == SSL_OCSP_OK)
+        rc = ap_ocsp_verify_ocsp(cert, ocspCtx, s, ocspStatus, pool);
+
+        if (subj_name)   OPENSSL_free(subj_name);
+        if (issuer_name) OPENSSL_free(issuer_name);
+    if (store)   X509_STORE_free(store);
+    if (ocspCtx) X509_STORE_CTX_free(ocspCtx);
+    return rc;
+}


-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to