summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/http/http_request.c2
-rw-r--r--modules/mappers/mod_rewrite.c14
-rw-r--r--modules/proxy/balancers/mod_lbmethod_bytraffic.c2
-rw-r--r--modules/proxy/mod_proxy.c111
-rw-r--r--modules/proxy/mod_proxy.h1
-rw-r--r--modules/proxy/mod_proxy_balancer.c98
-rw-r--r--modules/proxy/proxy_util.c154
-rw-r--r--modules/proxy/proxy_util.h17
-rw-r--r--modules/ssl/ssl_engine_init.c13
-rw-r--r--modules/ssl/ssl_engine_io.c82
-rw-r--r--modules/ssl/ssl_engine_kernel.c4
-rw-r--r--modules/ssl/ssl_engine_pphrase.c159
-rw-r--r--modules/ssl/ssl_private.h14
-rw-r--r--modules/ssl/ssl_util.c2
14 files changed, 440 insertions, 233 deletions
diff --git a/modules/http/http_request.c b/modules/http/http_request.c
index 71ecc2b..7e9477b 100644
--- a/modules/http/http_request.c
+++ b/modules/http/http_request.c
@@ -708,7 +708,7 @@ AP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r)
r->args = rr->args;
r->finfo = rr->finfo;
r->handler = rr->handler;
- ap_set_content_type_ex(r, rr->content_type, AP_REQUEST_IS_TRUSTED_CT(r));
+ ap_set_content_type_ex(r, rr->content_type, AP_REQUEST_IS_TRUSTED_CT(rr));
r->content_encoding = rr->content_encoding;
r->content_languages = rr->content_languages;
r->per_dir_config = rr->per_dir_config;
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
index 3fc2baf..f1c22e3 100644
--- a/modules/mappers/mod_rewrite.c
+++ b/modules/mappers/mod_rewrite.c
@@ -179,6 +179,7 @@ static const char* really_last_key = "rewrite_really_last";
#define RULEFLAG_ESCAPECTLS (1<<21)
#define RULEFLAG_UNSAFE_PREFIX_STAT (1<<22)
#define RULEFLAG_UNSAFE_ALLOW3F (1<<23)
+#define RULEFLAG_UNC (1<<24)
/* return code of the rewrite rule
* the result may be escaped - or not
@@ -3843,6 +3844,9 @@ static const char *cmd_rewriterule_setflag(apr_pool_t *p, void *_cfg,
else if(!strcasecmp(key, "nsafeAllow3F")) {
cfg->flags |= RULEFLAG_UNSAFE_ALLOW3F;
}
+ else if(!strcasecmp(key, "NC")) {
+ cfg->flags |= RULEFLAG_UNC;
+ }
else {
++error;
}
@@ -4462,6 +4466,16 @@ static rule_return_type apply_rewrite_rule(rewriterule_entry *p,
return RULE_RC_MATCH;
}
+ if (!(p->flags & RULEFLAG_UNC)) {
+ /* merge leading slashes, unless they were literals in the sub */
+ if (!AP_IS_SLASH(p->output[0]) || !AP_IS_SLASH(p->output[1])) {
+ while (AP_IS_SLASH(r->filename[0]) &&
+ AP_IS_SLASH(r->filename[1])) {
+ r->filename++;
+ }
+ }
+ }
+
/* Finally remember the forced mime-type */
force_type_handler(p, ctx);
diff --git a/modules/proxy/balancers/mod_lbmethod_bytraffic.c b/modules/proxy/balancers/mod_lbmethod_bytraffic.c
index 6cfab94..724b028 100644
--- a/modules/proxy/balancers/mod_lbmethod_bytraffic.c
+++ b/modules/proxy/balancers/mod_lbmethod_bytraffic.c
@@ -73,8 +73,6 @@ static apr_status_t reset(proxy_balancer *balancer, server_rec *s)
proxy_worker **worker;
worker = (proxy_worker **)balancer->workers->elts;
for (i = 0; i < balancer->workers->nelts; i++, worker++) {
- (*worker)->s->lbstatus = 0;
- (*worker)->s->busy = 0;
(*worker)->s->transferred = 0;
(*worker)->s->read = 0;
}
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index ad0c031..8f13e68 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -822,60 +822,6 @@ static int proxy_detect(request_rec *r)
return DECLINED;
}
-static const char *proxy_interpolate(request_rec *r, const char *str)
-{
- /* Interpolate an env str in a configuration string
- * Syntax ${var} --> value_of(var)
- * Method: replace one var, and recurse on remainder of string
- * Nothing clever here, and crap like nested vars may do silly things
- * but we'll at least avoid sending the unwary into a loop
- */
- const char *start;
- const char *end;
- const char *var;
- const char *val;
- const char *firstpart;
-
- start = ap_strstr_c(str, "${");
- if (start == NULL) {
- return str;
- }
- end = ap_strchr_c(start+2, '}');
- if (end == NULL) {
- return str;
- }
- /* OK, this is syntax we want to interpolate. Is there such a var ? */
- var = apr_pstrmemdup(r->pool, start+2, end-(start+2));
- val = apr_table_get(r->subprocess_env, var);
- firstpart = apr_pstrmemdup(r->pool, str, (start-str));
-
- if (val == NULL) {
- return apr_pstrcat(r->pool, firstpart,
- proxy_interpolate(r, end+1), NULL);
- }
- else {
- return apr_pstrcat(r->pool, firstpart, val,
- proxy_interpolate(r, end+1), NULL);
- }
-}
-static apr_array_header_t *proxy_vars(request_rec *r,
- apr_array_header_t *hdr)
-{
- int i;
- apr_array_header_t *ret = apr_array_make(r->pool, hdr->nelts,
- sizeof (struct proxy_alias));
- struct proxy_alias *old = (struct proxy_alias *) hdr->elts;
-
- for (i = 0; i < hdr->nelts; ++i) {
- struct proxy_alias *newcopy = apr_array_push(ret);
- newcopy->fake = (old[i].flags & PROXYPASS_INTERPOLATE)
- ? proxy_interpolate(r, old[i].fake) : old[i].fake;
- newcopy->real = (old[i].flags & PROXYPASS_INTERPOLATE)
- ? proxy_interpolate(r, old[i].real) : old[i].real;
- }
- return ret;
-}
-
PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent,
proxy_dir_conf *dconf)
{
@@ -891,8 +837,8 @@ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent,
const char *servlet_uri = NULL;
if (dconf && (dconf->interpolate_env == 1) && (ent->flags & PROXYPASS_INTERPOLATE)) {
- fake = proxy_interpolate(r, ent->fake);
- real = proxy_interpolate(r, ent->real);
+ fake = ap_proxy_interpolate(r, ent->fake);
+ real = ap_proxy_interpolate(r, ent->real);
}
else {
fake = ent->fake;
@@ -1212,38 +1158,12 @@ static int proxy_map_location(request_rec *r)
*/
static int proxy_fixup(request_rec *r)
{
- char *url, *p;
- int access_status;
- proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
- &proxy_module);
-
if (!r->proxyreq || !r->filename || strncmp(r->filename, "proxy:", 6) != 0)
return DECLINED;
/* XXX: Shouldn't we try this before we run the proxy_walk? */
- url = &r->filename[6];
- if ((dconf->interpolate_env == 1) && (r->proxyreq == PROXYREQ_REVERSE)) {
- /* create per-request copy of reverse proxy conf,
- * and interpolate vars in it
- */
- proxy_req_conf *rconf = apr_palloc(r->pool, sizeof(proxy_req_conf));
- ap_set_module_config(r->request_config, &proxy_module, rconf);
- rconf->raliases = proxy_vars(r, dconf->raliases);
- rconf->cookie_paths = proxy_vars(r, dconf->cookie_paths);
- rconf->cookie_domains = proxy_vars(r, dconf->cookie_domains);
- }
-
- /* canonicalise each specific scheme */
- if ((access_status = proxy_run_canon_handler(r, url))) {
- return access_status;
- }
-
- p = strchr(url, ':');
- if (p == NULL || p == url)
- return HTTP_BAD_REQUEST;
-
- return OK; /* otherwise; we've done the best we can */
+ return ap_proxy_canon_url(r);
}
/* Send a redirection if the request contains a hostname which is not */
@@ -1321,11 +1241,8 @@ static int proxy_handler(request_rec *r)
r->proxyreq = PROXYREQ_REVERSE;
r->filename = apr_pstrcat(r->pool, r->handler, r->filename, NULL);
- /* Still need to fixup/canonicalize r->filename */
- rc = ap_proxy_fixup_uds_filename(r);
- if (rc <= OK) {
- rc = proxy_fixup(r);
- }
+ /* Still need to canonicalize r->filename */
+ rc = ap_proxy_canon_url(r);
if (rc != OK) {
r->filename = old_filename;
r->proxyreq = 0;
@@ -1338,6 +1255,15 @@ static int proxy_handler(request_rec *r)
return rc;
}
+ uri = r->filename + 6;
+ p = strchr(uri, ':');
+ if (p == NULL) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01141)
+ "proxy_handler no URL in %s", r->filename);
+ return HTTP_BAD_REQUEST;
+ }
+ scheme = apr_pstrmemdup(r->pool, uri, p - uri);
+
/* handle max-forwards / OPTIONS / TRACE */
if ((str = apr_table_get(r->headers_in, "Max-Forwards"))) {
char *end;
@@ -1417,14 +1343,6 @@ static int proxy_handler(request_rec *r)
}
}
- uri = r->filename + 6;
- p = strchr(uri, ':');
- if (p == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01141)
- "proxy_handler no URL in %s", r->filename);
- return HTTP_BAD_REQUEST;
- }
-
/* If the host doesn't have a domain name, add one and redirect. */
if (conf->domain != NULL) {
rc = proxy_needsdomain(r, uri, conf->domain);
@@ -1432,7 +1350,6 @@ static int proxy_handler(request_rec *r)
return HTTP_MOVED_PERMANENTLY;
}
- scheme = apr_pstrmemdup(r->pool, uri, p - uri);
/* Check URI's destination host against NoProxy hosts */
/* Bypass ProxyRemote server lookup if configured as NoProxy */
for (direct_connect = i = 0; i < conf->dirconn->nelts &&
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index 59572bf..cd38889 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -1008,6 +1008,7 @@ PROXY_DECLARE(proxy_balancer_shared *) ap_proxy_find_balancershm(ap_slotmem_prov
* r->notes ("uds_path")
* @param r current request
* @return OK if fixed up, DECLINED if not UDS, or an HTTP_XXX error
+ * @remark Deprecated (for internal use only)
*/
PROXY_DECLARE(int) ap_proxy_fixup_uds_filename(request_rec *r);
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index 3c0f5a8..79cb8bb 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -17,6 +17,7 @@
/* Load balancer module for Apache proxy */
#include "mod_proxy.h"
+#include "proxy_util.h"
#include "scoreboard.h"
#include "ap_mpm.h"
#include "apr_version.h"
@@ -69,23 +70,21 @@ extern void proxy_update_members(proxy_balancer **balancer, request_rec *r,
static int proxy_balancer_canon(request_rec *r, char *url)
{
- char *host, *path;
- char *search = NULL;
- const char *err;
+ char *host;
apr_port_t port = 0;
+ const char *err;
/* TODO: offset of BALANCER_PREFIX ?? */
if (ap_cstr_casecmpn(url, "balancer:", 9) == 0) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "canonicalising URL %s", url);
url += 9;
}
else {
return DECLINED;
}
- ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "canonicalising URL %s", url);
-
/* do syntatic check.
- * We break the URL into host, port, path, search
+ * We break the URL into host, port, path
*/
err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
if (err) {
@@ -94,50 +93,12 @@ static int proxy_balancer_canon(request_rec *r, char *url)
url, err);
return HTTP_BAD_REQUEST;
}
- /*
- * now parse path/search args, according to rfc1738:
- * process the path. With proxy-noncanon set (by
- * mod_proxy) we use the raw, unparsed uri
- */
- if (apr_table_get(r->notes, "proxy-nocanon")) {
- path = url; /* this is the raw path */
- }
- else if (apr_table_get(r->notes, "proxy-noencode")) {
- path = url; /* this is the encoded path already */
- search = r->args;
- }
- else {
- core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
- int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
- path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
- r->proxyreq);
- if (!path) {
- return HTTP_BAD_REQUEST;
- }
- search = r->args;
- }
- /*
- * If we have a raw control character or a ' ' in nocanon path or
- * r->args, correct encoding was missed.
+ /* The canon_handler hooks are run per the BalancerMember in
+ * balancer_fixup(), keep the original/raw path for now.
*/
- if (path == url && *ap_scan_vchar_obstext(path)) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10416)
- "To be forwarded path contains control "
- "characters or spaces");
- return HTTP_FORBIDDEN;
- }
- if (search && *ap_scan_vchar_obstext(search)) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10407)
- "To be forwarded query string contains control "
- "characters or spaces");
- return HTTP_FORBIDDEN;
- }
-
- r->filename = apr_pstrcat(r->pool, "proxy:" BALANCER_PREFIX, host,
- "/", path, (search) ? "?" : "", (search) ? search : "", NULL);
-
- r->path_info = apr_pstrcat(r->pool, "/", path, NULL);
+ r->filename = apr_pstrcat(r->pool, "proxy:" BALANCER_PREFIX,
+ host, "/", url, NULL);
return OK;
}
@@ -429,25 +390,25 @@ static proxy_worker *find_best_worker(proxy_balancer *balancer,
}
-static int rewrite_url(request_rec *r, proxy_worker *worker,
- char **url)
+static int balancer_fixup(request_rec *r, proxy_worker *worker, char **url)
{
- const char *scheme = strstr(*url, "://");
- const char *path = NULL;
+ const char *path;
+ int rc;
- if (scheme)
- path = ap_strchr_c(scheme + 3, '/');
-
- /* we break the URL into host, port, uri */
- if (!worker) {
- return ap_proxyerror(r, HTTP_BAD_REQUEST, apr_pstrcat(r->pool,
- "missing worker. URI cannot be parsed: ", *url,
- NULL));
+ /* Build the proxy URL from the worker URL and the actual path */
+ path = strstr(*url, "://");
+ if (path) {
+ path = ap_strchr_c(path + 3, '/');
}
+ r->filename = apr_pstrcat(r->pool, "proxy:", worker->s->name_ex, path, NULL);
- *url = apr_pstrcat(r->pool, worker->s->name_ex, path, NULL);
-
- return OK;
+ /* Canonicalize r->filename per the worker scheme's canon_handler hook */
+ rc = ap_proxy_canon_url(r);
+ if (rc == OK) {
+ AP_DEBUG_ASSERT(strncmp(r->filename, "proxy:", 6) == 0);
+ *url = apr_pstrdup(r->pool, r->filename + 6);
+ }
+ return rc;
}
static void force_recovery(proxy_balancer *balancer, server_rec *s)
@@ -515,7 +476,8 @@ static int proxy_balancer_pre_request(proxy_worker **worker,
* for balancer, because this is failover attempt.
*/
if (!*balancer &&
- !(*balancer = ap_proxy_get_balancer(r->pool, conf, *url, 1)))
+ (ap_cstr_casecmpn(*url, BALANCER_PREFIX, sizeof(BALANCER_PREFIX) - 1)
+ || !(*balancer = ap_proxy_get_balancer(r->pool, conf, *url, 1))))
return DECLINED;
/* Step 2: Lock the LoadBalancer
@@ -649,10 +611,12 @@ static int proxy_balancer_pre_request(proxy_worker **worker,
/* Rewrite the url from 'balancer://url'
* to the 'worker_scheme://worker_hostname[:worker_port]/url'
- * This replaces the balancers fictional name with the
- * real hostname of the elected worker.
+ * This replaces the balancers fictional name with the real
+ * hostname of the elected worker and canonicalizes according
+ * to the worker scheme (calls canon_handler hooks).
*/
- access_status = rewrite_url(r, *worker, url);
+ access_status = balancer_fixup(r, *worker, url);
+
/* Add the session route to request notes if present */
if (route) {
apr_table_setn(r->notes, "session-sticky", sticky);
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index e71cbd8..7c0d315 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -1358,8 +1358,6 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balance
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, APLOGNO(00921) "slotmem_attach failed");
return APR_EGENERAL;
}
- if (balancer->lbmethod && balancer->lbmethod->reset)
- balancer->lbmethod->reset(balancer, s);
#if APR_HAS_THREADS
if (balancer->tmutex == NULL) {
@@ -2429,14 +2427,14 @@ static int ap_proxy_retry_worker(const char *proxy_function, proxy_worker *worke
* were passed a UDS url (eg: from mod_proxy) and adjust uds_path
* as required.
*/
-PROXY_DECLARE(int) ap_proxy_fixup_uds_filename(request_rec *r)
+static int fixup_uds_filename(request_rec *r)
{
char *uds_url = r->filename + 6, *origin_url;
if (!strncmp(r->filename, "proxy:", 6) &&
!ap_cstr_casecmpn(uds_url, "unix:", 5) &&
(origin_url = ap_strchr(uds_url + 5, '|'))) {
- char *uds_path = NULL;
+ char *uds_path = NULL, *end;
apr_uri_t urisock;
apr_status_t rv;
@@ -2448,9 +2446,10 @@ PROXY_DECLARE(int) ap_proxy_fixup_uds_filename(request_rec *r)
|| !urisock.hostname[0])) {
uds_path = ap_runtime_dir_relative(r->pool, urisock.path);
}
- if (!uds_path) {
+ if (!uds_path || !(end = ap_strchr(origin_url, ':'))) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10292)
"Invalid proxy UDS filename (%s)", r->filename);
+ apr_table_unset(r->notes, "uds_path");
return HTTP_BAD_REQUEST;
}
apr_table_setn(r->notes, "uds_path", uds_path);
@@ -2459,14 +2458,136 @@ PROXY_DECLARE(int) ap_proxy_fixup_uds_filename(request_rec *r)
"*: fixup UDS from %s: %s (%s)",
r->filename, origin_url, uds_path);
- /* Overwrite the UDS part in place */
- memmove(uds_url, origin_url, strlen(origin_url) + 1);
+ /* The hostname part of the URL is not mandated for UDS though
+ * the canon_handler hooks will require it, so add "localhost"
+ * if it's missing (won't be used anyway for an AF_UNIX socket).
+ */
+ if (!end[1]) {
+ r->filename = apr_pstrcat(r->pool, "proxy:",
+ origin_url, "//localhost",
+ NULL);
+ }
+ else if (end[1] == '/' && end[2] == '/' && !end[3]) {
+ r->filename = apr_pstrcat(r->pool, "proxy:",
+ origin_url, "localhost",
+ NULL);
+ }
+ else {
+ /* Overwrite the UDS part of r->filename in place */
+ memmove(uds_url, origin_url, strlen(origin_url) + 1);
+ }
return OK;
}
+ apr_table_unset(r->notes, "uds_path");
return DECLINED;
}
+/* Deprecated (unused upstream) */
+PROXY_DECLARE(int) ap_proxy_fixup_uds_filename(request_rec *r)
+{
+ return fixup_uds_filename(r);
+}
+
+PROXY_DECLARE(const char *) ap_proxy_interpolate(request_rec *r,
+ const char *str)
+{
+ /* Interpolate an env str in a configuration string
+ * Syntax ${var} --> value_of(var)
+ * Method: replace one var, and recurse on remainder of string
+ * Nothing clever here, and crap like nested vars may do silly things
+ * but we'll at least avoid sending the unwary into a loop
+ */
+ const char *start;
+ const char *end;
+ const char *var;
+ const char *val;
+ const char *firstpart;
+
+ start = ap_strstr_c(str, "${");
+ if (start == NULL) {
+ return str;
+ }
+ end = ap_strchr_c(start+2, '}');
+ if (end == NULL) {
+ return str;
+ }
+ /* OK, this is syntax we want to interpolate. Is there such a var ? */
+ var = apr_pstrmemdup(r->pool, start+2, end-(start+2));
+ val = apr_table_get(r->subprocess_env, var);
+ firstpart = apr_pstrmemdup(r->pool, str, (start-str));
+
+ if (val == NULL) {
+ return apr_pstrcat(r->pool, firstpart,
+ ap_proxy_interpolate(r, end+1), NULL);
+ }
+ else {
+ return apr_pstrcat(r->pool, firstpart, val,
+ ap_proxy_interpolate(r, end+1), NULL);
+ }
+}
+
+static apr_array_header_t *proxy_vars(request_rec *r, apr_array_header_t *hdr)
+{
+ int i;
+ apr_array_header_t *ret = apr_array_make(r->pool, hdr->nelts,
+ sizeof (struct proxy_alias));
+ struct proxy_alias *old = (struct proxy_alias *) hdr->elts;
+
+ for (i = 0; i < hdr->nelts; ++i) {
+ struct proxy_alias *newcopy = apr_array_push(ret);
+ newcopy->fake = (old[i].flags & PROXYPASS_INTERPOLATE)
+ ? ap_proxy_interpolate(r, old[i].fake) : old[i].fake;
+ newcopy->real = (old[i].flags & PROXYPASS_INTERPOLATE)
+ ? ap_proxy_interpolate(r, old[i].real) : old[i].real;
+ }
+ return ret;
+}
+
+PROXY_DECLARE(int) ap_proxy_canon_url(request_rec *r)
+{
+ char *url, *p;
+ int access_status;
+ proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config,
+ &proxy_module);
+
+ if (!r->proxyreq || !r->filename || strncmp(r->filename, "proxy:", 6) != 0)
+ return DECLINED;
+
+ /* Put the UDS path appart if any (and not already stripped) */
+ if (r->proxyreq == PROXYREQ_REVERSE) {
+ access_status = fixup_uds_filename(r);
+ if (ap_is_HTTP_ERROR(access_status)) {
+ return access_status;
+ }
+ }
+
+ /* Keep this after fixup_uds_filename() */
+ url = apr_pstrdup(r->pool, r->filename + 6);
+
+ if ((dconf->interpolate_env == 1) && (r->proxyreq == PROXYREQ_REVERSE)) {
+ /* create per-request copy of reverse proxy conf,
+ * and interpolate vars in it
+ */
+ proxy_req_conf *rconf = apr_palloc(r->pool, sizeof(proxy_req_conf));
+ ap_set_module_config(r->request_config, &proxy_module, rconf);
+ rconf->raliases = proxy_vars(r, dconf->raliases);
+ rconf->cookie_paths = proxy_vars(r, dconf->cookie_paths);
+ rconf->cookie_domains = proxy_vars(r, dconf->cookie_domains);
+ }
+
+ /* canonicalise each specific scheme */
+ if ((access_status = proxy_run_canon_handler(r, url))) {
+ return access_status;
+ }
+
+ p = strchr(url, ':');
+ if (p == NULL || p == url)
+ return HTTP_BAD_REQUEST;
+
+ return OK; /* otherwise; we've done the best we can */
+}
+
PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
proxy_balancer **balancer,
request_rec *r,
@@ -2476,16 +2597,16 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
access_status = proxy_run_pre_request(worker, balancer, r, conf, url);
if (access_status == DECLINED && *balancer == NULL) {
- const int forward = (r->proxyreq == PROXYREQ_PROXY);
+ /* UDS path stripped from *url by proxy_fixup() already */
*worker = ap_proxy_get_worker_ex(r->pool, NULL, conf, *url,
- forward ? AP_PROXY_WORKER_NO_UDS : 0);
+ AP_PROXY_WORKER_NO_UDS);
if (*worker) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
"%s: found worker %s for %s",
(*worker)->s->scheme, (*worker)->s->name_ex, *url);
access_status = OK;
}
- else if (forward) {
+ else if (r->proxyreq == PROXYREQ_PROXY) {
if (conf->forward) {
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
"*: found forward proxy worker for %s", *url);
@@ -2522,19 +2643,6 @@ PROXY_DECLARE(int) ap_proxy_pre_request(proxy_worker **worker,
access_status = HTTP_SERVICE_UNAVAILABLE;
}
- if (access_status == OK && r->proxyreq == PROXYREQ_REVERSE) {
- int rc = ap_proxy_fixup_uds_filename(r);
- if (ap_is_HTTP_ERROR(rc)) {
- return rc;
- }
- /* If the URL has changed in r->filename, take everything after
- * the "proxy:" prefix.
- */
- if (rc == OK) {
- *url = apr_pstrdup(r->pool, r->filename + 6);
- }
- }
-
return access_status;
}
diff --git a/modules/proxy/proxy_util.h b/modules/proxy/proxy_util.h
index bc131da..9bae20b 100644
--- a/modules/proxy/proxy_util.h
+++ b/modules/proxy/proxy_util.h
@@ -40,6 +40,23 @@ extern PROXY_DECLARE_DATA const apr_strmatch_pattern *ap_proxy_strmatch_domain;
*/
void proxy_util_register_hooks(apr_pool_t *p);
+/*
+ * interpolate an env str in a configuration string
+ *
+ * @param r current request
+ * @param str the string to interpolcate
+ * @return the interpolated string
+ */
+PROXY_DECLARE(const char *) ap_proxy_interpolate(request_rec *r,
+ const char *str);
+
+/*
+ * Canonicalize the URL in r->filename
+ * @param r current request
+ * @return OK or an HTTP_XXX error
+ */
+PROXY_DECLARE(int) ap_proxy_canon_url(request_rec *r);
+
/** @} */
#endif /* PROXY_UTIL_H_ */
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
index 443eac4..598e89f 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -1424,7 +1424,7 @@ static apr_status_t ssl_init_server_certs(server_rec *s,
if (modssl_is_engine_id(keyfile)) {
apr_status_t rv;
- if ((rv = modssl_load_engine_keypair(s, ptemp, vhost_id,
+ if ((rv = modssl_load_engine_keypair(s, p, ptemp, vhost_id,
engine_certfile, keyfile,
&cert, &pkey))) {
return rv;
@@ -1433,8 +1433,10 @@ static apr_status_t ssl_init_server_certs(server_rec *s,
if (cert) {
if (SSL_CTX_use_certificate(mctx->ssl_ctx, cert) < 1) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10137)
- "Failed to configure engine certificate %s, check %s",
- key_id, certfile);
+ "Failed to configure certificate %s from %s, check %s",
+ key_id, mc->szCryptoDevice ?
+ mc->szCryptoDevice : "provider",
+ certfile);
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
return APR_EGENERAL;
}
@@ -1445,8 +1447,9 @@ static apr_status_t ssl_init_server_certs(server_rec *s,
if (SSL_CTX_use_PrivateKey(mctx->ssl_ctx, pkey) < 1) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10130)
- "Failed to configure private key %s from engine",
- keyfile);
+ "Failed to configure private key %s from %s",
+ keyfile, mc->szCryptoDevice ?
+ mc->szCryptoDevice : "provider");
ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
return APR_EGENERAL;
}
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
index 9c7d216..0be5318 100644
--- a/modules/ssl/ssl_engine_io.c
+++ b/modules/ssl/ssl_engine_io.c
@@ -2285,9 +2285,7 @@ void ssl_io_filter_init(conn_rec *c, request_rec *r, SSL *ssl)
apr_pool_cleanup_register(c->pool, (void*)filter_ctx,
ssl_io_filter_cleanup, apr_pool_cleanup_null);
- if (APLOG_CS_IS_LEVEL(c, mySrvFromConn(c), APLOG_TRACE4)) {
- modssl_set_io_callbacks(ssl);
- }
+ modssl_set_io_callbacks(ssl, c, mySrvFromConn(c));
return;
}
@@ -2312,7 +2310,7 @@ void ssl_io_filter_register(apr_pool_t *p)
#define DUMP_WIDTH 16
static void ssl_io_data_dump(conn_rec *c, server_rec *s,
- const char *b, long len)
+ const char *b, int len)
{
char buf[256];
int i, j, rows, trunc, pos;
@@ -2365,11 +2363,13 @@ static void ssl_io_data_dump(conn_rec *c, server_rec *s,
}
if (trunc > 0)
ap_log_cserror(APLOG_MARK, APLOG_TRACE7, 0, c, s,
- "| %04ld - <SPACES/NULS>", len + trunc);
+ "| %04d - <SPACES/NULS>", len + trunc);
ap_log_cserror(APLOG_MARK, APLOG_TRACE7, 0, c, s,
"+-------------------------------------------------------------------------+");
}
+#define MODSSL_IO_DUMP_MAX APR_UINT16_MAX
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
static long modssl_io_cb(BIO *bio, int cmd, const char *argp,
size_t len, int argi, long argl, int rc,
@@ -2382,10 +2382,12 @@ static long modssl_io_cb(BIO *bio, int cmd, const char *argp,
SSL *ssl;
conn_rec *c;
server_rec *s;
+
+ /* unused */
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
- (void)len;
- (void)processed;
+ (void)argi;
#endif
+ (void)argl;
if ((ssl = (SSL *)BIO_get_callback_arg(bio)) == NULL)
return rc;
@@ -2395,28 +2397,59 @@ static long modssl_io_cb(BIO *bio, int cmd, const char *argp,
if ( cmd == (BIO_CB_WRITE|BIO_CB_RETURN)
|| cmd == (BIO_CB_READ |BIO_CB_RETURN) ) {
- if (rc >= 0) {
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ apr_size_t requested_len = len;
+ /*
+ * On OpenSSL >= 3 rc uses the meaning of the BIO_read_ex and
+ * BIO_write_ex functions return value and not the one of
+ * BIO_read and BIO_write. Hence 0 indicates an error.
+ */
+ int ok = (rc > 0);
+#else
+ apr_size_t requested_len = (apr_size_t)argi;
+ int ok = (rc >= 0);
+#endif
+ if (ok) {
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+ apr_size_t actual_len = *processed;
+#else
+ apr_size_t actual_len = (apr_size_t)rc;
+#endif
const char *dump = "";
if (APLOG_CS_IS_LEVEL(c, s, APLOG_TRACE7)) {
- if (argp != NULL)
- dump = "(BIO dump follows)";
- else
+ if (argp == NULL)
dump = "(Oops, no memory buffer?)";
+ else if (actual_len > MODSSL_IO_DUMP_MAX)
+ dump = "(BIO dump follows, truncated to "
+ APR_STRINGIFY(MODSSL_IO_DUMP_MAX) ")";
+ else
+ dump = "(BIO dump follows)";
}
ap_log_cserror(APLOG_MARK, APLOG_TRACE4, 0, c, s,
- "%s: %s %ld/%d bytes %s BIO#%pp [mem: %pp] %s",
+ "%s: %s %" APR_SIZE_T_FMT "/%" APR_SIZE_T_FMT
+ " bytes %s BIO#%pp [mem: %pp] %s",
MODSSL_LIBRARY_NAME,
- (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
- (long)rc, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"),
+ (cmd & BIO_CB_WRITE) ? "write" : "read",
+ actual_len, requested_len,
+ (cmd & BIO_CB_WRITE) ? "to" : "from",
bio, argp, dump);
- if (*dump != '\0' && argp != NULL)
- ssl_io_data_dump(c, s, argp, rc);
+ /*
+ * *dump will only be != '\0' if
+ * APLOG_CS_IS_LEVEL(c, s, APLOG_TRACE7)
+ */
+ if (*dump != '\0' && argp != NULL) {
+ int dump_len = (actual_len >= MODSSL_IO_DUMP_MAX
+ ? MODSSL_IO_DUMP_MAX
+ : actual_len);
+ ssl_io_data_dump(c, s, argp, dump_len);
+ }
}
else {
ap_log_cserror(APLOG_MARK, APLOG_TRACE4, 0, c, s,
- "%s: I/O error, %d bytes expected to %s on BIO#%pp [mem: %pp]",
- MODSSL_LIBRARY_NAME, argi,
- (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
+ "%s: I/O error, %" APR_SIZE_T_FMT
+ " bytes expected to %s on BIO#%pp [mem: %pp]",
+ MODSSL_LIBRARY_NAME, requested_len,
+ (cmd & BIO_CB_WRITE) ? "write" : "read",
bio, argp);
}
}
@@ -2433,10 +2466,15 @@ static APR_INLINE void set_bio_callback(BIO *bio, void *arg)
BIO_set_callback_arg(bio, arg);
}
-void modssl_set_io_callbacks(SSL *ssl)
+void modssl_set_io_callbacks(SSL *ssl, conn_rec *c, server_rec *s)
{
- BIO *rbio = SSL_get_rbio(ssl),
- *wbio = SSL_get_wbio(ssl);
+ BIO *rbio, *wbio;
+
+ if (!APLOG_CS_IS_LEVEL(c, s, APLOG_TRACE4))
+ return;
+
+ rbio = SSL_get_rbio(ssl);
+ wbio = SSL_get_wbio(ssl);
if (rbio) {
set_bio_callback(rbio, ssl);
}
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
index fa1b3a8..9c51021 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -2585,9 +2585,7 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s)
* (and the first vhost doesn't use APLOG_TRACE4), then
* we need to set that callback here.
*/
- if (APLOGtrace4(s)) {
- modssl_set_io_callbacks(ssl);
- }
+ modssl_set_io_callbacks(ssl, c, s);
return 1;
}
diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c
index 699019f..8a08ede 100644
--- a/modules/ssl/ssl_engine_pphrase.c
+++ b/modules/ssl/ssl_engine_pphrase.c
@@ -31,6 +31,9 @@
#include "ssl_private.h"
#include <openssl/ui.h>
+#if MODSSL_HAVE_OPENSSL_STORE
+#include <openssl/store.h>
+#endif
typedef struct {
server_rec *s;
@@ -608,7 +611,7 @@ int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify, void *srv)
return (len);
}
-#if MODSSL_HAVE_ENGINE_API
+#if MODSSL_HAVE_ENGINE_API || MODSSL_HAVE_OPENSSL_STORE
/* OpenSSL UI implementation for passphrase entry; largely duplicated
* from ssl_pphrase_Handle_CB but adjusted for UI API. TODO: Might be
@@ -826,21 +829,32 @@ static UI_METHOD *get_passphrase_ui(apr_pool_t *p)
}
#endif
+#if MODSSL_HAVE_ENGINE_API
+static apr_status_t modssl_engine_cleanup(void *engine)
+{
+ ENGINE *e = engine;
-apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
- const char *vhostid,
- const char *certid, const char *keyid,
- X509 **pubkey, EVP_PKEY **privkey)
+ ENGINE_finish(e);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t modssl_load_keypair_engine(server_rec *s, apr_pool_t *pconf,
+ apr_pool_t *ptemp,
+ const char *vhostid,
+ const char *certid,
+ const char *keyid,
+ X509 **pubkey,
+ EVP_PKEY **privkey)
{
-#if MODSSL_HAVE_ENGINE_API
const char *c, *scheme;
ENGINE *e;
- UI_METHOD *ui_method = get_passphrase_ui(p);
+ UI_METHOD *ui_method = get_passphrase_ui(ptemp);
pphrase_cb_arg_t ppcb;
memset(&ppcb, 0, sizeof ppcb);
ppcb.s = s;
- ppcb.p = p;
+ ppcb.p = ptemp;
ppcb.bPassPhraseDialogOnce = TRUE;
ppcb.key_id = vhostid;
ppcb.pkey_file = keyid;
@@ -853,7 +867,7 @@ apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
return ssl_die(s);
}
- scheme = apr_pstrmemdup(p, keyid, c - keyid);
+ scheme = apr_pstrmemdup(ptemp, keyid, c - keyid);
if (!(e = ENGINE_by_id(scheme))) {
ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10132)
"Init: Failed to load engine for private key %s",
@@ -902,11 +916,136 @@ apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
return ssl_die(s);
}
- ENGINE_finish(e);
+ /* Release the functional reference obtained by ENGINE_init() only
+ * when after the ENGINE is no longer used. */
+ apr_pool_cleanup_register(pconf, e, modssl_engine_cleanup, modssl_engine_cleanup);
+
+ /* Release the structural reference obtained by ENGINE_by_id()
+ * immediately. */
ENGINE_free(e);
return APR_SUCCESS;
+}
+#endif
+
+#if MODSSL_HAVE_OPENSSL_STORE
+static OSSL_STORE_INFO *modssl_load_store_uri(server_rec *s, apr_pool_t *p,
+ const char *vhostid,
+ const char *uri, int info_type)
+{
+ OSSL_STORE_CTX *sctx;
+ UI_METHOD *ui_method = get_passphrase_ui(p);
+ pphrase_cb_arg_t ppcb;
+ OSSL_STORE_INFO *info = NULL;
+
+ memset(&ppcb, 0, sizeof ppcb);
+ ppcb.s = s;
+ ppcb.p = p;
+ ppcb.bPassPhraseDialogOnce = TRUE;
+ ppcb.key_id = vhostid;
+ ppcb.pkey_file = uri;
+
+ sctx = OSSL_STORE_open(uri, ui_method, &ppcb, NULL, NULL);
+ if (!sctx) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(10491)
+ "Init: OSSL_STORE_open failed for PKCS#11 URI `%s'",
+ uri);
+ return NULL;
+ }
+
+ while (!OSSL_STORE_eof(sctx)) {
+ info = OSSL_STORE_load(sctx);
+ if (!info)
+ break;
+
+ if (OSSL_STORE_INFO_get_type(info) == info_type)
+ break;
+
+ OSSL_STORE_INFO_free(info);
+ info = NULL;
+ }
+
+ OSSL_STORE_close(sctx);
+
+ return info;
+}
+
+static apr_status_t modssl_load_keypair_store(server_rec *s, apr_pool_t *p,
+ const char *vhostid,
+ const char *certid,
+ const char *keyid,
+ X509 **pubkey,
+ EVP_PKEY **privkey)
+{
+ OSSL_STORE_INFO *info = NULL;
+
+ *privkey = NULL;
+ *pubkey = NULL;
+
+ info = modssl_load_store_uri(s, p, vhostid, keyid, OSSL_STORE_INFO_PKEY);
+ if (!info) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10492)
+ "Init: OSSL_STORE_INFO_PKEY lookup failed for private key identifier `%s'",
+ keyid);
+ return ssl_die(s);
+ }
+
+ *privkey = OSSL_STORE_INFO_get1_PKEY(info);
+ OSSL_STORE_INFO_free(info);
+ if (!*privkey) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10493)
+ "Init: OSSL_STORE_INFO_PKEY lookup failed for private key identifier `%s'",
+ keyid);
+ return ssl_die(s);
+ }
+
+ if (certid) {
+ info = modssl_load_store_uri(s, p, vhostid, certid, OSSL_STORE_INFO_CERT);
+ if (!info) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10494)
+ "Init: OSSL_STORE_INFO_CERT lookup failed for certificate identifier `%s'",
+ keyid);
+ return ssl_die(s);
+ }
+
+ *pubkey = OSSL_STORE_INFO_get1_CERT(info);
+ OSSL_STORE_INFO_free(info);
+ if (!*pubkey) {
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10495)
+ "Init: OSSL_STORE_INFO_CERT lookup failed for certificate identifier `%s'",
+ certid);
+ return ssl_die(s);
+ }
+ }
+
+ return APR_SUCCESS;
+}
+#endif
+
+apr_status_t modssl_load_engine_keypair(server_rec *s,
+ apr_pool_t *pconf, apr_pool_t *ptemp,
+ const char *vhostid,
+ const char *certid, const char *keyid,
+ X509 **pubkey, EVP_PKEY **privkey)
+{
+#if MODSSL_HAVE_ENGINE_API
+ SSLModConfigRec *mc = myModConfig(s);
+
+ /* For OpenSSL 3.x, use the STORE-based API if either ENGINE
+ * support was not present compile-time, or if it's built but
+ * SSLCryptoDevice is not configured. */
+ if (mc->szCryptoDevice)
+ return modssl_load_keypair_engine(s, pconf, ptemp,
+ vhostid, certid, keyid,
+ pubkey, privkey);
+#endif
+#if MODSSL_HAVE_OPENSSL_STORE
+ return modssl_load_keypair_store(s, ptemp, vhostid, certid, keyid,
+ pubkey, privkey);
#else
+ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(10496)
+ "Init: no method for loading keypair for %s (%s | %s)",
+ vhostid, certid ? certid : "no cert", keyid);
return APR_ENOTIMPL;
#endif
}
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index 25d79ce..c517a7b 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -118,6 +118,15 @@
#define MODSSL_HAVE_ENGINE_API 0
#endif
+/* Use OpenSSL 3.x STORE for loading URI keys and certificates starting with
+ * OpenSSL 3.0
+ */
+#if OPENSSL_VERSION_NUMBER >= 0x30000000
+#define MODSSL_HAVE_OPENSSL_STORE 1
+#else
+#define MODSSL_HAVE_OPENSSL_STORE 0
+#endif
+
#if (OPENSSL_VERSION_NUMBER < 0x0090801f)
#error mod_ssl requires OpenSSL 0.9.8a or later
#endif
@@ -1049,7 +1058,7 @@ void modssl_callback_keylog(const SSL *ssl, const char *line);
/** I/O */
void ssl_io_filter_init(conn_rec *, request_rec *r, SSL *);
void ssl_io_filter_register(apr_pool_t *);
-void modssl_set_io_callbacks(SSL *ssl);
+void modssl_set_io_callbacks(SSL *ssl, conn_rec *c, server_rec *s);
/* ssl_io_buffer_fill fills the setaside buffering of the HTTP request
* to allow an SSL renegotiation to take place. */
@@ -1081,7 +1090,8 @@ apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int,
/* Load public and/or private key from the configured ENGINE. Private
* key returned as *pkey. certid can be NULL, in which case *pubkey
* is not altered. Errors logged on failure. */
-apr_status_t modssl_load_engine_keypair(server_rec *s, apr_pool_t *p,
+apr_status_t modssl_load_engine_keypair(server_rec *s,
+ apr_pool_t *pconf, apr_pool_t *ptemp,
const char *vhostid,
const char *certid, const char *keyid,
X509 **pubkey, EVP_PKEY **privkey);
diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c
index 87ddfa7..7473edb 100644
--- a/modules/ssl/ssl_util.c
+++ b/modules/ssl/ssl_util.c
@@ -476,7 +476,7 @@ void ssl_util_thread_id_setup(apr_pool_t *p)
int modssl_is_engine_id(const char *name)
{
-#if MODSSL_HAVE_ENGINE_API
+#if MODSSL_HAVE_ENGINE_API || MODSSL_HAVE_OPENSSL_STORE
/* ### Can handle any other special ENGINE key names here? */
return strncmp(name, "pkcs11:", 7) == 0;
#else