mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-12-04 14:46:30 -05:00
Feature: Check if we know client's body length. If so do not allow reading more than it.
This commit is contained in:
parent
f370e88335
commit
01c35e2c41
26
src/client.c
26
src/client.c
@ -87,6 +87,8 @@ int client_create(client_t **c_ptr, connection_t *con, http_parser_t *parser)
|
||||
client->con = con;
|
||||
client->parser = parser;
|
||||
client->protocol = ICECAST_PROTOCOL_HTTP;
|
||||
client->request_body_length = 0;
|
||||
client->request_body_read = 0;
|
||||
client->admin_command = ADMIN_COMMAND_ERROR;
|
||||
client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
|
||||
client->refbuf->len = 0; /* force reader code to ignore buffer contents */
|
||||
@ -439,8 +441,25 @@ void client_set_queue(client_t *client, refbuf_t *refbuf)
|
||||
|
||||
ssize_t client_body_read(client_t *client, void *buf, size_t len)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
ICECAST_LOG_DEBUG("Reading from body (client=%p)", client);
|
||||
return client_read_bytes(client, buf, len);
|
||||
|
||||
if (client->request_body_length != -1) {
|
||||
size_t left = (size_t)client->request_body_length - client->request_body_read;
|
||||
if (len > left) {
|
||||
ICECAST_LOG_DEBUG("Limiting read request to left over body size: left %zu byte, requested %zu byte", left, len);
|
||||
len = left;
|
||||
}
|
||||
}
|
||||
|
||||
ret = client_read_bytes(client, buf, len);
|
||||
|
||||
if (ret > 0) {
|
||||
client->request_body_read += ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* we might un-static this if needed at some time in distant future. -- ph3-der-loewe, 2018-04-17 */
|
||||
@ -468,7 +487,10 @@ int client_body_eof(client_t *client)
|
||||
if (!client)
|
||||
return -1;
|
||||
|
||||
if (client->encoding) {
|
||||
if (client->request_body_length != -1 && client->request_body_read == (size_t)client->request_body_length) {
|
||||
ICECAST_LOG_DEBUG("Reached given body length (client=%p)", client);
|
||||
ret = 1;
|
||||
} else if (client->encoding) {
|
||||
ICECAST_LOG_DEBUG("Looking for body EOF with encoding (client=%p)", client);
|
||||
ret = httpp_encoding_eof(client->encoding, (int(*)(void*))client_eof, client);
|
||||
} else {
|
||||
|
@ -62,6 +62,14 @@ struct _client_tag {
|
||||
/* protocol client uses */
|
||||
protocol_t protocol;
|
||||
|
||||
/* http request body length
|
||||
* -1 for streaming (e.g. chunked), 0 for no body, >0 for NNN bytes
|
||||
*/
|
||||
ssize_t request_body_length;
|
||||
|
||||
/* http request body length read so far */
|
||||
size_t request_body_read;
|
||||
|
||||
/* http response code for this client */
|
||||
int respcode;
|
||||
|
||||
|
@ -1431,6 +1431,50 @@ static void __prepare_shoutcast_admin_cgi_request(client_t *client)
|
||||
global_unlock();
|
||||
}
|
||||
|
||||
static void _update_client_request_body_length(client_t *client)
|
||||
{
|
||||
const char *header;
|
||||
long long unsigned int scannumber;
|
||||
int have = 0;
|
||||
|
||||
if (!have) {
|
||||
if (client->parser->req_type == httpp_req_source) {
|
||||
client->request_body_length = -1; /* streaming */
|
||||
have = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!have) {
|
||||
header = httpp_getvar(client->parser, "transfer-encoding");
|
||||
if (header) {
|
||||
if (strcasecmp(header, "identity") != 0) {
|
||||
client->request_body_length = -1; /* streaming */
|
||||
have = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!have) {
|
||||
header = httpp_getvar(client->parser, "content-length");
|
||||
if (header) {
|
||||
if (sscanf(header, "%llu", &scannumber) == 1) {
|
||||
client->request_body_length = scannumber;
|
||||
have = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!have) {
|
||||
if (client->parser->req_type == httpp_req_put) {
|
||||
/* As we don't know yet, we asume this PUT is in streaming mode */
|
||||
client->request_body_length = -1; /* streaming */
|
||||
have = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ICECAST_LOG_DEBUG("Client %p has request_body_length=%zi", client, client->request_body_length);
|
||||
}
|
||||
|
||||
/* Connection thread. Here we take clients off the connection queue and check
|
||||
* the contents provided. We set up the parser then hand off to the specific
|
||||
* request handler.
|
||||
@ -1489,6 +1533,8 @@ static void _handle_connection(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
_update_client_request_body_length(client);
|
||||
|
||||
upgrade = httpp_getvar(parser, "upgrade");
|
||||
connection = httpp_getvar(parser, "connection");
|
||||
if (upgrade && connection && strcasecmp(connection, "upgrade") == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user