Commit abd69d0a2057d2d52f8794925854a82984d5135c
1 parent
dfdfd20d
disconnect on invalid request line
Showing
11 changed files
with
149 additions
and
58 deletions
| 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 \ |
src/cbuf/empty.c
0 → 100644
src/http/message/get_version.c
0 → 100644
| 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: |
src/http/message/has_valid_version.c
0 → 100644
| 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: |
src/http/request/has_valid_method.c
0 → 100644
| 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