http-request-parser.c revision e0cf44fb802a5e7aa4cbeee5e80ef8f3f6aecdbe
/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "istream.h"
#include "http-url.h"
#include "http-parser.h"
#include "http-message-parser.h"
#include "http-request-parser.h"
#define HTTP_REQUEST_PARSER_MAX_METHOD_LENGTH 32
enum http_request_parser_state {
};
struct http_request_parser {
struct http_message_parser parser;
const char *request_method;
const char *request_target;
unsigned int skipping_line:1;
};
struct http_request_parser *
const struct http_request_limits *limits)
{
struct http_request_parser *parser;
struct http_header_limits hdr_limits;
} else {
max_payload_size = 0;
}
/* substitute default limits */
if (parser->max_target_length == 0)
if (hdr_limits.max_size == 0)
if (hdr_limits.max_field_size == 0)
if (hdr_limits.max_fields == 0)
if (max_payload_size == 0)
return parser;
}
{
}
static void
{
}
{
/* method = token
*/
p++;
return -1;
}
return 0;
return 1;
}
{
/* We'll just parse anything up to the first SP or a control char.
We could also implement workarounds for buggy HTTP clients and
parse anything up to the HTTP-version and return 301 with the
target properly encoded (FIXME). */
p++;
/* target is too long when explicit limit is exceeded or when input buffer
runs out of space */
/* FIXME: put limit on full request line rather than target and method
separately */
/* FIXME: is it wise to keep target in stream buffer? It can become very
large for some applications, increasing the stream buffer size */
return -1;
}
return 0;
return 1;
}
static inline const char *_chr_sanitize(unsigned char c)
{
if (c >= 0x20 && c < 0x7F)
return t_strdup_printf("`%c'", c);
if (c == 0x0a)
return "<LF>";
if (c == 0x0d)
return "<CR>";
return t_strdup_printf("<0x%02x>", c);
}
{
int ret;
/* request-line = method SP request-target SP HTTP-version CRLF
*/
for (;;) {
return 0;
if (parser->skipping_line) {
/* second extra CRLF; not allowed */
return -1;
}
/* HTTP/1.0 client sent one extra CRLF after body.
ignore it. */
break;
}
/* fall through */
return ret;
return 0;
/* fall through */
("Unexpected character %s in request method",
return -1;
}
return 0;
/* fall through */
return ret;
return 0;
/* fall through */
("Unexpected character %s in request target",
return -1;
}
return 0;
/* fall through */
if (ret < 0) {
}
return ret;
}
return 0;
/* fall through */
return 0;
/* fall through */
("Unexpected character %s at end of request line",
return -1;
}
if (!parser->skipping_line) {
return 1;
}
break;
default:
i_unreached();
}
}
i_unreached();
return -1;
}
{
const unsigned char *begin;
int ret;
old_bytes)) > 0) {
return -1;
if (ret > 0)
return 1;
}
if (ret == -2) {
return -1;
}
if (ret < 0) {
return 0;
return -1;
}
return 0;
}
static inline enum http_request_parse_error
{
default:
break;
}
i_unreached();
}
{
return FALSE;
}
static int
{
struct http_parser hparser;
bool parse_error = FALSE;
unsigned int num_expectations = 0;
/* Expect = 1#expectation
expectation = expect-name [ BWS "=" BWS expect-value ]
*( OWS ";" [ OWS expect-param ] )
expect-param = expect-name [ BWS "=" BWS expect-value ]
expect-name = token
expect-value = token / quoted-string
*/
while (!parse_error) {
const char *expect_name, *expect_value;
/* expect-name */
} else {
Section 5.1.1:
If all received Expect header field(s) are syntactically valid but
contain an expectation that the recipient does not understand or
cannot comply with, the recipient MUST respond with a 417
(Expectation Failed) status code. A recipient of a syntactically
invalid Expectation header field MUST respond with a 4xx status code
other than 417.
--> Must check rest of expect header syntax before returning error.
*/
("Unknown Expectation `%s'", expect_name);
}
}
/* BWS "=" BWS */
break;
/* value */
parse_error = TRUE;
break;
}
("Expectation `%s' has unexpected value", expect_name);
}
}
/* *( OWS ";" [ OWS expect-param ] ) */
while (!parse_error) {
/* OWS ";" */
break;
/* expect-param */
parse_error = TRUE;
break;
}
/* BWS "=" BWS */
parse_error = TRUE;
break;
}
/* value */
parse_error = TRUE;
break;
}
("Expectation `%s' has unknown parameter `'%s'",
}
}
if (parse_error)
break;
}
break;
}
return -1;
}
return -1;
if (num_expectations == 0) {
return -1;
}
return 0;
}
static int
struct http_request *request)
{
const struct http_header_field *hdr;
int ret = 0;
if (ret < 0)
return -1;
}
return 0;
}
{
const struct http_header_field *hdr;
const char *error;
int ret;
/* make sure we finished streaming payload from previous request
before we continue. */
if (ret < 0) {
}
return ret;
}
/* HTTP-message = start-line
*( header-field CRLF )
CRLF
[ message-body ]
*/
/* assign early for error reporting */
if (ret <= 0) {
if (ret < 0) {
}
return ret;
}
}
if (ret < 0) {
}
return ret;
}
return -1;
}
Section 5.4:
A server MUST respond with a 400 (Bad Request) status code to any
HTTP/1.1 request message that lacks a Host header field and to any
request message that contains more than one Host header field or a
Host header field with an invalid field-value.
*/
if (ret == 0)
*error_r = "Missing Host header";
else
*error_r = "Duplicate Host header";
return -1;
}
return -1;
}
/* parse request-specific headers */
return -1;
}
return 1;
}