From: wessels <> Date: Tue, 31 Mar 1998 12:35:22 +0000 (+0000) Subject: new headersEnd() replaces mime_headers_end and eliminates buffer overruns X-Git-Tag: SQUID_3_0_PRE1~3683 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2334c19498e049e872a418808c532599df6e0fc5;p=thirdparty%2Fsquid.git new headersEnd() replaces mime_headers_end and eliminates buffer overruns --- diff --git a/src/client_side.cc b/src/client_side.cc index 4f329f4cb4..2d2a9ecea9 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.240 1998/03/31 03:57:15 wessels Exp $ + * $Id: client_side.cc,v 1.241 1998/03/31 05:35:22 wessels Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -52,7 +52,7 @@ static void CheckQuickAbort(clientHttpRequest *); static void checkFailureRatio(err_type, hier_code); static void clientProcessMiss(clientHttpRequest *); static void clientAppendReplyHeader(char *, const char *, size_t *, size_t); -size_t clientBuildReplyHeader(clientHttpRequest *, char *, size_t *, char *, size_t); +size_t clientBuildReplyHeader(clientHttpRequest *, char *, size_t, size_t *, char *, size_t); static clientHttpRequest *parseHttpRequest(ConnStateData *, method_t *, int *, char **, size_t *); static RH clientRedirectDone; static STCB clientHandleIMSReply; @@ -814,6 +814,7 @@ clientAppendReplyHeader(char *hdr, const char *line, size_t * sz, size_t max) size_t clientBuildReplyHeader(clientHttpRequest * http, char *hdr_in, + size_t hdr_in_sz, size_t * in_len, char *hdr_out, size_t out_sz) @@ -822,25 +823,25 @@ clientBuildReplyHeader(clientHttpRequest * http, char *xbuf; char *ybuf; char *t = NULL; - char *end = NULL; + char *end; size_t len = 0; size_t hdr_len = 0; size_t l; if (0 != strncmp(hdr_in, "HTTP/", 5)) return 0; - end = mime_headers_end(hdr_in); - if (end == NULL) { + hdr_len = headersEnd(hdr_in, hdr_in_sz); + if (hdr_len < 0) { debug(33, 3) ("clientBuildReplyHeader: DIDN'T FIND END-OF-HEADERS\n"); return 0; } xbuf = memAllocate(MEM_4K_BUF); ybuf = memAllocate(MEM_4K_BUF); + end = hdr_in + hdr_len; for (t = hdr_in; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) { - hdr_len = t - hdr_in; l = strcspn(t, crlf) + 1; xstrncpy(xbuf, t, l > 4096 ? 4096 : l); /* enforce 1.0 reply version, this hack will be rewritten */ - if (!hdr_len && !strncasecmp(xbuf, "HTTP/", 5) && l > 8 && + if (t == hdr_in && !strncasecmp(xbuf, "HTTP/", 5) && l > 8 && (isspace(xbuf[8]) || isspace(xbuf[9]))) xmemmove(xbuf + 5, "1.0 ", 4); #if DONT_FILTER_THESE @@ -866,7 +867,6 @@ clientBuildReplyHeader(clientHttpRequest * http, if (!handleConnectionHeader(1, no_forward, xbuf)) clientAppendReplyHeader(hdr_out, xbuf, &len, out_sz - 512); } - hdr_len = end - hdr_in; /* Append X-Cache: */ snprintf(ybuf, 4096, "X-Cache: %s from %s", isTcpHit(http->log_type) ? "HIT" : "MISS", @@ -922,14 +922,11 @@ clientSendMoreData(void *data, char *buf, ssize_t size) StoreEntry *entry = http->entry; ConnStateData *conn = http->conn; int fd = conn->fd; - char *p = NULL; size_t hdrlen; size_t l = 0; size_t writelen; char *newbuf; FREE *freefunc = memFree4K; - int hack = 0; - char C = '\0'; debug(33, 5) ("clientSendMoreData: %s, %d bytes\n", http->uri, (int) size); assert(size <= SM_PAGE_SIZE); assert(http->request != NULL); @@ -959,25 +956,16 @@ clientSendMoreData(void *data, char *buf, ssize_t size) writelen = size; if (http->out.offset == 0) { if (Config.onoff.log_mime_hdrs) { - if ((p = mime_headers_end(buf))) { + size_t k; + if ((k = headersEnd(buf, size))) { safe_free(http->al.headers.reply); - http->al.headers.reply = xcalloc(1 + p - buf, 1); - xstrncpy(http->al.headers.reply, buf, p - buf); + http->al.headers.reply = xcalloc(k+1, 1); + xstrncpy(http->al.headers.reply, buf, k); } } - /* make sure 'buf' is null terminated somewhere */ - if (size == SM_PAGE_SIZE) { - hack = 1; - size--; - C = *(buf + size); - } - *(buf + size) = '\0'; newbuf = memAllocate(MEM_8K_BUF); hdrlen = 0; - - l = clientBuildReplyHeader(http, buf, &hdrlen, newbuf, 8192); - if (hack) - *(buf + size++) = C; + l = clientBuildReplyHeader(http, buf, size, &hdrlen, newbuf, 8192); if (l != 0) { writelen = l + size - hdrlen; assert(writelen <= 8192); @@ -1019,9 +1007,9 @@ clientSendMoreData(void *data, char *buf, ssize_t size) * ick, this is gross */ if (http->request->method == METHOD_HEAD) { - if ((p = mime_headers_end(buf))) { - *p = '\0'; - writelen = p - buf; + size_t k; + if ((k = headersEnd(buf, size))) { + writelen = k; /* force end */ if (entry->store_status == STORE_PENDING) http->out.offset = entry->mem_obj->inmem_hi; @@ -1462,7 +1450,7 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, float http_ver; char *token = NULL; char *t = NULL; - char *end = NULL; + char *end; int free_request = 0; size_t header_sz; /* size of headers, not including first line */ size_t req_sz; /* size of whole request */ @@ -1556,20 +1544,24 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, } else http_ver = (float) atof(token + 5); + /* + * Skip whitespace at the end of the frist line, up to the + * first newline. + */ + while (isspace(*t)) + if (*(t++) == '\n') + break; + /* Check if headers are received */ - if ((end = mime_headers_end(t)) == NULL) { + header_sz = headersEnd(t, conn->in.offset); + if (0 == header_sz) { xfree(inbuf); *status = 0; return NULL; } req_hdr = t; - /* - * Skip whitespace at the end of the frist line, up to the - * first newline. - */ - while (isspace(*req_hdr)) - if (*(req_hdr++) == '\n') - break; + end = req_hdr + header_sz; + if (end <= req_hdr) { /* Invalid request */ debug(33, 3) ("parseHttpRequest: No request headers?\n"); @@ -1585,7 +1577,6 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status, *status = -1; return http; } - header_sz = end - req_hdr; req_sz = end - inbuf; /* Ok, all headers are received */ diff --git a/src/http.cc b/src/http.cc index 13c16dfa31..b2a8833e55 100644 --- a/src/http.cc +++ b/src/http.cc @@ -1,6 +1,6 @@ /* - * $Id: http.cc,v 1.259 1998/03/30 04:11:13 wessels Exp $ + * $Id: http.cc,v 1.260 1998/03/31 05:35:23 wessels Exp $ * * DEBUG: section 11 Hypertext Transfer Protocol (HTTP) * AUTHOR: Harvest Derived @@ -326,9 +326,12 @@ httpProcessReplyHeader(HttpStateData * httpState, const char *buf, int size) } t = httpState->reply_hdr + hdr_len; /* headers can be incomplete only if object still arriving */ - if (!httpState->eof) - if ((t = mime_headers_end(httpState->reply_hdr)) == NULL) + if (!httpState->eof) { + size_t k = headersEnd(httpState->reply_hdr, 8192); + if (0 == k) return; /* headers not complete */ + t = httpState->reply_hdr + k; + } *t = '\0'; httpState->reply_hdr_state++; } @@ -338,7 +341,7 @@ httpProcessReplyHeader(HttpStateData * httpState, const char *buf, int size) debug(11, 9) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n", httpState->reply_hdr); /* Parse headers into reply structure */ - /* Old code never parsed headers if mime_headers_end failed, was it intentional ? @?@ @?@ */ + /* Old code never parsed headers if headersEnd failed, was it intentional ? @?@ @?@ */ /* what happens if we fail to parse here? @?@ @?@ */ httpReplyParse(reply, httpState->reply_hdr); /* httpState->eof); */ storeTimestampsSet(entry); @@ -598,9 +601,10 @@ httpBuildRequestHeader(request_t * request, int cc_flags = 0; int n; const char *url = NULL; - char *hdr_in = orig_request->headers; + char *hdr_in; - assert(hdr_in != NULL); + assert(orig_request->headers != NULL); + hdr_in = orig_request->headers; debug(11, 3) ("httpBuildRequestHeader: INPUT:\n%s\n", hdr_in); xstrncpy(fwdbuf, "X-Forwarded-For: ", 4096); xstrncpy(viabuf, "Via: ", 4096); @@ -614,12 +618,15 @@ httpBuildRequestHeader(request_t * request, httpAppendRequestHeader(hdr_out, ybuf, &len, out_sz, 1); EBIT_SET(hdr_flags, HDR_IMS); } - end = mime_headers_end(hdr_in); + assert(orig_request->headers_sz > 0); + end = orig_request->headers + orig_request->headers_sz; for (t = hdr_in; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) { hdr_len = t - hdr_in; l = strcspn(t, crlf) + 1; if (l > 4096) l = 4096; + if (0 == l) + break; xstrncpy(xbuf, t, l); debug(11, 5) ("httpBuildRequestHeader: %s\n", xbuf); if (strncasecmp(xbuf, "Proxy-Connection:", 17) == 0) diff --git a/src/mime.cc b/src/mime.cc index e84d76cc07..7bc5be6b6f 100644 --- a/src/mime.cc +++ b/src/mime.cc @@ -1,6 +1,6 @@ /* - * $Id: mime.cc,v 1.55 1998/03/16 21:59:59 wessels Exp $ + * $Id: mime.cc,v 1.56 1998/03/31 05:35:24 wessels Exp $ * * DEBUG: section 25 MIME Parsing * AUTHOR: Harvest Derived @@ -166,6 +166,7 @@ mime_get_header(const char *mime, const char *name) return NULL; } +#if OLD_CODE /* need to take the lowest, non-zero pointer to the end of the headers. * The headers end at the first empty line */ char * @@ -173,19 +174,52 @@ mime_headers_end(const char *mime) { const char *p1, *p2; const char *end = NULL; - p1 = strstr(mime, "\n\r\n"); p2 = strstr(mime, "\n\n"); - if (p1 && p2) end = p1 < p2 ? p1 : p2; else end = p1 ? p1 : p2; if (end) end += (end == p1 ? 3 : 2); - return (char *) end; } +#endif + +size_t +headersEnd(const char *mime, size_t l) +{ + size_t e = 0; + int state = 0; + while (e < l && state < 3) { + switch (state) { + case 0: + if ('\n' == mime[e]) + state = 1; + break; + case 1: + if ('\r' == mime[e]) + state = 2; + else if ('\n' == mime[e]) + state = 3; + else + state = 0; + break; + case 2: + if ('\n' == mime[e]) + state = 3; + else + state = 0; + break; + default: + break; + } + e++; + } + if (3 == state) + return e; + return 0; +} /* * mk_mime_hdr - Generates a MIME header using the given parameters. diff --git a/src/urn.cc b/src/urn.cc index 5ba1dd581e..26ad088c7d 100644 --- a/src/urn.cc +++ b/src/urn.cc @@ -159,6 +159,7 @@ urnHandleReply(void *data, char *buf, ssize_t size) StoreEntry *e = urnState->entry; StoreEntry *urlres_e = urnState->urlres_e; char *s = NULL; + size_t k; HttpReply *rep; wordlist *w; wordlist *urls; @@ -191,12 +192,13 @@ urnHandleReply(void *data, char *buf, ssize_t size) return; } /* we know its STORE_OK */ - s = mime_headers_end(buf); - if (s == NULL) { + k = headersEnd(buf, size); + if (0 == k) { debug(52, 1) ("urnHandleReply: didn't find end-of-headers for %s\n", storeUrl(e)); return; } + s = buf + k; assert(urlres_e->mem_obj->reply); httpReplyParse(urlres_e->mem_obj->reply, buf); debug(52, 3) ("mem->reply exists, code=%d.\n",