Hans Leidekker : winhttp: Handle Passport redirects.

Alexandre Julliard julliard at winehq.org
Fri Aug 2 14:26:31 CDT 2019


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Fri Aug  2 11:01:37 2019 +0200

winhttp: Handle Passport redirects.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winhttp/request.c         | 46 +++++++++++++++++++++++--
 dlls/winhttp/session.c         |  2 +-
 dlls/winhttp/tests/winhttp.c   | 77 ++++++++++++++++++++++++++++++++++++++++++
 dlls/winhttp/winhttp_private.h |  1 +
 4 files changed, 122 insertions(+), 4 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 0e54168..175837d 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -873,7 +873,7 @@ static enum auth_scheme scheme_from_flag( DWORD flag )
     return SCHEME_INVALID;
 }
 
-static DWORD auth_scheme_from_header( WCHAR *header )
+static DWORD auth_scheme_from_header( const WCHAR *header )
 {
     unsigned int i;
 
@@ -2628,7 +2628,7 @@ static WCHAR *get_redirect_url( struct request *request, DWORD *len )
     WCHAR *ret;
 
     query_headers( request, WINHTTP_QUERY_LOCATION, NULL, NULL, &size, NULL );
-    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
+    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return NULL;
     if (!(ret = heap_alloc( size ))) return NULL;
     *len = size / sizeof(WCHAR) - 1;
     if (query_headers( request, WINHTTP_QUERY_LOCATION, NULL, ret, &size, NULL )) return ret;
@@ -2747,6 +2747,42 @@ end:
     return ret;
 }
 
+static BOOL is_passport_request( struct request *request )
+{
+    static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t','1','.','4'};
+    WCHAR buf[1024];
+    DWORD len = ARRAY_SIZE(buf);
+
+    if (!(request->connect->session->passport_flags & WINHTTP_ENABLE_PASSPORT_AUTH) ||
+        !query_headers( request, WINHTTP_QUERY_WWW_AUTHENTICATE, NULL, buf, &len, NULL )) return FALSE;
+
+    if (!strncmpiW( buf, passportW, ARRAY_SIZE(passportW) ) &&
+        (buf[ARRAY_SIZE(passportW)] == ' ' || !buf[ARRAY_SIZE(passportW)])) return TRUE;
+
+    return FALSE;
+}
+
+static BOOL handle_passport_redirect( struct request *request )
+{
+    static const WCHAR status401W[] = {'4','0','1',0};
+    DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE;
+    int i, len = strlenW( request->raw_headers );
+    WCHAR *p = request->raw_headers;
+
+    if (!process_header( request, attr_status, status401W, flags, FALSE )) return FALSE;
+
+    for (i = 0; i < len; i++)
+    {
+        if (i <= len - 3 && p[i] == '3' && p[i + 1] == '0' && p[i + 2] == '2')
+        {
+            p[i] = '4';
+            p[i + 2] = '1';
+            break;
+        }
+    }
+    return TRUE;
+}
+
 static BOOL receive_response( struct request *request, BOOL async )
 {
     BOOL ret;
@@ -2774,7 +2810,11 @@ static BOOL receive_response( struct request *request, BOOL async )
 
         if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request );
 
-        if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB)
+        if (status == HTTP_STATUS_REDIRECT && is_passport_request( request ))
+        {
+            ret = handle_passport_redirect( request );
+        }
+        else if (status == HTTP_STATUS_MOVED || status == HTTP_STATUS_REDIRECT || status == HTTP_STATUS_REDIRECT_KEEP_VERB)
         {
             if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS ||
                 request->hdr.redirect_policy == WINHTTP_OPTION_REDIRECT_POLICY_NEVER) break;
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c
index 239b86b..ef4bb17 100644
--- a/dlls/winhttp/session.c
+++ b/dlls/winhttp/session.c
@@ -210,7 +210,7 @@ static BOOL session_set_option( struct object_header *hdr, DWORD option, void *b
         return TRUE;
 
     case WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH:
-        FIXME("WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH: 0x%x\n", *(DWORD *)buffer);
+        session->passport_flags = *(DWORD *)buffer;
         return TRUE;
 
     case WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT:
diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c
index 5849257..b075638 100644
--- a/dlls/winhttp/tests/winhttp.c
+++ b/dlls/winhttp/tests/winhttp.c
@@ -2236,6 +2236,13 @@ static const char largeauth[] =
 "Content-Type: text/plain\r\n"
 "\r\n";
 
+static const char passportauth[] =
+"HTTP/1.1 302 Found\r\n"
+"Content-Length: 0\r\n"
+"Location: /\r\n"
+"WWW-Authenticate: Passport1.4\r\n"
+"\r\n";
+
 static const char unauthorized[] = "Unauthorized";
 static const char hello_world[] = "Hello World";
 static const char auth_unseen[] = "Auth Unseen";
@@ -2415,6 +2422,10 @@ static DWORD CALLBACK server_thread(LPVOID param)
             }
             else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
         }
