1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "http_config.h"
19 #include "http_request.h"
20 #include "http_connection.h"
21 #include "http_protocol.h"
23 #include "http_core.h"
24 #include "util_filter.h"
25 #define APR_WANT_STRFUNC
26 #include "apr_strings.h"
27 #include "apr_version.h"
29 module AP_MODULE_DECLARE_DATA reqtimeout_module;
32 #define MRT_DEFAULT_HEADER_TIMEOUT 20
33 #define MRT_DEFAULT_HEADER_MAX_TIMEOUT 40
34 #define MRT_DEFAULT_HEADER_MIN_RATE 500
35 #define MRT_DEFAULT_BODY_TIMEOUT 20
36 #define MRT_DEFAULT_BODY_MAX_TIMEOUT 0
37 #define MRT_DEFAULT_BODY_MIN_RATE 500
41 int header_timeout; /* timeout for reading the req hdrs in secs */
42 int header_max_timeout; /* max timeout for req hdrs in secs */
43 int header_min_rate; /* min rate for reading req hdrs in bytes/s */
44 apr_time_t header_rate_factor;
45 int body_timeout; /* timeout for reading the req body in secs */
46 int body_max_timeout; /* max timeout for req body in secs */
47 int body_min_rate; /* min rate for reading req body in bytes/s */
48 apr_time_t body_rate_factor;
51 /* this struct is used both as conn_config and as filter context */
54 apr_time_t timeout_at;
55 apr_time_t max_timeout_at;
62 apr_time_t rate_factor;
63 apr_bucket_brigade *tmpbb;
66 static const char *const reqtimeout_filter_name = "reqtimeout";
67 static int default_header_rate_factor;
68 static int default_body_rate_factor;
70 static void extend_timeout(reqtimeout_con_cfg *ccfg, apr_bucket_brigade *bb)
73 apr_time_t new_timeout_at;
75 if (apr_brigade_length(bb, 0, &len) != APR_SUCCESS || len <= 0)
78 new_timeout_at = ccfg->timeout_at + len * ccfg->rate_factor;
79 if (ccfg->max_timeout_at > 0 && new_timeout_at > ccfg->max_timeout_at) {
80 ccfg->timeout_at = ccfg->max_timeout_at;
83 ccfg->timeout_at = new_timeout_at;
87 static apr_status_t check_time_left(reqtimeout_con_cfg *ccfg,
88 apr_time_t *time_left_p,
93 *time_left_p = ccfg->timeout_at - now;
94 if (*time_left_p <= 0)
97 if (*time_left_p < apr_time_from_sec(1)) {
98 *time_left_p = apr_time_from_sec(1);
103 static apr_status_t have_lf_or_eos(apr_bucket_brigade *bb)
105 apr_bucket *b = APR_BRIGADE_LAST(bb);
107 for ( ; b != APR_BRIGADE_SENTINEL(bb) ; b = APR_BUCKET_PREV(b) ) {
112 if (APR_BUCKET_IS_EOS(b))
115 if (APR_BUCKET_IS_METADATA(b))
118 rv = apr_bucket_read(b, &str, &len, APR_BLOCK_READ);
119 if (rv != APR_SUCCESS)
125 if (str[len-1] == APR_ASCII_LF)
128 return APR_INCOMPLETE;
132 * Append bbIn to bbOut and merge small buckets, to avoid DoS by high memory
135 static apr_status_t brigade_append(apr_bucket_brigade *bbOut, apr_bucket_brigade *bbIn)
137 while (!APR_BRIGADE_EMPTY(bbIn)) {
138 apr_bucket *e = APR_BRIGADE_FIRST(bbIn);
143 rv = apr_bucket_read(e, &str, &len, APR_BLOCK_READ);
144 if (rv != APR_SUCCESS) {
148 APR_BUCKET_REMOVE(e);
149 if (APR_BUCKET_IS_METADATA(e) || len > APR_BUCKET_BUFF_SIZE/4) {
150 APR_BRIGADE_INSERT_TAIL(bbOut, e);
154 rv = apr_brigade_write(bbOut, NULL, NULL, str, len);
155 if (rv != APR_SUCCESS) {
156 apr_bucket_destroy(e);
160 apr_bucket_destroy(e);
167 #define MIN(x,y) ((x) < (y) ? (x) : (y))
168 static apr_status_t reqtimeout_filter(ap_filter_t *f,
169 apr_bucket_brigade *bb,
170 ap_input_mode_t mode,
171 apr_read_type_e block,
174 apr_time_t time_left;
177 apr_interval_time_t saved_sock_timeout = UNSET;
178 reqtimeout_con_cfg *ccfg = f->ctx;
180 if (block == APR_NONBLOCK_READ && mode == AP_MODE_SPECULATIVE) {
181 /* The source of these above us in the core is check_pipeline(), which
182 * is between requests but before this filter knows to reset timeouts
183 * during pre_read_request(). If they appear elsewhere, just don't
184 * check or extend the time since they won't block and we'll see the
187 return ap_get_brigade(f->next, bb, mode, block, readbytes);
190 if (ccfg->in_keep_alive) {
191 /* For this read[_request line()], wait for the first byte using the
192 * normal keep-alive timeout (hence don't take this expected idle time
193 * into account to setup the connection expiry below).
195 ccfg->in_keep_alive = 0;
196 rv = ap_get_brigade(f->next, bb, AP_MODE_SPECULATIVE, block, 1);
197 if (rv != APR_SUCCESS || APR_BRIGADE_EMPTY(bb)) {
200 apr_brigade_cleanup(bb);
203 if (ccfg->new_timeout > 0) {
204 /* set new timeout */
205 now = apr_time_now();
206 ccfg->timeout_at = now + apr_time_from_sec(ccfg->new_timeout);
207 ccfg->new_timeout = 0;
208 if (ccfg->new_max_timeout > 0) {
209 ccfg->max_timeout_at = now + apr_time_from_sec(ccfg->new_max_timeout);
210 ccfg->new_max_timeout = 0;
213 else if (ccfg->timeout_at == 0) {
215 return ap_get_brigade(f->next, bb, mode, block, readbytes);
219 ccfg->socket = ap_get_conn_socket(f->c);
222 rv = check_time_left(ccfg, &time_left, now);
223 if (rv != APR_SUCCESS)
226 if (block == APR_NONBLOCK_READ || mode == AP_MODE_INIT
227 || mode == AP_MODE_EATCRLF) {
228 rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
229 if (ccfg->min_rate > 0 && rv == APR_SUCCESS) {
230 extend_timeout(ccfg, bb);
235 rv = apr_socket_timeout_get(ccfg->socket, &saved_sock_timeout);
236 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
238 rv = apr_socket_timeout_set(ccfg->socket, MIN(time_left, saved_sock_timeout));
239 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
241 if (mode == AP_MODE_GETLINE) {
243 * For a blocking AP_MODE_GETLINE read, apr_brigade_split_line()
244 * would loop until a whole line has been read. As this would make it
245 * impossible to enforce a total timeout, we only do non-blocking
248 apr_off_t remaining = HUGE_STRING_LEN;
251 #if APR_MAJOR_VERSION < 2
253 apr_interval_time_t poll_timeout;
254 apr_pollfd_t pollset;
257 rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE, APR_NONBLOCK_READ, remaining);
258 if (rv != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(rv)) {
262 if (!APR_BRIGADE_EMPTY(bb)) {
263 if (ccfg->min_rate > 0) {
264 extend_timeout(ccfg, bb);
267 rv = have_lf_or_eos(bb);
268 if (rv != APR_INCOMPLETE) {
272 rv = apr_brigade_length(bb, 1, &bblen);
273 if (rv != APR_SUCCESS) {
277 if (remaining <= 0) {
281 /* Haven't got a whole line yet, save what we have ... */
283 ccfg->tmpbb = apr_brigade_create(f->c->pool, f->c->bucket_alloc);
285 rv = brigade_append(ccfg->tmpbb, bb);
286 if (rv != APR_SUCCESS)
290 /* ... and wait for more */
291 #if APR_MAJOR_VERSION < 2
292 pollset.p = f->c->pool;
293 pollset.desc_type = APR_POLL_SOCKET;
294 pollset.reqevents = APR_POLLIN|APR_POLLHUP;
295 pollset.desc.s = ccfg->socket;
296 apr_socket_timeout_get(ccfg->socket, &poll_timeout);
297 rv = apr_poll(&pollset, 1, &nsds, poll_timeout);
299 rv = apr_socket_wait(ccfg->socket, APR_WAIT_READ);
301 if (rv != APR_SUCCESS)
304 rv = check_time_left(ccfg, &time_left, 0);
305 if (rv != APR_SUCCESS)
308 rv = apr_socket_timeout_set(ccfg->socket,
309 MIN(time_left, saved_sock_timeout));
310 AP_DEBUG_ASSERT(rv == APR_SUCCESS);
315 APR_BRIGADE_PREPEND(bb, ccfg->tmpbb);
319 /* mode != AP_MODE_GETLINE */
320 rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
321 /* Don't extend the timeout in speculative mode, wait for
322 * the real (relevant) bytes to be asked later, within the
323 * currently alloted time.
325 if (ccfg->min_rate > 0 && rv == APR_SUCCESS
326 && mode != AP_MODE_SPECULATIVE) {
327 extend_timeout(ccfg, bb);
331 apr_socket_timeout_set(ccfg->socket, saved_sock_timeout);
334 if (APR_STATUS_IS_TIMEUP(rv)) {
335 ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c, APLOGNO(01382)
336 "Request %s read timeout", ccfg->type);
338 * If we allow a normal lingering close, the client may keep this
339 * process/thread busy for another 30s (MAX_SECS_TO_LINGER).
340 * Therefore we tell ap_lingering_close() to shorten this period to
341 * 2s (SECONDS_TO_LINGER).
343 apr_table_setn(f->c->notes, "short-lingering-close", "1");
346 * Also, we must not allow keep-alive requests, as
347 * ap_finalize_protocol() may ignore our error status (if the timeout
348 * happened on a request body that is discarded).
350 f->c->keepalive = AP_CONN_CLOSE;
355 static int reqtimeout_init(conn_rec *c)
357 reqtimeout_con_cfg *ccfg;
358 reqtimeout_srv_cfg *cfg;
360 cfg = ap_get_module_config(c->base_server->module_config,
362 AP_DEBUG_ASSERT(cfg != NULL);
363 if (cfg->header_timeout == 0 && cfg->body_timeout == 0) {
364 /* disabled for this vhost */
368 ccfg = ap_get_module_config(c->conn_config, &reqtimeout_module);
370 ccfg = apr_pcalloc(c->pool, sizeof(reqtimeout_con_cfg));
371 ap_set_module_config(c->conn_config, &reqtimeout_module, ccfg);
372 ap_add_input_filter(reqtimeout_filter_name, ccfg, NULL, c);
375 /* we are not handling the connection, we just do initialization */
379 static void reqtimeout_before_header(request_rec *r, conn_rec *c)
381 reqtimeout_srv_cfg *cfg;
382 reqtimeout_con_cfg *ccfg =
383 ap_get_module_config(c->conn_config, &reqtimeout_module);
386 /* not configured for this connection */
390 cfg = ap_get_module_config(c->base_server->module_config,
392 AP_DEBUG_ASSERT(cfg != NULL);
394 /* (Re)set the state for this new request, but ccfg->socket and
395 * ccfg->tmpbb which have the lifetime of the connection.
397 ccfg->timeout_at = 0;
398 ccfg->max_timeout_at = 0;
399 ccfg->in_keep_alive = (c->keepalives > 0);
400 ccfg->type = "header";
401 if (cfg->header_timeout != UNSET) {
402 ccfg->new_timeout = cfg->header_timeout;
403 ccfg->new_max_timeout = cfg->header_max_timeout;
404 ccfg->min_rate = cfg->header_min_rate;
405 ccfg->rate_factor = cfg->header_rate_factor;
408 ccfg->new_timeout = MRT_DEFAULT_HEADER_TIMEOUT;
409 ccfg->new_max_timeout = MRT_DEFAULT_HEADER_MAX_TIMEOUT;
410 ccfg->min_rate = MRT_DEFAULT_HEADER_MIN_RATE;
411 ccfg->rate_factor = default_header_rate_factor;
415 static int reqtimeout_before_body(request_rec *r)
417 reqtimeout_srv_cfg *cfg;
418 reqtimeout_con_cfg *ccfg =
419 ap_get_module_config(r->connection->conn_config, &reqtimeout_module);
421 if (ccfg == NULL || r->method_number == M_CONNECT) {
422 /* either disabled for this connection or a CONNECT request */
425 cfg = ap_get_module_config(r->connection->base_server->module_config,
427 AP_DEBUG_ASSERT(cfg != NULL);
429 ccfg->timeout_at = 0;
430 ccfg->max_timeout_at = 0;
432 if (cfg->body_timeout != UNSET) {
433 ccfg->new_timeout = cfg->body_timeout;
434 ccfg->new_max_timeout = cfg->body_max_timeout;
435 ccfg->min_rate = cfg->body_min_rate;
436 ccfg->rate_factor = cfg->body_rate_factor;
439 ccfg->new_timeout = MRT_DEFAULT_BODY_TIMEOUT;
440 ccfg->new_max_timeout = MRT_DEFAULT_BODY_MAX_TIMEOUT;
441 ccfg->min_rate = MRT_DEFAULT_BODY_MIN_RATE;
442 ccfg->rate_factor = default_body_rate_factor;
447 static void *reqtimeout_create_srv_config(apr_pool_t *p, server_rec *s)
449 reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg));
451 cfg->header_timeout = UNSET;
452 cfg->header_max_timeout = UNSET;
453 cfg->header_min_rate = UNSET;
454 cfg->body_timeout = UNSET;
455 cfg->body_max_timeout = UNSET;
456 cfg->body_min_rate = UNSET;
461 #define MERGE_INT(cfg, b, a, val) cfg->val = (a->val == UNSET) ? b->val : a->val;
462 static void *reqtimeout_merge_srv_config(apr_pool_t *p, void *base_, void *add_)
464 reqtimeout_srv_cfg *base = base_;
465 reqtimeout_srv_cfg *add = add_;
466 reqtimeout_srv_cfg *cfg = apr_pcalloc(p, sizeof(reqtimeout_srv_cfg));
468 MERGE_INT(cfg, base, add, header_timeout);
469 MERGE_INT(cfg, base, add, header_max_timeout);
470 MERGE_INT(cfg, base, add, header_min_rate);
471 MERGE_INT(cfg, base, add, body_timeout);
472 MERGE_INT(cfg, base, add, body_max_timeout);
473 MERGE_INT(cfg, base, add, body_min_rate);
475 cfg->header_rate_factor = (cfg->header_min_rate == UNSET) ?
476 base->header_rate_factor : add->header_rate_factor;
477 cfg->body_rate_factor = (cfg->body_min_rate == UNSET) ?
478 base->body_rate_factor : add->body_rate_factor;
482 static const char *parse_int(apr_pool_t *p, const char *arg, int *val) {
484 *val = strtol(arg, &endptr, 10);
487 return apr_psprintf(p, "Value '%s' not numerical", endptr);
489 if (*endptr != '\0') {
490 return apr_psprintf(p, "Cannot parse '%s'", endptr);
493 return "Value must be non-negative";
498 static const char *set_reqtimeout_param(reqtimeout_srv_cfg *conf,
503 const char *ret = NULL;
504 char *rate_str = NULL, *initial_str, *max_str = NULL;
505 int rate = 0, initial = 0, max = 0;
506 enum { PARAM_HEADER, PARAM_BODY } type;
508 if (!strcasecmp(key, "header")) {
511 else if (!strcasecmp(key, "body")) {
515 return "Unknown RequestReadTimeout parameter";
518 if ((rate_str = ap_strcasestr(val, ",minrate="))) {
519 initial_str = apr_pstrndup(p, val, rate_str - val);
520 rate_str += strlen(",minrate=");
521 ret = parse_int(p, rate_str, &rate);
526 return "Minimum data rate must be larger than 0";
528 if ((max_str = strchr(initial_str, '-'))) {
530 ret = parse_int(p, max_str, &max);
535 ret = parse_int(p, initial_str, &initial);
538 if (ap_strchr_c(val, '-'))
539 return "Must set MinRate option if using timeout range";
540 ret = parse_int(p, val, &initial);
546 if (max && initial >= max) {
547 return "Maximum timeout must be larger than initial timeout";
550 if (type == PARAM_HEADER) {
551 conf->header_timeout = initial;
552 conf->header_max_timeout = max;
553 conf->header_min_rate = rate;
555 conf->header_rate_factor = apr_time_from_sec(1) / rate;
558 conf->body_timeout = initial;
559 conf->body_max_timeout = max;
560 conf->body_min_rate = rate;
562 conf->body_rate_factor = apr_time_from_sec(1) / rate;
567 static const char *set_reqtimeouts(cmd_parms *cmd, void *mconfig,
570 reqtimeout_srv_cfg *conf =
571 ap_get_module_config(cmd->server->module_config,
578 word = ap_getword_conf(cmd->temp_pool, &arg);
579 val = strchr(word, '=');
581 return "Invalid RequestReadTimeout parameter. Parameter must be "
582 "in the form 'key=value'";
587 err = set_reqtimeout_param(conf, cmd->pool, word, val);
590 return apr_psprintf(cmd->temp_pool, "RequestReadTimeout: %s=%s: %s",
598 static void reqtimeout_hooks(apr_pool_t *pool)
601 * mod_ssl is AP_FTYPE_CONNECTION + 5 and mod_reqtimeout needs to
602 * be called before mod_ssl. Otherwise repeated reads during the ssl
603 * handshake can prevent the timeout from triggering.
605 ap_register_input_filter(reqtimeout_filter_name, reqtimeout_filter, NULL,
606 AP_FTYPE_CONNECTION + 8);
609 * mod_reqtimeout needs to be called before ap_process_http_request (which
610 * is run at APR_HOOK_REALLY_LAST) but after all other protocol modules.
611 * This ensures that it only influences normal http connections and not
612 * e.g. mod_ftp. Also, if mod_reqtimeout used the pre_connection hook, it
613 * would be inserted on mod_proxy's backend connections.
615 ap_hook_process_connection(reqtimeout_init, NULL, NULL, APR_HOOK_LAST);
617 ap_hook_pre_read_request(reqtimeout_before_header, NULL, NULL,
619 ap_hook_post_read_request(reqtimeout_before_body, NULL, NULL,
622 #if MRT_DEFAULT_HEADER_MIN_RATE > 0
623 default_header_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_HEADER_MIN_RATE;
625 #if MRT_DEFAULT_BODY_MIN_RATE > 0
626 default_body_rate_factor = apr_time_from_sec(1) / MRT_DEFAULT_BODY_MIN_RATE;
630 static const command_rec reqtimeout_cmds[] = {
631 AP_INIT_RAW_ARGS("RequestReadTimeout", set_reqtimeouts, NULL, RSRC_CONF,
632 "Set various timeout parameters for reading request "
637 AP_DECLARE_MODULE(reqtimeout) = {
638 STANDARD20_MODULE_STUFF,
639 NULL, /* create per-dir config structures */
640 NULL, /* merge per-dir config structures */
641 reqtimeout_create_srv_config, /* create per-server config structures */
642 reqtimeout_merge_srv_config, /* merge per-server config structures */
643 reqtimeout_cmds, /* table of config file commands */