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->con = con;
|
||||||
client->parser = parser;
|
client->parser = parser;
|
||||||
client->protocol = ICECAST_PROTOCOL_HTTP;
|
client->protocol = ICECAST_PROTOCOL_HTTP;
|
||||||
|
client->request_body_length = 0;
|
||||||
|
client->request_body_read = 0;
|
||||||
client->admin_command = ADMIN_COMMAND_ERROR;
|
client->admin_command = ADMIN_COMMAND_ERROR;
|
||||||
client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
|
client->refbuf = refbuf_new (PER_CLIENT_REFBUF_SIZE);
|
||||||
client->refbuf->len = 0; /* force reader code to ignore buffer contents */
|
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 client_body_read(client_t *client, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
ICECAST_LOG_DEBUG("Reading from body (client=%p)", client);
|
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 */
|
/* 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)
|
if (!client)
|
||||||
return -1;
|
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);
|
ICECAST_LOG_DEBUG("Looking for body EOF with encoding (client=%p)", client);
|
||||||
ret = httpp_encoding_eof(client->encoding, (int(*)(void*))client_eof, client);
|
ret = httpp_encoding_eof(client->encoding, (int(*)(void*))client_eof, client);
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,6 +62,14 @@ struct _client_tag {
|
|||||||
/* protocol client uses */
|
/* protocol client uses */
|
||||||
protocol_t protocol;
|
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 */
|
/* http response code for this client */
|
||||||
int respcode;
|
int respcode;
|
||||||
|
|
||||||
|
@ -1431,6 +1431,50 @@ static void __prepare_shoutcast_admin_cgi_request(client_t *client)
|
|||||||
global_unlock();
|
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
|
/* 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
|
* the contents provided. We set up the parser then hand off to the specific
|
||||||
* request handler.
|
* request handler.
|
||||||
@ -1489,6 +1533,8 @@ static void _handle_connection(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_update_client_request_body_length(client);
|
||||||
|
|
||||||
upgrade = httpp_getvar(parser, "upgrade");
|
upgrade = httpp_getvar(parser, "upgrade");
|
||||||
connection = httpp_getvar(parser, "connection");
|
connection = httpp_getvar(parser, "connection");
|
||||||
if (upgrade && connection && strcasecmp(connection, "upgrade") == 0) {
|
if (upgrade && connection && strcasecmp(connection, "upgrade") == 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user