httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pque...@apache.org
Subject svn commit: r645594 [25/28] - in /httpd/sandbox/amsterdam/d: ./ build/ docs/conf/ docs/conf/extra/ docs/man/ docs/manual/ docs/manual/developer/ docs/manual/faq/ docs/manual/howto/ docs/manual/misc/ docs/manual/mod/ docs/manual/platform/ docs/manual/pr...
Date Mon, 07 Apr 2008 16:31:24 GMT
Modified: httpd/sandbox/amsterdam/d/modules/proxy/mod_proxy_ftp.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/proxy/mod_proxy_ftp.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/proxy/mod_proxy_ftp.c (original)
+++ httpd/sandbox/amsterdam/d/modules/proxy/mod_proxy_ftp.c Mon Apr  7 09:28:58 2008
@@ -314,6 +314,7 @@
         /* basedir is either "", or "/%2f" for the "squid %2f hack" */
         const char *basedir = "";  /* By default, path is relative to the $HOME dir */
         char *wildcard = NULL;
+        const char *escpath;
 
         /* Save "scheme://site" prefix without password */
         site = apr_uri_unparse(p, &f->r->parsed_uri, APR_URI_UNP_OMITPASSWORD | APR_URI_UNP_OMITPATHINFO);
@@ -350,13 +351,14 @@
         str = (basedir[0] != '\0') ? "<a href=\"/%2f/\">%2f</a>/" : "";
 
         /* print "ftp://host/" */
+        escpath = ap_escape_html(p, path);
         str = apr_psprintf(p, DOCTYPE_HTML_3_2
                 "<html>\n <head>\n  <title>%s%s%s</title>\n"
+                "<base href=\"%s%s%s\">\n"
                 " </head>\n"
                 " <body>\n  <h2>Directory of "
                 "<a href=\"/\">%s</a>/%s",
-                site, basedir, ap_escape_html(p, path),
-                site, str);
+                site, basedir, escpath, site, basedir, escpath, site, str);
 
         APR_BRIGADE_INSERT_TAIL(out, apr_bucket_pool_create(str, strlen(str),
                                                           p, c->bucket_alloc));
@@ -959,6 +961,7 @@
         }
         /* TODO: see if ftp could use determine_connection */
         backend->addr = connect_addr;
+        backend->r = r;
         ap_set_module_config(c->conn_config, &proxy_ftp_module, backend);
     }
 
@@ -1690,7 +1693,13 @@
 
     /* set content-type */
     if (dirlisting) {
-        ap_set_content_type(r, "text/html");
+        proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
+                                                     &proxy_module);
+
+        ap_set_content_type(r, apr_pstrcat(p, "text/html;charset=",
+                                           dconf->ftp_directory_charset ?
+                                           dconf->ftp_directory_charset :
+                                           "ISO-8859-1",  NULL));
     }
     else {
         if (r->content_type) {

Modified: httpd/sandbox/amsterdam/d/modules/proxy/mod_proxy_http.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/proxy/mod_proxy_http.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/proxy/mod_proxy_http.c (original)
+++ httpd/sandbox/amsterdam/d/modules/proxy/mod_proxy_http.c Mon Apr  7 09:28:58 2008
@@ -259,7 +259,7 @@
     APR_BRIGADE_INSERT_TAIL(header_brigade, e);
 }
 
-static apr_status_t pass_brigade(apr_bucket_alloc_t *bucket_alloc,
+static int pass_brigade(apr_bucket_alloc_t *bucket_alloc,
                                  request_rec *r, proxy_conn_rec *conn,
                                  conn_rec *origin, apr_bucket_brigade *bb,
                                  int flush)
@@ -279,22 +279,27 @@
         ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
                      "proxy: pass request body failed to %pI (%s)",
                      conn->addr, conn->hostname);
-        return status;
+        if (origin->aborted) { 
+            return APR_STATUS_IS_TIMEUP(status) ? HTTP_GATEWAY_TIME_OUT : HTTP_BAD_GATEWAY;
+        }
+        else { 
+            return HTTP_BAD_REQUEST; 
+        }
     }
     apr_brigade_cleanup(bb);
-    return APR_SUCCESS;
+    return OK;
 }
 
 #define MAX_MEM_SPOOL 16384
 
-static apr_status_t stream_reqbody_chunked(apr_pool_t *p,
+static int stream_reqbody_chunked(apr_pool_t *p,
                                            request_rec *r,
                                            proxy_conn_rec *p_conn,
                                            conn_rec *origin,
                                            apr_bucket_brigade *header_brigade,
                                            apr_bucket_brigade *input_brigade)
 {
-    int seen_eos = 0;
+    int seen_eos = 0, rv = OK;
     apr_size_t hdr_len;
     apr_off_t bytes;
     apr_status_t status;
@@ -352,7 +357,7 @@
              */
             status = ap_save_brigade(NULL, &bb, &input_brigade, p);
             if (status != APR_SUCCESS) {
-                return status;
+                return HTTP_INTERNAL_SERVER_ERROR;
             }
 
             header_brigade = NULL;
@@ -362,9 +367,9 @@
         }
 
         /* The request is flushed below this loop with chunk EOS header */
-        status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 0);
-        if (status != APR_SUCCESS) {
-            return status;
+        rv = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 0);
+        if (rv != OK) {
+            return rv;
         }
 
         if (seen_eos) {
@@ -376,7 +381,7 @@
                                 HUGE_STRING_LEN);
 
         if (status != APR_SUCCESS) {
-            return status;
+            return HTTP_BAD_REQUEST;
         }
     }
 
@@ -408,11 +413,11 @@
     }
 
     /* Now we have headers-only, or the chunk EOS mark; flush it */
-    status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1);
-    return status;
+    rv = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1);
+    return rv;
 }
 
-static apr_status_t stream_reqbody_cl(apr_pool_t *p,
+static int stream_reqbody_cl(apr_pool_t *p,
                                       request_rec *r,
                                       proxy_conn_rec *p_conn,
                                       conn_rec *origin,
@@ -420,7 +425,7 @@
                                       apr_bucket_brigade *input_brigade,
                                       const char *old_cl_val)
 {
-    int seen_eos = 0;
+    int seen_eos = 0, rv = 0;
     apr_status_t status = APR_SUCCESS;
     apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
     apr_bucket_brigade *bb;
@@ -433,7 +438,7 @@
         add_cl(p, bucket_alloc, header_brigade, old_cl_val);
         if (APR_SUCCESS != (status = apr_strtoff(&cl_val, old_cl_val, NULL,
                                                  0))) {
-            return status;
+            return HTTP_INTERNAL_SERVER_ERROR;
         }
     }
     terminate_headers(bucket_alloc, header_brigade);
@@ -486,7 +491,7 @@
              */
             status = ap_save_brigade(NULL, &bb, &input_brigade, p);
             if (status != APR_SUCCESS) {
-                return status;
+                return HTTP_INTERNAL_SERVER_ERROR;
             }
 
             header_brigade = NULL;
@@ -496,9 +501,9 @@
         }
 
         /* Once we hit EOS, we are ready to flush. */
-        status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, seen_eos);
-        if (status != APR_SUCCESS) {
-            return status;
+        rv = pass_brigade(bucket_alloc, r, p_conn, origin, bb, seen_eos);
+        if (rv != OK) {
+            return rv ;
         }
 
         if (seen_eos) {
@@ -510,7 +515,7 @@
                                 HUGE_STRING_LEN);
 
         if (status != APR_SUCCESS) {
-            return status;
+            return HTTP_BAD_REQUEST;
         }
     }
 
@@ -518,7 +523,7 @@
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                      "proxy: client %s given Content-Length did not match"
                      " number of body bytes read", r->connection->remote_ip);
-        return APR_EOF;
+        return HTTP_BAD_REQUEST;
     }
 
     if (header_brigade) {
@@ -526,12 +531,13 @@
          * body; send it now with the flush flag
          */
         bb = header_brigade;
-        status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1);
+        return(pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1));
     }
-    return status;
+
+    return OK;
 }
 
-static apr_status_t spool_reqbody_cl(apr_pool_t *p,
+static int spool_reqbody_cl(apr_pool_t *p,
                                      request_rec *r,
                                      proxy_conn_rec *p_conn,
                                      conn_rec *origin,
@@ -572,7 +578,7 @@
                 if (status != APR_SUCCESS) {
                     ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
                                  "proxy: search for temporary directory failed");
-                    return status;
+                    return HTTP_INTERNAL_SERVER_ERROR;
                 }
                 apr_filepath_merge(&template, temp_dir,
                                    "modproxy.tmp.XXXXXX",
@@ -582,7 +588,7 @@
                     ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
                                  "proxy: creation of temporary file in directory %s failed",
                                  temp_dir);
-                    return status;
+                    return HTTP_INTERNAL_SERVER_ERROR;
                 }
             }
             for (e = APR_BRIGADE_FIRST(input_brigade);
@@ -602,7 +608,7 @@
                     ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
                                  "proxy: write to temporary file %s failed",
                                  tmpfile_name);
-                    return status;
+                    return HTTP_INTERNAL_SERVER_ERROR;
                 }
                 AP_DEBUG_ASSERT(bytes_read == bytes_written);
                 fsize += bytes_written;
@@ -622,7 +628,7 @@
              */
             status = ap_save_brigade(NULL, &body_brigade, &input_brigade, p);
             if (status != APR_SUCCESS) {
-                return status;
+                return HTTP_INTERNAL_SERVER_ERROR;
             }
 
         }
@@ -638,7 +644,7 @@
                                 HUGE_STRING_LEN);
 
         if (status != APR_SUCCESS) {
-            return status;
+            return HTTP_BAD_REQUEST;
         }
     }
 
@@ -655,12 +661,11 @@
         APR_BRIGADE_INSERT_TAIL(header_brigade, e);
     }
     /* This is all a single brigade, pass with flush flagged */
-    status = pass_brigade(bucket_alloc, r, p_conn, origin, header_brigade, 1);
-    return status;
+    return(pass_brigade(bucket_alloc, r, p_conn, origin, header_brigade, 1));
 }
 
 static
