Browse Source

disconnect on invalid request line

master
Georg Hopp 14 years ago
parent
commit
abd69d0a20
  1. 8
      ChangeLog
  2. 1
      include/cbuf.h
  3. 3
      include/http/message.h
  4. 6
      include/http/request.h
  5. 8
      src/Makefile.am
  6. 10
      src/cbuf/empty.c
  7. 28
      src/http/message/get_version.c
  8. 32
      src/http/message/has_valid_version.c
  9. 31
      src/http/request/has_valid_method.c
  10. 61
      src/http/request/parser/get_request_line.c
  11. 19
      src/http/request/parser/parse.c

8
ChangeLog

@ -1,10 +1,14 @@
2012-02-20 07:55:06 +0100 Georg Hopp
* disconnect on invalid request line (HEAD, master)
2012-02-19 20:12:40 +0100 Georg Hopp
* 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)
* 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)
2012-02-19 18:28:30 +0100 Georg Hopp
* increase writebuffer size a lot. (origin/master, origin/HEAD)
* increase writebuffer size a lot.
2012-02-19 18:15:55 +0100 Georg Hopp

1
include/cbuf.h

@ -45,6 +45,7 @@ ssize_t cbufWrite(Cbuf, int fd);
char * cbufGetLine(Cbuf);
char * cbufGetData(Cbuf, size_t);
char * cbufSetData(Cbuf, const void *, size_t);
void cbufEmpty(Cbuf);
char * cbufGetRead(Cbuf this);
char * cbufGetWrite(Cbuf this);

3
include/http/message.h

@ -26,6 +26,9 @@ char httpMessageHasKeepAlive(HttpMessage);
size_t httpMessageHeaderSizeGet(HttpMessage);
char * httpMessageHeaderToString(HttpMessage, char *);
int httpMessageGetVersion(HttpMessage, int *, int *);
int httpMessageHasValidVersion(HttpMessage);
#endif // __HTTP_MESSAGE__
// vim: set ts=4 sw=4:

6
include/http/request.h

