]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
new headersEnd() replaces mime_headers_end and eliminates buffer overruns
authorwessels <>
Tue, 31 Mar 1998 12:35:22 +0000 (12:35 +0000)
committerwessels <>
Tue, 31 Mar 1998 12:35:22 +0000 (12:35 +0000)
src/client_side.cc
src/http.cc
src/mime.cc
src/urn.cc

index 4f329f4cb46c7161cc9b2dcb7d3b1f8c3f8425d2..2d2a9ecea984980f0737fa468e8b0ce93b7d3b3e 100644 (file)
@@ -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 */
index 13c16dfa31a9c777b99c98163e4b860cf74828b4..b2a8833e55f105fa0674dfd1460d2d8b16853d36 100644 (file)
@@ -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)
index e84d76cc07a3bfe50eff37407357f3d128185cf5..7bc5be6b6f1cec7a8cba001b26d869abe3d19cc3 100644 (file)
@@ -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.
index 5ba1dd581efe8e8a9f3e1fd3d6b11c912ec7a0cd..26ad088c7d02a8cfb4ff30343c21abf2171cd8cb 100644 (file)
@@ -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",