-apr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r,
+int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
                                    proxy_conn_rec *p_conn, conn_rec *origin,
                                    proxy_server_conf *conf,
                                    apr_uri_t *uri,
@@ -683,7 +688,7 @@
     const char *old_te_val = NULL;
     apr_off_t bytes_read = 0;
     apr_off_t bytes;
-    int force10;
+    int force10, rv;
     apr_table_t *headers_in_copy;
 
     header_brigade = apr_brigade_create(p, origin->bucket_alloc);
@@ -926,7 +931,7 @@
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                      "proxy: %s Transfer-Encoding is not supported",
                      old_te_val);
-        return APR_EINVAL;
+        return HTTP_INTERNAL_SERVER_ERROR;
     }
 
     if (old_cl_val && old_te_val) {
@@ -959,7 +964,7 @@
                          " from %s (%s)",
                          p_conn->addr, p_conn->hostname ? p_conn->hostname: "",
                          c->remote_ip, c->remote_host ? c->remote_host: "");
-            return status;
+            return HTTP_BAD_REQUEST;
         }
 
         apr_brigade_length(temp_brigade, 1, &bytes);
@@ -981,7 +986,7 @@
                          " to %pI (%s) from %s (%s)",
                          p_conn->addr, p_conn->hostname ? p_conn->hostname: "",
                          c->remote_ip, c->remote_host ? c->remote_host: "");
-            return status;
+            return HTTP_INTERNAL_SERVER_ERROR;
         }
 
     /* Ensure we don't hit a wall where we have a buffer too small
@@ -1095,37 +1100,38 @@
     /* send the request body, if any. */
     switch(rb_method) {
     case RB_STREAM_CHUNKED:
-        status = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade,
+        rv = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade,
                                         input_brigade);
         break;
     case RB_STREAM_CL:
-        status = stream_reqbody_cl(p, r, p_conn, origin, header_brigade,
+        rv = stream_reqbody_cl(p, r, p_conn, origin, header_brigade,
                                    input_brigade, old_cl_val);
         break;
     case RB_SPOOL_CL:
-        status = spool_reqbody_cl(p, r, p_conn, origin, header_brigade,
+        rv = spool_reqbody_cl(p, r, p_conn, origin, header_brigade,
                                   input_brigade, (old_cl_val != NULL)
                                               || (old_te_val != NULL)
                                               || (bytes_read > 0));
         break;
     default:
         /* shouldn't be possible */
-        status = APR_EINVAL;
+        rv = HTTP_INTERNAL_SERVER_ERROR ;
         break;
     }
 
-    if (status != APR_SUCCESS) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
+    if (rv != OK) {
+        /* apr_errno value has been logged in lower level method */
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                      "proxy: pass request body failed to %pI (%s)"
                      " from %s (%s)",
                      p_conn->addr,
                      p_conn->hostname ? p_conn->hostname: "",
                      c->remote_ip,
                      c->remote_host ? c->remote_host: "");
-        return status;
+        return rv;
     }
 
-    return APR_SUCCESS;
+    return OK;
 }
 
 static void process_proxy_header(request_rec *r, proxy_dir_conf *c,
@@ -1325,6 +1331,7 @@
     static const char *hop_by_hop_hdrs[] =
         {"Keep-Alive", "Proxy-Authenticate", "TE", "Trailer", "Upgrade", NULL};
     int i;
+    const char *te = NULL;
 
     bb = apr_brigade_create(p, c->bucket_alloc);
 
@@ -1455,6 +1462,11 @@
                 backend->close += 1;
             }
 
+            /*
+             * Save a possible Transfer-Encoding header as we need it later for
+             * ap_http_filter to know where to end.
+             */
+            te = apr_table_get(r->headers_out, "Transfer-Encoding");
             /* strip connection listed hop-by-hop headers from response */
             backend->close += ap_proxy_liststr(apr_table_get(r->headers_out,
                                                              "Connection"),
@@ -1595,6 +1607,14 @@
              * ap_http_filter to know where to end.
              */
             rp->headers_in = apr_table_copy(r->pool, r->headers_out);
+            /*
+             * Restore Transfer-Encoding header from response if we saved
+             * one before and there is none left. We need it for the
+             * ap_http_filter. See above.
+             */
+            if (te && !apr_table_get(rp->headers_in, "Transfer-Encoding")) {
+                apr_table_add(rp->headers_in, "Transfer-Encoding", te);
+            }
 
             apr_table_unset(r->headers_out,"Transfer-Encoding");
 
@@ -1824,14 +1844,10 @@
 
 
     backend->is_ssl = is_ssl;
-    /*
-     * TODO: Currently we cannot handle persistent SSL backend connections,
-     * because we recreate backend->connection for each request and thus
-     * try to initialize an already existing SSL connection. This does
-     * not work.
-     */
-    if (is_ssl)
-        backend->close = 1;
+
+    if (is_ssl) {
+        ap_proxy_ssl_connection_cleanup(backend, r);
+    }
 
     /* Step One: Determine Who To Connect To */
     if ((status = ap_proxy_determine_connection(p, r, conf, worker, backend,

Modified: httpd/sandbox/amsterdam/d/modules/proxy/proxy_util.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/proxy/proxy_util.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/proxy/proxy_util.c (original)
+++ httpd/sandbox/amsterdam/d/modules/proxy/proxy_util.c Mon Apr  7 09:28:58 2008
@@ -332,16 +332,16 @@
 
 PROXY_DECLARE(request_rec *)ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
 {
-    request_rec *rp = apr_pcalloc(c->pool, sizeof(*r));
+    request_rec *rp = apr_pcalloc(r->pool, sizeof(*r));
 
-    rp->pool            = c->pool;
+    rp->pool            = r->pool;
     rp->status          = HTTP_OK;
 
-    rp->headers_in      = apr_table_make(c->pool, 50);
-    rp->subprocess_env  = apr_table_make(c->pool, 50);
-    rp->headers_out     = apr_table_make(c->pool, 12);
-    rp->err_headers_out = apr_table_make(c->pool, 5);
-    rp->notes           = apr_table_make(c->pool, 5);
+    rp->headers_in      = apr_table_make(r->pool, 50);
+    rp->subprocess_env  = apr_table_make(r->pool, 50);
+    rp->headers_out     = apr_table_make(r->pool, 12);
+    rp->err_headers_out = apr_table_make(r->pool, 5);
+    rp->notes           = apr_table_make(r->pool, 5);
 
     rp->server = r->server;
     rp->proxyreq = r->proxyreq;
@@ -352,7 +352,7 @@
     rp->proto_output_filters  = c->output_filters;
     rp->proto_input_filters   = c->input_filters;
 
-    rp->request_config  = ap_create_request_config(c->pool);
+    rp->request_config  = ap_create_request_config(r->pool);
     proxy_run_create_req(r, rp);
 
     return rp;
@@ -677,6 +677,9 @@
 
     if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
         for (addr.s_addr = 0, i = 0; i < 4; ++i) {
+            /* ap_proxy_is_ipaddr() already confirmed that we have
+             * a valid octet in ip_addr[i]
+             */
             addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
         }
 
@@ -1063,8 +1066,54 @@
         ent = (struct proxy_alias *)conf->raliases->elts;
     }
     for (i = 0; i < conf->raliases->nelts; i++) {
-        l2 = strlen(ent[i].real);
-        if (l1 >= l2 && strncasecmp(ent[i].real, url, l2) == 0) {
+        proxy_server_conf *sconf = (proxy_server_conf *)
+            ap_get_module_config(r->server->module_config, &proxy_module);
+        proxy_balancer *balancer;
+        const char *real;
+        real = ent[i].real;
+        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                         "ppr: real: %s", real);
+        /*
+         * First check if mapping against a balancer and see
+         * if we have such a entity. If so, then we need to
+         * find the particulars of the actual worker which may
+         * or may not be the right one... basically, we need
+         * to find which member actually handled this request.
+         */
+        if ((strncasecmp(real, "balancer:", 9) == 0) &&
+            (balancer = ap_proxy_get_balancer(r->pool, sconf, real))) {
+            int n;
+            proxy_worker *worker;
+            worker = (proxy_worker *)balancer->workers->elts;
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                         "ppr: checking balancer: %s",
+                         balancer->name);
+            for (n = 0; n < balancer->workers->nelts; n++) {
+                if (worker->port) {
+                    u = apr_psprintf(r->pool, "%s://%s:%d/", worker->scheme,
+                                     worker->hostname, worker->port);
+                }
+                else {
+                    u = apr_psprintf(r->pool, "%s://%s/", worker->scheme,
+                                     worker->hostname);
+                }
+                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                         "ppr: matching member (%s) and URL (%s)",
+                         u, url);
+
+                l2 = strlen(u);
+                if (l1 >= l2 && strncasecmp(u, url, l2) == 0) {
+                    u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
+                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+                         "ppr: matched member (%s)", u);
+                    return ap_construct_url(r->pool, u, r);
+                }
+                worker++;
+            }
+        }
+
+        l2 = strlen(real);
+        if (l1 >= l2 && strncasecmp(real, url, l2) == 0) {
             u = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);
             return ap_construct_url(r->pool, u, r);
         }
@@ -1349,6 +1398,7 @@
      * it can be disabled.
      */
     apr_pool_create(&pool, p);
+    apr_pool_tag(pool, "proxy_worker_cp");
     /*
      * Alloc from the same pool as worker.
      * proxy_conn_pool is permanently attached to the worker.
@@ -1576,6 +1626,9 @@
 {
     proxy_conn_rec *conn = (proxy_conn_rec *)theconn;
     proxy_worker *worker = conn->worker;
+    apr_bucket_brigade *bb;
+    conn_rec *c;
+    request_rec *r;
 
     /*
      * If the connection pool is NULL the worker
@@ -1596,13 +1649,66 @@
     }
 #endif
 
+    r = conn->r;
+    if (conn->need_flush && r && (r->bytes_sent || r->eos_sent)) {
+        /*
+         * We need to ensure that buckets that may have been buffered in the
+         * network filters get flushed to the network. This is needed since
+         * these buckets have been created with the bucket allocator of the
+         * backend connection. This allocator either gets destroyed if
+         * conn->close is set or the worker address is not reusable which
+         * causes the connection to the backend to be closed or it will be used
+         * again by another frontend connection that wants to recycle the
+         * backend connection.
+         * In this case we could run into nasty race conditions (e.g. if the
+         * next user of the backend connection destroys the allocator before we
+         * sent the buckets to the network).
+         *
+         * Remark 1: Only do this if buckets where sent down the chain before
+         * that could still be buffered in the network filter. This is the case
+         * if we have sent an EOS bucket or if we actually sent buckets with
+         * data down the chain. In all other cases we either have not sent any
+         * buckets at all down the chain or we only sent meta buckets that are
+         * not EOS buckets down the chain. The only meta bucket that remains in
+         * this case is the flush bucket which would have removed all possibly
+         * buffered buckets in the network filter.
+         * If we sent a flush bucket in the case where not ANY buckets were
+         * sent down the chain, we break error handling which happens AFTER us.
+         *
+         * Remark 2: Doing a setaside does not help here as the buckets remain
+         * created by the wrong allocator in this case.
+         *
+         * Remark 3: Yes, this creates a possible performance penalty in the case
+         * of pipelined requests as we may send only a small amount of data over
+         * the wire.
+         */
+        c = r->connection;
+        bb = apr_brigade_create(r->pool, c->bucket_alloc);
+        if (r->eos_sent) {
+            /*
+             * If we have already sent an EOS bucket send directly to the
+             * connection based filters. We just want to flush the buckets
+             * if something hasn't been sent to the network yet.
+             */
+            ap_fflush(c->output_filters, bb);
+        }
+        else {
+            ap_fflush(r->output_filters, bb);
+        }
+        apr_brigade_destroy(bb);
+        conn->r = NULL;
+        conn->need_flush = 0;
+    }
+
     /* determine if the connection need to be closed */
