Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.2
apache2
httpd-2.2.x-CVE-2011-3368-server_protocl_c.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File httpd-2.2.x-CVE-2011-3368-server_protocl_c.diff of Package apache2
diff -rNU 50 ../httpd-2.2.12-o/server/protocol.c ./server/protocol.c --- ../httpd-2.2.12-o/server/protocol.c 2011-10-26 15:08:02.000000000 +0200 +++ ./server/protocol.c 2011-10-26 15:08:13.000000000 +0200 @@ -590,100 +590,125 @@ apr_status_t rv; /* insure ap_rgetline allocates memory each time thru the loop * if there are empty lines */ r->the_request = NULL; rv = ap_rgetline(&(r->the_request), (apr_size_t)(r->server->limit_req_line + 2), &len, r, 0, bb); if (rv != APR_SUCCESS) { r->request_time = apr_time_now(); /* ap_rgetline returns APR_ENOSPC if it fills up the * buffer before finding the end-of-line. This is only going to * happen if it exceeds the configured limit for a request-line. */ if (rv == APR_ENOSPC) { r->status = HTTP_REQUEST_URI_TOO_LARGE; r->proto_num = HTTP_VERSION(1,0); r->protocol = apr_pstrdup(r->pool, "HTTP/1.0"); } return 0; } } while ((len <= 0) && (++num_blank_lines < max_blank_lines)); /* we've probably got something to do, ignore graceful restart requests */ r->request_time = apr_time_now(); ll = r->the_request; r->method = ap_getword_white(r->pool, &ll); #if 0 /* XXX If we want to keep track of the Method, the protocol module should do * it. That support isn't in the scoreboard yet. Hopefully next week * sometime. rbb */ ap_update_connection_status(AP_CHILD_THREAD_FROM_ID(conn->id), "Method", r->method); #endif uri = ap_getword_white(r->pool, &ll); /* Provide quick information about the request method as soon as known */ r->method_number = ap_method_number_of(r->method); if (r->method_number == M_GET && r->method[0] == 'H') { r->header_only = 1; } ap_parse_uri(r, uri); +/* + https://svn.apache.org/viewvc/httpd/httpd/trunk/server/protocol.c?r1=1178566&r2=1179239&pathrev=1179239&view=patch + This is the fix for CVE-2011-3368; via bnc#722545. + */ + + /* RFC 2616: + * Request-URI = "*" | absoluteURI | abs_path | authority + * + * authority is a special case for CONNECT. If the request is not + * using CONNECT, and the parsed URI does not have scheme, and + * it does not begin with '/', and it is not '*', then, fail + * and give a 400 response. */ + if (r->method_number != M_CONNECT + && !r->parsed_uri.scheme + && uri[0] != '/' + && !(uri[0] == '*' && uri[1] == '\0')) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "invalid request-URI %s", uri); + r->args = NULL; + r->hostname = NULL; + r->status = HTTP_BAD_REQUEST; + r->uri = apr_pstrdup(r->pool, uri); + return 0; + } + if (ll[0]) { r->assbackwards = 0; pro = ll; len = strlen(ll); } else { r->assbackwards = 1; pro = "HTTP/0.9"; len = 8; } r->protocol = apr_pstrmemdup(r->pool, pro, len); /* XXX ap_update_connection_status(conn->id, "Protocol", r->protocol); */ /* Avoid sscanf in the common case */ if (len == 8 && pro[0] == 'H' && pro[1] == 'T' && pro[2] == 'T' && pro[3] == 'P' && pro[4] == '/' && apr_isdigit(pro[5]) && pro[6] == '.' && apr_isdigit(pro[7])) { r->proto_num = HTTP_VERSION(pro[5] - '0', pro[7] - '0'); } else if (3 == sscanf(r->protocol, "%4s/%u.%u", http, &major, &minor) && (strcasecmp("http", http) == 0) && (minor < HTTP_VERSION(1, 0)) ) /* don't allow HTTP/0.1000 */ r->proto_num = HTTP_VERSION(major, minor); else r->proto_num = HTTP_VERSION(1, 0); return 1; } AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb) { char *last_field = NULL; apr_size_t last_len = 0; apr_size_t alloc_len = 0; char *field; char *value; apr_size_t len; int fields_read = 0; char *tmp_field; /* * Read header lines until we get the empty separator line, a read error, * the connection closes (EOF), reach the server limit, or we timeout. */ while(1) { apr_status_t rv; int folded = 0; field = NULL; @@ -842,103 +867,109 @@ int access_status; apr_bucket_brigade *tmp_bb; apr_socket_t *csd; apr_interval_time_t cur_timeout; apr_pool_create(&p, conn->pool); apr_pool_tag(p, "request"); r = apr_pcalloc(p, sizeof(request_rec)); r->pool = p; r->connection = conn; r->server = conn->base_server; r->user = NULL; r->ap_auth_type = NULL; r->allowed_methods = ap_make_method_list(p, 2); r->headers_in = apr_table_make(r->pool, 25); r->subprocess_env = apr_table_make(r->pool, 25); r->headers_out = apr_table_make(r->pool, 12); r->err_headers_out = apr_table_make(r->pool, 5); r->notes = apr_table_make(r->pool, 5); r->request_config = ap_create_request_config(r->pool); /* Must be set before we run create request hook */ r->proto_output_filters = conn->output_filters; r->output_filters = r->proto_output_filters; r->proto_input_filters = conn->input_filters; r->input_filters = r->proto_input_filters; ap_run_create_request(r); r->per_dir_config = r->server->lookup_defaults; r->sent_bodyct = 0; /* bytect isn't for body */ r->read_length = 0; r->read_body = REQUEST_NO_BODY; r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */ r->the_request = NULL; /* Begin by presuming any module can make its own path_info assumptions, * until some module interjects and changes the value. */ r->used_path_info = AP_REQ_DEFAULT_PATH_INFO; tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); /* Get the request... */ if (!read_request_line(r, tmp_bb)) { - if (r->status == HTTP_REQUEST_URI_TOO_LARGE) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + if (r->status == HTTP_REQUEST_URI_TOO_LARGE + || r->status == HTTP_BAD_REQUEST) { + if (r->status == HTTP_REQUEST_URI_TOO_LARGE) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "request failed: URI too long (longer than %d)", r->server->limit_req_line); + } else if (r->method == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "request failed: invalid characters in URI"); + } ap_send_error_response(r, 0); ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); ap_run_log_transaction(r); apr_brigade_destroy(tmp_bb); return r; } apr_brigade_destroy(tmp_bb); return NULL; } /* We may have been in keep_alive_timeout mode, so toggle back * to the normal timeout mode as we fetch the header lines, * as necessary. */ csd = ap_get_module_config(conn->conn_config, &core_module); apr_socket_timeout_get(csd, &cur_timeout); if (cur_timeout != conn->base_server->timeout) { apr_socket_timeout_set(csd, conn->base_server->timeout); cur_timeout = conn->base_server->timeout; } if (!r->assbackwards) { ap_get_mime_headers_core(r, tmp_bb); if (r->status != HTTP_REQUEST_TIME_OUT) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "request failed: error reading the headers"); ap_send_error_response(r, 0); ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); ap_run_log_transaction(r); apr_brigade_destroy(tmp_bb); return r; } if (apr_table_get(r->headers_in, "Transfer-Encoding") && apr_table_get(r->headers_in, "Content-Length")) { /* 2616 section 4.4, point 3: "if both Transfer-Encoding * and Content-Length are received, the latter MUST be * ignored"; so unset it here to prevent any confusion * later. */ apr_table_unset(r->headers_in, "Content-Length"); } } else { if (r->header_only) { /* * Client asked for headers only with HTTP/0.9, which doesn't send * headers! Have to dink things just to make sure the error message * comes through... */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor