Skip to content

Commit

Permalink
rest_client: Add the 'max_transfer_size' setting
Browse files Browse the repository at this point in the history
Sets a limit on the maximum size of a single download.  May be important
for security purposes, to prevent certain attack vectors such as
malicious "x5u" certificate URLs in STIR/SHAKEN setups.
    Default: 0 KB (check disabled)

Issue discovered during OpenSIPIt'02,
	by Alfred Farrugia & Sandro Gauci (Enable Security)

(cherry picked from commit b56bba3)
  • Loading branch information
liviuchircu committed Nov 18, 2021
1 parent 2f1727b commit 30029bd
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 3 deletions.
23 changes: 23 additions & 0 deletions modules/rest_client/doc/rest_client_admin.xml
Expand Up @@ -147,6 +147,29 @@ modparam("rest_client", "max_async_transfers", 300)
</example>
</section>

<section id="param_max_transfer_size" xreflabel="max_transfer_size">
<title><varname>max_transfer_size</varname> (integer)</title>
<para>
The maximum allowed size of a single transfer (download). Reaching
this limit during a transfer will cause the transfer to stop
immediately, returning error -10 at script level. A value of
<emphasis role='bold'>0</emphasis> will disable the check.
</para>
<para>
<emphasis>
Default value is <quote>0</quote> (KB).
</emphasis>
</para>
<example>
<title>Setting the <varname>max_transfer_size</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("rest_client", "max_transfer_size", 64)
...
</programlisting>
</example>
</section>

<section id="param_ssl_verifypeer" xreflabel="ssl_verifypeer">
<title><varname>ssl_verifypeer</varname> (integer)</title>
<para>
Expand Down
11 changes: 8 additions & 3 deletions modules/rest_client/rest_cb.c
Expand Up @@ -34,6 +34,8 @@
* @size: size of a block
* @nmemb: number of blocks
* @body: parameter previously set with the CURLOPT_WRITEDATA option
*
* Return: number of bytes processed (if != @len, transfer is aborted)
*/
size_t write_func(char *ptr, size_t size, size_t nmemb, void *body)
{
Expand All @@ -47,14 +49,17 @@ size_t write_func(char *ptr, size_t size, size_t nmemb, void *body)
if (len == 0)
return 0;

if (len < 0)
len = strlen(ptr);
if (max_transfer_size && buff->len + len > max_transfer_size * 1024UL) {
LM_ERR("max download size exceeded (%u KB, per 'max_transfer_size'), "
"aborting transfer\n", max_transfer_size);
return 0;
}

buff->s = pkg_realloc(buff->s, buff->len + len + 1);
if (!buff->s) {
buff->len = 0;
LM_ERR("No more pkg memory!\n");
return E_OUT_OF_MEM;
return 0;
}

memcpy(buff->s + buff->len, ptr, len);
Expand Down
2 changes: 2 additions & 0 deletions modules/rest_client/rest_cb.h
Expand Up @@ -25,6 +25,8 @@
#ifndef _REST_CB_H_
#define _REST_CB_H_

#include "rest_client.h"

#include "../../str.h"
#include "../../mem/mem.h"
#include "../../error.h"
Expand Down
2 changes: 2 additions & 0 deletions modules/rest_client/rest_client.c
Expand Up @@ -51,6 +51,7 @@ long connection_timeout_ms;
int max_async_transfers = 100;
long curl_timeout = 20;
char *ssl_capath;
unsigned int max_transfer_size = 0; /* KB */

/*
* curl_multi_perform() may indicate a "try again" response even
Expand Down Expand Up @@ -196,6 +197,7 @@ static param_export_t params[] = {
{ "connection_timeout", INT_PARAM, &connection_timeout },
{ "connect_poll_interval", INT_PARAM, &connect_poll_interval },
{ "max_async_transfers", INT_PARAM, &max_async_transfers },
{ "max_transfer_size", INT_PARAM, &max_transfer_size },
{ "curl_timeout", INT_PARAM, &curl_timeout },
{ "ssl_capath", STR_PARAM, &ssl_capath },
{ "ssl_verifypeer", INT_PARAM, &ssl_verifypeer },
Expand Down
1 change: 1 addition & 0 deletions modules/rest_client/rest_client.h
Expand Up @@ -31,5 +31,6 @@ enum tr_rest_subtype {
};

extern int enable_expect_100;
extern unsigned int max_transfer_size;

#endif /* _REST_CLIENT_ */

0 comments on commit 30029bd

Please sign in to comment.