@ -4,6 +4,10 @@
#include "class.h"
#include "http/message.h"
#define N_HTTP_METHOD 8
char * http_method[N_HTTP_METHOD];
CLASS(HttpRequest) {
EXTENDS(HttpMessage);
@ -11,6 +15,8 @@ CLASS(HttpRequest) {
char * uri;
};
int httpRequestHasValidMethod(HttpRequest);
#endif /* __HTTP_REQUEST_H__ */
// vim: set ts=4 sw=4:

8
src/Makefile.am

@ -13,10 +13,12 @@ CB = cbuf.c cbuf/read.c cbuf/write.c \
cbuf/get_line.c cbuf/set_data.c cbuf/get_data.c \
cbuf/addr_index.c cbuf/get_free.c cbuf/get_read.c cbuf/get_write.c \
cbuf/inc_read.c cbuf/inc_write.c cbuf/is_empty.c cbuf/memchr.c \
cbuf/skip_non_alpha.c cbuf/is_locked.c cbuf/lock.c cbuf/release.c
cbuf/skip_non_alpha.c cbuf/is_locked.c cbuf/lock.c cbuf/release.c \
cbuf/empty.c
MSG = http/message.c http/message/queue.c http/message/has_keep_alive.c \
http/message/header_size_get.c http/message/header_to_string.c
REQ = http/request.c
http/message/header_size_get.c http/message/header_to_string.c \
http/message/get_version.c http/message/has_valid_version.c
REQ = http/request.c http/request/has_valid_method.c
RESP = http/response.c \
http/response/404.c \
http/response/image.c \

10
src/cbuf/empty.c

@ -0,0 +1,10 @@
#include "cbuf.h"
void
cbufEmpty(Cbuf this)
{
this->bused = 0;
this->read = this->write;
}
// vim: set ts=4 sw=4:

28
src/http/message/get_version.c

@ -0,0 +1,28 @@
#include <string.h>
#include <stdlib.h>
#include "http/message.h"
int
httpMessageGetVersion(HttpMessage this, int * major, int * minor)
{
char * major_ptr = this->version + 5;
char * minor_ptr = strchr(major_ptr, '.') + 1;
char version[] = "\0\0\0";
if (NULL == minor_ptr ||
((minor_ptr - major_ptr - 1) > 2) ||
strlen(minor_ptr) > 2)
return -1;
memcpy(version, major_ptr, minor_ptr - major_ptr - 1);
*major = atoi(version);
memset(version, 0, 3);
strcpy(version, minor_ptr);
*minor = atoi(version);
return ((*major)<<7)|(*minor);
}
// vim: set ts=4 sw=4:

32
src/http/message/has_valid_version.c

@ -0,0 +1,32 @@
#include <string.h>
#include "http/message.h"
int
httpMessageHasValidVersion(HttpMessage this)
{
int major;
int minor;
if (NULL == this->version)
return 0;
if (8 > strlen(this->version))
return 0;
if (0 > httpMessageGetVersion(this, &major, &minor))
return 0;
if (0 != memcmp("HTTP/", this->version, sizeof("HTTP/")-1))
return 0;
if (1 != major)
return 0;
if (0 > minor || 1 < minor)
return 0;
return 1;
}
// vim: set ts=4 sw=4:

31
src/http/request/has_valid_method.c

@ -0,0 +1,31 @@
#include <string.h>
#include "http/request.h"
char * http_method[N_HTTP_METHOD] = {
"OPTIONS",
"GET",
"HEAD",
"POST",
"PUT",
"DELETE",
"TRACE",
"CONNECT"};
int
httpRequestHasValidMethod(HttpRequest this)
{
int i;
if (NULL == this->method)
return 0;
for (i=0; i<N_HTTP_METHOD; i++) {
if (0 == strcmp(http_method[i], this->method))
break;
}
return (i != N_HTTP_METHOD);
}
// vim: set ts=4 sw=4:

61
src/http/request/parser/get_request_line.c

@ -39,57 +39,32 @@ char * method[N_METHODS] = {
ssize_t
httpRequestParserGetRequestLine(HttpRequestParser this, char * cr)
{
HttpRequest request = this->cur_request;
char * method, * uri, * version;
HttpMessage message = (HttpMessage)request;
char * space1, * space2;
size_t len = cr - this->buffer->buffer - this->buffer->bstart;
int i;
space1 = memchr(
this->buffer->buffer + this->buffer->bstart,
' ', len);
method = line;
uri = strchr(line, ' ');
if (NULL == space1) {
return -1;
}
if (NULL == uri)
return;
len = cr - space1;
space2 = memchr(space1 + 1, ' ', len);
*uri++ = 0;
for (; *uri == ' ' && *uri != 0; uri++);
if (NULL == space2) {
return -1;
}
version = strchr(uri, ' ');
len = space1 - this->buffer->buffer - this->buffer->bstart;
request->method = calloc(1, len + 1);
memcpy(request->method,
this->buffer->buffer + this->buffer->bstart,
len);
if (NULL == version)
return;
for (i= 0; i< N_METHODS; i++) {
if (0 == memcmp(method[i], request->method, MIN_SIZE(method[i], len))) {
break;
}
}
*version++ = 0;
for (; *version == ' ' && *version != 0; version++);
if (i == N_METHODS) {
return -1;
}
len = space2 - space1 - 1;
request->uri = calloc(1, len + 1);
memcpy(request->uri, space1 + 1, len);
len = cr - space2 - 1;
message->version = calloc(1, len + 1);
memcpy(message->version, space2 + 1, len);
if (len+1 != sizeof("HTTP/1.1") ||
0 != memcmp("HTTP/1.", message->version, len-1)) {
return -1;
}
return 1; //* @TODO: return something useful here
request->method = malloc(strlen(method) + 1);
strcpy(request->method, method);
request->uri = malloc(strlen(uri) + 1);
strcpy(request->uri, uri);
message->version = malloc(strlen(version) + 1);
strcpy(message->version, version);
}
// vim: set ts=4 sw=4:

19
src/http/request/parser/parse.c

@ -83,18 +83,17 @@ httpRequestParserParse(HttpRequestParser this, int fd)
break;
}
if (0 > httpRequestParserGetRequestLine(this, line_end)) {
ret = -1;
cont = 0;
break;
httpRequestParserGetRequestLine(this->cur_request, line);
if (! httpRequestHasValidMethod(this->cur_request)) {
cbufRelease(this->buffer);
this->ourLock = FALSE;
return -1;
}
len = line_end - this->buffer->buffer - this->buffer->bstart + 2;
this->buffer->bstart += len;
if (this->buffer->bstart >= this->buffer->bsize) {
this->buffer->bstart -= this->buffer->bsize;
if (! httpMessageHasValidVersion((HttpMessage)this->cur_request)) {
cbufRelease(this->buffer);
this->ourLock = FALSE;
return -1;
}
this->buffer->bused -= len;
this->state = HTTP_REQUEST_REQUEST_LINE_DONE;
break;

Loading…
Cancel
Save