Commit abd69d0a2057d2d52f8794925854a82984d5135c

Authored by Georg Hopp
1 parent dfdfd20d

disconnect on invalid request line

  1 +2012-02-20 07:55:06 +0100 Georg Hopp
  2 +
  3 + * disconnect on invalid request line (HEAD, master)
  4 +
1 2012-02-19 20:12:40 +0100 Georg Hopp 5 2012-02-19 20:12:40 +0100 Georg Hopp
2 6
3 - * now incomplete requests should no longer block the complete server. Tested with \'echo -en "GET / HTTP\r\nConn" | nc -w 600 localhost 11212\' and then doing requests from my browser. @TODO: cleanup those stuff, check if a not correctly response reading would block the server. (HEAD, master) 7 + * now incomplete requests should no longer block the complete server. Tested with \'echo -en "GET / HTTP\r\nConn" | nc -w 600 localhost 11212\' and then doing requests from my browser. @TODO: cleanup those stuff, check if a not correctly response reading would block the server. (origin/master, origin/HEAD)
4 8
5 2012-02-19 18:28:30 +0100 Georg Hopp 9 2012-02-19 18:28:30 +0100 Georg Hopp
6 10
7 - * increase writebuffer size a lot. (origin/master, origin/HEAD) 11 + * increase writebuffer size a lot.
8 12
9 2012-02-19 18:15:55 +0100 Georg Hopp 13 2012-02-19 18:15:55 +0100 Georg Hopp
10 14
@@ -45,6 +45,7 @@ ssize_t cbufWrite(Cbuf, int fd); @@ -45,6 +45,7 @@ ssize_t cbufWrite(Cbuf, int fd);
45 char * cbufGetLine(Cbuf); 45 char * cbufGetLine(Cbuf);
46 char * cbufGetData(Cbuf, size_t); 46 char * cbufGetData(Cbuf, size_t);
47 char * cbufSetData(Cbuf, const void *, size_t); 47 char * cbufSetData(Cbuf, const void *, size_t);
  48 +void cbufEmpty(Cbuf);
48 49
49 char * cbufGetRead(Cbuf this); 50 char * cbufGetRead(Cbuf this);
50 char * cbufGetWrite(Cbuf this); 51 char * cbufGetWrite(Cbuf this);
@@ -26,6 +26,9 @@ char httpMessageHasKeepAlive(HttpMessage); @@ -26,6 +26,9 @@ char httpMessageHasKeepAlive(HttpMessage);
26 size_t httpMessageHeaderSizeGet(HttpMessage); 26 size_t httpMessageHeaderSizeGet(HttpMessage);
27 char * httpMessageHeaderToString(HttpMessage, char *); 27 char * httpMessageHeaderToString(HttpMessage, char *);
28 28
  29 +int httpMessageGetVersion(HttpMessage, int *, int *);
  30 +int httpMessageHasValidVersion(HttpMessage);
  31 +
29 #endif // __HTTP_MESSAGE__ 32 #endif // __HTTP_MESSAGE__
30 33
31 // vim: set ts=4 sw=4: 34 // vim: set ts=4 sw=4:
@@ -4,6 +4,10 @@ @@ -4,6 +4,10 @@
4 #include "class.h" 4 #include "class.h"
5 #include "http/message.h" 5 #include "http/message.h"
6 6
  7 +#define N_HTTP_METHOD 8
  8 +
  9 +char * http_method[N_HTTP_METHOD];
  10 +