-    if (conn->close) {
+    if (conn->close || !worker->is_address_reusable || worker->disablereuse) {
         apr_pool_t *p = conn->pool;
-        apr_pool_clear(conn->pool);
-        memset(conn, 0, sizeof(proxy_conn_rec));
+        apr_pool_clear(p);
+        conn = apr_pcalloc(p, sizeof(proxy_conn_rec));
         conn->pool = p;
         conn->worker = worker;
+        apr_pool_create(&(conn->scpool), p);
+        apr_pool_tag(conn->scpool, "proxy_conn_scpool");
     }
 #if APR_HAS_THREADS
     if (worker->hmax && worker->cp->res) {
@@ -1619,11 +1725,54 @@
     return APR_SUCCESS;
 }
 
+static void socket_cleanup(proxy_conn_rec *conn)
+{
+    conn->sock = NULL;
+    conn->connection = NULL;
+    apr_pool_clear(conn->scpool);
+}
+
+PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
+                                                            request_rec *r)
+{
+    apr_bucket_brigade *bb;
+    apr_status_t rv;
+
+    /*
+     * If we have an existing SSL connection it might be possible that the
+     * server sent some SSL message we have not read so far (e.g. a SSL
+     * shutdown message if the server closed the keepalive connection while
+     * the connection was held unused in our pool).
+     * So ensure that if present (=> APR_NONBLOCK_READ) it is read and
+     * processed. We don't expect any data to be in the returned brigade.
+     */
+    if (conn->sock && conn->connection) {
+        bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+        rv = ap_get_brigade(conn->connection->input_filters, bb,
+                            AP_MODE_READBYTES, APR_NONBLOCK_READ,
+                            HUGE_STRING_LEN);
+        if ((rv != APR_SUCCESS) && !APR_STATUS_IS_EAGAIN(rv)) {
+            socket_cleanup(conn);
+        }
+        if (!APR_BRIGADE_EMPTY(bb)) {
+            apr_off_t len;
+
+            rv = apr_brigade_length(bb, 0, &len);
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
+                          "proxy: SSL cleanup brigade contained %"
+                          APR_OFF_T_FMT " bytes of data.", len);
+        }
+        apr_brigade_destroy(bb);
+    }
+    return APR_SUCCESS;
+}
+
 /* reslist constructor */
 static apr_status_t connection_constructor(void **resource, void *params,
                                            apr_pool_t *pool)
 {
     apr_pool_t *ctx;
+    apr_pool_t *scpool;
     proxy_conn_rec *conn;
     proxy_worker *worker = (proxy_worker *)params;
 
@@ -1633,9 +1782,20 @@
      * when disconnecting from backend.
      */
     apr_pool_create(&ctx, pool);
-    conn = apr_pcalloc(pool, sizeof(proxy_conn_rec));
+    apr_pool_tag(ctx, "proxy_conn_pool");
+    /*
+     * Create another subpool that manages the data for the
+     * socket and the connection member of the proxy_conn_rec struct as we
+     * destroy this data more frequently than other data in the proxy_conn_rec
+     * struct like hostname and addr (at least in the case where we have
+     * keepalive connections that timed out).
+     */
+    apr_pool_create(&scpool, ctx);
+    apr_pool_tag(scpool, "proxy_conn_scpool");
+    conn = apr_pcalloc(ctx, sizeof(proxy_conn_rec));
 
     conn->pool   = ctx;
+    conn->scpool = scpool;
     conn->worker = worker;
 #if APR_HAS_THREADS
     conn->inreslist = 1;
@@ -1745,8 +1905,13 @@
     if (!worker->retry_set) {
         worker->retry = apr_time_from_sec(PROXY_WORKER_DEFAULT_RETRY);
     }
-    /* By default address is reusable */
-    worker->is_address_reusable = 1;
+    /* By default address is reusable unless DisableReuse is set */
+    if (worker->disablereuse) {
+        worker->is_address_reusable = 0;
+    }
+    else {
+        worker->is_address_reusable = 1;
+    }
 
 #if APR_HAS_THREADS
     ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads);
@@ -1895,11 +2060,6 @@
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "proxy: %s: has released connection for (%s)",
                  proxy_function, conn->worker->hostname);
-    /* If there is a connection kill it's cleanup */
-    if (conn->connection) {
-        apr_pool_cleanup_kill(conn->connection->pool, conn, connection_cleanup);
-        conn->connection = NULL;
-    }
     connection_cleanup(conn);
 
     return OK;
@@ -1921,6 +2081,8 @@
     apr_status_t err = APR_SUCCESS;
     apr_status_t uerr = APR_SUCCESS;
 
+    conn->r = r;
+
     /*
      * Break up the URL to determine the host to connect to
      */
@@ -1960,7 +2122,8 @@
      *
      * TODO: Handle this much better...
      */
