mirror of
https://github.com/openbsd/src.git
synced 2024-12-22 07:27:59 -08:00
Responses to HEAD requests must not have a message body (even though they have
a Content-Length header). HTTP RFC 7231 section 4.3.2. found by niklas@, claudio@ agrees.
This commit is contained in:
parent
d8ed2d1233
commit
53e8df0d32
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: http.h,v 1.11 2019/05/08 23:22:19 reyk Exp $ */
|
||||
/* $OpenBSD: http.h,v 1.12 2021/03/24 20:59:53 benno Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 - 2015 Reyk Floeter <reyk@openbsd.org>
|
||||
@ -19,6 +19,8 @@
|
||||
#ifndef HTTP_H
|
||||
#define HTTP_H
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#define HTTP_PORT 80
|
||||
#define HTTPS_PORT 443
|
||||
|
||||
@ -251,4 +253,13 @@ struct http_descriptor {
|
||||
struct kvtree http_headers;
|
||||
};
|
||||
|
||||
struct http_method_node {
|
||||
enum httpmethod hmn_method;
|
||||
SIMPLEQ_ENTRY(http_method_node) hmn_entry;
|
||||
};
|
||||
|
||||
struct http_session {
|
||||
SIMPLEQ_HEAD(, http_method_node) hs_methods;
|
||||
};
|
||||
|
||||
#endif /* HTTP_H */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: relay.c,v 1.253 2021/01/27 20:33:05 eric Exp $ */
|
||||
/* $OpenBSD: relay.c,v 1.254 2021/03/24 20:59:53 benno Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
|
||||
@ -800,7 +800,7 @@ relay_input(struct rsession *con)
|
||||
|
||||
switch (rlay->rl_proto->type) {
|
||||
case RELAY_PROTO_HTTP:
|
||||
if (relay_httpdesc_init(&con->se_in) == -1) {
|
||||
if (relay_http_priv_init(con) == -1) {
|
||||
relay_close(con,
|
||||
"failed to allocate http descriptor", 1);
|
||||
return;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: relay_http.c,v 1.80 2021/01/09 08:53:58 denis Exp $ */
|
||||
/* $OpenBSD: relay_http.c,v 1.81 2021/03/24 20:59:54 benno Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org>
|
||||
@ -112,6 +112,21 @@ relay_http_init(struct relay *rlay)
|
||||
relay_calc_skip_steps(&rlay->rl_proto->rules);
|
||||
}
|
||||
|
||||
int
|
||||
relay_http_priv_init(struct rsession *con)
|
||||
{
|
||||
|
||||
struct http_session *hs;
|
||||
|
||||
if ((hs = calloc(1, sizeof(*hs))) == NULL)
|
||||
return (-1);
|
||||
SIMPLEQ_INIT(&hs->hs_methods);
|
||||
DPRINTF("%s: session %d http_session %p", __func__,
|
||||
con->se_id, hs);
|
||||
con->se_priv = hs;
|
||||
return (relay_httpdesc_init(&con->se_in));
|
||||
}
|
||||
|
||||
int
|
||||
relay_httpdesc_init(struct ctl_relay_event *cre)
|
||||
{
|
||||
@ -162,6 +177,9 @@ relay_read_http(struct bufferevent *bev, void *arg)
|
||||
size_t size, linelen;
|
||||
struct kv *hdr = NULL;
|
||||
struct kv *upgrade = NULL, *upgrade_ws = NULL;
|
||||
struct http_method_node *hmn;
|
||||
struct http_session *hs;
|
||||
enum httpmethod request_method;
|
||||
|
||||
getmonotime(&con->se_tv_last);
|
||||
cre->timedout = 0;
|
||||
@ -239,11 +257,34 @@ relay_read_http(struct bufferevent *bev, void *arg)
|
||||
DPRINTF("%s: session %d: header '%s: %s'", __func__,
|
||||
con->se_id, key, value);
|
||||
|
||||
hs = con->se_priv;
|
||||
DPRINTF("%s: session %d http_session %p", __func__,
|
||||
con->se_id, hs);
|
||||
|
||||
/*
|
||||
* Identify and handle specific HTTP request methods
|
||||
*/
|
||||
if (cre->line == 1 && cre->dir == RELAY_DIR_RESPONSE) {
|
||||
desc->http_method = HTTP_METHOD_RESPONSE;
|
||||
hmn = SIMPLEQ_FIRST(&hs->hs_methods);
|
||||
|
||||
/*
|
||||
* There is nothing preventing the relay to send
|
||||
* an unbalanced response. Be prepared.
|
||||
*/
|
||||
if (hmn == NULL) {
|
||||
request_method = HTTP_METHOD_NONE;
|
||||
DPRINTF("%s: session %d unbalanced response",
|
||||
__func__, con->se_id);
|
||||
} else {
|
||||
SIMPLEQ_REMOVE_HEAD(&hs->hs_methods, hmn_entry);
|
||||
request_method = hmn->hmn_method;
|
||||
DPRINTF("%s: session %d dequeing %s", __func__,
|
||||
con->se_id,
|
||||
relay_httpmethod_byid(request_method));
|
||||
free(hmn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode response path and query
|
||||
*/
|
||||
@ -287,6 +328,15 @@ relay_read_http(struct bufferevent *bev, void *arg)
|
||||
free(line);
|
||||
goto fail;
|
||||
}
|
||||
if ((hmn = calloc(1, sizeof *hmn)) == NULL) {
|
||||
free(line);
|
||||
goto fail;
|
||||
}
|
||||
hmn->hmn_method = desc->http_method;
|
||||
DPRINTF("%s: session %d enqueing %s", __func__,
|
||||
con->se_id,
|
||||
relay_httpmethod_byid(hmn->hmn_method));
|
||||
SIMPLEQ_INSERT_TAIL(&hs->hs_methods, hmn, hmn_entry);
|
||||
/*
|
||||
* Decode request path and query
|
||||
*/
|
||||
@ -332,16 +382,26 @@ relay_read_http(struct bufferevent *bev, void *arg)
|
||||
goto abort;
|
||||
}
|
||||
/*
|
||||
* Need to read data from the client after the
|
||||
* HTTP header.
|
||||
* XXX What about non-standard clients not using
|
||||
* the carriage return? And some browsers seem to
|
||||
* include the line length in the content-length.
|
||||
* HEAD responses may provide a Content-Length header,
|
||||
* but if so it should just be ignored, since there is
|
||||
* no actual payload in the response.
|
||||
*/
|
||||
cre->toread = strtonum(value, 0, LLONG_MAX, &errstr);
|
||||
if (errstr) {
|
||||
relay_abort_http(con, 500, errstr, 0);
|
||||
goto abort;
|
||||
if (desc->http_method != HTTP_METHOD_RESPONSE
|
||||
|| request_method != HTTP_METHOD_HEAD) {
|
||||
/*
|
||||
* Need to read data from the client after the
|
||||
* HTTP header.
|
||||
* XXX What about non-standard clients not
|
||||
* using the carriage return? And some browsers
|
||||
* seem to include the line length in the
|
||||
* content-length.
|
||||
*/
|
||||
cre->toread = strtonum(value, 0, LLONG_MAX,
|
||||
&errstr);
|
||||
if (errstr) {
|
||||
relay_abort_http(con, 500, errstr, 0);
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* response with a status code of 1xx
|
||||
@ -502,8 +562,9 @@ relay_read_http(struct bufferevent *bev, void *arg)
|
||||
case HTTP_METHOD_SEARCH:
|
||||
case HTTP_METHOD_PATCH:
|
||||
/* HTTP request payload */
|
||||
if (cre->toread > 0)
|
||||
if (cre->toread > 0) {
|
||||
bev->readcb = relay_read_httpcontent;
|
||||
}
|
||||
|
||||
/* Single-pass HTTP body */
|
||||
if (cre->toread < 0) {
|
||||
@ -1117,6 +1178,19 @@ relay_abort_http(struct rsession *con, u_int code, const char *msg,
|
||||
void
|
||||
relay_close_http(struct rsession *con)
|
||||
{
|
||||
struct http_session *hs = con->se_priv;
|
||||
struct http_method_node *hmn;
|
||||
|
||||
DPRINTF("%s: session %d http_session %p", __func__,
|
||||
con->se_id, hs);
|
||||
if (hs != NULL)
|
||||
while (!SIMPLEQ_EMPTY(&hs->hs_methods)) {
|
||||
hmn = SIMPLEQ_FIRST(&hs->hs_methods);
|
||||
SIMPLEQ_REMOVE_HEAD(&hs->hs_methods, hmn_entry);
|
||||
DPRINTF("%s: session %d freeing %s", __func__,
|
||||
con->se_id, relay_httpmethod_byid(hmn->hmn_method));
|
||||
free(hmn);
|
||||
}
|
||||
relay_httpdesc_free(con->se_in.desc);
|
||||
free(con->se_in.desc);
|
||||
relay_httpdesc_free(con->se_out.desc);
|
||||
|
Loading…
Reference in New Issue
Block a user