winhttp: Allocate a credential handle for each session.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2017-09-12 09:59:05 +02:00 committed by Alexandre Julliard
parent 9b3b5fd0c0
commit d71fcc93e4
4 changed files with 25 additions and 46 deletions

View file

@ -254,46 +254,8 @@ static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD secu
return err;
}
static SecHandle cred_handle;
static BOOL cred_handle_initialized;
static CRITICAL_SECTION init_sechandle_cs;
static CRITICAL_SECTION_DEBUG init_sechandle_cs_debug = {
0, 0, &init_sechandle_cs,
{ &init_sechandle_cs_debug.ProcessLocksList,
&init_sechandle_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": init_sechandle_cs") }
};
static CRITICAL_SECTION init_sechandle_cs = { &init_sechandle_cs_debug, -1, 0, 0, 0, 0 };
static BOOL ensure_cred_handle(void)
{
BOOL ret = TRUE;
EnterCriticalSection(&init_sechandle_cs);
if(!cred_handle_initialized) {
SECURITY_STATUS res;
res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, NULL,
NULL, NULL, &cred_handle, NULL);
if(res == SEC_E_OK) {
cred_handle_initialized = TRUE;
}else {
WARN("AcquireCredentialsHandleW failed: %u\n", res);
ret = FALSE;
}
}
LeaveCriticalSection(&init_sechandle_cs);
return ret;
}
void netconn_unload( void )
{
if(cred_handle_initialized)
FreeCredentialsHandle(&cred_handle);
DeleteCriticalSection(&init_sechandle_cs);
#ifndef HAVE_GETADDRINFO
DeleteCriticalSection(&cs_gethostbyname);
#endif
@ -409,7 +371,7 @@ BOOL netconn_close( netconn_t *conn )
return TRUE;
}
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags )
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle )
{
SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
@ -425,14 +387,11 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl
const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY
|ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION;
if(!ensure_cred_handle())
return FALSE;
read_buf = heap_alloc(read_buf_size);
if(!read_buf)
return FALSE;
status = InitializeSecurityContextW(&cred_handle, NULL, hostname, isc_req_flags, 0, 0, NULL, 0,
status = InitializeSecurityContextW(cred_handle, NULL, hostname, isc_req_flags, 0, 0, NULL, 0,
&ctx, &out_desc, &attrs, NULL);
assert(status != SEC_E_OK);
@ -492,7 +451,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl
in_bufs[0].cbBuffer += size;
in_bufs[0].pvBuffer = read_buf;
status = InitializeSecurityContextW(&cred_handle, &ctx, hostname, isc_req_flags, 0, 0, &in_desc,
status = InitializeSecurityContextW(cred_handle, &ctx, hostname, isc_req_flags, 0, 0, &in_desc,
0, NULL, &out_desc, &attrs, NULL);
TRACE("InitializeSecurityContext ret %08x\n", status);

View file

@ -35,6 +35,7 @@
#include "initguid.h"
#include "httprequest.h"
#include "httprequestid.h"
#include "schannel.h"
#include "winhttp.h"
#include "winhttp_private.h"
@ -1092,6 +1093,20 @@ static void cache_connection( netconn_t *netconn )
LeaveCriticalSection( &connection_pool_cs );
}
static BOOL ensure_cred_handle( session_t *session )
{
SECURITY_STATUS status;
if (session->cred_handle_initialized) return TRUE;
if ((status = AcquireCredentialsHandleW( NULL, (WCHAR *)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, NULL,
NULL, NULL, &session->cred_handle, NULL )) != SEC_E_OK)
{
WARN( "AcquireCredentialsHandleW failed: 0x%08x\n", status );
return FALSE;
}
session->cred_handle_initialized = TRUE;
return TRUE;
}
static BOOL open_connection( request_t *request )
{
BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE;
@ -1219,7 +1234,9 @@ static BOOL open_connection( request_t *request )
return FALSE;
}
}
if (!netconn_secure_connect( netconn, connect->hostname, request->security_flags ))
if (!ensure_cred_handle( connect->session ) ||
!netconn_secure_connect( netconn, connect->hostname, request->security_flags,
&connect->session->cred_handle ))
{
heap_free( addressW );
netconn_close( netconn );

View file

@ -99,6 +99,7 @@ static void session_destroy( object_header_t *hdr )
TRACE("%p\n", session);
if (session->unload_event) SetEvent( session->unload_event );
if (session->cred_handle_initialized) FreeCredentialsHandle( &session->cred_handle );
LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache )
{

View file

@ -120,6 +120,8 @@ typedef struct
LPWSTR proxy_password;
struct list cookie_cache;
HANDLE unload_event;
CredHandle cred_handle;
BOOL cred_handle_initialized;
} session_t;
typedef struct
@ -300,7 +302,7 @@ void netconn_unload( void ) DECLSPEC_HIDDEN;
ULONG netconn_query_data_available( netconn_t * ) DECLSPEC_HIDDEN;
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * ) DECLSPEC_HIDDEN;
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD ) DECLSPEC_HIDDEN;
BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD, CredHandle * ) DECLSPEC_HIDDEN;
BOOL netconn_send( netconn_t *, const void *, size_t, int * ) DECLSPEC_HIDDEN;
DWORD netconn_set_timeout( netconn_t *, BOOL, int ) DECLSPEC_HIDDEN;
BOOL netconn_is_alive( netconn_t * ) DECLSPEC_HIDDEN;