mirror of https://git.kore.io/kore.git
better http header validation.
This commit is contained in:
parent
3312a2882f
commit
1447f6573f
123
src/http.c
123
src/http.c
|
@ -61,6 +61,58 @@ static struct {
|
|||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
#define HTTP_MAP_LIMIT 127
|
||||
|
||||
/*
|
||||
* token = 1*<any CHAR except CTLs or separators>
|
||||
* separators = "(" | ")" | "<" | ">" | "@"
|
||||
* | "," | ";" | ":" | "\" | <">
|
||||
* | "/" | "[" | "]" | "?" | "="
|
||||
* | "{" | "}" | SP | HT
|
||||
*/
|
||||
static const char http_token[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, '!' , 0x00, '#' , '$' , '%' , '&' , '\'',
|
||||
0x00, 0x00, '*' , '+' , 0x00, '-' , '.' , 0x00,
|
||||
'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
|
||||
'8' , '9' , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
|
||||
'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
|
||||
'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
|
||||
'X' , 'Y' , 'Z' , 0x00, 0x00, 0x00, '^' , '_' ,
|
||||
'`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
|
||||
'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
|
||||
'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
|
||||
'x' , 'y' , 'z' , 0x00, '|' , 0x00, '~' ,
|
||||
};
|
||||
|
||||
/*
|
||||
* field-content = <the OCTETs making up the field-value
|
||||
* and consisting of either *TEXT or combinations
|
||||
* of token, separators, and quoted-string>
|
||||
*/
|
||||
static const char http_field_content[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
' ' , '!' , '"' , '#' , '$' , '%' , '&' , '\'',
|
||||
'(' , ')' , '*' , '+' , ',' , '-' , '.' , '/' ,
|
||||
'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
|
||||
'8' , '9' , ':' , ';' , '<' , '=' , '>' , '?' ,
|
||||
'@' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
|
||||
'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
|
||||
'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
|
||||
'X' , 'Y' , 'Z' , '[' , '\\', ']' , '^' , '_' ,
|
||||
'`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
|
||||
'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
|
||||
'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
|
||||
'x' , 'y' , 'z' , '{' , '|' , '}' , '~' ,
|
||||
};
|
||||
|
||||
static int http_body_recv(struct netbuf *);
|
||||
static void http_error_response(struct connection *, int);
|
||||
static void http_write_response_cookie(struct http_cookie *);
|
||||
|
@ -77,6 +129,7 @@ static int multipart_parse_headers(struct http_request *,
|
|||
struct kore_buf *, struct kore_buf *,
|
||||
const char *, const int);
|
||||
|
||||
static char *http_validate_header(char *);
|
||||
static struct http_request *http_request_new(struct connection *,
|
||||
const char *, const char *, char *,
|
||||
const char *);
|
||||
|
@ -584,6 +637,7 @@ http_request_cookie(struct http_request *req, const char *cookie, char **out)
|
|||
int
|
||||
http_header_recv(struct netbuf *nb)
|
||||
{
|
||||
struct connection *c;
|
||||
size_t len;
|
||||
ssize_t ret;
|
||||
struct http_header *hdr;
|
||||
|
@ -592,10 +646,10 @@ http_header_recv(struct netbuf *nb)
|
|||
u_int64_t bytes_left;
|
||||
u_int8_t *end_headers;
|
||||
int h, i, v, skip, l;
|
||||
char *request[4], *host, *hbuf;
|
||||
char *p, *headers[HTTP_REQ_HEADER_MAX];
|
||||
struct connection *c = (struct connection *)nb->owner;
|
||||
char *headers[HTTP_REQ_HEADER_MAX];
|
||||
char *value, *host, *request[4], *hbuf;
|
||||
|
||||
c = nb->owner;
|
||||
kore_debug("http_header_recv(%p)", nb);
|
||||
|
||||
if (nb->b_len < 4)
|
||||
|
@ -633,19 +687,16 @@ http_header_recv(struct netbuf *nb)
|
|||
if (strncasecmp(headers[i], "host", 4))
|
||||
continue;
|
||||
|
||||
if ((host = strchr(headers[i], ':')) == NULL) {
|
||||
if ((host = http_validate_header(headers[i])) == NULL) {
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
*(host)++ = '\0';
|
||||
|
||||
if (*host == '\0') {
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
host++;
|
||||
skip = i;
|
||||
break;
|
||||
}
|
||||
|
@ -668,18 +719,21 @@ http_header_recv(struct netbuf *nb)
|
|||
if (i == skip)
|
||||
continue;
|
||||
|
||||
p = strchr(headers[i], ':');
|
||||
if (p == NULL) {
|
||||
kore_debug("malformed header: '%s'", headers[i]);
|
||||
continue;
|
||||
if ((value = http_validate_header(headers[i])) == NULL) {
|
||||
req->flags |= HTTP_REQUEST_DELETE;
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
if (*value == '\0') {
|
||||
req->flags |= HTTP_REQUEST_DELETE;
|
||||
http_error_response(c, 400);
|
||||
return (KORE_RESULT_OK);
|
||||
}
|
||||
|
||||
*(p++) = '\0';
|
||||
if (*p == ' ')
|
||||
p++;
|
||||
hdr = kore_pool_get(&http_header_pool);
|
||||
hdr->header = headers[i];
|
||||
hdr->value = p;
|
||||
hdr->value = value;
|
||||
TAILQ_INSERT_TAIL(&(req->req_headers), hdr, list);
|
||||
|
||||
if (req->agent == NULL &&
|
||||
|
@ -2083,3 +2137,42 @@ http_media_type(const char *path)
|
|||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static char *
|
||||
http_validate_header(char *header)
|
||||
{
|
||||
u_int8_t idx;
|
||||
char *p, *value;
|
||||
|
||||
for (p = header; *p != '\0'; p++) {
|
||||
idx = *p;
|
||||
if (idx > HTTP_MAP_LIMIT)
|
||||
return (NULL);
|
||||
|
||||
if (*p == ':') {
|
||||
*(p)++ = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
if (http_token[idx] == 0x00)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
while (isspace(*(unsigned char *)p))
|
||||
p++;
|
||||
|
||||
if (*p == '\0')
|
||||
return (NULL);
|
||||
|
||||
value = p;
|
||||
while (*p != '\0') {
|
||||
idx = *p;
|
||||
if (idx > HTTP_MAP_LIMIT)
|
||||
return (NULL);
|
||||
if (http_field_content[idx] == 0x00)
|
||||
return (NULL);
|
||||
p++;
|
||||
}
|
||||
|
||||
return (value);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue