Commit 99d97efb authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

url: validate host name and path

This avoids passing embedding unexpected garbage into network requests,
leading to weird errors, or in the worst cases, injection (e.g. white
spaces in HTTP/1.x requests).
parent 736e7e75
......@@ -72,7 +72,7 @@ char *vlc_uri_decode (char *str)
return str;
}
static inline bool isurisafe (int c)
static bool isurisafe (int c)
{
/* These are the _unreserved_ URI characters (RFC3986 §2.3) */
return ((unsigned char)(c - 'a') < 26)
......@@ -81,6 +81,18 @@ static inline bool isurisafe (int c)
|| (strchr ("-._~", c) != NULL);
}
static bool isurisubdelim(int c)
{
return strchr("!$&'()*+,;=", c) != NULL;
}
static bool isurihex(int c)
{ /* Same as isxdigit() but does not depend on locale and unsignedness */
return ((unsigned char)(c - '0') < 10)
|| ((unsigned char)(c - 'A') < 6)
|| ((unsigned char)(c - 'a') < 6);
}
static char *encode_URI_bytes (const char *str, size_t *restrict lenp)
{
char *buf = malloc (3 * *lenp + 1);
......@@ -309,6 +321,39 @@ out:
static char *vlc_idna_to_ascii (const char *);
static bool vlc_uri_component_validate(const char *str, const char *extras)
{
if (str == NULL)
return false;
for (size_t i = 0; str[i] != '\0'; i++)
{
int c = str[i];
if (isurisafe(c) || isurisubdelim(c))
continue;
if (strchr(extras, c) != NULL)
continue;
if (c == '%' && isurihex(str[i + 1]) && isurihex(str[i + 2]))
{
i += 2;
continue;
}
return false;
}
return true;
}
static bool vlc_uri_host_validate(const char *str)
{
return vlc_uri_component_validate(str, "");
}
static bool vlc_uri_path_validate(const char *str)
{
return vlc_uri_component_validate(str, "/@:");
}
/**
* Splits an URL into parts.
* \param url structure of URL parts [OUT]
......@@ -412,6 +457,11 @@ void vlc_UrlParse (vlc_url_t *restrict url, const char *str)
url->psz_host = vlc_idna_to_ascii (cur);
}
if (!vlc_uri_host_validate(url->psz_host))
{
free(url->psz_host);
url->psz_host = NULL;
}
/* Port number */
if (next != NULL)
......@@ -419,6 +469,8 @@ void vlc_UrlParse (vlc_url_t *restrict url, const char *str)
if (url->psz_path != NULL)
*url->psz_path = '/'; /* restore leading slash */
if (!vlc_uri_path_validate(url->psz_path))
url->psz_path = NULL;
}
/**
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment