Thomas Mullaly : urlmon: Implemented validation for the userinfo component when create an IUri with IUriBuilder .

Alexandre Julliard julliard at winehq.org
Mon Sep 20 12:12:19 CDT 2010


Module: wine
Branch: master
Commit: e48b81036aa36e91458e68745608de48650e8b8e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e48b81036aa36e91458e68745608de48650e8b8e

Author: Thomas Mullaly <thomas.mullaly at 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/",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/",0,S_OK,FALSE,
+        {
+            {TRUE,"user at 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/",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/",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/",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/",0,S_OK,FALSE,
+        {
+            {TRUE,"pass at 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/",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/",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/",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;
 }
 




More information about the wine-cvs mailing list