-    if (!conn->hostname || !worker->is_address_reusable ||
+    if (!conn->hostname || !worker->is_address_reusable || 
+         worker->disablereuse ||
          (r->connection->keepalives &&
          (r->proxyreq == PROXYREQ_PROXY || r->proxyreq == PROXYREQ_REVERSE) &&
          (strcasecmp(conn->hostname, uri->hostname) != 0) ) ) {
@@ -1972,14 +2135,7 @@
             conn->hostname = apr_pstrdup(conn->pool, uri->hostname);
             conn->port = uri->port;
         }
-        if (conn->sock) {
-            apr_socket_close(conn->sock);
-            conn->sock = NULL;
-        }
-        if (conn->connection) {
-            apr_pool_cleanup_kill(conn->connection->pool, conn, connection_cleanup);
-            conn->connection = NULL;
-        }
+        socket_cleanup(conn);
         err = apr_sockaddr_info_get(&(conn->addr),
                                     conn->hostname, APR_UNSPEC,
                                     conn->port, 0,
@@ -2125,14 +2281,8 @@
         (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
 
     if (conn->sock) {
-        /*
-         * This increases the connection pool size
-         * but the number of dropped connections is
-         * relatively small compared to connection lifetime
-         */
         if (!(connected = is_socket_connected(conn->sock))) {
-            apr_socket_close(conn->sock);
-            conn->sock = NULL;
+            socket_cleanup(conn);
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                          "proxy: %s: backend socket is disconnected.",
                          proxy_function);
@@ -2141,7 +2291,7 @@
     while (backend_addr && !connected) {
         if ((rv = apr_socket_create(&newsock, backend_addr->family,
                                 SOCK_STREAM, APR_PROTO_TCP,
-                                conn->pool)) != APR_SUCCESS) {
+                                conn->scpool)) != APR_SUCCESS) {
             loglevel = backend_addr->next ? APLOG_DEBUG : APLOG_ERR;
             ap_log_error(APLOG_MARK, loglevel, rv, s,
                          "proxy: %s: error creating fam %d socket for target %s",
@@ -2156,6 +2306,7 @@
             backend_addr = backend_addr->next;
             continue;
         }
+        conn->connection = NULL;
 
 #if !defined(TPF) && !defined(BEOS)
         if (worker->recv_buffer_size > 0 &&
@@ -2245,13 +2396,25 @@
     apr_sockaddr_t *backend_addr = conn->addr;
     int rc;
     apr_interval_time_t current_timeout;
+    apr_bucket_alloc_t *bucket_alloc;
 
+    if (conn->connection) {
+        return OK;
+    }
+
+    /*
+     * We need to flush the buckets before we return the connection to the
+     * connection pool. See comment in connection_cleanup for why this is
+     * needed.
+     */
+    conn->need_flush = 1;
+    bucket_alloc = apr_bucket_alloc_create(conn->scpool);
     /*
      * The socket is now open, create a new backend server connection
      */
-    conn->connection = ap_run_create_connection(c->pool, s, conn->sock,
-                                                c->id, c->sbh,
-                                                c->bucket_alloc);
+    conn->connection = ap_run_create_connection(conn->scpool, s, conn->sock,
+                                                0, NULL,
+                                                bucket_alloc);
 
     if (!conn->connection) {
         /*
@@ -2263,17 +2426,9 @@
                      "new connection to %pI (%s)", proxy_function,
                      backend_addr, conn->hostname);
         /* XXX: Will be closed when proxy_conn is closed */
-        apr_socket_close(conn->sock);
-        conn->sock = NULL;
+        socket_cleanup(conn);
         return HTTP_INTERNAL_SERVER_ERROR;
     }
-    /*
-     * register the connection cleanup to client connection
-     * so that the connection can be closed or reused
-     */
-    apr_pool_cleanup_register(c->pool, (void *)conn,
-                              connection_cleanup,
-                              apr_pool_cleanup_null);
 
     /* For ssl connection to backend */
     if (conn->is_ssl) {
@@ -2295,7 +2450,7 @@
                  proxy_function, backend_addr, conn->hostname);
 
     /*
-     * save the timout of the socket because core_pre_connection
+     * save the timeout of the socket because core_pre_connection
      * will set it to base_server->timeout
      * (core TimeOut directive).
      */

Propchange: httpd/sandbox/amsterdam/d/modules/session/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Apr  7 09:28:58 2008
@@ -0,0 +1,22 @@
+.deps
+.libs
+*.la
+modules.mk
+Makefile
+*.lo
+*.slo
+*.so
+Debug
+Release
+*.plg
+*.aps
+*.dep
+*.mak
+*.rc
+BuildLog.htm
+*.stc
+*.stt
+*.sto
+*.vcproj
+*.vcproj.*
+

Modified: httpd/sandbox/amsterdam/d/modules/ssl/config.m4
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/config.m4?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/config.m4 (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/config.m4 Mon Apr  7 09:28:58 2008
@@ -135,6 +135,11 @@
   fi
 ])
 
+AC_DEFUN([CHECK_OCSP], [
+AC_CHECK_HEADERS(openssl/ocsp.h, 
+  [AC_DEFINE([HAVE_OCSP], 1, [Define if OCSP is supported by OpenSSL])]
+)
+])
 
 dnl #  start of module specific part
 APACHE_MODPATH_INIT(ssl)
@@ -163,6 +168,8 @@
 ssl_scache_memcache.lo dnl
 ssl_util.lo dnl
 ssl_util_ssl.lo dnl
+ssl_engine_ocsp.lo dnl
+ssl_util_ocsp.lo dnl
 "
 dnl #  hook module into the Autoconf mechanism (--enable-ssl option)
 APACHE_MODULE(ssl, [SSL/TLS support (mod_ssl)], $ssl_objs, , no, [
@@ -170,6 +177,7 @@
     APR_SETVAR(MOD_SSL_LDADD, [\$(SSL_LIBS)])
     CHECK_DISTCACHE
     CHECK_SSL_MEMCACHE
+    CHECK_OCSP
     if test "x$enable_ssl" = "xshared"; then
        # The only symbol which needs to be exported is the module
        # structure, so ask libtool to hide everything else:

Modified: httpd/sandbox/amsterdam/d/modules/ssl/mod_ssl.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/mod_ssl.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/mod_ssl.c (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/mod_ssl.c Mon Apr  7 09:28:58 2008
@@ -28,6 +28,8 @@
 #include "mod_ssl.h"
 #include "util_md5.h"
 #include "util_mutex.h"
+#include "ap_provider.h"
+
 #include <assert.h>
 
 /*
@@ -178,6 +180,13 @@
                "Require a boolean expression to evaluate to true for granting access"
                "(arbitrary complex boolean expression - see manual)")
 
+    SSL_CMD_SRV(OCSPEnable, FLAG,
+               "Enable use of OCSP to verify certificate revocation (`on', `off')")
+    SSL_CMD_SRV(OCSPDefaultResponder, TAKE1,
+               "URL of the default OCSP Responder")
+    SSL_CMD_SRV(OCSPOverrideResponder, FLAG,
+               "Force use of the default responder URL (`on', `off')")
+
     /* Deprecated directives. */
     AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL,
       "SSLLog directive is no longer supported - use ErrorLog."),
@@ -445,6 +454,33 @@
     return ssl_init_ssl_connection(c, NULL);
 }
 
+/* Register all session cache providers. */
+static void modssl_register_scache(apr_pool_t *p)
+{
+    /* shmcb is a cache of many names. */
+    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "shmcb", 
+                         MODSSL_SESSCACHE_PROVIDER_VERSION,
+                         &modssl_sesscache_shmcb);
+    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "shmht", 
+                         MODSSL_SESSCACHE_PROVIDER_VERSION,
+                         &modssl_sesscache_shmcb);
+    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "shm", 
+                         MODSSL_SESSCACHE_PROVIDER_VERSION,
+                         &modssl_sesscache_shmcb);
+    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "dbm",
+                         MODSSL_SESSCACHE_PROVIDER_VERSION,
+                         &modssl_sesscache_dbm);
+#ifdef HAVE_DISTCACHE
+    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "dc",
+                         MODSSL_SESSCACHE_PROVIDER_VERSION,
+                         &modssl_sesscache_dc);
+#endif
+#ifdef HAVE_SSL_CACHE_MEMCACHE
+    ap_register_provider(p, MODSSL_SESSCACHE_PROVIDER_GROUP, "mc",
+                         MODSSL_SESSCACHE_PROVIDER_VERSION,
+                         &modssl_sesscache_mc);
+#endif
+}
 
 /*
  *  the module registration phase
@@ -465,13 +501,18 @@
     ap_hook_default_port  (ssl_hook_default_port,  NULL,NULL, APR_HOOK_MIDDLE);
     ap_hook_pre_config    (ssl_hook_pre_config,    NULL,NULL, APR_HOOK_MIDDLE);
     ap_hook_child_init    (ssl_init_Child,         NULL,NULL, APR_HOOK_MIDDLE);
-    ap_hook_check_user_id (ssl_hook_UserCheck,     NULL,NULL, APR_HOOK_FIRST);
+    ap_hook_check_authn   (ssl_hook_UserCheck,     NULL,NULL, APR_HOOK_FIRST,
+                           AP_AUTH_INTERNAL_PER_CONF);
     ap_hook_fixups        (ssl_hook_Fixup,         NULL,NULL, APR_HOOK_MIDDLE);
-    ap_hook_access_checker(ssl_hook_Access,        NULL,NULL, APR_HOOK_MIDDLE);
-    ap_hook_auth_checker  (ssl_hook_Auth,          NULL,NULL, APR_HOOK_MIDDLE);
+    ap_hook_check_access  (ssl_hook_Access,        NULL,NULL, APR_HOOK_MIDDLE,
+                           AP_AUTH_INTERNAL_PER_CONF);
+    ap_hook_check_authz   (ssl_hook_Auth,          NULL,NULL, APR_HOOK_MIDDLE,
+                           AP_AUTH_INTERNAL_PER_CONF);
     ap_hook_post_read_request(ssl_hook_ReadReq, pre_prr,NULL, APR_HOOK_MIDDLE);
 
     ssl_var_register(p);
+
+    modssl_register_scache(p);
 
     APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
     APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);

Modified: httpd/sandbox/amsterdam/d/modules/ssl/mod_ssl.dsp
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/mod_ssl.dsp?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/mod_ssl.dsp (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/mod_ssl.dsp Mon Apr  7 09:28:58 2008
@@ -44,7 +44,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE=1" /Fd"Release\mod_ssl_src" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE" /D "HAVE_OPENSSL_ENGINE_H" /D "HAVE_ENGINE_INIT" /D "HAVE_ENGINE_LOAD_BUILTIN_ENGINES" /Fd"Release\mod_ssl_src" /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -76,7 +76,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE=1" /Fd"Debug\mod_ssl_src" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE" /D "HAVE_OPENSSL_ENGINE_H" /D "HAVE_ENGINE_INIT" /D "HAVE_ENGINE_LOAD_BUILTIN_ENGINES" /Fd"Debug\mod_ssl_src" /FD /c
 # ADD BASE MTL /nologo /D "_DEBUG" /win32
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "_DEBUG"
@@ -108,7 +108,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE=1" /Fd"Release\mod_ssl_src" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../generators" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /I "../../srclib/openssl/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /D "NO_IDEA" /D "NO_RC5" /D "NO_MDC2" /D "OPENSSL_NO_IDEA" /D "OPENSSL_NO_RC5" /D "OPENSSL_NO_MDC2" /D "HAVE_OPENSSL" /D "HAVE_SSL_SET_STATE" /D "HAVE_OPENSSL_ENGINE_H" /D "HAVE_ENGINE_INIT" /D "HAVE_ENGINE_LOAD_BUILTIN_ENGINES" /Fd"Release\mod_ssl_src" /FD /c
 # ADD BASE MTL /nologo /D "NDEBUG" /win32
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -195,6 +195,14 @@
 # Begin Source File
 
 SOURCE=.\ssl_expr_scan.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ssl_engine_ocsp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ssl_util_ocsp.c
 # End Source File
 # Begin Source File
 

Modified: httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_config.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_config.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_config.c (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_config.c Mon Apr  7 09:28:58 2008
@@ -28,6 +28,7 @@
                                                -- Unknown        */
 #include "ssl_private.h"
 #include "util_mutex.h"
+#include "ap_provider.h"
 
 /*  _________________________________________________________________
 **
@@ -58,12 +59,8 @@
     /*
      * initialize per-module configuration
      */
-    mc->nSessionCacheMode      = SSL_SCMODE_UNSET;
-    mc->szSessionCacheDataFile = NULL;
-    mc->nSessionCacheDataSize  = 0;
-    mc->pSessionCacheDataMM    = NULL;
-    mc->pSessionCacheDataRMM   = NULL;
-    mc->tSessionCacheDataTable = NULL;
+    mc->sesscache_mode         = SSL_SESS_CACHE_OFF;
+    mc->sesscache              = NULL;
     mc->nMutexMode             = SSL_MUTEXMODE_UNSET;
     mc->nMutexMech             = APR_LOCK_DEFAULT;
     mc->szMutexFile            = NULL;
