Loading CHANGES +3 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ Changes with Apache 2.3.15 core: Fix integer overflow in ap_pregsub. This can be triggered e.g. with mod_setenvif via a malicious .htaccess. [Stefan Fritsch] *) mod_reqtimeout: Change the default to set some reasonable timeout values. [Stefan Fritsch] *) core, mod_dav_fs: Change default ETag to be "size mtime", i.e. remove the inode. PR 49623. [Stefan Fritsch] Loading docs/conf/extra/httpd-default.conf.in +15 −0 Original line number Diff line number Diff line Loading @@ -73,3 +73,18 @@ ServerSignature Off # nameserver. # HostnameLookups Off # # Set a timeout for how long the client may take to send the request header # and body. # The default for the headers is header=20-40,MinRate=500, which means wait # for the first byte of headers for 20 seconds. If some data arrives, # increase the timeout corresponding to a data rate of 500 bytes/s, but not # above 40 seconds. # The default for the request body is body=20,MinRate=500, which is the same # but has no upper limit for the timeout. # To disable, set to header=0 body=0 # <IfModule reqtimeout_module> RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500 </IfModule> docs/manual/mod/mod_reqtimeout.xml +13 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ <status>Extension</status> <sourcefile>mod_reqtimeout.c</sourcefile> <identifier>reqtimeout_module</identifier> <compatibility>Available in Apache 2.2.15 and later</compatibility> <compatibility>Available in Apache HTTPD 2.2.15 and later</compatibility> <section id="examples"><title>Examples</title> Loading Loading @@ -83,12 +83,14 @@ <description>Set timeout values for receiving request headers and body from client. </description> <syntax>RequestReadTimeout [header=<var>timeout</var>[[-<var>maxtimeout</var>],MinRate=<var>rate</var>] [body=<var>timeout</var>[[-<var>maxtimeout</var>],MinRate=<var>rate</var>] [header=<var>timeout</var>[-<var>maxtimeout</var>][,MinRate=<var>rate</var>] [body=<var>timeout</var>[-<var>maxtimeout</var>][,MinRate=<var>rate</var>] </syntax> <default>Unset; no limit</default> <default>header=20-40,MinRate=500 body=20,MinRate=500</default> <contextlist><context>server config</context><context>virtual host</context> </contextlist> <compatibility>Available in version 2.2.15 and later; defaulted to disabled in version 2.3.14 and earlier.</compatibility> <usage> <p>This directive can set various timeouts for receiving the request headers Loading Loading @@ -126,6 +128,13 @@ body, respectively. A value of 0 means no limit.</p> </li> <li><strong>Disable module for a vhost:</strong>:<br /> <example>header=0 body=0</example> <p>This disables <module>mod_reqtimeout</module> completely.</p> </li> <li><strong>Timeout value that is increased when data is received</strong>:<br /> <example> Loading docs/manual/upgrading.xml +3 −0 Original line number Diff line number Diff line Loading @@ -269,6 +269,9 @@ limited to 1MB. </li> <li><module>mod_reqtimeout</module>: If the module is loaded, it will now set some default timeouts.</li> </ul> </section> </section> Loading modules/filters/mod_reqtimeout.c +68 −33 Original line number Diff line number Diff line Loading @@ -28,6 +28,14 @@ module AP_MODULE_DECLARE_DATA reqtimeout_module; #define UNSET -1 #define MRT_DEFAULT_HEADER_TIMEOUT 20 #define MRT_DEFAULT_HEADER_MAX_TIMEOUT 40 #define MRT_DEFAULT_HEADER_MIN_RATE 500 #define MRT_DEFAULT_BODY_TIMEOUT 20 #define MRT_DEFAULT_BODY_MAX_TIMEOUT 0 #define MRT_DEFAULT_BODY_MIN_RATE 500 typedef struct { int header_timeout; /* timeout for reading the req hdrs in secs */ Loading Loading @@ -56,6 +64,8 @@ typedef struct } reqtimeout_con_cfg; static const char *const reqtimeout_filter_name = "reqtimeout"; static int default_header_rate_factor; static int default_body_rate_factor; static void extend_timeout(reqtimeout_con_cfg *ccfg, apr_bucket_brigade *bb) { Loading Loading @@ -161,7 +171,7 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f, apr_time_t time_left; apr_time_t now; apr_status_t rv; apr_interval_time_t saved_sock_timeout = -1; apr_interval_time_t saved_sock_timeout = UNSET; reqtimeout_con_cfg *ccfg = f->ctx; if (ccfg->in_keep_alive) { Loading Loading @@ -325,17 +335,25 @@ static int reqtimeout_init(conn_rec *c) cfg = ap_get_module_config(c->base_server->module_config, &reqtimeout_module); AP_DEBUG_ASSERT(cfg != NULL); if (cfg->header_timeout <= 0 && cfg->body_timeout <= 0) { /* not configured for this vhost */ if (cfg->header_timeout == 0 && cfg->body_timeout == 0) { /* disabled for this vhost */ return DECLINED; } ccfg = apr_pcalloc(c->pool, sizeof(reqtimeout_con_cfg)); ccfg->type = "header"; if (cfg->header_timeout != UNSET) { ccfg->new_timeout = cfg->header_timeout; ccfg->new_max_timeout = cfg->header_max_timeout; ccfg->type = "header"; ccfg->min_rate = cfg->header_min_rate; ccfg->rate_factor = cfg->header_rate_factor; } else { ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT; ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT; ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE; ccfg->rate_factor = default_header_rate_factor; } ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg); ap_add_input_filter("reqtimeout", ccfg, NULL, c); Loading @@ -349,25 +367,29 @@ static int reqtimeout_after_headers(request_rec *r) reqtimeout_con_cfg *ccfg = ap_get_module_config(r->connection->conn_config, &reqtimeout_module); if (ccfg == NULL) { /* not configured for this connection */ if (ccfg == NULL || r->method_number == M_CONNECT) { /* either disabled for this connection or a CONNECT request */ return OK; } cfg = ap_get_module_config(r->connection->base_server->module_config, &reqtimeout_module); AP_DEBUG_ASSERT(cfg != NULL); ccfg->timeout_at = 0; ccfg->max_timeout_at = 0; if (r->method_number != M_CONNECT) { ccfg->type = "body"; if (cfg->body_timeout != UNSET) { ccfg->new_timeout = cfg->body_timeout; ccfg->new_max_timeout = cfg->body_max_timeout; ccfg->min_rate = cfg->body_min_rate; ccfg->rate_factor = cfg->body_rate_factor; ccfg->type = "body"; } else { ccfg->new_timeout = MRT_DEFAULT_BODY_TIMEOUT; ccfg->new_max_timeout = MRT_DEFAULT_BODY_MAX_TIMEOUT; ccfg->min_rate = MRT_DEFAULT_BODY_MIN_RATE; ccfg->rate_factor = default_body_rate_factor; } return OK; } Loading @@ -389,12 +411,19 @@ static int reqtimeout_after_body(request_rec *r) ccfg->timeout_at = 0; ccfg->max_timeout_at = 0; ccfg->in_keep_alive = 1; ccfg->type = "header"; if (ccfg->new_timeout != UNSET) { ccfg->new_timeout = cfg->header_timeout; ccfg->new_max_timeout = cfg->header_max_timeout; ccfg->min_rate = cfg->header_min_rate; ccfg->rate_factor = cfg->header_rate_factor; ccfg->type = "header"; } else { ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT; ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT; ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE; ccfg->rate_factor = default_header_rate_factor; } return OK; } Loading @@ -403,17 +432,17 @@ static void *reqtimeout_create_srv_config(apr_pool_t *p, server_rec *s) { reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg)); cfg->header_timeout = -1; cfg->header_max_timeout = -1; cfg->header_min_rate = -1; cfg->body_timeout = -1; cfg->body_max_timeout = -1; cfg->body_min_rate = -1; cfg->header_timeout = UNSET; cfg->header_max_timeout = UNSET; cfg->header_min_rate = UNSET; cfg->body_timeout = UNSET; cfg->body_max_timeout = UNSET; cfg->body_min_rate = UNSET; return cfg; } #define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == -1) ? b->val : a->val; #define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == UNSET) ? b->val : a->val; static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_) { reqtimeout_srv_cfg *base = base_; Loading @@ -427,11 +456,10 @@ static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_) MERGE_INT(cfg, base, add, body_max_timeout); MERGE_INT(cfg, base, add, body_min_rate); cfg->header_rate_factor = (cfg->header_min_rate == -1) ? base->header_rate_factor : add->header_rate_factor; cfg->body_rate_factor = (cfg->body_min_rate == -1) ? base->body_rate_factor : add->body_rate_factor; cfg->header_rate_factor = (cfg->header_min_rate == UNSET) ? base->header_rate_factor : add->header_rate_factor; cfg->body_rate_factor = (cfg->body_min_rate == UNSET) ? base->body_rate_factor : add->body_rate_factor; return cfg; } Loading Loading @@ -574,6 +602,13 @@ static void reqtimeout_hooks(apr_pool_t *pool) APR_HOOK_MIDDLE); ap_hook_log_transaction(reqtimeout_after_body, NULL, NULL, APR_HOOK_MIDDLE); #if MRT_DEFAULT_HEADER_MIN_RATE > 0 default_header_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_HEADER_MIN_RATE; #endif #if MRT_DEFAULT_BODY_MIN_RATE > 0 default_body_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_BODY_MIN_RATE; #endif } static const command_rec reqtimeout_cmds[] = { Loading Loading
CHANGES +3 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ Changes with Apache 2.3.15 core: Fix integer overflow in ap_pregsub. This can be triggered e.g. with mod_setenvif via a malicious .htaccess. [Stefan Fritsch] *) mod_reqtimeout: Change the default to set some reasonable timeout values. [Stefan Fritsch] *) core, mod_dav_fs: Change default ETag to be "size mtime", i.e. remove the inode. PR 49623. [Stefan Fritsch] Loading
docs/conf/extra/httpd-default.conf.in +15 −0 Original line number Diff line number Diff line Loading @@ -73,3 +73,18 @@ ServerSignature Off # nameserver. # HostnameLookups Off # # Set a timeout for how long the client may take to send the request header # and body. # The default for the headers is header=20-40,MinRate=500, which means wait # for the first byte of headers for 20 seconds. If some data arrives, # increase the timeout corresponding to a data rate of 500 bytes/s, but not # above 40 seconds. # The default for the request body is body=20,MinRate=500, which is the same # but has no upper limit for the timeout. # To disable, set to header=0 body=0 # <IfModule reqtimeout_module> RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500 </IfModule>
docs/manual/mod/mod_reqtimeout.xml +13 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ <status>Extension</status> <sourcefile>mod_reqtimeout.c</sourcefile> <identifier>reqtimeout_module</identifier> <compatibility>Available in Apache 2.2.15 and later</compatibility> <compatibility>Available in Apache HTTPD 2.2.15 and later</compatibility> <section id="examples"><title>Examples</title> Loading Loading @@ -83,12 +83,14 @@ <description>Set timeout values for receiving request headers and body from client. </description> <syntax>RequestReadTimeout [header=<var>timeout</var>[[-<var>maxtimeout</var>],MinRate=<var>rate</var>] [body=<var>timeout</var>[[-<var>maxtimeout</var>],MinRate=<var>rate</var>] [header=<var>timeout</var>[-<var>maxtimeout</var>][,MinRate=<var>rate</var>] [body=<var>timeout</var>[-<var>maxtimeout</var>][,MinRate=<var>rate</var>] </syntax> <default>Unset; no limit</default> <default>header=20-40,MinRate=500 body=20,MinRate=500</default> <contextlist><context>server config</context><context>virtual host</context> </contextlist> <compatibility>Available in version 2.2.15 and later; defaulted to disabled in version 2.3.14 and earlier.</compatibility> <usage> <p>This directive can set various timeouts for receiving the request headers Loading Loading @@ -126,6 +128,13 @@ body, respectively. A value of 0 means no limit.</p> </li> <li><strong>Disable module for a vhost:</strong>:<br /> <example>header=0 body=0</example> <p>This disables <module>mod_reqtimeout</module> completely.</p> </li> <li><strong>Timeout value that is increased when data is received</strong>:<br /> <example> Loading
docs/manual/upgrading.xml +3 −0 Original line number Diff line number Diff line Loading @@ -269,6 +269,9 @@ limited to 1MB. </li> <li><module>mod_reqtimeout</module>: If the module is loaded, it will now set some default timeouts.</li> </ul> </section> </section> Loading
modules/filters/mod_reqtimeout.c +68 −33 Original line number Diff line number Diff line Loading @@ -28,6 +28,14 @@ module AP_MODULE_DECLARE_DATA reqtimeout_module; #define UNSET -1 #define MRT_DEFAULT_HEADER_TIMEOUT 20 #define MRT_DEFAULT_HEADER_MAX_TIMEOUT 40 #define MRT_DEFAULT_HEADER_MIN_RATE 500 #define MRT_DEFAULT_BODY_TIMEOUT 20 #define MRT_DEFAULT_BODY_MAX_TIMEOUT 0 #define MRT_DEFAULT_BODY_MIN_RATE 500 typedef struct { int header_timeout; /* timeout for reading the req hdrs in secs */ Loading Loading @@ -56,6 +64,8 @@ typedef struct } reqtimeout_con_cfg; static const char *const reqtimeout_filter_name = "reqtimeout"; static int default_header_rate_factor; static int default_body_rate_factor; static void extend_timeout(reqtimeout_con_cfg *ccfg, apr_bucket_brigade *bb) { Loading Loading @@ -161,7 +171,7 @@ static apr_status_t reqtimeout_filter(ap_filter_t *f, apr_time_t time_left; apr_time_t now; apr_status_t rv; apr_interval_time_t saved_sock_timeout = -1; apr_interval_time_t saved_sock_timeout = UNSET; reqtimeout_con_cfg *ccfg = f->ctx; if (ccfg->in_keep_alive) { Loading Loading @@ -325,17 +335,25 @@ static int reqtimeout_init(conn_rec *c) cfg = ap_get_module_config(c->base_server->module_config, &reqtimeout_module); AP_DEBUG_ASSERT(cfg != NULL); if (cfg->header_timeout <= 0 && cfg->body_timeout <= 0) { /* not configured for this vhost */ if (cfg->header_timeout == 0 && cfg->body_timeout == 0) { /* disabled for this vhost */ return DECLINED; } ccfg = apr_pcalloc(c->pool, sizeof(reqtimeout_con_cfg)); ccfg->type = "header"; if (cfg->header_timeout != UNSET) { ccfg->new_timeout = cfg->header_timeout; ccfg->new_max_timeout = cfg->header_max_timeout; ccfg->type = "header"; ccfg->min_rate = cfg->header_min_rate; ccfg->rate_factor = cfg->header_rate_factor; } else { ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT; ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT; ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE; ccfg->rate_factor = default_header_rate_factor; } ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg); ap_add_input_filter("reqtimeout", ccfg, NULL, c); Loading @@ -349,25 +367,29 @@ static int reqtimeout_after_headers(request_rec *r) reqtimeout_con_cfg *ccfg = ap_get_module_config(r->connection->conn_config, &reqtimeout_module); if (ccfg == NULL) { /* not configured for this connection */ if (ccfg == NULL || r->method_number == M_CONNECT) { /* either disabled for this connection or a CONNECT request */ return OK; } cfg = ap_get_module_config(r->connection->base_server->module_config, &reqtimeout_module); AP_DEBUG_ASSERT(cfg != NULL); ccfg->timeout_at = 0; ccfg->max_timeout_at = 0; if (r->method_number != M_CONNECT) { ccfg->type = "body"; if (cfg->body_timeout != UNSET) { ccfg->new_timeout = cfg->body_timeout; ccfg->new_max_timeout = cfg->body_max_timeout; ccfg->min_rate = cfg->body_min_rate; ccfg->rate_factor = cfg->body_rate_factor; ccfg->type = "body"; } else { ccfg->new_timeout = MRT_DEFAULT_BODY_TIMEOUT; ccfg->new_max_timeout = MRT_DEFAULT_BODY_MAX_TIMEOUT; ccfg->min_rate = MRT_DEFAULT_BODY_MIN_RATE; ccfg->rate_factor = default_body_rate_factor; } return OK; } Loading @@ -389,12 +411,19 @@ static int reqtimeout_after_body(request_rec *r) ccfg->timeout_at = 0; ccfg->max_timeout_at = 0; ccfg->in_keep_alive = 1; ccfg->type = "header"; if (ccfg->new_timeout != UNSET) { ccfg->new_timeout = cfg->header_timeout; ccfg->new_max_timeout = cfg->header_max_timeout; ccfg->min_rate = cfg->header_min_rate; ccfg->rate_factor = cfg->header_rate_factor; ccfg->type = "header"; } else { ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT; ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT; ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE; ccfg->rate_factor = default_header_rate_factor; } return OK; } Loading @@ -403,17 +432,17 @@ static void *reqtimeout_create_srv_config(apr_pool_t *p, server_rec *s) { reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg)); cfg->header_timeout = -1; cfg->header_max_timeout = -1; cfg->header_min_rate = -1; cfg->body_timeout = -1; cfg->body_max_timeout = -1; cfg->body_min_rate = -1; cfg->header_timeout = UNSET; cfg->header_max_timeout = UNSET; cfg->header_min_rate = UNSET; cfg->body_timeout = UNSET; cfg->body_max_timeout = UNSET; cfg->body_min_rate = UNSET; return cfg; } #define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == -1) ? b->val : a->val; #define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == UNSET) ? b->val : a->val; static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_) { reqtimeout_srv_cfg *base = base_; Loading @@ -427,11 +456,10 @@ static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_) MERGE_INT(cfg, base, add, body_max_timeout); MERGE_INT(cfg, base, add, body_min_rate); cfg->header_rate_factor = (cfg->header_min_rate == -1) ? base->header_rate_factor : add->header_rate_factor; cfg->body_rate_factor = (cfg->body_min_rate == -1) ? base->body_rate_factor : add->body_rate_factor; cfg->header_rate_factor = (cfg->header_min_rate == UNSET) ? base->header_rate_factor : add->header_rate_factor; cfg->body_rate_factor = (cfg->body_min_rate == UNSET) ? base->body_rate_factor : add->body_rate_factor; return cfg; } Loading Loading @@ -574,6 +602,13 @@ static void reqtimeout_hooks(apr_pool_t *pool) APR_HOOK_MIDDLE); ap_hook_log_transaction(reqtimeout_after_body, NULL, NULL, APR_HOOK_MIDDLE); #if MRT_DEFAULT_HEADER_MIN_RATE > 0 default_header_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_HEADER_MIN_RATE; #endif #if MRT_DEFAULT_BODY_MIN_RATE > 0 default_body_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_BODY_MIN_RATE; #endif } static const command_rec reqtimeout_cmds[] = { Loading