urlmon: Implemented validation of the host name component of a IUriBuilder.
This commit is contained in:
parent
fb161e216f
commit
63723845c4
|
@ -4823,7 +4823,6 @@ static const uri_builder_test uri_builder_tests[] = {
|
||||||
{
|
{
|
||||||
{FALSE},
|
{FALSE},
|
||||||
},
|
},
|
||||||
|
|
||||||
{TRUE,TRUE,999999,S_OK,FALSE},
|
{TRUE,TRUE,999999,S_OK,FALSE},
|
||||||
0,S_OK,TRUE,
|
0,S_OK,TRUE,
|
||||||
0,S_OK,TRUE,
|
0,S_OK,TRUE,
|
||||||
|
@ -5236,6 +5235,66 @@ static const uri_builder_test uri_builder_tests[] = {
|
||||||
0,INET_E_INVALID_URL,FALSE,
|
0,INET_E_INVALID_URL,FALSE,
|
||||||
0,INET_E_INVALID_URL,FALSE,
|
0,INET_E_INVALID_URL,FALSE,
|
||||||
0,0,0,INET_E_INVALID_URL,FALSE
|
0,0,0,INET_E_INVALID_URL,FALSE
|
||||||
|
},
|
||||||
|
{ "http://google.com/",0,S_OK,FALSE,
|
||||||
|
{
|
||||||
|
{TRUE,"winehq.org/test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
|
||||||
|
},
|
||||||
|
{FALSE},
|
||||||
|
0,INET_E_INVALID_URL,FALSE,
|
||||||
|
0,INET_E_INVALID_URL,FALSE,
|
||||||
|
0,0,0,INET_E_INVALID_URL,FALSE
|
||||||
|
},
|
||||||
|
{ "http://google.com/",0,S_OK,FALSE,
|
||||||
|
{
|
||||||
|
{TRUE,"winehq.org?test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
|
||||||
|
},
|
||||||
|
{FALSE},
|
||||||
|
0,INET_E_INVALID_URL,FALSE,
|
||||||
|
0,INET_E_INVALID_URL,FALSE,
|
||||||
|
0,0,0,INET_E_INVALID_URL,FALSE
|
||||||
|
},
|
||||||
|
{ "http://google.com/",0,S_OK,FALSE,
|
||||||
|
{
|
||||||
|
{TRUE,"winehq.org#test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE}
|
||||||
|
},
|
||||||
|
{FALSE},
|
||||||
|
0,INET_E_INVALID_URL,FALSE,
|
||||||
|
0,INET_E_INVALID_URL,FALSE,
|
||||||
|
0,0,0,INET_E_INVALID_URL,FALSE
|
||||||
|
},
|
||||||
|
/* Hostname is allowed to contain a ':' (even for known scheme types). */
|
||||||
|
{ "http://google.com/",0,S_OK,FALSE,
|
||||||
|
{
|
||||||
|
{TRUE,"winehq.org:test",NULL,Uri_PROPERTY_HOST,S_OK,FALSE},
|
||||||
|
},
|
||||||
|
{FALSE},
|
||||||
|
0,S_OK,TRUE,
|
||||||
|
0,S_OK,TRUE,
|
||||||
|
0,0,0,S_OK,TRUE,
|
||||||
|
{
|
||||||
|
{"http://winehq.org:test/",S_OK},
|
||||||
|
{"winehq.org:test",S_OK},
|
||||||
|
{"http://winehq.org:test/",S_OK},
|
||||||
|
{"winehq.org:test",S_OK},
|
||||||
|
{"",S_FALSE},
|
||||||
|
{"",S_FALSE},
|
||||||
|
{"winehq.org:test",S_OK},
|
||||||
|
{"",S_FALSE},
|
||||||
|
{"/",S_OK},
|
||||||
|
{"/",S_OK},
|
||||||
|
{"",S_FALSE},
|
||||||
|
{"http://winehq.org:test/",S_OK},
|
||||||
|
{"http",S_OK},
|
||||||
|
{"",S_FALSE},
|
||||||
|
{"",S_FALSE}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{Uri_HOST_DNS,S_OK},
|
||||||
|
{80,S_OK},
|
||||||
|
{URL_SCHEME_HTTP,S_OK},
|
||||||
|
{URLZONE_INVALID,E_NOTIMPL}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,12 @@
|
||||||
#define UINT_MAX 0xffffffff
|
#define UINT_MAX 0xffffffff
|
||||||
#define USHORT_MAX 0xffff
|
#define USHORT_MAX 0xffff
|
||||||
|
|
||||||
#define ALLOW_NULL_TERM_SCHEME 0x1
|
#define ALLOW_NULL_TERM_SCHEME 0x01
|
||||||
#define ALLOW_NULL_TERM_USER_NAME 0x2
|
#define ALLOW_NULL_TERM_USER_NAME 0x02
|
||||||
#define ALLOW_NULL_TERM_PASSWORD 0x4
|
#define ALLOW_NULL_TERM_PASSWORD 0x04
|
||||||
|
#define ALLOW_BRACKETLESS_IP_LITERAL 0x08
|
||||||
|
#define SKIP_IP_FUTURE_CHECK 0x10
|
||||||
|
#define IGNORE_PORT_DELIMITER 0x20
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
|
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
|
||||||
|
|
||||||
|
@ -1516,11 +1519,11 @@ static BOOL parse_ipv4address(const WCHAR **ptr, parse_data *data, DWORD flags)
|
||||||
*
|
*
|
||||||
* A reg-name CAN be empty.
|
* A reg-name CAN be empty.
|
||||||
*/
|
*/
|
||||||
static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
|
||||||
const BOOL has_start_bracket = **ptr == '[';
|
const BOOL has_start_bracket = **ptr == '[';
|
||||||
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
|
||||||
BOOL inside_brackets = has_start_bracket;
|
BOOL inside_brackets = has_start_bracket;
|
||||||
BOOL ignore_col = FALSE;
|
BOOL ignore_col = extras & IGNORE_PORT_DELIMITER;
|
||||||
|
|
||||||
/* We have to be careful with file schemes. */
|
/* We have to be careful with file schemes. */
|
||||||
if(data->scheme_type == URL_SCHEME_FILE) {
|
if(data->scheme_type == URL_SCHEME_FILE) {
|
||||||
|
@ -1554,7 +1557,7 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
||||||
if(data->scheme_type != URL_SCHEME_UNKNOWN) {
|
if(data->scheme_type != URL_SCHEME_UNKNOWN) {
|
||||||
*ptr = data->host;
|
*ptr = data->host;
|
||||||
data->host = NULL;
|
data->host = NULL;
|
||||||
TRACE("(%p %p %x): Expected valid port\n", ptr, data, flags);
|
TRACE("(%p %p %x %x): Expected valid port\n", ptr, data, flags, extras);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
} else
|
} else
|
||||||
/* Windows gives up on trying to parse a port when it
|
/* Windows gives up on trying to parse a port when it
|
||||||
|
@ -1585,8 +1588,8 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
||||||
if(has_start_bracket) {
|
if(has_start_bracket) {
|
||||||
/* Make sure the last character of the host wasn't a ']'. */
|
/* Make sure the last character of the host wasn't a ']'. */
|
||||||
if(*(*ptr-1) == ']') {
|
if(*(*ptr-1) == ']') {
|
||||||
TRACE("(%p %p %x): Expected an IP literal inside of the host\n",
|
TRACE("(%p %p %x %x): Expected an IP literal inside of the host\n",
|
||||||
ptr, data, flags);
|
ptr, data, flags, extras);
|
||||||
*ptr = data->host;
|
*ptr = data->host;
|
||||||
data->host = NULL;
|
data->host = NULL;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1603,7 +1606,7 @@ static BOOL parse_reg_name(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
||||||
else
|
else
|
||||||
data->host_type = Uri_HOST_DNS;
|
data->host_type = Uri_HOST_DNS;
|
||||||
|
|
||||||
TRACE("(%p %p %x): Parsed reg-name. host=%s len=%d\n", ptr, data, flags,
|
TRACE("(%p %p %x %x): Parsed reg-name. host=%s len=%d\n", ptr, data, flags, extras,
|
||||||
debugstr_wn(data->host, data->host_len), data->host_len);
|
debugstr_wn(data->host, data->host_len), data->host_len);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1816,27 +1819,33 @@ static BOOL parse_ipvfuture(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IP-literal = "[" ( IPv6address / IPvFuture ) "]" */
|
/* IP-literal = "[" ( IPv6address / IPvFuture ) "]" */
|
||||||
static BOOL parse_ip_literal(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
static BOOL parse_ip_literal(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
|
||||||
data->host = *ptr;
|
data->host = *ptr;
|
||||||
|
|
||||||
if(**ptr != '[') {
|
if(**ptr != '[' && !(extras & ALLOW_BRACKETLESS_IP_LITERAL)) {
|
||||||
data->host = NULL;
|
data->host = NULL;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
} else if(**ptr == '[')
|
||||||
|
|
||||||
++(*ptr);
|
++(*ptr);
|
||||||
|
|
||||||
if(!parse_ipv6address(ptr, data, flags)) {
|
if(!parse_ipv6address(ptr, data, flags)) {
|
||||||
if(!parse_ipvfuture(ptr, data, flags)) {
|
if(extras & SKIP_IP_FUTURE_CHECK || !parse_ipvfuture(ptr, data, flags)) {
|
||||||
*ptr = data->host;
|
*ptr = data->host;
|
||||||
data->host = NULL;
|
data->host = NULL;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(**ptr != ']') {
|
if(**ptr != ']' && !(extras & ALLOW_BRACKETLESS_IP_LITERAL)) {
|
||||||
*ptr = data->host;
|
*ptr = data->host;
|
||||||
data->host = NULL;
|
data->host = NULL;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
} else if(!**ptr && extras & ALLOW_BRACKETLESS_IP_LITERAL) {
|
||||||
|
/* The IP literal didn't contain brackets and was followed by
|
||||||
|
* a NULL terminator, so no reason to even check the port.
|
||||||
|
*/
|
||||||
|
data->host_len = *ptr - data->host;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
++(*ptr);
|
++(*ptr);
|
||||||
|
@ -1860,12 +1869,12 @@ static BOOL parse_ip_literal(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
||||||
*
|
*
|
||||||
* host = IP-literal / IPv4address / reg-name
|
* host = IP-literal / IPv4address / reg-name
|
||||||
*/
|
*/
|
||||||
static BOOL parse_host(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
static BOOL parse_host(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) {
|
||||||
if(!parse_ip_literal(ptr, data, flags)) {
|
if(!parse_ip_literal(ptr, data, flags, extras)) {
|
||||||
if(!parse_ipv4address(ptr, data, flags)) {
|
if(!parse_ipv4address(ptr, data, flags)) {
|
||||||
if(!parse_reg_name(ptr, data, flags)) {
|
if(!parse_reg_name(ptr, data, flags, extras)) {
|
||||||
TRACE("(%p %p %x): Malformed URI, Unknown host type.\n",
|
TRACE("(%p %p %x %x): Malformed URI, Unknown host type.\n",
|
||||||
ptr, data, flags);
|
ptr, data, flags, extras);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1884,7 +1893,7 @@ static BOOL parse_authority(const WCHAR **ptr, parse_data *data, DWORD flags) {
|
||||||
/* Parsing the port will happen during one of the host parsing
|
/* Parsing the port will happen during one of the host parsing
|
||||||
* routines (if the URI has a port).
|
* routines (if the URI has a port).
|
||||||
*/
|
*/
|
||||||
if(!parse_host(ptr, data, flags))
|
if(!parse_host(ptr, data, flags, 0))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -3651,6 +3660,37 @@ static HRESULT validate_userinfo(const UriBuilder *builder, parse_data *data, DW
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT validate_host(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
||||||
|
const WCHAR *ptr;
|
||||||
|
const WCHAR **pptr;
|
||||||
|
DWORD expected_len;
|
||||||
|
|
||||||
|
if(builder->host) {
|
||||||
|
ptr = builder->host;
|
||||||
|
expected_len = builder->host_len;
|
||||||
|
} else if(!(builder->modified_props & Uri_HAS_HOST) && builder->uri && builder->uri->host_start > -1) {
|
||||||
|
ptr = builder->uri->canon_uri + builder->uri->host_start;
|
||||||
|
expected_len = builder->uri->host_len;
|
||||||
|
} else
|
||||||
|
ptr = NULL;
|
||||||
|
|
||||||
|
if(ptr) {
|
||||||
|
DWORD extras = ALLOW_BRACKETLESS_IP_LITERAL|IGNORE_PORT_DELIMITER|SKIP_IP_FUTURE_CHECK;
|
||||||
|
pptr = &ptr;
|
||||||
|
|
||||||
|
if(parse_host(pptr, data, flags, extras) && data->host_len == expected_len)
|
||||||
|
TRACE("(%p %p %x): Found valid host name %s len=%d type=%d.\n", builder, data, flags,
|
||||||
|
debugstr_wn(data->host, data->host_len), data->host_len, data->host_type);
|
||||||
|
else {
|
||||||
|
TRACE("(%p %p %x): Invalid host name found %s expected_len=%d.\n", builder, data, flags,
|
||||||
|
debugstr_wn(ptr, expected_len), expected_len);
|
||||||
|
return INET_E_INVALID_URL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT validate_components(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
static HRESULT validate_components(const UriBuilder *builder, parse_data *data, DWORD flags) {
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -3676,6 +3716,13 @@ static HRESULT validate_components(const UriBuilder *builder, parse_data *data,
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
|
hr = validate_host(builder, data, flags);
|
||||||
|
if(FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
/* The URI is opaque if it doesn't have an authority component. */
|
||||||
|
data->is_opaque = !data->username && !data->password && !data->host;
|
||||||
|
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue