You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by so...@apache.org on 2018/07/18 20:23:05 UTC
[trafficserver] 01/02: Adds a new configuration
proxy.config.http.allow_multi_range
This is an automated email from the ASF dual-hosted git repository.
sorber pushed a commit to branch 6.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 92d93d26d15230b16e4dcdac387def49e622ce5c
Author: Leif Hedstrom <zw...@apache.org>
AuthorDate: Tue Feb 6 13:28:30 2018 -0800
Adds a new configuration proxy.config.http.allow_multi_range
This is needed to prevent potential abuse with well formed multi-
range requests.
(cherry picked from commit 3b48c5e42780b53c31445507fd05f8f54378efd1)
---
doc/admin-guide/files/records.config.en.rst | 16 +++++++
.../api/functions/TSHttpOverridableConfig.en.rst | 1 +
.../api/types/TSOverridableConfigKey.en.rst | 2 +
lib/ts/apidefs.h.in | 1 +
mgmt/RecordsConfig.cc | 2 +
plugins/experimental/ts_lua/ts_lua_http_config.c | 2 +
proxy/InkAPI.cc | 5 +++
proxy/InkAPITest.cc | 1 +
proxy/http/HttpConfig.cc | 2 +
proxy/http/HttpConfig.h | 2 +
proxy/http/HttpSM.cc | 49 ++++++++++++++++------
11 files changed, 71 insertions(+), 12 deletions(-)
diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
index 8ccbc86..126c452 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -1475,6 +1475,22 @@ Security
post body larger than this limit the response will be terminated with
413 - Request Entity Too Large and logged accordingly.
+.. ts:cv:: CONFIG proxy.config.http.allow_multi_range INT 1
+ :reloadable:
+ :overridable:
+
+ This option allows the administrator to configure different behavior and
+ handling of requests with multiple ranges in the ``Range`` header.
+
+ ===== ======================================================================
+ Value Description
+ ===== ======================================================================
+ ``0`` Do not allow multiple ranges, effectively ignoring the ``Range`` header
+ ``1`` Allows multiple ranges. This can be potentially dangerous since well
+ formed requests can cause excessive resource consumption on the server.
+ ``2`` Similar to 0, except return a 416 error code and no response body.
+ ===== ======================================================================
+
Cache Control
=============
diff --git a/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst b/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
index 1f4575f..98a6ed7 100644
--- a/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
+++ b/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
@@ -153,6 +153,7 @@ The following configurations (from ``records.config``) are overridable.
| :ts:cv:`proxy.config.http.cache.max_open_write_retries`
| :ts:cv:`proxy.config.http.redirect_use_orig_cache_key`
| :ts:cv:`proxy.config.http.parent_proxy.mark_down_hostdb`
+| :ts:cv:`proxy.config.http.allow_multi_range`
Examples
========
diff --git a/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst b/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
index abe1045..5470dbc 100644
--- a/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
+++ b/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
@@ -207,6 +207,8 @@ Enumeration Members
.. c:member:: TSOverridableConfigKey TS_CONFIG_LAST_ENTRY
+.. c:member:: TSOverridableConfigKey TS_CONFIG_HTTP_ALLOW_MULTI_RANGE
+
Description
===========
diff --git a/lib/ts/apidefs.h.in b/lib/ts/apidefs.h.in
index 7da895a..ceafb39 100644
--- a/lib/ts/apidefs.h.in
+++ b/lib/ts/apidefs.h.in
@@ -683,6 +683,7 @@ typedef enum {
TS_CONFIG_HTTP_PARENT_PROXY_TOTAL_CONNECT_ATTEMPTS,
TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_IN,
TS_CONFIG_PARENT_FAILURES_UPDATE_HOSTDB,
+ TS_CONFIG_HTTP_ALLOW_MULTI_RANGE,
TS_CONFIG_LAST_ENTRY
} TSOverridableConfigKey;
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index f310c17..5b29c90 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -611,6 +611,8 @@ static const RecordElement RecordsConfig[] =
,
{RECT_CONFIG, "proxy.config.http.normalize_ae_gzip", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-1]", RECA_NULL}
,
+ {RECT_CONFIG, "proxy.config.http.allow_multi_range", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-2]", RECA_NULL}
+ ,
// ####################################################
// # Global User-Agent header #
diff --git a/plugins/experimental/ts_lua/ts_lua_http_config.c b/plugins/experimental/ts_lua/ts_lua_http_config.c
index 70d692e..d93f7eb 100644
--- a/plugins/experimental/ts_lua/ts_lua_http_config.c
+++ b/plugins/experimental/ts_lua/ts_lua_http_config.c
@@ -120,6 +120,7 @@ typedef enum {
TS_LUA_CONFIG_HTTP_UNCACHEABLE_REQUESTS_BYPASS_PARENT = TS_CONFIG_HTTP_UNCACHEABLE_REQUESTS_BYPASS_PARENT,
TS_LUA_CONFIG_HTTP_PARENT_PROXY_TOTAL_CONNECT_ATTEMPTS = TS_CONFIG_HTTP_PARENT_PROXY_TOTAL_CONNECT_ATTEMPTS,
TS_LUA_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_IN = TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_IN,
+ TS_LUA_CONFIG_HTTP_ALLOW_MULTI_RANGE = TS_CONFIG_HTTP_ALLOW_MULTI_RANGE,
TS_LUA_CONFIG_LAST_ENTRY = TS_CONFIG_LAST_ENTRY,
TS_LUA_CONFIG_PARENT_FAILURES_UPDATE_HOSTDB = TS_CONFIG_PARENT_FAILURES_UPDATE_HOSTDB,
} TSLuaOverridableConfigKey;
@@ -234,6 +235,7 @@ ts_lua_var_item ts_lua_http_config_vars[] = {
TS_LUA_MAKE_VAR_ITEM(TS_LUA_CONFIG_HTTP_PARENT_PROXY_TOTAL_CONNECT_ATTEMPTS),
TS_LUA_MAKE_VAR_ITEM(TS_LUA_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_IN),
TS_LUA_MAKE_VAR_ITEM(TS_LUA_CONFIG_PARENT_FAILURES_UPDATE_HOSTDB),
+ TS_LUA_MAKE_VAR_ITEM(TS_LUA_CONFIG_HTTP_ALLOW_MULTI_RANGE),
TS_LUA_MAKE_VAR_ITEM(TS_LUA_CONFIG_LAST_ENTRY),
};
diff --git a/proxy/InkAPI.cc b/proxy/InkAPI.cc
index 26326a4..4827f35 100644
--- a/proxy/InkAPI.cc
+++ b/proxy/InkAPI.cc
@@ -7986,6 +7986,9 @@ _conf_to_memberp(TSOverridableConfigKey conf, OverridableHttpConfigParams *overr
case TS_CONFIG_PARENT_FAILURES_UPDATE_HOSTDB:
ret = &overridableHttpConfig->parent_failures_update_hostdb;
break;
+ case TS_CONFIG_HTTP_ALLOW_MULTI_RANGE:
+ ret = &overridableHttpConfig->allow_multi_range;
+ break;
// This helps avoiding compiler warnings, yet detect unhandled enum members.
case TS_CONFIG_NULL:
case TS_CONFIG_LAST_ENTRY:
@@ -8225,6 +8228,8 @@ TSHttpTxnConfigFind(const char *name, int length, TSOverridableConfigKey *conf,
case 'e':
if (!strncmp(name, "proxy.config.http.cache.range.write", length))
cnf = TS_CONFIG_HTTP_CACHE_RANGE_WRITE;
+ else if (!strncmp(name, "proxy.config.http.allow_multi_range", length))
+ cnf = TS_CONFIG_HTTP_ALLOW_MULTI_RANGE;
break;
case 'p':
if (!strncmp(name, "proxy.config.http.normalize_ae_gzip", length))
diff --git a/proxy/InkAPITest.cc b/proxy/InkAPITest.cc
index edbe44e..0694e4e 100644
--- a/proxy/InkAPITest.cc
+++ b/proxy/InkAPITest.cc
@@ -7489,6 +7489,7 @@ const char *SDK_Overridable_Configs[TS_CONFIG_LAST_ENTRY] = {
"proxy.config.http.parent_proxy.total_connect_attempts",
"proxy.config.http.transaction_active_timeout_in",
"proxy.config.http.parent_proxy.mark_down_hostdb",
+ "proxy.config.http.allow_multi_range",
};
REGRESSION_TEST(SDK_API_OVERRIDABLE_CONFIGS)(RegressionTest *test, int /* atype ATS_UNUSED */, int *pstatus)
diff --git a/proxy/http/HttpConfig.cc b/proxy/http/HttpConfig.cc
index ec5b0b9..82df56d 100644
--- a/proxy/http/HttpConfig.cc
+++ b/proxy/http/HttpConfig.cc
@@ -1069,6 +1069,7 @@ HttpConfig::startup()
HttpEstablishStaticConfigByte(c.record_cop_page, "proxy.config.http.record_heartbeat");
HttpEstablishStaticConfigByte(c.oride.send_http11_requests, "proxy.config.http.send_http11_requests");
+ HttpEstablishStaticConfigByte(c.oride.allow_multi_range, "proxy.config.http.allow_multi_range");
// HTTP Referer Filtering
HttpEstablishStaticConfigByte(c.referer_filter_enabled, "proxy.config.http.referer_filter");
@@ -1322,6 +1323,7 @@ HttpConfig::reconfigure()
params->oride.cache_required_headers = m_master.oride.cache_required_headers;
params->oride.cache_range_lookup = INT_TO_BOOL(m_master.oride.cache_range_lookup);
params->oride.cache_range_write = INT_TO_BOOL(m_master.oride.cache_range_write);
+ params->oride.allow_multi_range = m_master.oride.allow_multi_range;
params->connect_ports_string = ats_strdup(m_master.connect_ports_string);
params->connect_ports = parse_ports_list(params->connect_ports_string);
diff --git a/proxy/http/HttpConfig.h b/proxy/http/HttpConfig.h
index 0766013..db9a42d 100644
--- a/proxy/http/HttpConfig.h
+++ b/proxy/http/HttpConfig.h
@@ -397,6 +397,7 @@ struct OverridableHttpConfigParams {
cache_required_headers(2),
cache_range_lookup(1),
cache_range_write(0),
+ allow_multi_range(1),
insert_request_via_string(1),
insert_response_via_string(0),
doc_in_cache_skip_dns(1),
@@ -538,6 +539,7 @@ struct OverridableHttpConfigParams {
MgmtByte cache_required_headers;
MgmtByte cache_range_lookup;
MgmtByte cache_range_write;
+ MgmtByte allow_multi_range;
MgmtByte insert_request_via_string;
MgmtByte insert_response_via_string;
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index a47da7a..e2b4355 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -4405,24 +4405,49 @@ HttpSM::do_range_setup_if_necessary()
do_range_parse(field);
if (t_state.range_setup == HttpTransact::RANGE_REQUESTED) {
+ bool do_transform = false;
+
if (!t_state.range_in_cache) {
Debug("http_range", "range can't be satisifed from cache, force origin request");
t_state.cache_lookup_result = HttpTransact::CACHE_LOOKUP_MISS;
return;
}
- // if only one range entry and pread is capable, no need transform range
- if (t_state.num_range_fields == 1 && cache_sm.cache_read_vc->is_pread_capable()) {
- t_state.range_setup = HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED;
- } else if (api_hooks.get(TS_HTTP_RESPONSE_TRANSFORM_HOOK) == NULL) {
- Debug("http_trans", "Unable to accelerate range request, fallback to transform");
- content_type = t_state.cache_info.object_read->response_get()->value_get(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE,
- &field_content_type_len);
- // create a Range: transform processor for requests of type Range: bytes=1-2,4-5,10-100 (eg. multiple ranges)
- range_trans = transformProcessor.range_transform(mutex, t_state.ranges, t_state.num_range_fields,
- &t_state.hdr_info.transform_response, content_type, field_content_type_len,
- t_state.cache_info.object_read->object_size_get());
- api_hooks.append(TS_HTTP_RESPONSE_TRANSFORM_HOOK, range_trans);
+ if (t_state.num_range_fields > 1) {
+ if (0 == t_state.txn_conf->allow_multi_range) {
+ t_state.range_setup = HttpTransact::RANGE_NONE; // No Range required (not allowed)
+ t_state.hdr_info.client_request.field_delete(MIME_FIELD_RANGE, MIME_LEN_RANGE); // ... and nuke the Range header too
+ t_state.num_range_fields = 0;
+ } else if (1 == t_state.txn_conf->allow_multi_range) {
+ do_transform = true;
+ } else {
+ t_state.num_range_fields = 0;
+ t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
+ }
+ } else {
+ if (cache_sm.cache_read_vc->is_pread_capable()) {
+ // If only one range entry and pread is capable, no need transform range
+ t_state.range_setup = HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED;
+ } else {
+ do_transform = true;
+ }
+ }
+
+ // We have to do the transform on (allowed) multi-range request, *or* if the VC is not pread capable
+ if (do_transform) {
+ if (api_hooks.get(TS_HTTP_RESPONSE_TRANSFORM_HOOK) == nullptr) {
+ Debug("http_trans", "Unable to accelerate range request, fallback to transform");
+ content_type = t_state.cache_info.object_read->response_get()->value_get(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE,
+ &field_content_type_len);
+ // create a Range: transform processor for requests of type Range: bytes=1-2,4-5,10-100 (eg. multiple ranges)
+ range_trans = transformProcessor.range_transform(
+ mutex, t_state.ranges, t_state.num_range_fields, &t_state.hdr_info.transform_response, content_type,
+ field_content_type_len, t_state.cache_info.object_read->object_size_get());
+ api_hooks.append(TS_HTTP_RESPONSE_TRANSFORM_HOOK, range_trans);
+ } else {
+ // ToDo: Do we do something here? The theory is that multiple transforms do not behave well with
+ // the range transform needed here.
+ }
}
}
}