mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-04 19:31:56 +00:00
Merge commit from fork
Cap `Content-Length` at `HTTP_POST_MAX_BODY` (10 MiB) and size the allocation to the actual body length (`content_length + 1` for the trailing NUL). Also fix `WS_BLOCK` units — `kws_raw_read` takes ms, set to 10000.
This commit is contained in:
committed by
GitHub
parent
e3dc9950fd
commit
33ee3663bb
@@ -41,6 +41,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_verto_runtime);
|
||||
SWITCH_MODULE_DEFINITION(mod_verto, mod_verto_load, mod_verto_shutdown, mod_verto_runtime);
|
||||
|
||||
#define HTTP_CHUNK_SIZE 1024 * 32
|
||||
#define HTTP_POST_MAX_BODY (10 * 1024 * 1024) /* max accepted Content-Length for form-urlencoded POST */
|
||||
#define EP_NAME "verto.rtc"
|
||||
//#define WSS_STANDALONE 1
|
||||
#include "libks/ks.h"
|
||||
@@ -1824,7 +1825,7 @@ new_req:
|
||||
char *buffer = NULL;
|
||||
switch_ssize_t len = 0, bytes = 0;
|
||||
|
||||
if (request->content_length && request->content_length > 10 * 1024 * 1024 - 1) {
|
||||
if (request->content_length && request->content_length >= HTTP_POST_MAX_BODY) {
|
||||
char *data = "HTTP/1.1 413 Request Entity Too Large\r\n"
|
||||
"Content-Length: 0\r\n\r\n";
|
||||
kws_raw_write(jsock->ws, data, strlen(data));
|
||||
@@ -1832,16 +1833,16 @@ new_req:
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!(buffer = malloc(2 * 1024 * 1024))) {
|
||||
if (!(buffer = malloc(request->content_length + 1))) {
|
||||
goto request_err;
|
||||
}
|
||||
|
||||
while(bytes < (switch_ssize_t)request->content_length) {
|
||||
len = request->content_length - bytes;
|
||||
|
||||
#define WS_BLOCK 1
|
||||
#define WS_BLOCK 10000 /* ms; matches libks's internal default */
|
||||
|
||||
if ((len = kws_raw_read(jsock->ws, buffer + bytes, len, WS_BLOCK)) < 0) {
|
||||
if ((len = kws_raw_read(jsock->ws, buffer + bytes, len, WS_BLOCK)) <= 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read error %" SWITCH_SSIZE_T_FMT"\n", len);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ noinst_PROGRAMS += switch_core_video switch_core_db switch_vad switch_packetizer
|
||||
noinst_PROGRAMS += switch_stun
|
||||
noinst_PROGRAMS += test_tts_format
|
||||
noinst_PROGRAMS+= switch_hold switch_sip
|
||||
noinst_PROGRAMS += test_mod_verto
|
||||
|
||||
if HAVE_PCAP
|
||||
noinst_PROGRAMS += switch_rtp_pcap
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0"?>
|
||||
<document type="freeswitch/xml">
|
||||
<X-PRE-PROCESS cmd="set" data="local_ip_v4=127.0.0.1"/>
|
||||
<X-PRE-PROCESS cmd="set" data="domain=127.0.0.1"/>
|
||||
|
||||
<section name="configuration" description="Configuration">
|
||||
|
||||
<configuration name="modules.conf" description="Modules">
|
||||
<modules>
|
||||
<load module="mod_console"/>
|
||||
<load module="mod_loopback"/>
|
||||
<load module="mod_dptools"/>
|
||||
<load module="mod_dialplan_xml"/>
|
||||
<load module="mod_sndfile"/>
|
||||
<load module="mod_verto"/>
|
||||
</modules>
|
||||
</configuration>
|
||||
|
||||
<configuration name="switch.conf" description="Core Configuration">
|
||||
<settings>
|
||||
<param name="colorize-console" value="false"/>
|
||||
<param name="loglevel" value="debug"/>
|
||||
<param name="rtp-start-port" value="16384"/>
|
||||
<param name="rtp-end-port" value="16484"/>
|
||||
</settings>
|
||||
</configuration>
|
||||
|
||||
<configuration name="console.conf" description="Console Logger">
|
||||
<mappings>
|
||||
<map name="all" value="console,debug,info,notice,warning,err,crit,alert"/>
|
||||
</mappings>
|
||||
<settings>
|
||||
<param name="colorize" value="false"/>
|
||||
<param name="loglevel" value="debug"/>
|
||||
</settings>
|
||||
</configuration>
|
||||
|
||||
<configuration name="timezones.conf" description="Timezones">
|
||||
<timezones>
|
||||
<zone name="GMT" value="GMT0"/>
|
||||
</timezones>
|
||||
</configuration>
|
||||
|
||||
<X-PRE-PROCESS cmd="include" data="verto.conf.xml"/>
|
||||
|
||||
</section>
|
||||
</document>
|
||||
@@ -0,0 +1,36 @@
|
||||
<configuration name="verto.conf" description="HTML5 Verto Endpoint (test)">
|
||||
|
||||
<settings>
|
||||
<param name="debug" value="0"/>
|
||||
</settings>
|
||||
|
||||
<profiles>
|
||||
<profile name="test-v4">
|
||||
<!--
|
||||
bind-local without "secure" → plain TCP. Port 33081 chosen to avoid
|
||||
clashing with a default vanilla install on 8081.
|
||||
-->
|
||||
<param name="bind-local" value="127.0.0.1:33081"/>
|
||||
<param name="force-register-domain" value="127.0.0.1"/>
|
||||
<param name="userauth" value="true"/>
|
||||
<param name="blind-reg" value="false"/>
|
||||
<param name="rtp-ip" value="127.0.0.1"/>
|
||||
<param name="timer-name" value="soft"/>
|
||||
|
||||
<!--
|
||||
vhosts block is REQUIRED for http_run() to be invoked
|
||||
(see mod_verto.c:2041,2061 — KWS_HTTP flag depends on it).
|
||||
No auth-realm here, so requests bypass the 401 challenge and
|
||||
reach the body-read path (which is itself pre-auth anyway).
|
||||
-->
|
||||
<vhosts>
|
||||
<vhost domain="127.0.0.1">
|
||||
<param name="alias" value="localhost"/>
|
||||
<param name="root" value="."/>
|
||||
<param name="index" value="index.html"/>
|
||||
</vhost>
|
||||
</vhosts>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2026, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dmitry Verenitsin <dmitry.verenitsin@signalwire.com>
|
||||
*
|
||||
*
|
||||
* test_mod_verto.c -- Tests for mod_verto
|
||||
*
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <test/switch_test.h>
|
||||
|
||||
#define VERTO_TEST_HOST "127.0.0.1"
|
||||
#define VERTO_TEST_PORT 33081
|
||||
|
||||
/* Must match HTTP_POST_MAX_BODY in src/mod/endpoints/mod_verto/mod_verto.c */
|
||||
#define VERTO_POST_MAX_BODY (10 * 1024 * 1024)
|
||||
|
||||
static switch_status_t verto_connect(switch_socket_t **sock_out, switch_memory_pool_t *pool)
|
||||
{
|
||||
switch_sockaddr_t *addr = NULL;
|
||||
switch_socket_t *sock = NULL;
|
||||
int attempts;
|
||||
|
||||
if (switch_sockaddr_info_get(&addr, VERTO_TEST_HOST, SWITCH_UNSPEC,
|
||||
VERTO_TEST_PORT, 0, pool) != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
for (attempts = 0; attempts < 50; attempts++) {
|
||||
if (switch_socket_create(&sock, switch_sockaddr_get_family(addr),
|
||||
SOCK_STREAM, SWITCH_PROTO_TCP, pool) != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
switch_socket_opt_set(sock, SWITCH_SO_TCP_NODELAY, 1);
|
||||
|
||||
if (switch_socket_connect(sock, addr) == SWITCH_STATUS_SUCCESS) {
|
||||
*sock_out = sock;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_socket_close(sock);
|
||||
sock = NULL;
|
||||
switch_yield(100000);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
static switch_status_t send_all(switch_socket_t *sock, const char *buf, switch_size_t len)
|
||||
{
|
||||
switch_size_t remaining = len;
|
||||
const char *p = buf;
|
||||
|
||||
while (remaining > 0) {
|
||||
switch_size_t n = remaining;
|
||||
if (switch_socket_send(sock, p, &n) != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (n == 0) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
p += n;
|
||||
remaining -= n;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_size_t read_status_line(switch_socket_t *sock, char *out, switch_size_t cap)
|
||||
{
|
||||
switch_size_t got = 0;
|
||||
|
||||
while (got < cap - 1) {
|
||||
switch_size_t want = cap - 1 - got;
|
||||
if (switch_socket_recv(sock, out + got, &want) != SWITCH_STATUS_SUCCESS || want == 0) {
|
||||
break;
|
||||
}
|
||||
got += want;
|
||||
if (memchr(out, '\n', got)) break;
|
||||
}
|
||||
out[got] = '\0';
|
||||
return got;
|
||||
}
|
||||
|
||||
FST_CORE_DB_BEGIN("./conf_verto")
|
||||
{
|
||||
FST_SUITE_BEGIN(test_mod_verto)
|
||||
{
|
||||
FST_SETUP_BEGIN()
|
||||
{
|
||||
fst_requires_module("mod_verto");
|
||||
switch_yield(500000);
|
||||
}
|
||||
FST_SETUP_END()
|
||||
|
||||
FST_TEARDOWN_BEGIN()
|
||||
{
|
||||
}
|
||||
FST_TEARDOWN_END()
|
||||
|
||||
FST_TEST_BEGIN(post_at_cap_returns_413)
|
||||
{
|
||||
switch_memory_pool_t *pool = NULL;
|
||||
switch_socket_t *sock = NULL;
|
||||
char req[256];
|
||||
char resp[64] = { 0 };
|
||||
switch_size_t req_len;
|
||||
|
||||
do {
|
||||
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not allocate memory pool");
|
||||
break;
|
||||
}
|
||||
if (verto_connect(&sock, pool) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not connect to verto listener");
|
||||
break;
|
||||
}
|
||||
|
||||
req_len = switch_snprintf(req, sizeof(req),
|
||||
"POST / HTTP/1.1\r\n"
|
||||
"Host: " VERTO_TEST_HOST "\r\n"
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
"Content-Length: %d\r\n"
|
||||
"\r\n",
|
||||
VERTO_POST_MAX_BODY);
|
||||
|
||||
if (send_all(sock, req, req_len) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not send request");
|
||||
break;
|
||||
}
|
||||
|
||||
read_status_line(sock, resp, sizeof(resp));
|
||||
fst_check_string_starts_with(resp, "HTTP/1.1 413");
|
||||
} while (0);
|
||||
|
||||
if (sock) switch_socket_close(sock);
|
||||
if (pool) switch_core_destroy_memory_pool(&pool);
|
||||
}
|
||||
FST_TEST_END()
|
||||
|
||||
FST_TEST_BEGIN(post_small_body_parsed)
|
||||
{
|
||||
switch_memory_pool_t *pool = NULL;
|
||||
switch_socket_t *sock = NULL;
|
||||
const switch_size_t body_len = 32 * 1024;
|
||||
char *body = NULL;
|
||||
char req[256];
|
||||
char resp[64] = { 0 };
|
||||
switch_size_t req_len;
|
||||
|
||||
do {
|
||||
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not allocate memory pool");
|
||||
break;
|
||||
}
|
||||
if (verto_connect(&sock, pool) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not connect to verto listener");
|
||||
break;
|
||||
}
|
||||
|
||||
body = malloc(body_len);
|
||||
if (!body) {
|
||||
fst_fail("could not allocate body buffer");
|
||||
break;
|
||||
}
|
||||
memset(body, 'x', body_len);
|
||||
|
||||
req_len = switch_snprintf(req, sizeof(req),
|
||||
"POST / HTTP/1.1\r\n"
|
||||
"Host: " VERTO_TEST_HOST "\r\n"
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
"Content-Length: %" SWITCH_SIZE_T_FMT "\r\n"
|
||||
"\r\n",
|
||||
body_len);
|
||||
|
||||
if (send_all(sock, req, req_len) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not send headers");
|
||||
break;
|
||||
}
|
||||
if (send_all(sock, body, body_len) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not send body");
|
||||
break;
|
||||
}
|
||||
|
||||
read_status_line(sock, resp, sizeof(resp));
|
||||
fst_check_string_starts_with(resp, "HTTP/1.1 ");
|
||||
fst_xcheck(strncmp(resp, "HTTP/1.1 413", 12) != 0,
|
||||
"server returned 413 below cap");
|
||||
} while (0);
|
||||
|
||||
free(body);
|
||||
if (sock) switch_socket_close(sock);
|
||||
if (pool) switch_core_destroy_memory_pool(&pool);
|
||||
}
|
||||
FST_TEST_END()
|
||||
|
||||
FST_TEST_BEGIN(post_large_body_no_overflow)
|
||||
{
|
||||
switch_memory_pool_t *pool = NULL;
|
||||
switch_socket_t *sock = NULL;
|
||||
const switch_size_t body_len = 8 * 1024 * 1024;
|
||||
char *body = NULL;
|
||||
char req[256];
|
||||
char resp[64] = { 0 };
|
||||
switch_size_t req_len;
|
||||
|
||||
do {
|
||||
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not allocate memory pool");
|
||||
break;
|
||||
}
|
||||
if (verto_connect(&sock, pool) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not connect to verto listener");
|
||||
break;
|
||||
}
|
||||
|
||||
body = malloc(body_len);
|
||||
if (!body) {
|
||||
fst_fail("could not allocate body buffer");
|
||||
break;
|
||||
}
|
||||
memset(body, 'x', body_len);
|
||||
|
||||
req_len = switch_snprintf(req, sizeof(req),
|
||||
"POST / HTTP/1.1\r\n"
|
||||
"Host: " VERTO_TEST_HOST "\r\n"
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
"Content-Length: %" SWITCH_SIZE_T_FMT "\r\n"
|
||||
"\r\n",
|
||||
body_len);
|
||||
|
||||
if (send_all(sock, req, req_len) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not send headers");
|
||||
break;
|
||||
}
|
||||
if (send_all(sock, body, body_len) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not send body");
|
||||
break;
|
||||
}
|
||||
|
||||
read_status_line(sock, resp, sizeof(resp));
|
||||
fst_check_string_starts_with(resp, "HTTP/1.1 ");
|
||||
fst_xcheck(strncmp(resp, "HTTP/1.1 413", 12) != 0,
|
||||
"server returned 413 below cap");
|
||||
} while (0);
|
||||
|
||||
free(body);
|
||||
if (sock) switch_socket_close(sock);
|
||||
if (pool) switch_core_destroy_memory_pool(&pool);
|
||||
}
|
||||
FST_TEST_END()
|
||||
|
||||
FST_TEST_BEGIN(post_overflow_length_returns_413)
|
||||
{
|
||||
switch_memory_pool_t *pool = NULL;
|
||||
switch_socket_t *sock = NULL;
|
||||
char req[256];
|
||||
char resp[64] = { 0 };
|
||||
switch_size_t req_len;
|
||||
|
||||
do {
|
||||
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not allocate memory pool");
|
||||
break;
|
||||
}
|
||||
if (verto_connect(&sock, pool) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not connect to verto listener");
|
||||
break;
|
||||
}
|
||||
|
||||
req_len = switch_snprintf(req, sizeof(req),
|
||||
"POST / HTTP/1.1\r\n"
|
||||
"Host: " VERTO_TEST_HOST "\r\n"
|
||||
"Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
"Content-Length: 9999999999\r\n"
|
||||
"\r\n");
|
||||
|
||||
if (send_all(sock, req, req_len) != SWITCH_STATUS_SUCCESS) {
|
||||
fst_fail("could not send request");
|
||||
break;
|
||||
}
|
||||
|
||||
read_status_line(sock, resp, sizeof(resp));
|
||||
fst_check_string_starts_with(resp, "HTTP/1.1 413");
|
||||
} while (0);
|
||||
|
||||
if (sock) switch_socket_close(sock);
|
||||
if (pool) switch_core_destroy_memory_pool(&pool);
|
||||
}
|
||||
FST_TEST_END()
|
||||
}
|
||||
FST_SUITE_END()
|
||||
}
|
||||
FST_CORE_END()
|
||||
Reference in New Issue
Block a user