From 6ce8624760a219cea311b70246df6b455c706ab3 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Mon, 2 Oct 2017 09:47:27 +0100 Subject: [PATCH] winhttp: Send basic authorization credentials with the first request if they've been set. Signed-off-by: Huw Davies Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- 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 05f4b963ddb..a3558875cc6 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 2babe98c20f..469b882bec6 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.11.4.GIT