7 CLASS(HttpRequest) { 11 CLASS(HttpRequest) {
8 EXTENDS(HttpMessage); 12 EXTENDS(HttpMessage);
9 13
@@ -11,6 +15,8 @@ CLASS(HttpRequest) { @@ -11,6 +15,8 @@ CLASS(HttpRequest) {
11 char * uri; 15 char * uri;
12 }; 16 };
13 17
  18 +int httpRequestHasValidMethod(HttpRequest);
  19 +
14 #endif /* __HTTP_REQUEST_H__ */ 20 #endif /* __HTTP_REQUEST_H__ */
15 21
16 // vim: set ts=4 sw=4: 22 // vim: set ts=4 sw=4:
@@ -13,10 +13,12 @@ CB = cbuf.c cbuf/read.c cbuf/write.c \ @@ -13,10 +13,12 @@ CB = cbuf.c cbuf/read.c cbuf/write.c \
13 cbuf/get_line.c cbuf/set_data.c cbuf/get_data.c \ 13 cbuf/get_line.c cbuf/set_data.c cbuf/get_data.c \
14 cbuf/addr_index.c cbuf/get_free.c cbuf/get_read.c cbuf/get_write.c \ 14 cbuf/addr_index.c cbuf/get_free.c cbuf/get_read.c cbuf/get_write.c \
15 cbuf/inc_read.c cbuf/inc_write.c cbuf/is_empty.c cbuf/memchr.c \ 15 cbuf/inc_read.c cbuf/inc_write.c cbuf/is_empty.c cbuf/memchr.c \
16 - cbuf/skip_non_alpha.c cbuf/is_locked.c cbuf/lock.c cbuf/release.c 16 + cbuf/skip_non_alpha.c cbuf/is_locked.c cbuf/lock.c cbuf/release.c \
  17 + cbuf/empty.c
17 MSG = http/message.c http/message/queue.c http/message/has_keep_alive.c \ 18 MSG = http/message.c http/message/queue.c http/message/has_keep_alive.c \
18 - http/message/header_size_get.c http/message/header_to_string.c  
19 -REQ = http/request.c 19 + http/message/header_size_get.c http/message/header_to_string.c \
  20 + http/message/get_version.c http/message/has_valid_version.c
  21 +REQ = http/request.c http/request/has_valid_method.c
20 RESP = http/response.c \ 22 RESP = http/response.c \
21 http/response/404.c \ 23 http/response/404.c \
22 http/response/image.c \ 24 http/response/image.c \
  1 +#include "cbuf.h"
  2 +
  3 +void
  4 +cbufEmpty(Cbuf this)
  5 +{
  6 + this->bused = 0;
  7 + this->read = this->write;
  8 +}
  9 +
  10 +// vim: set ts=4 sw=4:
  1 +#include <string.h>
  2 +#include <stdlib.h>
  3 +
  4 +#include "http/message.h"
  5 +
  6 +int
  7 +httpMessageGetVersion(HttpMessage this, int * major, int * minor)
  8 +{
  9 + char * major_ptr = this->version + 5;
  10 + char * minor_ptr = strchr(major_ptr, '.') + 1;
  11 + char version[] = "\0\0\0";
  12 +
  13 + if (NULL == minor_ptr ||
  14 + ((minor_ptr - major_ptr - 1) > 2) ||
  15 + strlen(minor_ptr) > 2)
  16 + return -1;
  17 +
  18 + memcpy(version, major_ptr, minor_ptr - major_ptr - 1);
  19 + *major = atoi(version);
  20 +
  21 + memset(version, 0, 3);
  22 + strcpy(version, minor_ptr);
  23 + *minor = atoi(version);
  24 +
  25 + return ((*major)<<7)|(*minor);
  26 +}
  27 +
  28 +// vim: set ts=4 sw=4:
  1 +#include <string.h>
  2 +
  3 +#include "http/message.h"
  4 +
  5 +int
  6 +httpMessageHasValidVersion(HttpMessage this)
  7 +{
  8 + int major;
  9 + int minor;
  10 +
  11 + if (NULL == this->version)
  12 + return 0;
  13 +
  14 + if (8 > strlen(this->version))
  15 + return 0;
  16 +
  17 + if (0 > httpMessageGetVersion(this, &major, &minor))
  18 + return 0;
  19 +
  20 + if (0 != memcmp("HTTP/", this->version, sizeof("HTTP/")-1))
  21 + return 0;
  22 +
  23 + if (1 != major)
  24 + return 0;
  25 +
  26 + if (0 > minor || 1 < minor)
  27 + return 0;
  28 +
  29 + return 1;
  30 +}
  31 +
  32 +// vim: set ts=4 sw=4:
  1 +#include <string.h>
  2 +
  3 +#include "http/request.h"
  4 +
  5 +char * http_method[N_HTTP_METHOD] = {
  6 + "OPTIONS",
  7 + "GET",
  8 + "HEAD",
  9 + "POST",
  10 + "PUT",
  11 + "DELETE",
  12 + "TRACE",
  13 + "CONNECT"};
  14 +
  15 +int
  16 +httpRequestHasValidMethod(HttpRequest this)
  17 +{
  18 + int i;
  19 +
  20 + if (NULL == this->method)
  21 + return 0;
  22 +
  23 + for (i=0; i<N_HTTP_METHOD; i++) {
  24 + if (0 == strcmp(http_method[i], this->method))
  25 + break;
  26 + }
  27 +
  28 + return (i != N_HTTP_METHOD);
  29 +}
  30 +
  31 +// vim: set ts=4 sw=4:
@@ -39,57 +39,32 @@ char * method[N_METHODS] = { @@ -39,57 +39,32 @@ char * method[N_METHODS] = {
39 ssize_t 39 ssize_t
40 httpRequestParserGetRequestLine(HttpRequestParser this, char * cr) 40 httpRequestParserGetRequestLine(HttpRequestParser this, char * cr)
41 { 41 {
42 - HttpRequest request = this->cur_request; 42 + char * method, * uri, * version;
43 HttpMessage message = (HttpMessage)request; 43 HttpMessage message = (HttpMessage)request;
44 - char * space1, * space2;  
45 - size_t len = cr - this->buffer->buffer - this->buffer->bstart;  
46 - int i;  
47 44
48 - space1 = memchr(  
49 - this->buffer->buffer + this->buffer->bstart,  
50 - ' ', len); 45 + method = line;
  46 + uri = strchr(line, ' ');
51 47
52 - if (NULL == space1) {  
53 - return -1;  
54 - } 48 + if (NULL == uri)
  49 + return;
55 50
56 - len = cr - space1;  
57 - space2 = memchr(space1 + 1, ' ', len); 51 + *uri++ = 0;
  52 + for (; *uri == ' ' && *uri != 0; uri++);
58 53
59 - if (NULL == space2) {  
60 - return -1;  
61 - } 54 + version = strchr(uri, ' ');
62 55
63 - len = space1 - this->buffer->buffer - this->buffer->bstart;  
64 - request->method = calloc(1, len + 1);  
65 - memcpy(request->method,  
66 - this->buffer->buffer + this->buffer->bstart,  
67 - len); 56 + if (NULL == version)
  57 + return;
68 58
69 - for (i= 0; i< N_METHODS; i++) {  
70 - if (0 == memcmp(method[i], request->method, MIN_SIZE(method[i], len))) {  
71 - break;  
72 - }  
73 - } 59 + *version++ = 0;
  60 + for (; *version == ' ' && *version != 0; version++);
74 61
75 - if (i == N_METHODS) {  
76 - return -1;  
77 - }  
78 -  
79 - len = space2 - space1 - 1;  
80 - request->uri = calloc(1, len + 1);  
81 - memcpy(request->uri, space1 + 1, len);  
82 -  
83 - len = cr - space2 - 1;  
84 - message->version = calloc(1, len + 1);  
85 - memcpy(message->version, space2 + 1, len);  
86 -  
87 - if (len+1 != sizeof("HTTP/1.1") ||  
88 - 0 != memcmp("HTTP/1.", message->version, len-1)) {  
89 - return -1;  
90 - }  
91 -  
92 - return 1; //* @TODO: return something useful here 62 + request->method = malloc(strlen(method) + 1);
  63 + strcpy(request->method, method);
  64 + request->uri = malloc(strlen(uri) + 1);
  65 + strcpy(request->uri, uri);
  66 + message->version = malloc(strlen(version) + 1);
  67 + strcpy(message->version, version);
93 } 68 }
94 69
95 // vim: set ts=4 sw=4: 70 // vim: set ts=4 sw=4:
@@ -83,18 +83,17 @@ httpRequestParserParse(HttpRequestParser this, int fd) @@ -83,18 +83,17 @@ httpRequestParserParse(HttpRequestParser this, int fd)
83 break; 83 break;
84 } 84 }
85 85
86 - if (0 > httpRequestParserGetRequestLine(this, line_end)) {  
87 - ret = -1;  
88 - cont = 0;  
89 - break; 86 + httpRequestParserGetRequestLine(this->cur_request, line);
  87 + if (! httpRequestHasValidMethod(this->cur_request)) {
  88 + cbufRelease(this->buffer);
  89 + this->ourLock = FALSE;
  90 + return -1;
90 } 91 }
91 -  
92 - len = line_end - this->buffer->buffer - this->buffer->bstart + 2;  
93 - this->buffer->bstart += len;  
94 - if (this->buffer->bstart >= this->buffer->bsize) {  
95 - this->buffer->bstart -= this->buffer->bsize; 92 + if (! httpMessageHasValidVersion((HttpMessage)this->cur_request)) {
  93 + cbufRelease(this->buffer);
  94 + this->ourLock = FALSE;
  95 + return -1;
96 } 96 }
97 - this->buffer->bused -= len;  
98 97
99 this->state = HTTP_REQUEST_REQUEST_LINE_DONE; 98 this->state = HTTP_REQUEST_REQUEST_LINE_DONE;
100 break; 99 break;
Please register or login to post a comment