@@ -128,6 +125,10 @@
     mctx->auth.cipher_suite   = NULL;
     mctx->auth.verify_depth   = UNSET;
     mctx->auth.verify_mode    = SSL_CVERIFY_UNSET;
+
+    mctx->ocsp_enabled        = FALSE;
+    mctx->ocsp_force_default  = FALSE;
+    mctx->ocsp_responder      = NULL;
 }
 
 static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
@@ -217,6 +218,10 @@
     cfgMergeString(auth.cipher_suite);
     cfgMergeInt(auth.verify_depth);
     cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET);
+
+    cfgMergeBool(ocsp_enabled);
+    cfgMergeBool(ocsp_force_default);
+    cfgMerge(ocsp_responder, NULL);
 }
 
 static void modssl_ctx_cfg_merge_proxy(modssl_ctx_t *base,
@@ -947,9 +952,8 @@
                                     const char *arg)
 {
     SSLModConfigRec *mc = myModConfig(cmd->server);
-    const char *err, *colon;
-    char *cp, *cp2;
-    int arglen = strlen(arg);
+    const char *err, *sep;
+    long enabled_flags;
 
     if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
         return err;
@@ -959,98 +963,61 @@
         return NULL;
     }
 
+    /* The OpenSSL session cache mode must have both the flags
+     * SSL_SESS_CACHE_SERVER and SSL_SESS_CACHE_NO_INTERNAL set if a
+     * session cache is configured; NO_INTERNAL prevents the
+     * OpenSSL-internal session cache being used in addition to the
+     * "external" (mod_ssl-provided) cache, which otherwise causes
+     * additional memory consumption. */
+    enabled_flags = SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL;
+
     if (strcEQ(arg, "none")) {
-        mc->nSessionCacheMode      = SSL_SCMODE_NONE;
-        mc->szSessionCacheDataFile = NULL;
+        /* Nothing to do; session cache will be off. */
     }
     else if (strcEQ(arg, "nonenotnull")) {
-        mc->nSessionCacheMode      = SSL_SCMODE_NONE_NOT_NULL;
-        mc->szSessionCacheDataFile = NULL;
-    }
-    else if ((arglen > 4) && strcEQn(arg, "dbm:", 4)) {
-        mc->nSessionCacheMode      = SSL_SCMODE_DBM;
-        mc->szSessionCacheDataFile = ap_server_root_relative(mc->pPool, arg+4);
-        if (!mc->szSessionCacheDataFile) {
-            return apr_psprintf(cmd->pool,
-                                "SSLSessionCache: Invalid cache file path %s",
-                                arg+4);
-        }
-    }
-    else if (((arglen > 4) && strcEQn(arg, "shm:", 4)) ||
-             ((arglen > 6) && strcEQn(arg, "shmht:", 6)) ||
-             ((arglen > 6) && strcEQn(arg, "shmcb:", 6))) {
-#if !APR_HAS_SHARED_MEMORY
-        return MODSSL_NO_SHARED_MEMORY_ERROR;
-#endif
-        mc->nSessionCacheMode      = SSL_SCMODE_SHMCB;
-        colon = ap_strchr_c(arg, ':');
-        mc->szSessionCacheDataFile =
-            ap_server_root_relative(mc->pPool, colon+1);
-        if (!mc->szSessionCacheDataFile) {
-            return apr_psprintf(cmd->pool,
-                                "SSLSessionCache: Invalid cache file path %s",
-                                colon+1);
-        }
-        mc->tSessionCacheDataTable = NULL;
-        mc->nSessionCacheDataSize  = 1024*512; /* 512KB */
-
-        if ((cp = strchr(mc->szSessionCacheDataFile, '('))) {
-            *cp++ = NUL;
-
-            if (!(cp2 = strchr(cp, ')'))) {
-                return "SSLSessionCache: Invalid argument: "
-                       "no closing parenthesis";
-            }
-
-            *cp2 = NUL;
-
-            mc->nSessionCacheDataSize = atoi(cp);
-
-            if (mc->nSessionCacheDataSize < 8192) {
-                return "SSLSessionCache: Invalid argument: "
-                       "size has to be >= 8192 bytes";
-
-            }
-
-            if (mc->nSessionCacheDataSize >= APR_SHM_MAXSIZE) {
-                return apr_psprintf(cmd->pool,
-                                    "SSLSessionCache: Invalid argument: "
-                                    "size has to be < %d bytes on this "
-                                    "platform", APR_SHM_MAXSIZE);
-
-            }
-        }
-    }
-    else if ((arglen > 3) && strcEQn(arg, "dc:", 3)) {
-#ifdef HAVE_DISTCACHE
-        mc->nSessionCacheMode      = SSL_SCMODE_DC;
-        mc->szSessionCacheDataFile = apr_pstrdup(mc->pPool, arg+3);
-        if (!mc->szSessionCacheDataFile) {
-            return apr_pstrcat(cmd->pool,
-                               "SSLSessionCache: Invalid cache file path: ",
-                               arg+3, NULL);
+        /* ### Having a separate mode for this seems logically
+         * unnecessary; the stated purpose of sending non-empty
+         * session IDs would be better fixed in OpenSSL or simply
+         * doing it by default if "none" is used. */
+        mc->sesscache_mode = enabled_flags;
+    }
+    else if ((sep = ap_strchr_c(arg, ':')) != NULL) {
+        char *name = apr_pstrmemdup(cmd->pool, arg, sep - arg);
+
+        /* Find the provider of given name. */
+        mc->sesscache = ap_lookup_provider(MODSSL_SESSCACHE_PROVIDER_GROUP,
+                                           name,
+                                           MODSSL_SESSCACHE_PROVIDER_VERSION);
+        if (mc->sesscache) {
+            /* Cache found; create it, passing anything beyond the colon. */
+            mc->sesscache_mode = enabled_flags;
+            err = mc->sesscache->create(&mc->sesscache_context, sep + 1, 
+                                        cmd->pool, mc->pPool);
         }
-#else
-        return "SSLSessionCache: distcache support disabled";
-#endif
-    }
-    else if ((arglen > 3) && strcEQn(arg, "memcache:", 9)) {
-#ifdef HAVE_SSL_CACHE_MEMCACHE
-        mc->nSessionCacheMode      = SSL_SCMODE_MC;
-        mc->szSessionCacheDataFile = apr_pstrdup(mc->pPool, arg+9);
-        if (!mc->szSessionCacheDataFile) {
-            return apr_pstrcat(cmd->pool,
-                               "SSLSessionCache: Invalid memcache config: ",
-                               arg+9, NULL);
+        else {
+            apr_array_header_t *name_list;
+            const char *all_names;
+
+            /* Build a comma-separated list of all registered provider
+             * names: */
+            name_list = ap_list_provider_names(cmd->pool, 
+                                               MODSSL_SESSCACHE_PROVIDER_GROUP,
+                                               MODSSL_SESSCACHE_PROVIDER_VERSION);
+            all_names = apr_array_pstrcat(cmd->pool, name_list, ',');
+
+            err = apr_psprintf(cmd->pool, "'%s' session cache not supported "
+                               "(known names: %s)", name, all_names);
         }
-#else
-        return "SSLSessionCache: memcache support disabled";
-#endif
     }
     else {
-        return "SSLSessionCache: Invalid argument";
+        err = apr_psprintf(cmd->pool, "'%s' session cache not supported or missing argument",
+                           arg);
     }
 
+    if (err) {
+        return apr_psprintf(cmd->pool, "SSLSessionCache: %s", err);
+    }
+    
     return NULL;
 }
 
@@ -1407,6 +1374,40 @@
 {
     SSLDirConfigRec *dc = (SSLDirConfigRec *)dcfg;
     dc->szUserName = arg;
+    return NULL;
+}
+
+const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag)
+{   
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+    sc->server->ocsp_enabled = flag ? TRUE : FALSE;
+
+#ifndef HAVE_OCSP
+    if (flag) {
+        return "OCSP support not detected in SSL library; cannot enable "
+            "OCSP validation";
+    }
+#endif    
+
+    return NULL;
+}
+	        
+const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag)
+{
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+    sc->server->ocsp_force_default = flag ? TRUE : FALSE;
+
+    return NULL;
+}
+
+const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const char *arg)
+{   
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+
+    sc->server->ocsp_responder = arg;
+
     return NULL;
 }
 

Modified: httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_init.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_init.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_init.c (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_init.c Mon Apr  7 09:28:58 2008
@@ -355,13 +355,40 @@
     }
 }
 
