[PATCH] wininet: Option INTERNET_OPTION_END_BROWSER_SESSION clears cached credentials

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Wed Sep 18 19:47:44 CDT 2019


Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
 dlls/wininet/http.c       | 31 ++++++++++++++
 dlls/wininet/internet.c   |  1 +
 dlls/wininet/internet.h   |  1 +
 dlls/wininet/tests/http.c | 87 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 120 insertions(+)

diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index 5844a7c7d6..60dab62441 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -1019,6 +1019,37 @@ static void cache_authorization(LPWSTR host, LPWSTR scheme,
     LeaveCriticalSection(&authcache_cs);
 }
 
+void free_authorization_cache(void)
+{
+    authorizationData *ad, *sa_safe;
+    basicAuthorizationData *basic, *basic_safe;
+
+    EnterCriticalSection(&authcache_cs);
+
+    LIST_FOR_EACH_ENTRY_SAFE(basic, basic_safe, &basicAuthorizationCache, basicAuthorizationData, entry)
+    {
+        heap_free(basic->host);
+        heap_free(basic->realm);
+        heap_free(basic->authorization);
+
+        list_remove(&basic->entry);
+        heap_free(basic);
+    }
+
+    LIST_FOR_EACH_ENTRY_SAFE(ad, sa_safe, &authorizationCache, authorizationData, entry)
+    {
+        heap_free(ad->host);
+        heap_free(ad->scheme);
+        heap_free(ad->user);
+        heap_free(ad->password);
+        heap_free(ad->domain);
+        list_remove(&ad->entry);
+        heap_free(ad);
+    }
+
+    LeaveCriticalSection(&authcache_cs);
+}
+
 static BOOL HTTP_DoAuthorization( http_request_t *request, LPCWSTR pszAuthValue,
                                   struct HttpAuthInfo **ppAuthInfo,
                                   LPWSTR domain_and_username, LPWSTR password,
diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c
index b7aa5fe330..266100861d 100644
--- a/dlls/wininet/internet.c
+++ b/dlls/wininet/internet.c
@@ -2821,6 +2821,7 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption,
     case INTERNET_OPTION_END_BROWSER_SESSION:
         FIXME("Option INTERNET_OPTION_END_BROWSER_SESSION: semi-stub\n");
         free_cookie();
+        free_authorization_cache();
         break;
     case INTERNET_OPTION_CONNECTED_STATE:
         FIXME("Option INTERNET_OPTION_CONNECTED_STATE: STUB\n");
diff --git a/dlls/wininet/internet.h b/dlls/wininet/internet.h
index 40e51bec32..8954d071f9 100644
--- a/dlls/wininet/internet.h
+++ b/dlls/wininet/internet.h
@@ -456,6 +456,7 @@ static inline req_file_t *req_file_addref(req_file_t *req_file)
 BOOL init_urlcache(void) DECLSPEC_HIDDEN;
 void free_urlcache(void) DECLSPEC_HIDDEN;
 void free_cookie(void) DECLSPEC_HIDDEN;
+void free_authorization_cache(void) DECLSPEC_HIDDEN;
 
 void init_winsock(void) DECLSPEC_HIDDEN;
 
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
index b61d5c7030..f1a647346e 100644
--- a/dlls/wininet/tests/http.c
+++ b/dlls/wininet/tests/http.c
@@ -4502,6 +4502,92 @@ static void test_basic_auth_credentials_reuse(int port)
     InternetCloseHandle( ses );
 }
 
+static void test_basic_auth_credentials_end_session(int port)
+{
+    HINTERNET ses, con, req;
+    DWORD status, size;
+    BOOL ret;
+    char buffer[0x40];
+
+    ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
+    ok( ses != NULL, "InternetOpenA failed\n" );
+
+    con = InternetConnectA( ses, "localhost", port, "user", "pwd",
+                            INTERNET_SERVICE_HTTP, 0, 0 );
+    ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
+
+    req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 );
+    ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
+
+    ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
+    ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
+
+    size = sizeof(buffer);
+    SetLastError(0xdeadbeef);
+    ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size);
+    ok(ret, "unexpected failure %u\n", GetLastError());
+    ok(!strcmp(buffer, "user"), "got %s\n", buffer);
+    ok(size == 4, "got %u\n", size);
+
+    size = sizeof(buffer);
+    SetLastError(0xdeadbeef);
+    ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size);
+    ok(ret, "unexpected failure %u\n", GetLastError());
+    ok(!strcmp(buffer, "pwd"), "got %s\n", buffer);
+    ok(size == 3, "got %u\n", size);
+
+    status = 0xdeadbeef;
+    size = sizeof(status);
+    ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
+    ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
+    ok( status == HTTP_STATUS_OK, "got %u\n", status );
+
+    InternetCloseHandle( req );
+    InternetCloseHandle( con );
+    InternetCloseHandle( ses );
+
+    ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
+    ok( ses != NULL, "InternetOpenA failed\n" );
+
+    /* Clear the cached credentials */
+    ret = InternetSetOptionA(ses,  INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
+    ok(ret, "unexpected failure %u\n", GetLastError());
+
+    con = InternetConnectA( ses, "localhost", port, NULL, NULL,
+                            INTERNET_SERVICE_HTTP, 0, 0 );
+    ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
+
+    req = HttpOpenRequestA( con, "PUT", "/upload2.txt", NULL, NULL, NULL, 0, 0 );
+    ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
+
+    ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
+    ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
+
+    size = sizeof(buffer);
+    SetLastError(0xdeadbeef);
+    ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size);
+    ok(ret, "unexpected failure %u\n", GetLastError());
+    ok(!strcmp(buffer, ""), "got %s\n", buffer);
+    ok(size == 0, "got %u\n", size);
+
+    size = sizeof(buffer);
+    SetLastError(0xdeadbeef);
+    ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size);
+    ok(ret, "unexpected failure %u\n", GetLastError());
+    ok(!strcmp(buffer, ""), "got %s\n", buffer);
+    ok(size == 0, "got %u\n", size);
+
+    status = 0xdeadbeef;
+    size = sizeof(status);
+    ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
+    ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
+    ok( status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status );
+
+    InternetCloseHandle( req );
+    InternetCloseHandle( con );
+    InternetCloseHandle( ses );
+}
+
 static void test_async_read(int port)
 {
     HINTERNET ses, con, req;
@@ -5696,6 +5782,7 @@ static void test_http_connection(void)
     test_request_content_length(si.port);
     test_accept_encoding(si.port);
     test_basic_auth_credentials_reuse(si.port);
+    test_basic_auth_credentials_end_session(si.port);
     test_async_read(si.port);
     test_http_read(si.port);
     test_connection_break(si.port);
-- 
2.17.1




More information about the wine-devel mailing list