better handling of HTTP POSTs or requests with Content-Length.
authorreyk <reyk@openbsd.org>
Mon, 11 Aug 2008 08:07:14 +0000 (08:07 +0000)
committerreyk <reyk@openbsd.org>
Mon, 11 Aug 2008 08:07:14 +0000 (08:07 +0000)
usr.sbin/relayd/relay.c
usr.sbin/relayd/relayd.h

index fb83a7c..31bbb96 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: relay.c,v 1.102 2008/08/11 06:42:06 reyk Exp $        */
+/*     $OpenBSD: relay.c,v 1.103 2008/08/11 08:07:14 reyk Exp $        */
 
 /*
  * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -1146,7 +1146,7 @@ relay_read_httpcontent(struct bufferevent *bev, void *arg)
        size_t                   size;
 
        if (gettimeofday(&con->se_tv_last, NULL) == -1)
-               goto done;
+               goto fail;
        size = EVBUFFER_LENGTH(src);
        DPRINTF("relay_read_httpcontent: size %d, to read %d",
            size, cre->toread);
@@ -1161,7 +1161,7 @@ relay_read_httpcontent(struct bufferevent *bev, void *arg)
            size, cre->toread);
        if (con->se_done)
                goto done;
-       if (EVBUFFER_LENGTH(src) && bev->readcb != relay_read_httpcontent)
+       if (bev->readcb != relay_read_httpcontent)
                bev->readcb(bev, arg);
        bufferevent_enable(bev, EV_READ);
        return;
@@ -1183,7 +1183,7 @@ relay_read_httpchunks(struct bufferevent *bev, void *arg)
        size_t                   size;
 
        if (gettimeofday(&con->se_tv_last, NULL) == -1)
-               goto done;
+               goto fail;
        size = EVBUFFER_LENGTH(src);
        DPRINTF("relay_read_httpchunks: size %d, to read %d",
            size, cre->toread);
@@ -1282,11 +1282,15 @@ relay_read_http(struct bufferevent *bev, void *arg)
        size_t                   size;
 
        if (gettimeofday(&con->se_tv_last, NULL) == -1)
-               goto done;
+               goto fail;
        size = EVBUFFER_LENGTH(src);
        DPRINTF("relay_read_http: size %d, to read %d", size, cre->toread);
-       if (!size)
-               return;
+       if (!size) {
+               if (cre->dir == RELAY_DIR_RESPONSE)
+                       return;
+               cre->toread = 0;
+               goto done;
+       }
 
        pk.type = NODE_TYPE_HEADER;
 
@@ -1345,9 +1349,7 @@ relay_read_http(struct bufferevent *bev, void *arg)
                        if (cre->dir == RELAY_DIR_RESPONSE) {
                                cre->method = HTTP_METHOD_RESPONSE;
                                goto lookup;
-                       } else if (strcmp("GET", pk.key) == 0)
-                               cre->method = HTTP_METHOD_GET;
-                       else if (strcmp("HEAD", pk.key) == 0)
+                       } else if (strcmp("HEAD", pk.key) == 0)
                                cre->method = HTTP_METHOD_HEAD;
                        else if (strcmp("POST", pk.key) == 0)
                                cre->method = HTTP_METHOD_POST;
@@ -1361,6 +1363,10 @@ relay_read_http(struct bufferevent *bev, void *arg)
                                cre->method = HTTP_METHOD_TRACE;
                        else if (strcmp("CONNECT", pk.key) == 0)
                                cre->method = HTTP_METHOD_CONNECT;
+                       else {
+                               /* Use GET method as the default */
+                               cre->method = HTTP_METHOD_GET;
+                       }
 
                        /*
                         * Decode the path and query
@@ -1496,6 +1502,9 @@ relay_read_http(struct bufferevent *bev, void *arg)
                }
 
                switch (cre->method) {
+               case HTTP_METHOD_NONE:
+                       relay_close_http(con, 406, "no method", 0);
+                       return;
                case HTTP_METHOD_CONNECT:
                        /* Data stream */
                        bev->readcb = relay_read;
@@ -1526,12 +1535,14 @@ relay_read_http(struct bufferevent *bev, void *arg)
                /* Write empty newline and switch to relay mode */
                if (relay_bufferevent_print(cre->dst, "\r\n") == -1)
                        goto fail;
+
                cre->line = 0;
                cre->method = 0;
                cre->done = 0;
                cre->chunked = 0;
 
-               if (cre->dir == RELAY_DIR_REQUEST &&
+ done:
+               if (cre->dir == RELAY_DIR_REQUEST && !cre->toread &&
                    proto->lateconnect && cre->dst->bev == NULL) {
                        if (rlay->rl_conf.fwdmode == FWD_TRANS) {
                                relay_bindanyreq(con, 0, IPPROTO_TCP);
@@ -1542,15 +1553,14 @@ relay_read_http(struct bufferevent *bev, void *arg)
                        return;
                }
        }
-       if (con->se_done)
-               goto done;
+       if (con->se_done) {
+               relay_close(con, "last http read (done)");
+               return;
+       }
        if (EVBUFFER_LENGTH(src) && bev->readcb != relay_read_http)
                bev->readcb(bev, arg);
        bufferevent_enable(bev, EV_READ);
        return;
- done:
-       relay_close(con, "last http read (done)");
-       return;
  fail:
        relay_close_http(con, 500, strerror(errno), 0);
        return;
index 30143f1..e9a5279 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: relayd.h,v 1.109 2008/07/22 23:17:37 reyk Exp $       */
+/*     $OpenBSD: relayd.h,v 1.110 2008/08/11 08:07:14 reyk Exp $       */
 
 /*
  * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -227,15 +227,16 @@ struct ctl_tcp_event {
 };
 
 enum httpmethod {
-       HTTP_METHOD_GET         = 0,
-       HTTP_METHOD_HEAD        = 1,
-       HTTP_METHOD_POST        = 2,
-       HTTP_METHOD_PUT         = 3,
-       HTTP_METHOD_DELETE      = 4,
-       HTTP_METHOD_OPTIONS     = 5,
-       HTTP_METHOD_TRACE       = 6,
-       HTTP_METHOD_CONNECT     = 7,
-       HTTP_METHOD_RESPONSE    = 8     /* Server response */
+       HTTP_METHOD_NONE        = 0,
+       HTTP_METHOD_GET         = 1,
+       HTTP_METHOD_HEAD        = 2,
+       HTTP_METHOD_POST        = 3,
+       HTTP_METHOD_PUT         = 4,
+       HTTP_METHOD_DELETE      = 5,
+       HTTP_METHOD_OPTIONS     = 6,
+       HTTP_METHOD_TRACE       = 7,
+       HTTP_METHOD_CONNECT     = 8,
+       HTTP_METHOD_RESPONSE    = 9     /* Server response */
 };
 
 enum direction {