diff options
Diffstat (limited to '')
-rw-r--r-- | include/ap_mmn.h | 4 | ||||
-rw-r--r-- | include/http_core.h | 7 | ||||
-rw-r--r-- | server/core.c | 54 | ||||
-rw-r--r-- | server/protocol.c | 27 |
4 files changed, 63 insertions, 29 deletions
diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 74dab7c32a..18827118c2 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -404,6 +404,8 @@ * 20120724.4 (2.5.0-dev) Add dirwalk_stat hook. * 20120724.5 (2.5.0-dev) Add ap_get_sload() and ap_get_loadavg(). * 20120724.6 (2.5.0-dev) Add sticky_separator to proxy_balancer_shared struct. + * 20120724.7 (2.5.0-dev) Add min_http_version/max_http_version to + * core_server_config */ #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */ @@ -411,7 +413,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120724 #endif -#define MODULE_MAGIC_NUMBER_MINOR 6 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 7 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_core.h b/include/http_core.h index bb1102aa83..ca480f01a2 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -664,10 +664,9 @@ typedef struct { #define AP_TRACE_EXTENDED 2 int trace_enable; -#define AP_HTTP09_UNSET 0 -#define AP_HTTP09_ENABLE 1 -#define AP_HTTP09_DISABLE 2 - char http09_enable; +#define AP_HTTP_VERSION_UNSET 0 + uint16_t min_http_version; + uint16_t max_http_version; } core_server_config; diff --git a/server/core.c b/server/core.c index 871c1c9750..c6c47d3360 100644 --- a/server/core.c +++ b/server/core.c @@ -502,8 +502,10 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv) if (virt->trace_enable != AP_TRACE_UNSET) conf->trace_enable = virt->trace_enable; - if (virt->http09_enable != AP_HTTP09_UNSET) - conf->http09_enable = virt->http09_enable; + if (virt->min_http_version != AP_HTTP_VERSION_UNSET) { + conf->min_http_version = virt->min_http_version; + conf->max_http_version = virt->max_http_version; + } /* no action for virt->accf_map, not allowed per-vhost */ @@ -3615,21 +3617,45 @@ static const char *set_trace_enable(cmd_parms *cmd, void *dummy, } static const char *set_http_protocol(cmd_parms *cmd, void *dummy, - const char *arg1) + const char *arg) { - core_server_config *conf = - ap_get_core_module_config(cmd->server->module_config); + core_server_config *conf; + conf = ap_get_core_module_config(cmd->server->module_config); + if (apr_isdigit(arg[0])) { + unsigned short min_major, min_minor, max_major, max_minor; + unsigned int min, max; + char ch; - if (strcmp(arg1, "+0.9") == 0) { - conf->http09_enable = AP_HTTP09_ENABLE; - } - else if (strcmp(arg1, "-0.9") == 0) { - conf->http09_enable = AP_HTTP09_DISABLE; + if (sscanf(arg, "%hu.%hu-%hu.%hu%c", &min_major, &min_minor, + &max_major, &max_minor, &ch) == 4) { + } + else if (sscanf(arg, "%hu.%hu%c", &min_major, &min_minor, &ch) == 2) { + max_major = min_major; + max_minor = min_minor; + } + else { + return "Protocol version must be in format a.b or a.b-c.d"; + } + if ( HTTP_VERSION(0, min_minor) >= HTTP_VERSION(1,0) + || HTTP_VERSION(0, max_minor) >= HTTP_VERSION(1,0)) { + return "HTTP minor version may not be more than 999"; + } + min = HTTP_VERSION(min_major, min_minor); + max = HTTP_VERSION(max_major, max_minor); + if (min > APR_UINT16_MAX || max > APR_UINT16_MAX) + return "HTTP major version may not be more than 64"; + if (min > max) + return "HTTP version range must be min-max"; + /* 0 is used for "unset", so make sure the min is larger */ + if (min < HTTP_VERSION(0,9)) + min = HTTP_VERSION(0,9); + conf->min_http_version = min; + conf->max_http_version = max; } else { - return "HttpProtocol must be one of '+0.9' and '-0.9'"; + return "Valid arguments are a version number (e.g. '1.1')" + "or a version range (e.g. '1.0-9.9')"; } - return NULL; } @@ -4141,8 +4167,8 @@ AP_INIT_TAKE1("EnableExceptionHook", ap_mpm_set_exception_hook, NULL, RSRC_CONF, #endif AP_INIT_TAKE1("TraceEnable", set_trace_enable, NULL, RSRC_CONF, "'on' (default), 'off' or 'extended' to trace request body content"), -AP_INIT_TAKE1("HttpProtocol", set_http_protocol, NULL, RSRC_CONF, - "'+0.9' (default) or '-0.9' to allow/deny HTTP/0.9"), +AP_INIT_ITERATE("HttpProtocol", set_http_protocol, NULL, RSRC_CONF, + "Allowed HTTP version or range (e.g. '1.1', '1.0-9.9'"), AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF, "Registers non-standard HTTP methods"), { NULL } diff --git a/server/protocol.c b/server/protocol.c index 2fa3895cbd..a3710a58f6 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -566,6 +566,8 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) apr_size_t len; int num_blank_lines = 0; int max_blank_lines = r->server->limit_req_fields; + core_server_config *conf = + ap_get_core_module_config(r->server->module_config); if (max_blank_lines <= 0) { max_blank_lines = DEFAULT_LIMIT_REQUEST_FIELDS; @@ -644,19 +646,9 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) pro = ll; len = strlen(ll); } else { - core_server_config *conf; - conf = ap_get_core_module_config(r->server->module_config); r->assbackwards = 1; pro = "HTTP/0.9"; len = 8; - if (conf->http09_enable == AP_HTTP09_DISABLE) { - r->status = HTTP_VERSION_NOT_SUPPORTED; - r->protocol = apr_pstrmemdup(r->pool, pro, len); - r->proto_num = HTTP_VERSION(0, 9); - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02401) - "HTTP/0.9 denied by server configuration"); - return 0; - } } r->protocol = apr_pstrmemdup(r->pool, pro, len); @@ -674,6 +666,21 @@ static int read_request_line(request_rec *r, apr_bucket_brigade *bb) else r->proto_num = HTTP_VERSION(1, 0); + if (conf->min_http_version != AP_HTTP_VERSION_UNSET + && ( conf->min_http_version > r->proto_num + || conf->max_http_version < r->proto_num)) { + r->status = HTTP_VERSION_NOT_SUPPORTED; + if (r->proto_num == HTTP_VERSION(0, 9)) { + /* If we deny 0.9, send error message with 1.x */ + r->assbackwards = 0; + } + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02401) + "HTTP/%d.%d denied by server configuration", + HTTP_VERSION_MAJOR(r->proto_num), + HTTP_VERSION_MINOR(r->proto_num)); + return 0; + } + return 1; } |