diff --git a/dlls/secur32/Makefile.in b/dlls/secur32/Makefile.in index 2887377f051..5b71cd82417 100644 --- a/dlls/secur32/Makefile.in +++ b/dlls/secur32/Makefile.in @@ -1,5 +1,6 @@ MODULE = secur32.dll IMPORTLIB = secur32 +UNIXLIB = secur32.so IMPORTS = advapi32 DELAYIMPORTS = crypt32 EXTRAINCL = $(GNUTLS_CFLAGS) diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 14645080f38..32181b3b35f 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -33,12 +33,15 @@ #include "sspi.h" #include "schannel.h" +#include "wine/unixlib.h" #include "wine/debug.h" #include "secur32_priv.h" WINE_DEFAULT_DEBUG_CHANNEL(secur32); -const struct schan_funcs *schan_funcs = NULL; +static unixlib_handle_t gnutls_handle; + +#define GNUTLS_CALL( func, params ) __wine_unix_call( gnutls_handle, unix_ ## func, params ) #define SCHAN_INVALID_HANDLE ~0UL @@ -231,7 +234,7 @@ static void read_config(void) RegCloseKey(protocols_key); - config_enabled_protocols = enabled & schan_funcs->get_enabled_protocols(); + config_enabled_protocols = enabled & GNUTLS_CALL( get_enabled_protocols, NULL ); config_default_disabled_protocols = default_disabled; config_read = TRUE; @@ -492,6 +495,7 @@ static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schan SECURITY_STATUS status = SEC_E_OK; const CERT_CONTEXT *cert = NULL; DATA_BLOB key_blob = {0}; + struct allocate_certificate_credentials_params params; TRACE("schanCred %p, phCredential %p, ptsExpiry %p\n", schanCred, phCredential, ptsExpiry); @@ -526,7 +530,10 @@ static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schan creds->enabled_protocols = enabled_protocols; if (cert && !(key_blob.pbData = get_key_blob(cert, &key_blob.cbData))) goto fail; - if (!schan_funcs->allocate_certificate_credentials(creds, cert, &key_blob)) goto fail; + params.c = creds; + params.ctx = cert; + params.key_blob = &key_blob; + if (GNUTLS_CALL( allocate_certificate_credentials, ¶ms )) goto fail; RtlFreeHeap(GetProcessHeap(), 0, key_blob.pbData); handle = schan_alloc_handle(creds, SCHAN_HANDLE_CRED); @@ -634,7 +641,11 @@ static SECURITY_STATUS SEC_ENTRY schan_FreeCredentialsHandle( creds = schan_free_handle(phCredential->dwLower, SCHAN_HANDLE_CRED); if (!creds) return SEC_E_INVALID_HANDLE; - if (creds->credential_use == SECPKG_CRED_OUTBOUND) schan_funcs->free_certificate_credentials(creds); + if (creds->credential_use == SECPKG_CRED_OUTBOUND) + { + struct free_certificate_credentials_params params = { creds }; + GNUTLS_CALL( free_certificate_credentials, ¶ms ); + } free(creds); return SEC_E_OK; } @@ -697,6 +708,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( SECURITY_STATUS ret; SecBuffer *buffer; SecBuffer alloc_buffer = { 0 }; + struct handshake_params params; int idx; TRACE("%p %p %s 0x%08x %d %d %p %d %p %p %p %p\n", phCredential, phContext, @@ -715,6 +727,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( if (!phContext) { ULONG_PTR handle; + struct create_session_params create_params; if (!phCredential) return SEC_E_INVALID_HANDLE; @@ -737,7 +750,9 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( return SEC_E_INTERNAL_ERROR; } - if (!schan_funcs->create_session(&ctx->transport.session, cred)) + create_params.transport = &ctx->transport; + create_params.cred = cred; + if (GNUTLS_CALL( create_session, &create_params )) { schan_free_handle(handle, SCHAN_HANDLE_CTX); free(ctx); @@ -750,7 +765,6 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( ctx->header_size = HEADER_SIZE_TLS; ctx->transport.ctx = ctx; - schan_funcs->set_session_transport(ctx->transport.session, &ctx->transport); if (pszTargetName && *pszTargetName) { @@ -759,22 +773,28 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( if (target) { + struct set_session_target_params params = { ctx->transport.session, target }; WideCharToMultiByte( CP_UNIXCP, 0, pszTargetName, -1, target, len, NULL, NULL ); - schan_funcs->set_session_target( ctx->transport.session, target ); + GNUTLS_CALL( set_session_target, ¶ms ); free( target ); } } if (pInput && (idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_APPLICATION_PROTOCOLS)) != -1) { - buffer = &pInput->pBuffers[idx]; - schan_funcs->set_application_protocols(ctx->transport.session, buffer->pvBuffer, buffer->cbBuffer); + struct set_application_protocols_params params = { ctx->transport.session, + pInput->pBuffers[idx].pvBuffer, pInput->pBuffers[idx].cbBuffer }; + GNUTLS_CALL( set_application_protocols, ¶ms ); } if (pInput && (idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_DTLS_MTU)) != -1) { buffer = &pInput->pBuffers[idx]; - if (buffer->cbBuffer >= sizeof(WORD)) schan_funcs->set_dtls_mtu(ctx->transport.session, *(WORD *)buffer->pvBuffer); + if (buffer->cbBuffer >= sizeof(WORD)) + { + struct set_dtls_mtu_params params = { ctx->transport.session, *(WORD *)buffer->pvBuffer }; + GNUTLS_CALL( set_dtls_mtu, ¶ms ); + } else WARN("invalid buffer size %u\n", buffer->cbBuffer); } @@ -822,7 +842,12 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( alloc_buffer.BufferType = SECBUFFER_TOKEN; alloc_buffer.pvBuffer = RtlAllocateHeap( GetProcessHeap(), 0, extra_size ); } - ret = schan_funcs->handshake(ctx->transport.session, pInput, expected_size, pOutput, &alloc_buffer); + params.session = ctx->transport.session; + params.input = pInput; + params.input_size = expected_size; + params.output = pOutput; + params.alloc_buffer = &alloc_buffer; + ret = GNUTLS_CALL( handshake, ¶ms ); out_buffers = &ctx->transport.out; if (out_buffers->current_buffer_idx != -1) @@ -926,19 +951,21 @@ static SECURITY_STATUS ensure_remote_cert(struct schan_context *ctx) SECURITY_STATUS status; CERT_BLOB *certs; ULONG count, size = 0; + struct get_session_peer_certificate_params params = { ctx->transport.session, NULL, &size, &count }; if (ctx->cert) return SEC_E_OK; if (!(store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL))) return GetLastError(); - status = schan_funcs->get_session_peer_certificate(ctx->transport.session, NULL, &size, &count); + status = GNUTLS_CALL( get_session_peer_certificate, ¶ms ); if (status != SEC_E_BUFFER_TOO_SMALL) goto done; if (!(certs = malloc( size ))) { status = SEC_E_INSUFFICIENT_MEMORY; goto done; } - status = schan_funcs->get_session_peer_certificate(ctx->transport.session, certs, &size, &count); + params.certs = certs; + status = GNUTLS_CALL( get_session_peer_certificate, ¶ms ); if (status == SEC_E_OK) { unsigned int i; @@ -977,13 +1004,15 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( case SECPKG_ATTR_STREAM_SIZES: { SecPkgContext_ConnectionInfo info; - status = schan_funcs->get_connection_info(ctx->transport.session, &info); + struct get_connection_info_params params = { ctx->transport.session, &info }; + status = GNUTLS_CALL( get_connection_info, ¶ms ); if (status == SEC_E_OK) { + struct session_params params = { ctx->transport.session }; SecPkgContext_StreamSizes *stream_sizes = buffer; SIZE_T mac_size = info.dwHashStrength; - unsigned int block_size = schan_funcs->get_session_cipher_block_size(ctx->transport.session); - unsigned int message_size = schan_funcs->get_max_message_size(ctx->transport.session); + unsigned int block_size = GNUTLS_CALL( get_session_cipher_block_size, ¶ms ); + unsigned int message_size = GNUTLS_CALL( get_max_message_size, ¶ms ); TRACE("Using header size %lu mac bytes %lu, message size %u, block size %u\n", ctx->header_size, mac_size, message_size, block_size); @@ -1001,12 +1030,14 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( case SECPKG_ATTR_KEY_INFO: { SecPkgContext_ConnectionInfo conn_info; - status = schan_funcs->get_connection_info(ctx->transport.session, &conn_info); + struct get_connection_info_params params = { ctx->transport.session, &conn_info }; + status = GNUTLS_CALL( get_connection_info, ¶ms ); if (status == SEC_E_OK) { + struct session_params params = { ctx->transport.session }; SecPkgContext_KeyInfoW *info = buffer; info->KeySize = conn_info.dwCipherStrength; - info->SignatureAlgorithm = schan_funcs->get_key_signature_algorithm(ctx->transport.session); + info->SignatureAlgorithm = GNUTLS_CALL( get_key_signature_algorithm, ¶ms ); info->EncryptAlgorithm = conn_info.aiCipher; info->sSignatureAlgorithmName = get_alg_name(info->SignatureAlgorithm, TRUE); info->sEncryptAlgorithmName = get_alg_name(info->EncryptAlgorithm, TRUE); @@ -1027,7 +1058,8 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( case SECPKG_ATTR_CONNECTION_INFO: { SecPkgContext_ConnectionInfo *info = buffer; - return schan_funcs->get_connection_info(ctx->transport.session, info); + struct get_connection_info_params params = { ctx->transport.session, info }; + return GNUTLS_CALL( get_connection_info, ¶ms ); } case SECPKG_ATTR_ENDPOINT_BINDINGS: { @@ -1076,8 +1108,9 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( SecPkgContext_Bindings *bindings = buffer; ULONG size; char *p; + struct get_unique_channel_binding_params params = { ctx->transport.session, NULL, &size }; - if (schan_funcs->get_unique_channel_binding(ctx->transport.session, NULL, &size) != SEC_E_BUFFER_TOO_SMALL) + if (GNUTLS_CALL( get_unique_channel_binding, ¶ms ) != SEC_E_BUFFER_TOO_SMALL) return SEC_E_INTERNAL_ERROR; bindings->BindingsLength = sizeof(*bindings->Bindings) + sizeof(prefix)-1 + size; @@ -1092,12 +1125,14 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( p = (char*)(bindings->Bindings+1); memcpy(p, prefix, sizeof(prefix)-1); p += sizeof(prefix)-1; - return schan_funcs->get_unique_channel_binding(ctx->transport.session, p, &size); + params.buffer = p; + return GNUTLS_CALL( get_unique_channel_binding, ¶ms ); } case SECPKG_ATTR_APPLICATION_PROTOCOL: { SecPkgContext_ApplicationProtocol *protocol = buffer; - return schan_funcs->get_application_protocol(ctx->transport.session, protocol); + struct get_application_protocol_params params = { ctx->transport.session, protocol }; + return GNUTLS_CALL( get_application_protocol, ¶ms ); } default: @@ -1148,6 +1183,7 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle ULONG quality, PSecBufferDesc message, ULONG message_seq_no) { struct schan_context *ctx; + struct send_params params; SECURITY_STATUS status; SecBuffer *buffer; SIZE_T data_size; @@ -1176,7 +1212,11 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle memcpy(data, buffer->pvBuffer, data_size); length = data_size; - status = schan_funcs->send(ctx->transport.session, message, data, &length); + params.session = ctx->transport.session; + params.output = message; + params.buffer = data; + params.length = &length; + status = GNUTLS_CALL( send, ¶ms ); TRACE("Sent %ld bytes.\n", length); @@ -1251,6 +1291,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle { SECURITY_STATUS status = SEC_E_OK; struct schan_context *ctx; + struct recv_params params; SecBuffer *buffer; SIZE_T data_size; char *data; @@ -1294,7 +1335,13 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle data = malloc(data_size); received = data_size; - status = schan_funcs->recv(ctx->transport.session, message, expected_size, data, &received); + + params.session = ctx->transport.session; + params.input = message; + params.input_size = expected_size; + params.buffer = data; + params.length = &received; + status = GNUTLS_CALL( recv, ¶ms ); if (status != SEC_E_OK && status != SEC_I_RENEGOTIATE) { @@ -1327,6 +1374,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle static SECURITY_STATUS SEC_ENTRY schan_DeleteSecurityContext(PCtxtHandle context_handle) { struct schan_context *ctx; + struct session_params params; TRACE("context_handle %p\n", context_handle); @@ -1336,7 +1384,8 @@ static SECURITY_STATUS SEC_ENTRY schan_DeleteSecurityContext(PCtxtHandle context if (!ctx) return SEC_E_INVALID_HANDLE; if (ctx->cert) CertFreeCertificateContext(ctx->cert); - schan_funcs->dispose_session(ctx->transport.session); + params.session = ctx->transport.session; + GNUTLS_CALL( dispose_session, ¶ms ); free(ctx); return SEC_E_OK; } @@ -1428,10 +1477,15 @@ void SECUR32_initSchannelSP(void) }; SecureProvider *provider; - if (!schan_funcs && __wine_init_unix_lib(hsecur32, DLL_PROCESS_ATTACH, NULL, &schan_funcs)) + if (!gnutls_handle) { - ERR( "no schannel support, expect problems\n" ); - return; + if (NtQueryVirtualMemory( GetCurrentProcess(), hsecur32, MemoryWineUnixFuncs, + &gnutls_handle, sizeof(gnutls_handle), NULL ) || + GNUTLS_CALL( process_attach, NULL )) + { + ERR( "no schannel support, expect problems\n" ); + return; + } } schan_handle_table = malloc(64 * sizeof(*schan_handle_table)); @@ -1471,7 +1525,8 @@ void SECUR32_deinitSchannelSP(void) if (schan_handle_table[i].type == SCHAN_HANDLE_CTX) { struct schan_context *ctx = schan_free_handle(i, SCHAN_HANDLE_CTX); - schan_funcs->dispose_session(ctx->transport.session); + struct session_params params = { ctx->transport.session }; + GNUTLS_CALL( dispose_session, ¶ms ); free(ctx); } } @@ -1480,14 +1535,13 @@ void SECUR32_deinitSchannelSP(void) { if (schan_handle_table[i].type != SCHAN_HANDLE_FREE) { - struct schan_credentials *cred; - cred = schan_free_handle(i, SCHAN_HANDLE_CRED); - schan_funcs->free_certificate_credentials(cred); + struct schan_credentials *cred = schan_free_handle(i, SCHAN_HANDLE_CRED); + struct free_certificate_credentials_params params = { cred }; + GNUTLS_CALL( free_certificate_credentials, ¶ms ); free(cred); } } free(schan_handle_table); - - __wine_init_unix_lib(hsecur32, DLL_PROCESS_DETACH, NULL, NULL); - schan_funcs = NULL; + GNUTLS_CALL( process_detach, NULL ); + gnutls_handle = 0; } diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index d832c353fcd..31fdb769677 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -45,6 +45,7 @@ #include "sspi.h" #include "secur32_priv.h" +#include "wine/unixlib.h" #include "wine/debug.h" #if defined(SONAME_LIBGNUTLS) @@ -445,7 +446,7 @@ static void check_supported_protocols(void) pgnutls_deinit(session); } -static DWORD CDECL schan_get_enabled_protocols(void) +static NTSTATUS schan_get_enabled_protocols( void *args ) { return supported_protocols; } @@ -463,9 +464,11 @@ static int pull_timeout(gnutls_transport_ptr_t transport, unsigned int timeout) return -1; } -static BOOL CDECL schan_create_session(schan_session *session, schan_credentials *cred) +static NTSTATUS schan_create_session( void *args ) { - gnutls_session_t *s = (gnutls_session_t*)session; + const struct create_session_params *params = args; + schan_credentials *cred = params->cred; + gnutls_session_t *s = (gnutls_session_t*)¶ms->transport->session; char priority[128] = "NORMAL:%LATEST_RECORD_VERSION", *p; BOOL using_vers_all = FALSE, disabled; unsigned int i, flags = (cred->credential_use == SECPKG_CRED_INBOUND) ? GNUTLS_SERVER : GNUTLS_CLIENT; @@ -480,7 +483,7 @@ static BOOL CDECL schan_create_session(schan_session *session, schan_credentials if (err != GNUTLS_E_SUCCESS) { pgnutls_perror(err); - return FALSE; + return STATUS_INTERNAL_ERROR; } p = priority + strlen(priority); @@ -514,7 +517,7 @@ static BOOL CDECL schan_create_session(schan_session *session, schan_credentials { pgnutls_perror(err); pgnutls_deinit(*s); - return FALSE; + return STATUS_INTERNAL_ERROR; } err = pgnutls_credentials_set(*s, GNUTLS_CRD_CERTIFICATE, @@ -523,46 +526,44 @@ static BOOL CDECL schan_create_session(schan_session *session, schan_credentials { pgnutls_perror(err); pgnutls_deinit(*s); - return FALSE; + return STATUS_INTERNAL_ERROR; } pgnutls_transport_set_pull_function(*s, pull_adapter); if (flags & GNUTLS_DATAGRAM) pgnutls_transport_set_pull_timeout_function(*s, pull_timeout); pgnutls_transport_set_push_function(*s, push_adapter); + pgnutls_transport_set_ptr(*s, (gnutls_transport_ptr_t)params->transport); - return TRUE; + return STATUS_SUCCESS; } -static void CDECL schan_dispose_session(schan_session session) +static NTSTATUS schan_dispose_session( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct session_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; pgnutls_deinit(s); + return STATUS_SUCCESS; } -static void CDECL schan_set_session_transport(schan_session session, struct schan_transport *t) +static NTSTATUS schan_set_session_target( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; - pgnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)t); + const struct set_session_target_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; + pgnutls_server_name_set( s, GNUTLS_NAME_DNS, params->target, strlen(params->target) ); + return STATUS_SUCCESS; } -static void CDECL schan_set_session_target(schan_session session, const char *target) +static NTSTATUS schan_handshake( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; - pgnutls_server_name_set( s, GNUTLS_NAME_DNS, target, strlen(target) ); -} - -static SECURITY_STATUS CDECL schan_handshake(schan_session session, SecBufferDesc *input, - SIZE_T input_size, SecBufferDesc *output, - SecBuffer *alloc_buffer ) -{ - gnutls_session_t s = (gnutls_session_t)session; + const struct handshake_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s); int err; - init_schan_buffers(&t->in, input, handshake_get_next_buffer); - t->in.limit = input_size; - init_schan_buffers(&t->out, output, handshake_get_next_buffer_alloc ); - t->out.alloc_buffer = alloc_buffer; + init_schan_buffers(&t->in, params->input, handshake_get_next_buffer); + t->in.limit = params->input_size; + init_schan_buffers(&t->out, params->output, handshake_get_next_buffer_alloc ); + t->out.alloc_buffer = params->alloc_buffer; while(1) { err = pgnutls_handshake(s); @@ -698,20 +699,24 @@ static ALG_ID get_kx_algid(int kx) } } -static unsigned int CDECL schan_get_session_cipher_block_size(schan_session session) +static NTSTATUS schan_get_session_cipher_block_size( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct session_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; return pgnutls_cipher_get_block_size(pgnutls_cipher_get(s)); } -static unsigned int CDECL schan_get_max_message_size(schan_session session) +static NTSTATUS schan_get_max_message_size( void *args ) { - return pgnutls_record_get_max_size((gnutls_session_t)session); + const struct session_params *params = args; + return pgnutls_record_get_max_size((gnutls_session_t)params->session); } -static SECURITY_STATUS CDECL schan_get_connection_info(schan_session session, SecPkgContext_ConnectionInfo *info) +static NTSTATUS schan_get_connection_info( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct get_connection_info_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; + SecPkgContext_ConnectionInfo *info = params->info; gnutls_protocol_t proto = pgnutls_protocol_get_version(s); gnutls_cipher_algorithm_t alg = pgnutls_cipher_get(s); gnutls_mac_algorithm_t mac = pgnutls_mac_get(s); @@ -728,12 +733,13 @@ static SECURITY_STATUS CDECL schan_get_connection_info(schan_session session, Se return SEC_E_OK; } -static SECURITY_STATUS CDECL schan_get_unique_channel_binding(schan_session session, void *buffer, ULONG *bufsize) +static NTSTATUS schan_get_unique_channel_binding( void *args ) { + const struct get_unique_channel_binding_params *params = args; gnutls_datum_t datum; int rc; SECURITY_STATUS ret; - gnutls_session_t s = (gnutls_session_t)session; + gnutls_session_t s = (gnutls_session_t)params->session; rc = pgnutls_session_channel_binding(s, GNUTLS_CB_TLS_UNIQUE, &datum); if (rc) @@ -741,24 +747,25 @@ static SECURITY_STATUS CDECL schan_get_unique_channel_binding(schan_session sess pgnutls_perror(rc); return SEC_E_INTERNAL_ERROR; } - if (buffer && *bufsize >= datum.size) + if (params->buffer && *params->bufsize >= datum.size) { - memcpy( buffer, datum.data, datum.size ); + memcpy( params->buffer, datum.data, datum.size ); ret = SEC_E_OK; } else ret = SEC_E_BUFFER_TOO_SMALL; - *bufsize = datum.size; + *params->bufsize = datum.size; free(datum.data); return ret; } -static ALG_ID CDECL schan_get_key_signature_algorithm(schan_session session) +static NTSTATUS schan_get_key_signature_algorithm( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct session_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; gnutls_kx_algorithm_t kx = pgnutls_kx_get(s); - TRACE("(%p)\n", session); + TRACE("(%p)\n", params->session); switch (kx) { @@ -774,10 +781,11 @@ static ALG_ID CDECL schan_get_key_signature_algorithm(schan_session session) } } -static SECURITY_STATUS CDECL schan_get_session_peer_certificate(schan_session session, CERT_BLOB *certs, - ULONG *bufsize, ULONG *retcount) +static NTSTATUS schan_get_session_peer_certificate( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct get_session_peer_certificate_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; + CERT_BLOB *certs = params->certs; const gnutls_datum_t *datum; unsigned int i, size; BYTE *ptr; @@ -788,9 +796,9 @@ static SECURITY_STATUS CDECL schan_get_session_peer_certificate(schan_session se size = count * sizeof(certs[0]); for (i = 0; i < count; i++) size += datum[i].size; - if (!certs || *bufsize < size) + if (!certs || *params->bufsize < size) { - *bufsize = size; + *params->bufsize = size; return SEC_E_BUFFER_TOO_SMALL; } ptr = (BYTE *)&certs[count]; @@ -802,31 +810,31 @@ static SECURITY_STATUS CDECL schan_get_session_peer_certificate(schan_session se ptr += datum[i].size; } - *bufsize = size; - *retcount = count; + *params->bufsize = size; + *params->retcount = count; return SEC_E_OK; } -static SECURITY_STATUS CDECL schan_send(schan_session session, SecBufferDesc *output, - const void *buffer, SIZE_T *length) +static NTSTATUS schan_send( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct send_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s); SSIZE_T ret, total = 0; - if (schan_find_sec_buffer_idx(output, 0, SECBUFFER_STREAM_HEADER) != -1) - init_schan_buffers(&t->out, output, send_message_get_next_buffer); + if (schan_find_sec_buffer_idx(params->output, 0, SECBUFFER_STREAM_HEADER) != -1) + init_schan_buffers(&t->out, params->output, send_message_get_next_buffer); else - init_schan_buffers(&t->out, output, send_message_get_next_buffer_token); + init_schan_buffers(&t->out, params->output, send_message_get_next_buffer_token); for (;;) { - ret = pgnutls_record_send(s, (const char *)buffer + total, *length - total); + ret = pgnutls_record_send(s, (const char *)params->buffer + total, *params->length - total); if (ret >= 0) { total += ret; - TRACE( "sent %ld now %ld/%ld\n", ret, total, *length ); - if (total == *length) break; + TRACE( "sent %ld now %ld/%ld\n", ret, total, *params->length ); + if (total == *params->length) break; } else if (ret == GNUTLS_E_AGAIN) { @@ -846,22 +854,22 @@ static SECURITY_STATUS CDECL schan_send(schan_session session, SecBufferDesc *ou return SEC_E_OK; } -static SECURITY_STATUS CDECL schan_recv(schan_session session, SecBufferDesc *input, - SIZE_T input_size, void *buffer, SIZE_T *length) +static NTSTATUS schan_recv( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct recv_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s); - size_t data_size = *length; + size_t data_size = *params->length; size_t received = 0; ssize_t ret; SECURITY_STATUS status = SEC_E_OK; - init_schan_buffers(&t->in, input, recv_message_get_next_buffer); - t->in.limit = input_size; + init_schan_buffers(&t->in, params->input, recv_message_get_next_buffer); + t->in.limit = params->input_size; while (received < data_size) { - ret = pgnutls_record_recv(s, (char *)buffer + received, data_size - received); + ret = pgnutls_record_recv(s, (char *)params->buffer + received, data_size - received); if (ret > 0) received += ret; else if (!ret) break; @@ -884,7 +892,7 @@ static SECURITY_STATUS CDECL schan_recv(schan_session session, SecBufferDesc *in } } - *length = received; + *params->length = received; return status; } @@ -910,48 +918,51 @@ static unsigned int parse_alpn_protocol_list(unsigned char *buffer, unsigned int return count; } -static void CDECL schan_set_application_protocols(schan_session session, unsigned char *buffer, unsigned int buflen) +static NTSTATUS schan_set_application_protocols( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct set_application_protocols_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; unsigned int extension_len, extension, count = 0, offset = 0; unsigned short list_len; gnutls_datum_t *protocols; int ret; - if (sizeof(extension_len) > buflen) return; - extension_len = *(unsigned int *)&buffer[offset]; + if (sizeof(extension_len) > params->buflen) return STATUS_INVALID_PARAMETER; + extension_len = *(unsigned int *)¶ms->buffer[offset]; offset += sizeof(extension_len); - if (offset + sizeof(extension) > buflen) return; - extension = *(unsigned int *)&buffer[offset]; + if (offset + sizeof(extension) > params->buflen) return STATUS_INVALID_PARAMETER; + extension = *(unsigned int *)¶ms->buffer[offset]; if (extension != SecApplicationProtocolNegotiationExt_ALPN) { FIXME("extension %u not supported\n", extension); - return; + return STATUS_NOT_SUPPORTED; } offset += sizeof(extension); - if (offset + sizeof(list_len) > buflen) return; - list_len = *(unsigned short *)&buffer[offset]; + if (offset + sizeof(list_len) > params->buflen) return STATUS_INVALID_PARAMETER; + list_len = *(unsigned short *)¶ms->buffer[offset]; offset += sizeof(list_len); - if (offset + list_len > buflen) return; - count = parse_alpn_protocol_list(&buffer[offset], list_len, NULL); - if (!count || !(protocols = RtlAllocateHeap(GetProcessHeap(), 0, count * sizeof(*protocols)))) return; + if (offset + list_len > params->buflen) return STATUS_INVALID_PARAMETER; + count = parse_alpn_protocol_list(¶ms->buffer[offset], list_len, NULL); + if (!count || !(protocols = malloc(count * sizeof(*protocols)))) return STATUS_NO_MEMORY; - parse_alpn_protocol_list(&buffer[offset], list_len, protocols); + parse_alpn_protocol_list(¶ms->buffer[offset], list_len, protocols); if ((ret = pgnutls_alpn_set_protocols(s, protocols, count, GNUTLS_ALPN_SERVER_PRECEDENCE) < 0)) { pgnutls_perror(ret); } - RtlFreeHeap(GetProcessHeap(), 0, protocols); + free(protocols); + return STATUS_SUCCESS; } -static SECURITY_STATUS CDECL schan_get_application_protocol(schan_session session, - SecPkgContext_ApplicationProtocol *protocol) +static NTSTATUS schan_get_application_protocol( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct get_application_protocol_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; + SecPkgContext_ApplicationProtocol *protocol = params->protocol; gnutls_datum_t selected; memset(protocol, 0, sizeof(*protocol)); @@ -968,12 +979,13 @@ static SECURITY_STATUS CDECL schan_get_application_protocol(schan_session sessio return SEC_E_OK; } -static SECURITY_STATUS CDECL schan_set_dtls_mtu(schan_session session, unsigned int mtu) +static NTSTATUS schan_set_dtls_mtu( void *args ) { - gnutls_session_t s = (gnutls_session_t)session; + const struct set_dtls_mtu_params *params = args; + gnutls_session_t s = (gnutls_session_t)params->session; - pgnutls_dtls_set_mtu(s, mtu); - TRACE("MTU set to %u\n", mtu); + pgnutls_dtls_set_mtu(s, params->mtu); + TRACE("MTU set to %u\n", params->mtu); return SEC_E_OK; } @@ -1079,9 +1091,9 @@ static gnutls_x509_crt_t get_x509_crt(const CERT_CONTEXT *ctx) return crt; } -static BOOL CDECL schan_allocate_certificate_credentials(schan_credentials *c, const CERT_CONTEXT *ctx, - const DATA_BLOB *key_blob ) +static NTSTATUS schan_allocate_certificate_credentials( void *args ) { + const struct allocate_certificate_credentials_params *params = args; gnutls_certificate_credentials_t creds; gnutls_x509_crt_t crt; gnutls_x509_privkey_t key; @@ -1091,26 +1103,26 @@ static BOOL CDECL schan_allocate_certificate_credentials(schan_credentials *c, c if (ret != GNUTLS_E_SUCCESS) { pgnutls_perror(ret); - return FALSE; + return STATUS_INTERNAL_ERROR; } - if (!ctx) + if (!params->ctx) { - c->credentials = creds; - return TRUE; + params->c->credentials = creds; + return STATUS_SUCCESS; } - if (!(crt = get_x509_crt(ctx))) + if (!(crt = get_x509_crt(params->ctx))) { pgnutls_certificate_free_credentials(creds); - return FALSE; + return STATUS_INTERNAL_ERROR; } - if (!(key = get_x509_key(key_blob))) + if (!(key = get_x509_key(params->key_blob))) { pgnutls_x509_crt_deinit(crt); pgnutls_certificate_free_credentials(creds); - return FALSE; + return STATUS_INTERNAL_ERROR; } ret = pgnutls_certificate_set_x509_key(creds, &crt, 1, key); @@ -1120,16 +1132,18 @@ static BOOL CDECL schan_allocate_certificate_credentials(schan_credentials *c, c { pgnutls_perror(ret); pgnutls_certificate_free_credentials(creds); - return FALSE; + return STATUS_INTERNAL_ERROR; } - c->credentials = creds; - return TRUE; + params->c->credentials = creds; + return STATUS_SUCCESS; } -static void CDECL schan_free_certificate_credentials(schan_credentials *c) +static NTSTATUS schan_free_certificate_credentials( void *args ) { - pgnutls_certificate_free_credentials(c->credentials); + const struct free_certificate_credentials_params *params = args; + pgnutls_certificate_free_credentials(params->c->credentials); + return STATUS_SUCCESS; } static void gnutls_log(int level, const char *msg) @@ -1137,7 +1151,7 @@ static void gnutls_log(int level, const char *msg) TRACE("<%d> %s", level, msg); } -static BOOL gnutls_initialize(void) +static NTSTATUS process_attach( void *args ) { const char *env_str; int ret; @@ -1156,7 +1170,7 @@ static BOOL gnutls_initialize(void) if (!libgnutls_handle) { ERR_(winediag)("Failed to load libgnutls, secure connections will not be available.\n"); - return FALSE; + return STATUS_DLL_NOT_FOUND; } #define LOAD_FUNCPTR(f) \ @@ -1256,23 +1270,26 @@ static BOOL gnutls_initialize(void) } check_supported_protocols(); - return TRUE; + return STATUS_SUCCESS; fail: dlclose(libgnutls_handle); libgnutls_handle = NULL; - return FALSE; + return STATUS_DLL_NOT_FOUND; } -static void gnutls_uninitialize(void) +static NTSTATUS process_detach( void *args ) { pgnutls_global_deinit(); dlclose(libgnutls_handle); libgnutls_handle = NULL; + return STATUS_SUCCESS; } -static const struct schan_funcs funcs = +const unixlib_entry_t __wine_unix_call_funcs[] = { + process_attach, + process_detach, schan_allocate_certificate_credentials, schan_create_session, schan_dispose_session, @@ -1291,22 +1308,6 @@ static const struct schan_funcs funcs = schan_set_application_protocols, schan_set_dtls_mtu, schan_set_session_target, - schan_set_session_transport, }; -NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out ) -{ - switch (reason) - { - case DLL_PROCESS_ATTACH: - if (!gnutls_initialize()) return STATUS_DLL_NOT_FOUND; - *(const struct schan_funcs **)ptr_out = &funcs; - break; - case DLL_PROCESS_DETACH: - if (libgnutls_handle) gnutls_uninitialize(); - break; - } - return STATUS_SUCCESS; -} - #endif /* SONAME_LIBGNUTLS */ diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index 6bfa1ff7a26..c17adc96dc6 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -108,29 +108,123 @@ struct schan_transport struct schan_buffers out; }; -struct schan_funcs +struct session_params { - BOOL (CDECL *allocate_certificate_credentials)(schan_credentials *, const CERT_CONTEXT *, const DATA_BLOB *); - BOOL (CDECL *create_session)(schan_session *, schan_credentials *); - void (CDECL *dispose_session)(schan_session); - void (CDECL *free_certificate_credentials)(schan_credentials *); - SECURITY_STATUS (CDECL *get_application_protocol)(schan_session, SecPkgContext_ApplicationProtocol *); - SECURITY_STATUS (CDECL *get_connection_info)(schan_session, SecPkgContext_ConnectionInfo *); - DWORD (CDECL *get_enabled_protocols)(void); - ALG_ID (CDECL *get_key_signature_algorithm)(schan_session); - unsigned int (CDECL *get_max_message_size)(schan_session); - unsigned int (CDECL *get_session_cipher_block_size)(schan_session); - SECURITY_STATUS (CDECL *get_session_peer_certificate)(schan_session, CERT_BLOB *, ULONG *, ULONG *); - SECURITY_STATUS (CDECL *get_unique_channel_binding)(schan_session, void *, ULONG *); - SECURITY_STATUS (CDECL *handshake)(schan_session, SecBufferDesc *, SIZE_T, SecBufferDesc *, SecBuffer * ); - SECURITY_STATUS (CDECL *recv)(schan_session, SecBufferDesc *, SIZE_T, void *, SIZE_T *); - SECURITY_STATUS (CDECL *send)(schan_session, SecBufferDesc *, const void *, SIZE_T *); - void (CDECL *set_application_protocols)(schan_session, unsigned char *, unsigned int); - SECURITY_STATUS (CDECL *set_dtls_mtu)(schan_session, unsigned int); - void (CDECL *set_session_target)(schan_session, const char *); - void (CDECL *set_session_transport)(schan_session, struct schan_transport *); + schan_session session; }; -extern const struct schan_funcs *schan_funcs; +struct allocate_certificate_credentials_params +{ + schan_credentials *c; + const CERT_CONTEXT *ctx; + const DATA_BLOB *key_blob; +}; + +struct create_session_params +{ + struct schan_transport *transport; + schan_credentials *cred; +}; + +struct free_certificate_credentials_params +{ + schan_credentials *c; +}; + +struct get_application_protocol_params +{ + schan_session session; + SecPkgContext_ApplicationProtocol *protocol; +}; + +struct get_connection_info_params +{ + schan_session session; + SecPkgContext_ConnectionInfo *info; +}; + +struct get_session_peer_certificate_params +{ + schan_session session; + CERT_BLOB *certs; + ULONG *bufsize; + ULONG *retcount; +}; + +struct get_unique_channel_binding_params +{ + schan_session session; + void *buffer; + ULONG *bufsize; +}; + +struct handshake_params +{ + schan_session session; + SecBufferDesc *input; + SIZE_T input_size; + SecBufferDesc *output; + SecBuffer *alloc_buffer; +}; + +struct recv_params +{ + schan_session session; + SecBufferDesc *input; + SIZE_T input_size; + void *buffer; + SIZE_T *length; +}; + +struct send_params +{ + schan_session session; + SecBufferDesc *output; + const void *buffer; + SIZE_T *length; +}; + +struct set_application_protocols_params +{ + schan_session session; + unsigned char *buffer; + unsigned int buflen; +}; + +struct set_dtls_mtu_params +{ + schan_session session; + unsigned int mtu; +}; + +struct set_session_target_params +{ + schan_session session; + const char *target; +}; + +enum schan_funcs +{ + unix_process_attach, + unix_process_detach, + unix_allocate_certificate_credentials, + unix_create_session, + unix_dispose_session, + unix_free_certificate_credentials, + unix_get_application_protocol, + unix_get_connection_info, + unix_get_enabled_protocols, + unix_get_key_signature_algorithm, + unix_get_max_message_size, + unix_get_session_cipher_block_size, + unix_get_session_peer_certificate, + unix_get_unique_channel_binding, + unix_handshake, + unix_recv, + unix_send, + unix_set_application_protocols, + unix_set_dtls_mtu, + unix_set_session_target, +}; #endif /* __SECUR32_PRIV_H__ */