+        else if (strstr(buffer, "GET /passport"))
+        {
+            send(c, passportauth, sizeof(passportauth) - 1, 0);
+        }
         if (strstr(buffer, "GET /quit"))
         {
             send(c, okmsg, sizeof okmsg - 1, 0);
@@ -3518,6 +3529,71 @@ static void test_connection_info( int port )
     WinHttpCloseHandle( ses );
 }
 
+static void test_passport_auth( int port )
+{
+    static const WCHAR passportW[] =
+        {'/','p','a','s','s','p','o','r','t',0};
+    static const WCHAR foundW[] =
+        {'F','o','u','n','d',0};
+    static const WCHAR unauthorizedW[] =
+        {'U','n','a','u','t','h','o','r','i','z','e','d',0};
+    static const WCHAR headersW[] =
+        {'H','T','T','P','/','1','.','1',' ','4','0','1',' ','F','o','u','n','d','\r','\n',
+         'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','0','\r','\n',
+         'L','o','c','a','t','i','o','n',':',' ','/','\r','\n',
+         'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',':',' ',
+         'P','a','s','s','p','o','r','t','1','.','4','\r','\n','\r','\n',0};
+    HINTERNET ses, con, req;
+    DWORD status, size, option;
+    WCHAR buf[128];
+    BOOL ret;
+
+    ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
+    ok( ses != NULL, "got %u\n", GetLastError() );
+
+    option = WINHTTP_ENABLE_PASSPORT_AUTH;
+    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH, &option, sizeof(option) );
+    ok( ret, "got %u\n", GetLastError() );
+
+    con = WinHttpConnect( ses, localhostW, port, 0 );
+    ok( con != NULL, "got %u\n", GetLastError() );
+
+    req = WinHttpOpenRequest( con, NULL, passportW, NULL, NULL, NULL, 0 );
+    ok( req != NULL, "got %u\n", GetLastError() );
+
+    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
+    ok( ret, "got %u\n", GetLastError() );
+
+    ret = WinHttpReceiveResponse( req, NULL );
+    ok( ret, "got %u\n", GetLastError() );
+
+    status = 0xdeadbeef;
+    size = sizeof(status);
+    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
+    ok( ret, "got %u\n", GetLastError() );
+    ok( status == HTTP_STATUS_DENIED, "got %u\n", status );
+
+    buf[0] = 0;
+    size = sizeof(buf);
+    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_TEXT, NULL, buf, &size, NULL );
+    ok( ret, "got %u\n", GetLastError() );
+    ok( !lstrcmpW(foundW, buf) || broken(!lstrcmpW(unauthorizedW, buf)) /* < win7 */, "got %s\n", wine_dbgstr_w(buf) );
+
+    buf[0] = 0;
+    size = sizeof(buf);
+    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buf, &size, NULL );
+    ok( ret || broken(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* < win7 */, "got %u\n", GetLastError() );
+    if (ret)
+    {
+        ok( size == lstrlenW(headersW) * sizeof(WCHAR), "got %u\n", size );
+        ok( !lstrcmpW(headersW, buf), "got %s\n", wine_dbgstr_w(buf) );
+    }
+
+    WinHttpCloseHandle( req );
+    WinHttpCloseHandle( con );
+    WinHttpCloseHandle( ses );
+}
+
 static void test_credentials(void)
 {
     static WCHAR userW[] = {'u','s','e','r',0};
@@ -4783,6 +4859,7 @@ START_TEST (winhttp)
     test_multiple_reads(si.port);
     test_cookies(si.port);
     test_request_path_escapes(si.port);
+    test_passport_auth(si.port);
 
     /* send the basic request again to shutdown the server thread */
     test_basic_request(si.port, NULL, quitW);
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 38e39cb..93cf0f7 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -93,6 +93,7 @@ struct session
     struct list cookie_cache;
     HANDLE unload_event;
     DWORD secure_protocols;
+    DWORD passport_flags;
 };
 
 struct connect




More information about the wine-cvs mailing list