Module: wine Branch: master Commit: e48b81036aa36e91458e68745608de48650e8b8e URL: http://source.winehq.org/git/wine.git/?a=commit;h=e48b81036aa36e91458e687456...
Author: Thomas Mullaly thomas.mullaly@gmail.com Date: Sat Sep 18 17:10:33 2010 -0400
urlmon: Implemented validation for the userinfo component when create an IUri with IUriBuilder.
---
dlls/urlmon/tests/uri.c | 84 ++++++++++++++++++++++++++++++++++++ dlls/urlmon/uri.c | 108 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 185 insertions(+), 7 deletions(-)
diff --git a/dlls/urlmon/tests/uri.c b/dlls/urlmon/tests/uri.c index 617486f..3bbb578 100644 --- a/dlls/urlmon/tests/uri.c +++ b/dlls/urlmon/tests/uri.c @@ -5124,6 +5124,90 @@ static const uri_builder_test uri_builder_tests[] = { 0,INET_E_INVALID_URL,FALSE, 0,INET_E_INVALID_URL,FALSE, 0,0,0,INET_E_INVALID_URL,FALSE + }, + /* UserName can't contain any character that is a delimeter for another + * component that appears after it in a normal URI. + */ + { "http://google.com/%22,0,S_OK,FALSE, + { + {TRUE,"user:pass",NULL,Uri_PROPERTY_USER_NAME,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/%22,0,S_OK,FALSE, + { + {TRUE,"user@google.com",NULL,Uri_PROPERTY_USER_NAME,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/%22,0,S_OK,FALSE, + { + {TRUE,"user/path",NULL,Uri_PROPERTY_USER_NAME,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/%22,0,S_OK,FALSE, + { + {TRUE,"user?Query",NULL,Uri_PROPERTY_USER_NAME,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/%22,0,S_OK,FALSE, + { + {TRUE,"user#Frag",NULL,Uri_PROPERTY_USER_NAME,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/%22,0,S_OK,FALSE, + { + {TRUE,"pass@google.com",NULL,Uri_PROPERTY_PASSWORD,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/%22,0,S_OK,FALSE, + { + {TRUE,"pass/path",NULL,Uri_PROPERTY_PASSWORD,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/%22,0,S_OK,FALSE, + { + {TRUE,"pass?query",NULL,Uri_PROPERTY_PASSWORD,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/%22,0,S_OK,FALSE, + { + {TRUE,"pass#frag",NULL,Uri_PROPERTY_PASSWORD,S_OK,FALSE} + }, + {FALSE}, + 0,INET_E_INVALID_URL,FALSE, + 0,INET_E_INVALID_URL,FALSE, + 0,0,0,INET_E_INVALID_URL,FALSE } };
diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c index f46cbfb..eaf8c83 100644 --- a/dlls/urlmon/uri.c +++ b/dlls/urlmon/uri.c @@ -26,7 +26,9 @@ #define UINT_MAX 0xffffffff #define USHORT_MAX 0xffff
-#define ALLOW_NULL_TERM_SCHEME 0x1 +#define ALLOW_NULL_TERM_SCHEME 0x1 +#define ALLOW_NULL_TERM_USER_NAME 0x2 +#define ALLOW_NULL_TERM_PASSWORD 0x4
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
@@ -1281,7 +1283,7 @@ static BOOL parse_scheme(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD return TRUE; }
-static BOOL parse_username(const WCHAR **ptr, parse_data *data, DWORD flags) { +static BOOL parse_username(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) { data->username = *ptr;
while(**ptr != ':' && **ptr != '@') { @@ -1294,7 +1296,9 @@ static BOOL parse_username(const WCHAR **ptr, parse_data *data, DWORD flags) { } } else continue; - } else if(is_auth_delim(**ptr, data->scheme_type != URL_SCHEME_UNKNOWN)) { + } else if(extras & ALLOW_NULL_TERM_USER_NAME && !**ptr) + break; + else if(is_auth_delim(**ptr, data->scheme_type != URL_SCHEME_UNKNOWN)) { *ptr = data->username; data->username = NULL; return FALSE; @@ -1307,7 +1311,7 @@ static BOOL parse_username(const WCHAR **ptr, parse_data *data, DWORD flags) { return TRUE; }
-static BOOL parse_password(const WCHAR **ptr, parse_data *data, DWORD flags) { +static BOOL parse_password(const WCHAR **ptr, parse_data *data, DWORD flags, DWORD extras) { const WCHAR *start = *ptr;
if(**ptr != ':') @@ -1326,7 +1330,9 @@ static BOOL parse_password(const WCHAR **ptr, parse_data *data, DWORD flags) { } } else continue; - } else if(is_auth_delim(**ptr, data->scheme_type != URL_SCHEME_UNKNOWN)) { + } else if(extras & ALLOW_NULL_TERM_PASSWORD && !**ptr) + break; + else if(is_auth_delim(**ptr, data->scheme_type != URL_SCHEME_UNKNOWN)) { *ptr = start; data->password = NULL; return FALSE; @@ -1361,12 +1367,12 @@ static BOOL parse_password(const WCHAR **ptr, parse_data *data, DWORD flags) { static void parse_userinfo(const WCHAR **ptr, parse_data *data, DWORD flags) { const WCHAR *start = *ptr;
- if(!parse_username(ptr, data, flags)) { + if(!parse_username(ptr, data, flags, 0)) { TRACE("(%p %p %x): URI contained no userinfo.\n", ptr, data, flags); return; }
- if(!parse_password(ptr, data, flags)) { + if(!parse_password(ptr, data, flags, 0)) { *ptr = start; data->username = NULL; data->username_len = 0; @@ -3561,6 +3567,90 @@ static HRESULT validate_scheme_name(const UriBuilder *builder, parse_data *data, return S_OK; }
+static HRESULT validate_username(const UriBuilder *builder, parse_data *data, DWORD flags) { + const WCHAR *ptr; + const WCHAR **pptr; + DWORD expected_len; + + if(builder->username) { + ptr = builder->username; + expected_len = builder->username_len; + } else if(!(builder->modified_props & Uri_HAS_USER_NAME) && builder->uri && + builder->uri->userinfo_start > -1 && builder->uri->userinfo_split != 0) { + /* Just use the username from the base Uri. */ + data->username = builder->uri->canon_uri+builder->uri->userinfo_start; + data->username_len = (builder->uri->userinfo_split > -1) ? + builder->uri->userinfo_split : builder->uri->userinfo_len; + ptr = NULL; + } else { + ptr = NULL; + expected_len = 0; + } + + if(ptr) { + pptr = &ptr; + if(parse_username(pptr, data, flags, ALLOW_NULL_TERM_USER_NAME) && + data->username_len == expected_len) + TRACE("(%p %p %x): Found valid username component %s.\n", builder, data, flags, + debugstr_wn(data->username, data->username_len)); + else { + TRACE("(%p %p %x): Invalid username component found %s.\n", builder, data, flags, + debugstr_wn(ptr, expected_len)); + return INET_E_INVALID_URL; + } + } + + return S_OK; +} + +static HRESULT validate_password(const UriBuilder *builder, parse_data *data, DWORD flags) { + const WCHAR *ptr; + const WCHAR **pptr; + DWORD expected_len; + + if(builder->password) { + ptr = builder->password; + expected_len = builder->password_len; + } else if(!(builder->modified_props & Uri_HAS_PASSWORD) && builder->uri && + builder->uri->userinfo_split > -1) { + data->password = builder->uri->canon_uri+builder->uri->userinfo_start+builder->uri->userinfo_split+1; + data->password_len = builder->uri->userinfo_len-builder->uri->userinfo_split-1; + ptr = NULL; + } else { + ptr = NULL; + expected_len = 0; + } + + if(ptr) { + pptr = &ptr; + if(parse_password(pptr, data, flags, ALLOW_NULL_TERM_PASSWORD) && + data->password_len == expected_len) + TRACE("(%p %p %x): Found valid password component %s.\n", builder, data, flags, + debugstr_wn(data->password, data->password_len)); + else { + TRACE("(%p %p %x): Invalid password component found %s.\n", builder, data, flags, + debugstr_wn(ptr, expected_len)); + return INET_E_INVALID_URL; + } + } + + return S_OK; +} + +static HRESULT validate_userinfo(const UriBuilder *builder, parse_data *data, DWORD flags) { + HRESULT hr; + + hr = validate_username(builder, data, flags); + if(FAILED(hr)) + return hr; + + hr = validate_password(builder, data, flags); + if(FAILED(hr)) + return hr; + + return S_OK; +} + static HRESULT validate_components(const UriBuilder *builder, parse_data *data, DWORD flags) { HRESULT hr;
@@ -3582,6 +3672,10 @@ static HRESULT validate_components(const UriBuilder *builder, parse_data *data, } }
+ hr = validate_userinfo(builder, data, flags); + if(FAILED(hr)) + return hr; + return E_NOTIMPL; }