+#ifndef OPENSSL_NO_TLSEXT
+static void ssl_init_ctx_tls_extensions(server_rec *s,
+                                        apr_pool_t *p,
+                                        apr_pool_t *ptemp,
+                                        modssl_ctx_t *mctx)
+{
+    /*
+     * Configure TLS extensions support
+     */
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                 "Configuring TLS extension handling");
+
+    /*
+     * Server name indication (SNI)
+     */
+    if (!SSL_CTX_set_tlsext_servername_callback(mctx->ssl_ctx,
+                          ssl_callback_ServerNameIndication) ||
+        !SSL_CTX_set_tlsext_servername_arg(mctx->ssl_ctx, mctx)) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                     "Unable to initialize TLS servername extension "
+                     "callback (incompatible OpenSSL version?)");
+        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
+        ssl_die();
+    }
+}
+#endif
+
 static void ssl_init_ctx_protocol(server_rec *s,
                                   apr_pool_t *p,
                                   apr_pool_t *ptemp,
                                   modssl_ctx_t *mctx)
 {
     SSL_CTX *ctx = NULL;
-    SSL_METHOD *method = NULL;
+    MODSSL_SSL_METHOD_CONST SSL_METHOD *method = NULL;
     char *cp;
     int protocol = mctx->protocol;
 
@@ -454,20 +481,14 @@
 {
     SSL_CTX *ctx = mctx->ssl_ctx;
     SSLModConfigRec *mc = myModConfig(s);
-    long cache_mode = SSL_SESS_CACHE_OFF;
-    if (mc->nSessionCacheMode != SSL_SCMODE_NONE) {
-        /* SSL_SESS_CACHE_NO_INTERNAL will force OpenSSL
-         * to ignore process local-caching and
-         * to always get/set/delete sessions using mod_ssl's callbacks.
-         */
-        cache_mode = SSL_SESS_CACHE_SERVER|SSL_SESS_CACHE_NO_INTERNAL;
-    }
 
-    SSL_CTX_set_session_cache_mode(ctx, cache_mode);
+    SSL_CTX_set_session_cache_mode(ctx, mc->sesscache_mode);
 
-    SSL_CTX_sess_set_new_cb(ctx,    ssl_callback_NewSessionCacheEntry);
-    SSL_CTX_sess_set_get_cb(ctx,    ssl_callback_GetSessionCacheEntry);
-    SSL_CTX_sess_set_remove_cb(ctx, ssl_callback_DelSessionCacheEntry);
+    if (mc->sesscache) {
+        SSL_CTX_sess_set_new_cb(ctx,    ssl_callback_NewSessionCacheEntry);
+        SSL_CTX_sess_set_get_cb(ctx,    ssl_callback_GetSessionCacheEntry);
+        SSL_CTX_sess_set_remove_cb(ctx, ssl_callback_DelSessionCacheEntry);
+    }
 }
 
 static void ssl_init_ctx_callbacks(server_rec *s,
@@ -711,6 +732,9 @@
     if (mctx->pks) {
         /* XXX: proxy support? */
         ssl_init_ctx_cert_chain(s, p, ptemp, mctx);
+#ifndef OPENSSL_NO_TLSEXT
+        ssl_init_ctx_tls_extensions(s, p, ptemp, mctx);
+#endif
     }
 }
 
@@ -1060,9 +1084,19 @@
         klen = strlen(key);
 
         if ((ps = (server_rec *)apr_hash_get(table, key, klen))) {
-            ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
+            ap_log_error(APLOG_MARK, 
+#ifdef OPENSSL_NO_TLSEXT
+                         APLOG_WARNING, 
+#else
+                         APLOG_DEBUG, 
+#endif
+                         0,
                          base_server,
+#ifdef OPENSSL_NO_TLSEXT
                          "Init: SSL server IP/port conflict: "
+#else
+                         "Init: SSL server IP/port overlap: "
+#endif
                          "%s (%s:%d) vs. %s (%s:%d)",
                          ssl_util_vhostid(p, s),
                          (s->defn_name ? s->defn_name : "unknown"),
@@ -1079,8 +1113,14 @@
 
     if (conflict) {
         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server,
+#ifdef OPENSSL_NO_TLSEXT
                      "Init: You should not use name-based "
                      "virtual hosts in conjunction with SSL!!");
+#else
+                     "Init: Name-based SSL virtual hosts only "
+                     "work for clients with TLS server name indication "
+                     "support (RFC 4366)");
+#endif
     }
 }
 
@@ -1187,7 +1227,7 @@
     /*
      * Cleanup
      */
-    sk_X509_NAME_set_cmp_func(ca_list, NULL);
+    (void) sk_X509_NAME_set_cmp_func(ca_list, NULL);
 
     return ca_list;
 }

Modified: httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_io.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_io.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_io.c (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_io.c Mon Apr  7 09:28:58 2008
@@ -1586,9 +1586,6 @@
     inctx = apr_palloc(c->pool, sizeof(*inctx));
 
     filter_ctx->pInputFilter = ap_add_input_filter(ssl_io_filter, inctx, r, c);
-    /* Immediately forget the request_rec pointer stored in the
-     * filter; it will go out of scope. */
-    filter_ctx->pInputFilter->r = NULL;
 
     filter_ctx->pbioRead = BIO_new(&bio_filter_in_method);
     filter_ctx->pbioRead->ptr = (void *)inctx;
@@ -1619,9 +1616,6 @@
     filter_ctx->nobuffer        = 0;
     filter_ctx->pOutputFilter   = ap_add_output_filter(ssl_io_filter,
                                                        filter_ctx, r, c);
-    /* Immediately forget the request_rec pointer stored in the
-     * filter; it will go out of scope. */
-    filter_ctx->pOutputFilter->r = NULL;
 
     filter_ctx->pbioWrite       = BIO_new(&bio_filter_out_method);
     filter_ctx->pbioWrite->ptr  = (void *)bio_filter_out_ctx_new(filter_ctx, c);

Modified: httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_kernel.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_kernel.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_kernel.c (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_kernel.c Mon Apr  7 09:28:58 2008
@@ -31,6 +31,9 @@
 #include "ssl_private.h"
 
 static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
+#ifndef OPENSSL_NO_TLSEXT
+static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s);
+#endif
 
 #define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols"
 #define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1"
@@ -70,10 +73,7 @@
     sslconn = myConnConfig(conn);
     ssl = sslconn->ssl;
     
-    /* XXX: Should replace SSL_set_state with SSL_renegotiate(ssl);
-     * However, this causes failures in perl-framework currently,
-     * perhaps pre-test if we have already negotiated?
-     */
+    /* Perform initial SSL handshake. */
     SSL_set_accept_state(ssl);
     SSL_do_handshake(ssl);
 
@@ -95,6 +95,9 @@
     SSLSrvConfigRec *sc = mySrvConfig(r->server);
     SSLConnRec *sslconn;
     const char *upgrade;
+#ifndef OPENSSL_NO_TLSEXT
+    const char *servername;
+#endif
     SSL *ssl;
     
     /* Perform TLS upgrade here if "SSLEngine optional" is configured,
@@ -102,7 +105,7 @@
      * has sent a suitable Upgrade header. */
     if (sc->enabled == SSL_ENABLED_OPTIONAL && !myConnConfig(r->connection)
         && (upgrade = apr_table_get(r->headers_in, "Upgrade")) != NULL
-        && strcmp(ap_getword(r->pool, &upgrade, ','), "TLS/1.0") == 0) {
+        && ap_find_token(r->pool, upgrade, "TLS/1.0")) {
         if (upgrade_connection(r)) {
             return HTTP_INTERNAL_SERVER_ERROR;
         }
@@ -156,6 +159,14 @@
     if (!ssl) {
         return DECLINED;
     }
+#ifndef OPENSSL_NO_TLSEXT
+    if (!r->hostname &&
+        (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
+        /* Use the SNI extension as the hostname if no Host: header was sent */
+        r->hostname = apr_pstrdup(r->pool, servername);
+        ap_update_vhost_from_headers(r);
+    }
+#endif
     SSL_set_app_data2(ssl, r);
 
     /*
@@ -1066,6 +1077,9 @@
     SSLDirConfigRec *dc = myDirConfig(r);
     apr_table_t *env = r->subprocess_env;
     char *var, *val = "";
+#ifndef OPENSSL_NO_TLSEXT
+    const char *servername;
+#endif
     STACK_OF(X509) *peer_certs;
     SSL *ssl;
     int i;
@@ -1092,6 +1106,13 @@
     /* the always present HTTPS (=HTTP over SSL) flag! */
     apr_table_setn(env, "HTTPS", "on");
 
+#ifndef OPENSSL_NO_TLSEXT
+    /* add content of SNI TLS extension (if supplied with ClientHello) */
+    if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
+        apr_table_set(env, "SSL_TLS_SNI", servername);
+    }
+#endif
+
     /* standard SSL environment variables */
     if (dc->nOptions & SSL_OPT_STDENVVARS) {
         for (i = 0; ssl_hook_Fixup_vars[i]; i++) {
@@ -1256,26 +1277,10 @@
     /*
      * Log verification information
      */
-    if (s->loglevel >= APLOG_DEBUG) {
-        X509 *cert  = X509_STORE_CTX_get_current_cert(ctx);
-        char *sname = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
-        char *iname = X509_NAME_oneline(X509_get_issuer_name(cert),  NULL, 0);
-
-        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, conn,
-                      "Certificate Verification: "
-                      "depth: %d, subject: %s, issuer: %s",
-                      errdepth,
-                      sname ? sname : "-unknown-",
-                      iname ? iname : "-unknown-");
-
-        if (sname) {
-            modssl_free(sname);
-        }
-
-        if (iname) {
-            modssl_free(iname);
-        }
-    }
+    ssl_log_cxerror(APLOG_MARK, APLOG_DEBUG, 0, conn,
+                    X509_STORE_CTX_get_current_cert(ctx),
+                    "Certificate Verification, depth %d",
+                    errdepth);
 
     /*
      * Check for optionally acceptable non-verifiable issuer situation
@@ -1309,12 +1314,35 @@
     }
 
     /*
-     * Additionally perform CRL-based revocation checks
+     * Perform OCSP/CRL-based revocation checks
      */
     if (ok) {
         if (!(ok = ssl_callback_SSLVerify_CRL(ok, ctx, conn))) {
             errnum = X509_STORE_CTX_get_error(ctx);
         }
+        
+#ifdef HAVE_OCSP
+        /* 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 (ok && ssl_verify_error_is_optional(errnum)
+            && sc->server->ocsp_enabled) {
+            X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
+            errnum = X509_V_ERR_APPLICATION_VERIFICATION;
+            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, conn,
+                          "cannot perform OCSP validation for cert "
+                          "if issuer has not been verified "
+                          "(optional_no_ca configured)");
+            ok = FALSE;
+        }
+
+        if (ok && sc->server->ocsp_enabled) {
+            ok = modssl_verify_ocsp(ctx, sc, s, conn, conn->pool);
+            if (!ok) {
+                errnum = X509_STORE_CTX_get_error(ctx);
+            }
+        }
+#endif
     }
 
     /*
@@ -1885,3 +1913,141 @@
     }
 }
 
+#ifndef OPENSSL_NO_TLSEXT
+/*
+ * This callback function is executed when OpenSSL encounters an extended
+ * client hello with a server name indication extension ("SNI", cf. RFC 4366).
+ */
+int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
+{
+    const char *servername =
+                SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+
+    if (servername) {
+        conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
+        if (c) {
+            if (ap_vhost_iterate_given_conn(c, ssl_find_vhost,
+                                            (void *)servername)) {
+                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
+                              "SSL virtual host for servername %s found",
+                              servername);
+                return SSL_TLSEXT_ERR_OK;
+            }
+            else {
+                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
+                              "No matching SSL virtual host for servername "
+                              "%s found (using default/first virtual host)",
+                              servername);
+                return SSL_TLSEXT_ERR_ALERT_WARNING;
+            }
+        }
+    }
+
+    return SSL_TLSEXT_ERR_NOACK;
+}
+
+/*
+ * Find a (name-based) SSL virtual host where either the ServerName
+ * or one of the ServerAliases matches the supplied name (to be used
+ * with ap_vhost_iterate_given_conn())
+ */
+static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) 
+{
+    SSLSrvConfigRec *sc;
+    SSL *ssl;
+    BOOL found = FALSE;
+    apr_array_header_t *names;
+    int i;
+
+    /* check ServerName */
+    if (!strcasecmp(servername, s->server_hostname)) {
+        found = TRUE;
+    }
+
+    /* 
+     * if not matched yet, check ServerAlias entries
+     * (adapted from vhost.c:matches_aliases())
+     */
+    if (!found) {
+        names = s->names;
+        if (names) {
+            char **name = (char **)names->elts;
+            for (i = 0; i < names->nelts; ++i) {
+                if (!name[i])
+                    continue;
+                if (!strcasecmp(servername, name[i])) {
+                    found = TRUE;
+                    break;
+                }
+            }
+        }
+    }
+
+    /* if still no match, check ServerAlias entries with wildcards */
+    if (!found) {
+        names = s->wild_names;
+        if (names) {
+            char **name = (char **)names->elts;
+            for (i = 0; i < names->nelts; ++i) {
+                if (!name[i])
+                    continue;
+                if (!ap_strcasecmp_match(servername, name[i])) {
+                    found = TRUE;
+                    break;
+                }
+            }
+        }
+    }
+
+    /* set SSL_CTX (if matched) */
+    if (found && (ssl = ((SSLConnRec *)myConnConfig(c))->ssl) &&
+        (sc = mySrvConfig(s))) {
+        SSL_set_SSL_CTX(ssl, sc->server->ssl_ctx);
+        /*
+         * SSL_set_SSL_CTX() only deals with the server cert,
+         * so we need to duplicate a few additional settings
+         * from the ctx by hand
+         */
+        SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx));
+        if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
+            (SSL_num_renegotiations(ssl) == 0)) {
+           /*
+            * Only initialize the verification settings from the ctx
+            * if they are not yet set, or if we're called when a new
+            * SSL connection is set up (num_renegotiations == 0).
+            * Otherwise, we would possibly reset a per-directory
+            * configuration which was put into effect by ssl_hook_Access.
+            */
+            SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx),
+                           SSL_CTX_get_verify_callback(ssl->ctx));
+        }
+
+        /*
+         * We also need to make sure that the correct mctx
+         * (accessed through the c->base_server->module_config vector)
+         * is assigned to the connection - the CRL callback e.g.
+         * makes use of it for retrieving its store (mctx->crl).
+         * Since logging in callbacks uses c->base_server in many
+         * cases, it also ensures that these messages are routed
+         * to the proper log.
+         */
+        c->base_server = s;
+
+        /*
+         * There is one special filter callback, which is set
+         * very early depending on the base_server's log level.
+         * If this is not the first vhost we're now selecting
+         * (and the first vhost doesn't use APLOG_DEBUG), then
+         * we need to set that callback here.
+         */
+        if (c->base_server->loglevel >= APLOG_DEBUG) {
+            BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);
+            BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl);
+        }
+
+        return 1;
+    }
+
+    return 0;
+}
+#endif

