home *** CD-ROM | disk | FTP | other *** search
- Date: Thu, 5 Feb 1998 12:01:21 -0800 (PST)
- From: Ed Korthof <ed@organic.com>
- To: new-httpd@apache.org
- Subject: [PATCH] http_protocol (was Re: case insensitive, multi-line headers)
-
- Sorry 'bout missing the case-insensitivity & the way multi-line headers
- are handled. <rueful>
-
- I'd like to fix the actual bugs Marc and Dean described, as I have some
- free time on my hands.
-
- So far as fixing the 408 -> 414 problem, we could set the status to
- HTTP_OK if it's currently 408 (we'd just do this in the sections where
- we're reading headers and we're about to return a 414 error to the client
- anyway, so this wouldn't mess up other parts of the code & vice versa),
- and then die() with an appropriate error. So far as I can see, it really
- is true that other than timeouts and the potential to return an error
- while reading the headers, there's no way we'll have to worry about
- r->status being set to HTTP_REQUEST_TIME_OUT.
-
- There are, of course, other ways to do the HTTP_REQUEST_TIME_OUT thing,
- and perhaps it'd be worthwhile to change it. I dunno. Each of the other
- solutions I heard when we last went over this had it's own set of
- problems...
-
- Anyway, I put together a patch to fix some the problems Marc described
- (without changing how we handle HTTP_REQUEST_TIME_OUT) and the one Dean
- described. So far as the latter problem is concerned, I wrote the patch
- to keep pulling data and discard it. It'd certainly also be possible to
- have it return a 400 error or pull in all the data and then combine it;
- I'd be happy to reimplement this either of those ways.
-
- In this patch, I have set it up to log failures in the access log as well
- as in the error log. Also, if run_post_read_request() returned something,
- the request would be killed (via die()), but it wouldn't be logged. I've
- changed that as well... it seems we should log such stuff.
- Clients who trigger 400, 408, and 414 errors generally don't see the error
- itself, though it will be logged. That might be worth fixing...
-
- Comments are welcome, as always.
-
- This is only lightly tested, though it does appear to work fine.
-
- -- Ed Korthof | Web Server Engineer --
- -- ed@organic.com | Organic Online, Inc --
- -- (415) 278-5676 | Fax: (415) 284-6891 --
-
- On Wed, 4 Feb 1998, Marc Slemko wrote:
-
- > Yes. This is mixed in with a bunch of other brokenness in this area (eg.
- > logging 408 (timeout) for a 414 (URI too large) that I ranted on a bit
- > ago. Unfortunately, I'm swamped right now. Sigh. Perhaps next year.
- >
- > On Wed, 4 Feb 1998, Dean Gaudet wrote:
- > > On Wed, 4 Feb 1998, Dean Gaudet wrote:
- > > > Look at getline() we handle multiline headers.
- > >
- > > Although there's an obvious bug. If there's a line that exceeds the
- > > buffer size then we bail without reading the rest of the line and any
- > > possible continuation lines. So we'll treat the rest of the line as if
- > > it's a new line. Bad.
- > >
- > > Dean
-
-
-
- Index: http_protocol.c
- ===================================================================
- RCS file: /export/home/cvs/apache-1.3/src/main/http_protocol.c,v
- retrieving revision 1.212
- diff -C3 -r1.212 http_protocol.c
- *** http_protocol.c 1998/04/27 06:59:35 1.212
- --- http_protocol.c 1998/05/06 00:07:41
- ***************
- *** 662,668 ****
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
- "request failed for %s, reason: URI too long",
- ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME));
- ! r->status = HTTP_REQUEST_URI_TOO_LARGE;
- return 0;
- }
-
- --- 662,672 ----
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
- "request failed for %s, reason: URI too long",
- ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME));
- ! /* hack to deal with the HTTP_REQUEST_TIME_OUT setting up above: */
- ! if (r->status == HTTP_REQUEST_TIME_OUT)
- ! r->status = HTTP_OK;
- ! r->request_time = time(NULL);
- ! ap_die (HTTP_REQUEST_URI_TOO_LARGE, r);
- return 0;
- }
-
- ***************
- *** 721,736 ****
- while ((len = getline(field, MAX_STRING_LEN, c->client, 1)) > 0) {
- char *copy = ap_palloc(r->pool, len + 1);
- memcpy(copy, field, len + 1);
-
- - if (!(value = strchr(copy, ':'))) /* Find the colon separator */
- - continue; /* or should puke 400 here */
- -
- *value = '\0';
- ++value;
- while (isspace(*value))
- ++value; /* Skip to start of value */
-
- ap_table_mergen(r->headers_in, copy, value);
- }
- }
-
- --- 725,757 ----
- while ((len = getline(field, MAX_STRING_LEN, c->client, 1)) > 0) {
- char *copy = ap_palloc(r->pool, len + 1);
- memcpy(copy, field, len + 1);
- +
- + if (!(value = strchr(copy, ':'))) { /* Find the colon separator */
- + /* if there's none, this request is screwed up.
- + * a hack to deal with how we set HTTP_REQUEST_TIME_OUT earlier.*/
- + if (r->status == HTTP_REQUEST_TIME_OUT)
- + r->status = HTTP_OK;
- +
- + ap_die (HTTP_BAD_REQUEST, r);
- + return;
- + }
-
- *value = '\0';
- ++value;
- while (isspace(*value))
- ++value; /* Skip to start of value */
-
- ap_table_mergen(r->headers_in, copy, value);
- +
- + /* the header was too long; at the least we should skip extra data */
- + if (len >= MAX_STRING_LEN - 1) {
- + char junk[MAX_STRING_LEN];
- + while ((len = getline(junk, MAX_STRING_LEN, c->client, 1))
- + >= MAX_STRING_LEN - 1) /* soak up the extra data */
- + ;
- + if (len == 0) /* time to exit the larger loop as well */
- + break;
- + }
- }
- }
-
- ***************
- *** 768,773 ****
- --- 789,795 ----
- r->read_body = REQUEST_NO_BODY;
-
- r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */
- + r->the_request = NULL;
-
- /* Get the request... */
-
- ***************
- *** 777,787 ****
- --- 799,820 ----
- ap_keepalive_timeout("read request line", r);
- if (!read_request_line(r)) {
- ap_kill_timeout(r);
- + if (r->status != HTTP_REQUEST_TIME_OUT) /* we must have had an error.*/
- + ap_log_transaction(r);
- return NULL;
- }
- if (!r->assbackwards) {
- ap_hard_timeout("read request headers", r);
- get_mime_headers(r);
- + if (r->status != HTTP_REQUEST_TIME_OUT) {/* we must have had an error.*/
- + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server,
- + "request failed for %s: error reading the headers",
- + ap_get_remote_host(r->connection, r->per_dir_config,
- + REMOTE_NAME));
- + ap_log_transaction(r);
- + return NULL;
- + }
- +
- }
- ap_kill_timeout(r);
-
- ***************
- *** 799,804 ****
- --- 832,839 ----
-
- if ((access_status = ap_run_post_read_request(r))) {
- ap_die(access_status, r);
- + ap_log_transaction(r);
- +
- return NULL;
- }
-
- ***************
- *** 1986,1992 ****
- * redirect URL. We don't really want to output this URL
- * as a text message, so first check the custom response
- * string to ensure that it is a text-string (using the
- ! * same test used in die(), i.e. does it start with a ").
- * If it doesn't, we've got a recursive error, so find
- * the original error and output that as well.
- */
- --- 2021,2027 ----
- * redirect URL. We don't really want to output this URL
- * as a text message, so first check the custom response
- * string to ensure that it is a text-string (using the
- ! * same test used in ap_die(), i.e. does it start with a ").
- * If it doesn't, we've got a recursive error, so find
- * the original error and output that as well.
- */
-