[PATCH 2/2] winhttp: Send basic authorization credentials with the first request if they've been set.

Huw Davies huw at codeweavers.com
Mon Oct 2 03:47:27 CDT 2017


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/winhttp/request.c       | 10 ++++++---
 dlls/winhttp/tests/winhttp.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 05f4b963dd..a3558875cc 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -1142,24 +1142,25 @@ static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_fla
     const WCHAR *auth_target, *username, *password;
     WCHAR auth_value[2048], *auth_reply;
     DWORD len = sizeof(auth_value), len_scheme, flags;
-    BOOL ret;
+    BOOL ret, has_auth_value;
 
     if (scheme == SCHEME_INVALID) return FALSE;
 
     switch (target)
     {
     case WINHTTP_AUTH_TARGET_SERVER:
-        if (!get_authvalue( request, WINHTTP_QUERY_WWW_AUTHENTICATE, scheme_flag, auth_value, len ))
-            return FALSE;
+        has_auth_value = get_authvalue( request, WINHTTP_QUERY_WWW_AUTHENTICATE, scheme_flag, auth_value, len );
         auth_ptr = &request->authinfo;
         auth_target = attr_authorization;
         if (request->creds[TARGET_SERVER][scheme].username)
         {
+            if (scheme != SCHEME_BASIC && !has_auth_value) return FALSE;
             username = request->creds[TARGET_SERVER][scheme].username;
             password = request->creds[TARGET_SERVER][scheme].password;
         }
         else
         {
+            if (!has_auth_value) return FALSE;
             username = request->connect->username;
             password = request->connect->password;
         }
@@ -2086,6 +2087,9 @@ static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len
     if (connect->hostname)
         add_host_header( request, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW );
 
+    if (request->creds[TARGET_SERVER][SCHEME_BASIC].username)
+        do_authorization( request, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC );
+
     if (total_len || (request->verb && !strcmpW( request->verb, postW )))
     {
         WCHAR length[21]; /* decimal long int + null */
diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c
index 2babe98c20..469b882bec 100644
--- a/dlls/winhttp/tests/winhttp.c
+++ b/dlls/winhttp/tests/winhttp.c
@@ -2075,6 +2075,7 @@ static const char largeauth[] =
 
 static const char unauthorized[] = "Unauthorized";
 static const char hello_world[] = "Hello World";
+static const char auth_unseen[] = "Auth Unseen";
 
 struct server_info
 {
@@ -2134,6 +2135,15 @@ static DWORD CALLBACK server_thread(LPVOID param)
             send(c, okmsg, sizeof okmsg - 1, 0);
             send(c, page1, sizeof page1 - 1, 0);
         }
+        if (strstr(buffer, "/auth_with_creds"))
+        {
+            send(c, okauthmsg, sizeof okauthmsg - 1, 0);
+            if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
+                send(c, hello_world, sizeof hello_world - 1, 0);
+            else
+                send(c, auth_unseen, sizeof auth_unseen - 1, 0);
+            continue;
+        }
         if (strstr(buffer, "/auth"))
         {
             if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
@@ -2309,6 +2319,7 @@ static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
 static void test_basic_authentication(int port)
 {
     static const WCHAR authW[] = {'/','a','u','t','h',0};
+    static const WCHAR auth_with_credsW[] = {'/','a','u','t','h','_','w','i','t','h','_','c','r','e','d','s',0};
     static WCHAR userW[] = {'u','s','e','r',0};
     static WCHAR passW[] = {'p','w','d',0};
     static WCHAR pass2W[] = {'p','w','d','2',0};
@@ -2472,6 +2483,45 @@ static void test_basic_authentication(int port)
     WinHttpCloseHandle(con);
     WinHttpCloseHandle(ses);
 
+    /* now set the credentials first to show that they get sent with the first request */
+    ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
+    ok(ses != NULL, "failed to open session %u\n", GetLastError());
+
+    con = WinHttpConnect(ses, localhostW, port, 0);
+    ok(con != NULL, "failed to open a connection %u\n", GetLastError());
+
+    req = WinHttpOpenRequest(con, NULL, auth_with_credsW, NULL, NULL, NULL, 0);
+    ok(req != NULL, "failed to open a request %u\n", GetLastError());
+
+    ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
+    ok(ret, "failed to set credentials %u\n", GetLastError());
+
+    ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
+    ok(ret, "failed to send request %u\n", GetLastError());
+
+    ret = WinHttpReceiveResponse(req, NULL);
+    ok(ret, "failed to receive response %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, "failed to query status code %u\n", GetLastError());
+    ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
+
+    size = 0;
+    ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
+    error = GetLastError();
+    ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
+    if (ret)
+    {
+        ok(size == 11, "expected 11, got %u\n", size);
+        ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
+    }
+
+    WinHttpCloseHandle(req);
+    WinHttpCloseHandle(con);
+    WinHttpCloseHandle(ses);
+
     /* credentials set with WinHttpSetCredentials take precedence over those set through options */
 
     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
-- 
2.12.0




More information about the wine-patches mailing list