Modified: httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_log.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_log.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_log.c (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_log.c Mon Apr  7 09:28:58 2008
@@ -79,23 +79,78 @@
 void ssl_log_ssl_error(const char *file, int line, int level, server_rec *s)
 {
     unsigned long e;
+    const char *data;
+    int flags;
 
-    while ((e = ERR_get_error())) {
+    while ((e = ERR_peek_error_line_data(NULL, NULL, &data, &flags))) {
         const char *annotation;
         char err[256];
 
+        if (!(flags & ERR_TXT_STRING)) {
+            data = NULL;
+        }
+
         ERR_error_string_n(e, err, sizeof err);
         annotation = ssl_log_annotation(err);
 
-        if (annotation) {
-            ap_log_error(file, line, level, 0, s,
-                         "SSL Library Error: %lu %s %s",
-                         e, err, annotation);
-        }
-        else {
-            ap_log_error(file, line, level, 0, s,
-                         "SSL Library Error: %lu %s",
-                         e, err);
-        }
+        ap_log_error(file, line, level, 0, s,
+                     "SSL Library Error: %s%s%s%s%s%s",
+                     /* %s */
+                     err, 
+                     /* %s%s%s */
+                     data ? " (" : "", data ? data : "", data ? ")" : "", 
+                     /* %s%s */
+                     annotation ? " -- " : "",
+                     annotation ? annotation : "");
+
+        /* Pop the error off the stack: */
+        ERR_get_error();
+    }
+}
+
+void ssl_log_cxerror(const char *file, int line, int level, 
+                     apr_status_t rv, conn_rec *c, X509 *cert,
+                     const char *format, ...)
+{
+    va_list ap;
+    char buf[HUGE_STRING_LEN];
+    char *sname, *iname, *serial;
+    BIGNUM *bn;
+    
+    if (c->base_server->loglevel < level) {
+        /* Bail early since the rest of this function is expensive. */
+        return;
+    }
+
+    sname = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
+    iname = X509_NAME_oneline(X509_get_issuer_name(cert),  NULL, 0);
+    bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), NULL);
+    serial = bn && !BN_is_zero(bn) ? BN_bn2hex(bn) : NULL;
+    
+    va_start(ap, format);
+    apr_vsnprintf(buf, sizeof buf, format, ap);
+    va_end(ap);
+
+    ap_log_cerror(file, line, level, rv, c, 
+                  "%s [subject: %s, issuer: %s, serial: %s]",
+                  buf,
+                  sname ? sname : "-unknown-",
+                  iname ? iname : "-unknown-",
+                  serial ? serial : "-unknown-");
+
+    if (sname) {
+        modssl_free(sname);
+    }
+    
+    if (iname) {
+        modssl_free(iname);
+    }
+    
+    if (serial) {
+        modssl_free(serial);
+    }
+
+    if (bn) {
+        BN_free(bn);
     }
 }

