Fix a denial of service attack against mod_reqtimeout.
[Stefan Fritsch]
+ *) mod_cache: Allow control over the base URL of reverse proxied requests
+ using the CacheKeyBaseURL directive, so that the cache key can be
+ calculated from the endpoint URL instead of the server URL. [Graham
+ Leggett]
+
*) mod_cache: CacheLastModifiedFactor, CacheStoreNoStore, CacheStorePrivate,
CacheStoreExpired, CacheIgnoreNoLastMod, CacheDefaultExpire,
CacheMinExpire and CacheMaxExpire can be set per directory/location.
</usage>
</directivesynopsis>
+<directivesynopsis>
+<name>CacheKeyBaseURL</name>
+<description>Override the base URL of reverse proxied cache keys.</description>
+<syntax>CacheKeyBaseURL <var>URL</var></syntax>
+<default>CacheKeyBaseURL http://example.com</default>
+<contextlist><context>server config</context>
+<context>virtual host</context>
+</contextlist>
+<compatibility>Available in Apache 2.3.9 and later</compatibility>
+
+<usage>
+ <p>When the <directive module="mod_cache">CacheKeyBaseURL</directive> directive
+ is specified, the URL provided will be used as the base URL to calculate
+ the URL of the cache keys in the reverse proxy configuration. When not specified,
+ the scheme, hostname and port of the current virtual host is used to construct
+ the cache key. When a cluster of machines is present, and all cached entries
+ should be cached beneath the same cache key, a new base URL can be specified
+ with this directive.</p>
+
+ <example>
+ # Override the base URL of the cache key.<br />
+ CacheKeyBaseURL http://www.example.com/<br />
+ </example>
+
+ <note type="warning">Take care when setting this directive. If two separate virtual
+ hosts are accidentally given the same base URL, entries from one virtual host
+ will be served to the other.</note>
+
+</usage>
+</directivesynopsis>
+
</modulesynopsis>
* in the reverse proxy case.
*/
if (!r->proxyreq || (r->proxyreq == PROXYREQ_REVERSE)) {
- /* Use _default_ as the hostname if none present, as in mod_vhost */
- hostname = ap_get_server_name(r);
- if (!hostname) {
- hostname = "_default_";
+ if (conf->base_uri && conf->base_uri->hostname) {
+ hostname = conf->base_uri->hostname;
+ }
+ else {
+ /* Use _default_ as the hostname if none present, as in mod_vhost */
+ hostname = ap_get_server_name(r);
+ if (!hostname) {
+ hostname = "_default_";
+ }
}
}
else if(r->parsed_uri.hostname) {
scheme = lcs;
}
else {
- scheme = ap_http_scheme(r);
+ if (conf->base_uri && conf->base_uri->scheme) {
+ scheme = conf->base_uri->scheme;
+ }
+ else {
+ scheme = ap_http_scheme(r);
+ }
}
/*
* scheme - if available. Otherwise use the port-number of the current
* server.
*/
- if(r->proxyreq && (r->proxyreq != PROXYREQ_REVERSE)) {
+ if (r->proxyreq && (r->proxyreq != PROXYREQ_REVERSE)) {
if (r->parsed_uri.port_str) {
port_str = apr_pcalloc(p, strlen(r->parsed_uri.port_str) + 2);
port_str[0] = ':';
}
}
else {
- /* Use the server port */
- port_str = apr_psprintf(p, ":%u", ap_get_server_port(r));
+ if (conf->base_uri && conf->base_uri->port_str) {
+ port_str = conf->base_uri->port_str;
+ }
+ else if (conf->base_uri && conf->base_uri->hostname) {
+ port_str = "";
+ }
+ else {
+ /* Use the server port */
+ port_str = apr_psprintf(p, ":%u", ap_get_server_port(r));
+ }
}
/*
int x_cache_set;
int x_cache_detail;
int x_cache_detail_set;
+ apr_uri_t *base_uri;
+ int base_uri_set;
} cache_server_conf;
typedef struct {
(overrides->x_cache_detail_set == 0)
? base->x_cache_detail
: overrides->x_cache_detail;
+ ps->base_uri =
+ (overrides->base_uri_set == 0)
+ ? base->base_uri
+ : overrides->base_uri;
return ps;
}
return NULL;
}
+static const char *set_cache_key_base_url(cmd_parms *parms, void *dummy,
+ const char *arg)
+{
+ cache_server_conf *conf;
+ apr_status_t rv;
+
+ conf =
+ (cache_server_conf *)ap_get_module_config(parms->server->module_config,
+ &cache_module);
+ conf->base_uri = apr_pcalloc(parms->pool, sizeof(apr_uri_t));
+ rv = apr_uri_parse(parms->pool, arg, conf->base_uri);
+ if (rv != APR_SUCCESS) {
+ return apr_psprintf(parms->pool, "Could not parse '%s' as an URL.", arg);
+ }
+ else if (!conf->base_uri->scheme && !conf->base_uri->hostname &&
+ !conf->base_uri->port_str) {
+ return apr_psprintf(parms->pool, "URL '%s' must contain at least one of a scheme, a hostname or a port.", arg);
+ }
+ conf->base_uri_set = 1;
+ return NULL;
+}
+
static int cache_post_config(apr_pool_t *p, apr_pool_t *plog,
apr_pool_t *ptemp, server_rec *s)
{
AP_INIT_FLAG("CacheDetailHeader", set_cache_x_cache_detail, NULL,
RSRC_CONF | ACCESS_CONF,
"Add a X-Cache-Detail header to responses. Default is off."),
+ AP_INIT_TAKE1("CacheKeyBaseURL", set_cache_key_base_url, NULL, RSRC_CONF,
+ "Override the base URL of reverse proxied cache keys."),
{NULL}
};