Modified: httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_mutex.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_mutex.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_mutex.c (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_mutex.c Mon Apr  7 09:28:58 2008
@@ -39,12 +39,24 @@
     SSLModConfigRec *mc = myModConfig(s);
     apr_status_t rv;
 
-    if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
+    /* A mutex is only needed if a session cache is configured, and
+     * the provider used is not internally multi-process/thread
+     * safe. */
+    if (!mc->sesscache
+        || (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) == 0) {
         return TRUE;
+    }
 
     if (mc->pMutex) {
         return TRUE;
     }
+    else if (mc->nMutexMode == SSL_MUTEXMODE_NONE) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
+                     "An SSLMutex is required for the '%s' session cache",
+                     mc->sesscache->name);
+        return FALSE;
+    }
+
     if ((rv = apr_global_mutex_create(&mc->pMutex, mc->szMutexFile,
                                       mc->nMutexMech, s->process->pool))
             != APR_SUCCESS) {
@@ -75,8 +87,10 @@
     SSLModConfigRec *mc = myModConfig(s);
     apr_status_t rv;
 
-    if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
+    if (mc->nMutexMode == SSL_MUTEXMODE_NONE || !mc->sesscache
+        || (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) == 0) {
         return TRUE;
+    }
 
     if ((rv = apr_global_mutex_child_init(&mc->pMutex,
                                     mc->szMutexFile, p)) != APR_SUCCESS) {
@@ -97,8 +111,6 @@
     SSLModConfigRec *mc = myModConfig(s);
     apr_status_t rv;
 
-    if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
-        return TRUE;
     if ((rv = apr_global_mutex_lock(mc->pMutex)) != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s,
                      "Failed to acquire SSL session cache lock");
@@ -112,8 +124,6 @@
     SSLModConfigRec *mc = myModConfig(s);
     apr_status_t rv;
 
-    if (mc->nMutexMode == SSL_MUTEXMODE_NONE)
-        return TRUE;
     if ((rv = apr_global_mutex_unlock(mc->pMutex)) != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s,
                      "Failed to release SSL session cache lock");

Modified: httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_vars.c
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_vars.c?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_vars.c (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/ssl_engine_vars.c Mon Apr  7 09:28:58 2008
@@ -320,6 +320,12 @@
     else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) {
         result = ssl_var_lookup_ssl_compress_meth(ssl);
     }
+#ifndef OPENSSL_NO_TLSEXT
+    else if (ssl != NULL && strcEQ(var, "TLS_SNI")) {
+        result = apr_pstrdup(p, SSL_get_servername(ssl,
+                                                   TLSEXT_NAMETYPE_host_name));
+    }
+#endif
     return result;
 }
 

Modified: httpd/sandbox/amsterdam/d/modules/ssl/ssl_private.h
URL: http://svn.apache.org/viewvc/httpd/sandbox/amsterdam/d/modules/ssl/ssl_private.h?rev=645594&r1=645593&r2=645594&view=diff
==============================================================================
--- httpd/sandbox/amsterdam/d/modules/ssl/ssl_private.h (original)
+++ httpd/sandbox/amsterdam/d/modules/ssl/ssl_private.h Mon Apr  7 09:28:58 2008
@@ -35,6 +35,7 @@
 #include "http_connection.h"
 #include "http_request.h"
 #include "http_protocol.h"
+#include "http_vhost.h"
 #include "util_script.h"
 #include "util_filter.h"
 #include "util_ebcdic.h"
@@ -270,19 +271,6 @@
 typedef unsigned int ssl_pathcheck_t;
 
 /**
- * Define the SSL session cache modes and structures
- */
-typedef enum {
-    SSL_SCMODE_UNSET = UNSET,
-    SSL_SCMODE_NONE  = 0,
-    SSL_SCMODE_DBM   = 1,
-    SSL_SCMODE_SHMCB = 3,
-    SSL_SCMODE_DC    = 4,
-    SSL_SCMODE_MC    = 5,
-    SSL_SCMODE_NONE_NOT_NULL = 6
-} ssl_scmode_t;
-
-/**
  * Define the SSL mutex modes
  */
 typedef enum {
@@ -363,16 +351,72 @@
     int non_ssl_request;
 } SSLConnRec;
 
+#define MODSSL_SESSCACHE_PROVIDER_GROUP "mod_ssl-sesscache"
+#define MODSSL_SESSCACHE_PROVIDER_VERSION "0"
+
+/* If this flag is set, the store/retrieve/delete/status interfaces of
+ * the provider are NOT safe to be called concurrently from multiple
+ * processes or threads, and an external global mutex must be used to
+ * serialize access to the provider. */
+#define MODSSL_SESSCACHE_FLAG_NOTMPSAFE (0x0001)
+
+/* Session cache provider vtable. */
+typedef struct {
+    /* Canonical provider name: */
+    const char *name;
+
+    /* Bitmask of MODSSL_SESSCACHE_FLAG_* flags: */
+    unsigned int flags;
+
+    /* Create a session cache based on the given configuration string
+     * ARG.  Returns NULL on success, or an error string on failure.
+     * Pool TMP should be used for any temporary allocations, pool P
+     * should be used for any allocations lasting as long as the
+     * lifetime of the return context.
+     *
+     * The context pointer returned in *CONTEXT will be passed as the
+     * first argument to subsequent invocations. */
+    const char *(*create)(void **context, const char *arg, 
+                          apr_pool_t *tmp, apr_pool_t *p);
+    /* Initialize the cache.  Return APR error code.   */
+    apr_status_t (*init)(void *context, server_rec *s, apr_pool_t *pool);
+    /* Destroy a given cache context. */    
+    void (*destroy)(void *context, server_rec *s);
+    /* Store an object in the cache. */
+    apr_status_t (*store)(void *context, server_rec *s, 
+                          const unsigned char *id, unsigned int idlen, 
+                          time_t expiry, 
+                          unsigned char *data, unsigned int datalen);
+    /* Retrieve cached data with key ID of length IDLEN,
+     * returning TRUE on success or FALSE otherwise.  If
+     * TRUE, the data must be placed in DEST, which has length
+     * on entry of *DESTLEN.  *DESTLEN must be updated to 
+     * equal the length of data written on exit. */
+    apr_status_t (*retrieve)(void *context, server_rec *s,
+                             const unsigned char *id, unsigned int idlen,
+                             unsigned char *dest, unsigned int *destlen,
+                             apr_pool_t *pool);
+    /* Remove an object from the cache. */
+    void (*delete)(void *context, server_rec *s,
+                   const unsigned char *id, unsigned int idlen,
+                   apr_pool_t *pool);
+    /* Dump cache status for mod_status output. */
+    void (*status)(void *context, request_rec *r, int flags);
+} modssl_sesscache_provider;
+
 typedef struct {
     pid_t           pid;
     apr_pool_t     *pPool;
     BOOL            bFixed;
-    int             nSessionCacheMode;
-    char           *szSessionCacheDataFile;
-    int             nSessionCacheDataSize;
-    apr_shm_t      *pSessionCacheDataMM;
-    apr_rmm_t      *pSessionCacheDataRMM;
-    void           *tSessionCacheDataTable;
+
+    /* OpenSSL SSL_SESS_CACHE_* flags: */
+    long            sesscache_mode;
+
+    /* The configured provider, and associated private data
+     * structure. */
+    const modssl_sesscache_provider *sesscache;
+    void *sesscache_context;
+
     ssl_mutexmode_t nMutexMode;
     apr_lockmech_e  nMutexMech;
     const char     *szMutexFile;
@@ -452,6 +496,12 @@
     X509_STORE  *crl;
 
     modssl_auth_ctx_t auth;
+
+    BOOL ocsp_enabled; /* true if OCSP verification enabled */
+    BOOL ocsp_force_default; /* true if the default responder URL is
+                              * used regardless of per-cert URL */
+    const char *ocsp_responder; /* default responder URL */
+
 } modssl_ctx_t;
 
 struct SSLSrvConfigRec {
@@ -541,6 +591,10 @@
 const char  *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *, void *, const char *);
 const char  *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *, void *, const char *);
 
+const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag);
+const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const char *arg);
+const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag);
+
 /**  module initialization  */
 int          ssl_init_Module(apr_pool_t *, apr_pool_t *, apr_pool_t *, server_rec *);
 void         ssl_init_Engine(server_rec *, apr_pool_t *);
@@ -570,6 +624,9 @@
 SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *);
 void         ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
 void         ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE, int, int);
+#ifndef OPENSSL_NO_TLSEXT
+int          ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
+#endif
 
 /**  Session Cache Support  */
 void         ssl_scache_init(server_rec *, apr_pool_t *);
@@ -581,38 +638,15 @@
 void         ssl_scache_remove(server_rec *, UCHAR *, int,
                                apr_pool_t *);
 
-char        *ssl_scache_id2sz(UCHAR *, int);
-void         ssl_scache_dbm_init(server_rec *, apr_pool_t *);
-void         ssl_scache_dbm_kill(server_rec *);
-BOOL         ssl_scache_dbm_store(server_rec *, UCHAR *, int,
-                                  time_t, SSL_SESSION *, apr_pool_t *);
-SSL_SESSION *ssl_scache_dbm_retrieve(server_rec *, UCHAR *, int,
-                                     apr_pool_t *);
-void         ssl_scache_dbm_remove(server_rec *, UCHAR *, int,
-                                   apr_pool_t *);
-void         ssl_scache_dbm_status(request_rec *r, int flags, apr_pool_t *);
-
-void         ssl_scache_shmcb_init(server_rec *, apr_pool_t *);
-void         ssl_scache_shmcb_kill(server_rec *);
-BOOL         ssl_scache_shmcb_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *);
-SSL_SESSION *ssl_scache_shmcb_retrieve(server_rec *, UCHAR *, int);
-void         ssl_scache_shmcb_remove(server_rec *, UCHAR *, int);
-void         ssl_scache_shmcb_status(request_rec *r, int flags, apr_pool_t *pool);
-
-void         ssl_scache_dc_init(server_rec *, apr_pool_t *);
-void         ssl_scache_dc_kill(server_rec *);
-BOOL         ssl_scache_dc_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *);
-SSL_SESSION *ssl_scache_dc_retrieve(server_rec *, UCHAR *, int);
-void         ssl_scache_dc_remove(server_rec *, UCHAR *, int);
-void         ssl_scache_dc_status(request_rec *r, int flags, apr_pool_t *pool);
+extern const modssl_sesscache_provider modssl_sesscache_shmcb;
+extern const modssl_sesscache_provider modssl_sesscache_dbm;
+
+#ifdef HAVE_DISTCACHE
+extern const modssl_sesscache_provider modssl_sesscache_dc;
+#endif
 
 #ifdef HAVE_SSL_CACHE_MEMCACHE
-void         ssl_scache_mc_init(server_rec *, apr_pool_t *);
-void         ssl_scache_mc_kill(server_rec *);
-BOOL         ssl_scache_mc_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *);
-SSL_SESSION *ssl_scache_mc_retrieve(server_rec *, UCHAR *, int, apr_pool_t *);
-void         ssl_scache_mc_remove(server_rec *, UCHAR *, int);
-void         ssl_scache_mc_status(request_rec *r, int flags, apr_pool_t *pool);
+extern const modssl_sesscache_provider modssl_sesscache_mc;
 #endif
 
 /** Proxy Support */
@@ -679,6 +713,16 @@
 void         ssl_die(void);
 void         ssl_log_ssl_error(const char *, int, int, server_rec *);
 
+/* ssl_log_cxerror is a wrapper for ap_log_cerror which takes a
+ * certificate as an additional argument and appends details of that
+ * cert to the log message.  All other arguments interpreted exactly
+ * as ap_log_cerror. */
+void ssl_log_cxerror(const char *file, int line, int level, 
+                     apr_status_t rv, conn_rec *c, X509 *cert,
+                     const char *format, ...)
+    __attribute__((format(printf,7,8)));
+
+
 /**  Variables  */
 
 /* Register variables for the lifetime of the process pool 'p'. */
@@ -689,6 +733,22 @@
 void         ssl_var_log_config_register(apr_pool_t *p);
 
 #define APR_SHM_MAXSIZE (64 * 1024 * 1024)
+
+#ifdef HAVE_OCSP
+/* Perform OCSP validation of the current cert in the given context.
+ * Returns non-zero on success or zero on failure.  On failure, the
+ * context error code is set. */
+int modssl_verify_ocsp(X509_STORE_CTX *ctx, SSLSrvConfigRec *sc, 
+                       server_rec *s, conn_rec *c, apr_pool_t *pool);
+
+/* OCSP helper interface; dispatches the given OCSP request to the
+ * responder at the given URI.  Returns the decoded OCSP response
+ * object, or NULL on error (in which case, errors will have been
+ * logged).  Pool 'p' is used for temporary allocations. */
+OCSP_RESPONSE *modssl_dispatch_ocsp_request(const apr_uri_t *uri, 
+                                            OCSP_REQUEST *request,
+                                            conn_rec *c, apr_pool_t *p);
+#endif
 
 #endif /* SSL_PRIVATE_H */
 /** @} */



Mime
View raw message