This seems to work for me on Linux.
-- v2: secur32: Add wow64 support to the unixlib. secur32: Store certificate credentials object pointer as 64-bit. secur32: Use 32-bit sizes in parameters structures. secur32: Remove unused pointer parameter from send request. secur32: Remove duplicate check. secur32: Get rid of buffer iteration callback in unixlib. secur32: Prepare schan_send() buffers on PE side. secur32: Update output buffer offset on return from schan_send() call. secur32: Simplify input buffer handling for schan_recv() call. secur32: Pass single input and output buffers for handshake call. secur32: Manage gnutls transport data in unixlib. secur32: Remove unused argument from buffer iteration helpers.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel_gnutls.c | 28 ++++++++++++++-------------- dlls/secur32/secur32_priv.h | 4 +--- 2 files changed, 15 insertions(+), 17 deletions(-)
diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 2e462b409d8..a79ca7040a5 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -211,7 +211,7 @@ static void compat_gnutls_dtls_set_timeouts(gnutls_session_t session, unsigned i }
static void init_schan_buffers(struct schan_buffers *s, const PSecBufferDesc desc, - int (*get_next_buffer)(const struct schan_transport *, struct schan_buffers *)) + int (*get_next_buffer)(struct schan_buffers *)) { s->offset = 0; s->limit = ~0UL; @@ -236,14 +236,14 @@ static int schan_find_sec_buffer_idx(const SecBufferDesc *desc, unsigned int sta return -1; }
-static int handshake_get_next_buffer(const struct schan_transport *t, struct schan_buffers *s) +static int handshake_get_next_buffer(struct schan_buffers *s) { if (s->current_buffer_idx != -1) return -1; return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_TOKEN); }
-static int handshake_get_next_buffer_alloc(const struct schan_transport *t, struct schan_buffers *s) +static int handshake_get_next_buffer_alloc(struct schan_buffers *s) { if (s->current_buffer_idx == -1) { @@ -262,7 +262,7 @@ static int handshake_get_next_buffer_alloc(const struct schan_transport *t, stru return -1; }
-static int send_message_get_next_buffer(const struct schan_transport *t, struct schan_buffers *s) +static int send_message_get_next_buffer(struct schan_buffers *s) { SecBuffer *b;
@@ -280,7 +280,7 @@ static int send_message_get_next_buffer(const struct schan_transport *t, struct return -1; }
-static int send_message_get_next_buffer_token(const struct schan_transport *t, struct schan_buffers *s) +static int send_message_get_next_buffer_token(struct schan_buffers *s) { SecBuffer *b;
@@ -307,14 +307,14 @@ static int send_message_get_next_buffer_token(const struct schan_transport *t, s return -1; }
-static int recv_message_get_next_buffer(const struct schan_transport *t, struct schan_buffers *s) +static int recv_message_get_next_buffer(struct schan_buffers *s) { if (s->current_buffer_idx != -1) return -1; return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_DATA); }
-static char *get_buffer(const struct schan_transport *t, struct schan_buffers *s, SIZE_T *count) +static char *get_buffer(struct schan_buffers *s, SIZE_T *count) { SIZE_T max_count; PSecBuffer buffer; @@ -328,7 +328,7 @@ static char *get_buffer(const struct schan_transport *t, struct schan_buffers *s if (s->current_buffer_idx == -1) { /* Initial buffer */ - int buffer_idx = s->get_next_buffer(t, s); + int buffer_idx = s->get_next_buffer(s); if (buffer_idx == -1) { TRACE("No next buffer\n"); @@ -349,7 +349,7 @@ static char *get_buffer(const struct schan_transport *t, struct schan_buffers *s { int buffer_idx;
- buffer_idx = s->get_next_buffer(t, s); + buffer_idx = s->get_next_buffer(s); if (buffer_idx == -1) { TRACE("No next buffer\n"); @@ -380,7 +380,7 @@ static ssize_t pull_adapter(gnutls_transport_ptr_t transport, void *buff, size_t
TRACE("Pull %lu bytes\n", len);
- b = get_buffer(t, &t->in, &len); + b = get_buffer(&t->in, &len); if (!b) { pgnutls_transport_set_errno(s, EAGAIN); @@ -401,7 +401,7 @@ static ssize_t push_adapter(gnutls_transport_ptr_t transport, const void *buff,
TRACE("Push %lu bytes\n", len);
- b = get_buffer(t, &t->out, &len); + b = get_buffer(&t->out, &len); if (!b) { pgnutls_transport_set_errno(s, EAGAIN); @@ -471,7 +471,7 @@ static int pull_timeout(gnutls_transport_ptr_t transport, unsigned int timeout)
TRACE("\n");
- if (get_buffer(t, &t->in, &count)) return 1; + if (get_buffer(&t->in, &count)) return 1;
return 0; } @@ -856,7 +856,7 @@ static NTSTATUS schan_send( void *args ) { SIZE_T count = 0;
- if (get_buffer(t, &t->out, &count)) continue; + if (get_buffer(&t->out, &count)) continue; return SEC_I_CONTINUE_NEEDED; } else @@ -893,7 +893,7 @@ static NTSTATUS schan_recv( void *args ) { SIZE_T count = 0;
- if (!get_buffer(t, &t->in, &count)) break; + if (!get_buffer(&t->in, &count)) break; } else if (ret == GNUTLS_E_REHANDSHAKE) { diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index e58303a4e1b..fcc007f77ef 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -88,8 +88,6 @@ typedef struct schan_credentials DWORD enabled_protocols; } schan_credentials;
-struct schan_transport; - struct schan_buffers { SIZE_T offset; @@ -97,7 +95,7 @@ struct schan_buffers const SecBufferDesc *desc; SecBuffer *alloc_buffer; int current_buffer_idx; - int (*get_next_buffer)(const struct schan_transport *, struct schan_buffers *); + int (*get_next_buffer)(struct schan_buffers *); };
struct schan_transport
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel.c | 66 +++++++++++++------------- dlls/secur32/schannel_gnutls.c | 86 ++++++++++++++++++++++++---------- dlls/secur32/secur32_priv.h | 21 ++------- 3 files changed, 97 insertions(+), 76 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 30c86c724b4..3242aebebbe 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -61,7 +61,7 @@ struct schan_handle
struct schan_context { - struct schan_transport transport; + schan_session session; ULONG req_ctx_attr; const CERT_CONTEXT *cert; SIZE_T header_size; @@ -758,14 +758,15 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( { const ULONG extra_size = 0x10000; struct schan_context *ctx; - struct schan_buffers *out_buffers; struct schan_credentials *cred; SIZE_T expected_size = 0; SECURITY_STATUS ret; SecBuffer *buffer; SecBuffer alloc_buffer = { 0 }; - struct handshake_params params; + struct handshake_params params = { 0 }; + int output_buffer_idx = -1; int idx, i; + ULONG input_offset = 0, output_offset = 0;
TRACE("%p %p %s 0x%08lx %ld %ld %p %ld %p %p %p %p\n", phCredential, phContext, debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, @@ -815,9 +816,8 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( return SEC_E_INTERNAL_ERROR; }
- create_params.transport = &ctx->transport; create_params.cred = cred; - create_params.session = &ctx->transport.session; + create_params.session = &ctx->session; if (GNUTLS_CALL( create_session, &create_params )) { schan_free_handle(handle, SCHAN_HANDLE_CTX); @@ -837,7 +837,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
if (target) { - struct set_session_target_params params = { ctx->transport.session, target }; + struct set_session_target_params params = { ctx->session, target }; WideCharToMultiByte( CP_UNIXCP, 0, pszTargetName, -1, target, len, NULL, NULL ); GNUTLS_CALL( set_session_target, ¶ms ); free( target ); @@ -846,8 +846,8 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
if (pInput && (idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_APPLICATION_PROTOCOLS)) != -1) { - struct set_application_protocols_params params = { ctx->transport.session, - pInput->pBuffers[idx].pvBuffer, pInput->pBuffers[idx].cbBuffer }; + struct set_application_protocols_params params = { ctx->session, pInput->pBuffers[idx].pvBuffer, + pInput->pBuffers[idx].cbBuffer }; GNUTLS_CALL( set_application_protocols, ¶ms ); }
@@ -856,7 +856,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( buffer = &pInput->pBuffers[idx]; if (buffer->cbBuffer >= sizeof(WORD)) { - struct set_dtls_mtu_params params = { ctx->transport.session, *(WORD *)buffer->pvBuffer }; + struct set_dtls_mtu_params params = { ctx->session, *(WORD *)buffer->pvBuffer }; GNUTLS_CALL( set_dtls_mtu, ¶ms ); } else WARN("invalid buffer size %lu\n", buffer->cbBuffer); @@ -864,7 +864,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
if (is_dtls_context(ctx)) { - struct set_dtls_timeouts_params params = { ctx->transport.session, 0, 60000 }; + struct set_dtls_timeouts_params params = { ctx->session, 0, 60000 }; GNUTLS_CALL( set_dtls_timeouts, ¶ms ); }
@@ -917,18 +917,20 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( alloc_buffer.BufferType = SECBUFFER_TOKEN; alloc_buffer.pvBuffer = RtlAllocateHeap( GetProcessHeap(), 0, extra_size ); } - params.session = ctx->transport.session; + params.session = ctx->session; params.input = pInput; params.input_size = expected_size; params.output = pOutput; params.alloc_buffer = &alloc_buffer; + params.input_offset = &input_offset; + params.output_buffer_idx = &output_buffer_idx; + params.output_offset = &output_offset; ret = GNUTLS_CALL( handshake, ¶ms );
- out_buffers = &ctx->transport.out; - if (out_buffers->current_buffer_idx != -1) + if (output_buffer_idx != -1) { - SecBuffer *buffer = &out_buffers->desc->pBuffers[out_buffers->current_buffer_idx]; - buffer->cbBuffer = out_buffers->offset; + SecBuffer *buffer = &pOutput->pBuffers[output_buffer_idx]; + buffer->cbBuffer = output_offset; if (buffer->pvBuffer == alloc_buffer.pvBuffer) { RtlReAllocateHeap( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, @@ -936,19 +938,19 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( alloc_buffer.pvBuffer = NULL; } } - else if (out_buffers->desc && out_buffers->desc->cBuffers > 0) + else if (pOutput && pOutput->cBuffers) { - SecBuffer *buffer = &out_buffers->desc->pBuffers[0]; - buffer->cbBuffer = 0; + pOutput->pBuffers[0].cbBuffer = 0; } RtlFreeHeap( GetProcessHeap(), 0, alloc_buffer.pvBuffer );
- if(ctx->transport.in.offset && ctx->transport.in.offset != pInput->pBuffers[0].cbBuffer) { + if (input_offset && input_offset != pInput->pBuffers[0].cbBuffer) + { if(pInput->cBuffers<2 || pInput->pBuffers[1].BufferType!=SECBUFFER_EMPTY) return SEC_E_INVALID_TOKEN;
pInput->pBuffers[1].BufferType = SECBUFFER_EXTRA; - pInput->pBuffers[1].cbBuffer = pInput->pBuffers[0].cbBuffer-ctx->transport.in.offset; + pInput->pBuffers[1].cbBuffer = pInput->pBuffers[0].cbBuffer - input_offset; }
for (i = 0; i < pOutput->cBuffers; i++) @@ -1031,7 +1033,7 @@ static SECURITY_STATUS ensure_remote_cert(struct schan_context *ctx) PCCERT_CONTEXT cert = NULL; SECURITY_STATUS status; ULONG count, size = 0; - struct get_session_peer_certificate_params params = { ctx->transport.session, NULL, &size, &count }; + struct get_session_peer_certificate_params params = { ctx->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))) @@ -1089,11 +1091,11 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( case SECPKG_ATTR_STREAM_SIZES: { SecPkgContext_ConnectionInfo info; - struct get_connection_info_params params = { ctx->transport.session, &info }; + struct get_connection_info_params params = { ctx->session, &info }; status = GNUTLS_CALL( get_connection_info, ¶ms ); if (status == SEC_E_OK) { - struct session_params params = { ctx->transport.session }; + struct session_params params = { ctx->session }; SecPkgContext_StreamSizes *stream_sizes = buffer; SIZE_T mac_size = info.dwHashStrength; unsigned int block_size = GNUTLS_CALL( get_session_cipher_block_size, ¶ms ); @@ -1115,11 +1117,11 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( case SECPKG_ATTR_KEY_INFO: { SecPkgContext_ConnectionInfo conn_info; - struct get_connection_info_params params = { ctx->transport.session, &conn_info }; + struct get_connection_info_params params = { ctx->session, &conn_info }; status = GNUTLS_CALL( get_connection_info, ¶ms ); if (status == SEC_E_OK) { - struct session_params params = { ctx->transport.session }; + struct session_params params = { ctx->session }; SecPkgContext_KeyInfoW *info = buffer; info->KeySize = conn_info.dwCipherStrength; info->SignatureAlgorithm = GNUTLS_CALL( get_key_signature_algorithm, ¶ms ); @@ -1143,7 +1145,7 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( case SECPKG_ATTR_CONNECTION_INFO: { SecPkgContext_ConnectionInfo *info = buffer; - struct get_connection_info_params params = { ctx->transport.session, info }; + struct get_connection_info_params params = { ctx->session, info }; return GNUTLS_CALL( get_connection_info, ¶ms ); } case SECPKG_ATTR_ENDPOINT_BINDINGS: @@ -1193,7 +1195,7 @@ 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 }; + struct get_unique_channel_binding_params params = { ctx->session, NULL, &size };
if (GNUTLS_CALL( get_unique_channel_binding, ¶ms ) != SEC_E_BUFFER_TOO_SMALL) return SEC_E_INTERNAL_ERROR; @@ -1216,7 +1218,7 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW( case SECPKG_ATTR_APPLICATION_PROTOCOL: { SecPkgContext_ApplicationProtocol *protocol = buffer; - struct get_application_protocol_params params = { ctx->transport.session, protocol }; + struct get_application_protocol_params params = { ctx->session, protocol }; return GNUTLS_CALL( get_application_protocol, ¶ms ); }
@@ -1297,7 +1299,7 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle memcpy(data, buffer->pvBuffer, data_size);
length = data_size; - params.session = ctx->transport.session; + params.session = ctx->session; params.output = message; params.buffer = data; params.length = &length; @@ -1421,7 +1423,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
received = data_size;
- params.session = ctx->transport.session; + params.session = ctx->session; params.input = message; params.input_size = expected_size; params.buffer = data; @@ -1469,7 +1471,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DeleteSecurityContext(PCtxtHandle context if (!ctx) return SEC_E_INVALID_HANDLE;
if (ctx->cert) CertFreeCertificateContext(ctx->cert); - params.session = ctx->transport.session; + params.session = ctx->session; GNUTLS_CALL( dispose_session, ¶ms ); free(ctx); return SEC_E_OK; @@ -1610,7 +1612,7 @@ void SECUR32_deinitSchannelSP(void) if (schan_handle_table[i].type == SCHAN_HANDLE_CTX) { struct schan_context *ctx = schan_free_handle(i, SCHAN_HANDLE_CTX); - struct session_params params = { ctx->transport.session }; + struct session_params params = { ctx->session }; GNUTLS_CALL( dispose_session, ¶ms ); free(ctx); } diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index a79ca7040a5..098ca239598 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -141,6 +141,23 @@ static inline gnutls_session_t session_from_handle(UINT64 handle) return (gnutls_session_t)(ULONG_PTR)handle; }
+struct schan_buffers +{ + SIZE_T offset; + SIZE_T limit; + const SecBufferDesc *desc; + SecBuffer *alloc_buffer; + int current_buffer_idx; + int (*get_next_buffer)(struct schan_buffers *); +}; + +struct schan_transport +{ + gnutls_session_t session; + struct schan_buffers in; + struct schan_buffers out; +}; + static int compat_cipher_get_block_size(gnutls_cipher_algorithm_t cipher) { switch(cipher) { @@ -374,7 +391,6 @@ static char *get_buffer(struct schan_buffers *s, SIZE_T *count) static ssize_t pull_adapter(gnutls_transport_ptr_t transport, void *buff, size_t buff_len) { struct schan_transport *t = (struct schan_transport*)transport; - gnutls_session_t s = session_from_handle(t->session); SIZE_T len = buff_len; char *b;
@@ -383,7 +399,7 @@ static ssize_t pull_adapter(gnutls_transport_ptr_t transport, void *buff, size_t b = get_buffer(&t->in, &len); if (!b) { - pgnutls_transport_set_errno(s, EAGAIN); + pgnutls_transport_set_errno(t->session, EAGAIN); return -1; } memcpy(buff, b, len); @@ -395,7 +411,6 @@ static ssize_t pull_adapter(gnutls_transport_ptr_t transport, void *buff, size_t static ssize_t push_adapter(gnutls_transport_ptr_t transport, const void *buff, size_t buff_len) { struct schan_transport *t = (struct schan_transport*)transport; - gnutls_session_t s = session_from_handle(t->session); SIZE_T len = buff_len; char *b;
@@ -404,7 +419,7 @@ static ssize_t push_adapter(gnutls_transport_ptr_t transport, const void *buff, b = get_buffer(&t->out, &len); if (!b) { - pgnutls_transport_set_errno(s, EAGAIN); + pgnutls_transport_set_errno(t->session, EAGAIN); return -1; } memcpy(b, buff, len); @@ -483,6 +498,7 @@ static NTSTATUS schan_create_session( void *args ) 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; + struct schan_transport *transport; gnutls_session_t s; int err;
@@ -500,6 +516,13 @@ static NTSTATUS schan_create_session( void *args ) return STATUS_INTERNAL_ERROR; }
+ if (!(transport = calloc(1, sizeof(*transport)))) + { + pgnutls_deinit(s); + return STATUS_INTERNAL_ERROR; + } + transport->session = s; + p = priority + strlen(priority);
/* VERS-ALL is nice to use for forward compatibility. It was introduced before support for TLS1.3, @@ -531,6 +554,7 @@ static NTSTATUS schan_create_session( void *args ) { pgnutls_perror(err); pgnutls_deinit(s); + free(transport); return STATUS_INTERNAL_ERROR; }
@@ -540,13 +564,14 @@ static NTSTATUS schan_create_session( void *args ) { pgnutls_perror(err); pgnutls_deinit(s); + free(transport); 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); + pgnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)transport); *params->session = (ULONG_PTR)s;
return STATUS_SUCCESS; @@ -556,7 +581,10 @@ static NTSTATUS schan_dispose_session( void *args ) { const struct session_params *params = args; gnutls_session_t s = session_from_handle(params->session); + struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s); + pgnutls_transport_set_ptr(s, NULL); pgnutls_deinit(s); + free(t); return STATUS_SUCCESS; }
@@ -573,6 +601,7 @@ static NTSTATUS schan_handshake( void *args ) const struct handshake_params *params = args; gnutls_session_t s = session_from_handle(params->session); struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s); + NTSTATUS status; int err;
init_schan_buffers(&t->in, params->input, handshake_get_next_buffer); @@ -580,47 +609,52 @@ static NTSTATUS schan_handshake( void *args ) init_schan_buffers(&t->out, params->output, handshake_get_next_buffer_alloc ); t->out.alloc_buffer = params->alloc_buffer;
- while(1) { + while (1) + { err = pgnutls_handshake(s); - switch(err) { - case GNUTLS_E_SUCCESS: + if (err == GNUTLS_E_SUCCESS) + { TRACE("Handshake completed\n"); - return SEC_E_OK; - - case GNUTLS_E_AGAIN: + status = SEC_E_OK; + } + else if (err == GNUTLS_E_AGAIN) + { TRACE("Continue...\n"); - return SEC_I_CONTINUE_NEEDED; - - case GNUTLS_E_WARNING_ALERT_RECEIVED: + status = SEC_I_CONTINUE_NEEDED; + } + else if (err == GNUTLS_E_WARNING_ALERT_RECEIVED) { gnutls_alert_description_t alert = pgnutls_alert_get(s);
WARN("WARNING ALERT: %d %s\n", alert, pgnutls_alert_get_name(alert));
- switch(alert) { - case GNUTLS_A_UNRECOGNIZED_NAME: + if (alert == GNUTLS_A_UNRECOGNIZED_NAME) + { TRACE("Ignoring\n"); continue; - default: - return SEC_E_INTERNAL_ERROR; } + else + status = SEC_E_INTERNAL_ERROR; } - - case GNUTLS_E_FATAL_ALERT_RECEIVED: + else if (err == GNUTLS_E_FATAL_ALERT_RECEIVED) { gnutls_alert_description_t alert = pgnutls_alert_get(s); WARN("FATAL ALERT: %d %s\n", alert, pgnutls_alert_get_name(alert)); - return SEC_E_INTERNAL_ERROR; + status = SEC_E_INTERNAL_ERROR; } - - default: + else + { pgnutls_perror(err); - return SEC_E_INTERNAL_ERROR; + status = SEC_E_INTERNAL_ERROR; } + break; }
- /* Never reached */ - return SEC_E_OK; + *params->input_offset = t->in.offset; + *params->output_buffer_idx = t->out.current_buffer_idx; + *params->output_offset = t->out.offset; + + return status; }
static DWORD get_protocol(gnutls_protocol_t proto) diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index fcc007f77ef..8a59458e875 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -88,23 +88,6 @@ typedef struct schan_credentials DWORD enabled_protocols; } schan_credentials;
-struct schan_buffers -{ - SIZE_T offset; - SIZE_T limit; - const SecBufferDesc *desc; - SecBuffer *alloc_buffer; - int current_buffer_idx; - int (*get_next_buffer)(struct schan_buffers *); -}; - -struct schan_transport -{ - schan_session session; - struct schan_buffers in; - struct schan_buffers out; -}; - struct session_params { schan_session session; @@ -122,7 +105,6 @@ struct allocate_certificate_credentials_params
struct create_session_params { - struct schan_transport *transport; schan_credentials *cred; schan_session *session; }; @@ -166,6 +148,9 @@ struct handshake_params SIZE_T input_size; SecBufferDesc *output; SecBuffer *alloc_buffer; + ULONG *input_offset; + int *output_buffer_idx; + ULONG *output_offset; };
struct recv_params
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel.c | 35 ++++++++++++++++++++++++++++------ dlls/secur32/schannel_gnutls.c | 26 ++----------------------- dlls/secur32/secur32_priv.h | 1 - 3 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 3242aebebbe..6a8d667a32f 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -767,6 +767,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( int output_buffer_idx = -1; int idx, i; ULONG input_offset = 0, output_offset = 0; + SecBufferDesc input_desc, output_desc;
TRACE("%p %p %s 0x%08lx %ld %ld %p %ld %p %p %p %p\n", phCredential, phContext, debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, @@ -917,11 +918,30 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( alloc_buffer.BufferType = SECBUFFER_TOKEN; alloc_buffer.pvBuffer = RtlAllocateHeap( GetProcessHeap(), 0, extra_size ); } + + memset(&input_desc, 0, sizeof(input_desc)); + if (pInput && (idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_TOKEN)) != -1) + { + input_desc.cBuffers = 1; + input_desc.pBuffers = &pInput->pBuffers[idx]; + } + + memset(&output_desc, 0, sizeof(output_desc)); + idx = schan_find_sec_buffer_idx(pOutput, 0, SECBUFFER_TOKEN); + if (idx == -1) + idx = schan_find_sec_buffer_idx(pOutput, 0, SECBUFFER_EMPTY); + if (idx != -1) + { + output_desc.cBuffers = 1; + output_desc.pBuffers = &pOutput->pBuffers[idx]; + if (!output_desc.pBuffers->pvBuffer) + output_desc.pBuffers = &alloc_buffer; + } + params.session = ctx->session; - params.input = pInput; + params.input = pInput ? &input_desc : NULL; params.input_size = expected_size; - params.output = pOutput; - params.alloc_buffer = &alloc_buffer; + params.output = &output_desc; params.input_offset = &input_offset; params.output_buffer_idx = &output_buffer_idx; params.output_offset = &output_offset; @@ -929,12 +949,15 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
if (output_buffer_idx != -1) { - SecBuffer *buffer = &pOutput->pBuffers[output_buffer_idx]; + SecBuffer *buffer = &pOutput->pBuffers[idx]; + buffer->BufferType = SECBUFFER_TOKEN; buffer->cbBuffer = output_offset; - if (buffer->pvBuffer == alloc_buffer.pvBuffer) + if (output_desc.pBuffers == &alloc_buffer) { RtlReAllocateHeap( GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY, - buffer->pvBuffer, buffer->cbBuffer ); + alloc_buffer.pvBuffer, buffer->cbBuffer ); + + buffer->pvBuffer = alloc_buffer.pvBuffer; alloc_buffer.pvBuffer = NULL; } } diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 098ca239598..696790f44dc 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -146,7 +146,6 @@ struct schan_buffers SIZE_T offset; SIZE_T limit; const SecBufferDesc *desc; - SecBuffer *alloc_buffer; int current_buffer_idx; int (*get_next_buffer)(struct schan_buffers *); }; @@ -234,7 +233,6 @@ static void init_schan_buffers(struct schan_buffers *s, const PSecBufferDesc des s->limit = ~0UL; s->desc = desc; s->current_buffer_idx = -1; - s->alloc_buffer = NULL; s->get_next_buffer = get_next_buffer; }
@@ -257,26 +255,7 @@ static int handshake_get_next_buffer(struct schan_buffers *s) { if (s->current_buffer_idx != -1) return -1; - return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_TOKEN); -} - -static int handshake_get_next_buffer_alloc(struct schan_buffers *s) -{ - if (s->current_buffer_idx == -1) - { - int idx = schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_TOKEN); - if (idx == -1) - { - idx = schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_EMPTY); - if (idx != -1) s->desc->pBuffers[idx].BufferType = SECBUFFER_TOKEN; - } - if (idx != -1 && !s->desc->pBuffers[idx].pvBuffer && s->alloc_buffer) - { - s->desc->pBuffers[idx] = *s->alloc_buffer; - } - return idx; - } - return -1; + return s->desc->cBuffers ? 0 : -1; }
static int send_message_get_next_buffer(struct schan_buffers *s) @@ -606,8 +585,7 @@ static NTSTATUS schan_handshake( void *args )
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; + init_schan_buffers(&t->out, params->output, handshake_get_next_buffer);
while (1) { diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index 8a59458e875..574d3d51cb5 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -147,7 +147,6 @@ struct handshake_params SecBufferDesc *input; SIZE_T input_size; SecBufferDesc *output; - SecBuffer *alloc_buffer; ULONG *input_offset; int *output_buffer_idx; ULONG *output_offset;
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel.c | 6 +++++- dlls/secur32/schannel_gnutls.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 6a8d667a32f..1f4a1005550 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -1409,6 +1409,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle SIZE_T received = 0; int idx; unsigned char *buf_ptr; + SecBufferDesc input_desc = { 0 };
TRACE("context_handle %p, message %p, message_seq_no %ld, quality %p\n", context_handle, message, message_seq_no, quality); @@ -1446,8 +1447,11 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
received = data_size;
+ input_desc.cBuffers = 1; + input_desc.pBuffers = &message->pBuffers[idx]; + params.session = ctx->session; - params.input = message; + params.input = &input_desc; params.input_size = expected_size; params.buffer = data; params.length = &received; diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 696790f44dc..82437207982 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -307,7 +307,7 @@ static int recv_message_get_next_buffer(struct schan_buffers *s) { if (s->current_buffer_idx != -1) return -1; - return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_DATA); + return s->desc->cBuffers ? 0 : -1; }
static char *get_buffer(struct schan_buffers *s, SIZE_T *count)
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel.c | 8 +++++++- dlls/secur32/schannel_gnutls.c | 3 ++- dlls/secur32/secur32_priv.h | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 1f4a1005550..289802c5b32 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -1299,7 +1299,8 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle SIZE_T data_size; SIZE_T length; char *data; - int idx; + int idx, output_buffer_idx = -1; + ULONG output_offset = 0;
TRACE("context_handle %p, quality %ld, message %p, message_seq_no %ld\n", context_handle, quality, message, message_seq_no); @@ -1326,8 +1327,13 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle params.output = message; params.buffer = data; params.length = &length; + params.output_buffer_idx = &output_buffer_idx; + params.output_offset = &output_offset; status = GNUTLS_CALL( send, ¶ms );
+ if (!status && output_buffer_idx != -1) + message->pBuffers[output_buffer_idx].cbBuffer = output_offset; + TRACE("Sent %Id bytes.\n", length);
if (length != data_size) diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 82437207982..ebce6bacde0 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -878,7 +878,8 @@ static NTSTATUS schan_send( void *args ) } }
- t->out.desc->pBuffers[t->out.current_buffer_idx].cbBuffer = t->out.offset; + *params->output_buffer_idx = t->out.current_buffer_idx; + *params->output_offset = t->out.offset; return SEC_E_OK; }
diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index 574d3d51cb5..8a494309710 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -167,6 +167,8 @@ struct send_params SecBufferDesc *output; const void *buffer; SIZE_T *length; + int *output_buffer_idx; + ULONG *output_offset; };
struct set_application_protocols_params
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel.c | 45 +++++++++++++++--- dlls/secur32/schannel_gnutls.c | 84 ++++------------------------------ 2 files changed, 46 insertions(+), 83 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 289802c5b32..4508bc2f4b6 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -1299,8 +1299,12 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle SIZE_T data_size; SIZE_T length; char *data; - int idx, output_buffer_idx = -1; + int output_buffer_idx = -1; ULONG output_offset = 0; + SecBufferDesc output_desc = { 0 }; + SecBuffer output_buffers[3]; + int header_idx, data_idx, trailer_idx = -1; + int buffer_index[3];
TRACE("context_handle %p, quality %ld, message %p, message_seq_no %ld\n", context_handle, quality, message, message_seq_no); @@ -1310,29 +1314,56 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle
dump_buffer_desc(message);
- idx = schan_find_sec_buffer_idx(message, 0, SECBUFFER_DATA); - if (idx == -1) + data_idx = schan_find_sec_buffer_idx(message, 0, SECBUFFER_DATA); + if (data_idx == -1) { WARN("No data buffer passed\n"); return SEC_E_INTERNAL_ERROR; } - buffer = &message->pBuffers[idx]; + buffer = &message->pBuffers[data_idx];
data_size = buffer->cbBuffer; data = malloc(data_size); memcpy(data, buffer->pvBuffer, data_size);
+ /* Use { STREAM_HEADER, DATA, STREAM_TRAILER } or { TOKEN, DATA, TOKEN } buffers. */ + + output_desc.pBuffers = output_buffers; + if ((header_idx = schan_find_sec_buffer_idx(message, 0, SECBUFFER_STREAM_HEADER)) == -1) + { + if ((header_idx = schan_find_sec_buffer_idx(message, 0, SECBUFFER_TOKEN)) != -1) + { + output_buffers[output_desc.cBuffers++] = message->pBuffers[header_idx]; + output_buffers[output_desc.cBuffers++] = message->pBuffers[data_idx]; + trailer_idx = schan_find_sec_buffer_idx(message, header_idx + 1, SECBUFFER_TOKEN); + if (trailer_idx != -1) + output_buffers[output_desc.cBuffers++] = message->pBuffers[trailer_idx]; + } + } + else + { + output_buffers[output_desc.cBuffers++] = message->pBuffers[header_idx]; + output_buffers[output_desc.cBuffers++] = message->pBuffers[data_idx]; + trailer_idx = schan_find_sec_buffer_idx(message, 0, SECBUFFER_STREAM_TRAILER); + if (trailer_idx != -1) + output_buffers[output_desc.cBuffers++] = message->pBuffers[trailer_idx]; + } + + buffer_index[0] = header_idx; + buffer_index[1] = data_idx; + buffer_index[2] = trailer_idx; + length = data_size; params.session = ctx->session; - params.output = message; + params.output = &output_desc; params.buffer = data; params.length = &length; params.output_buffer_idx = &output_buffer_idx; params.output_offset = &output_offset; status = GNUTLS_CALL( send, ¶ms );
- if (!status && output_buffer_idx != -1) - message->pBuffers[output_buffer_idx].cbBuffer = output_offset; + if (!status) + message->pBuffers[buffer_index[output_buffer_idx]].cbBuffer = output_offset;
TRACE("Sent %Id bytes.\n", length);
diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index ebce6bacde0..44ad7c2c1da 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -236,78 +236,13 @@ static void init_schan_buffers(struct schan_buffers *s, const PSecBufferDesc des s->get_next_buffer = get_next_buffer; }
-static int schan_find_sec_buffer_idx(const SecBufferDesc *desc, unsigned int start_idx, ULONG buffer_type) +static int common_get_next_buffer(struct schan_buffers *s) { - unsigned int i; - PSecBuffer buffer; - - for (i = start_idx; i < desc->cBuffers; ++i) - { - buffer = &desc->pBuffers[i]; - if ((buffer->BufferType | SECBUFFER_ATTRMASK) == (buffer_type | SECBUFFER_ATTRMASK)) - return i; - } - - return -1; -} - -static int handshake_get_next_buffer(struct schan_buffers *s) -{ - if (s->current_buffer_idx != -1) - return -1; - return s->desc->cBuffers ? 0 : -1; -} - -static int send_message_get_next_buffer(struct schan_buffers *s) -{ - SecBuffer *b; - - if (s->current_buffer_idx == -1) - return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_STREAM_HEADER); - - b = &s->desc->pBuffers[s->current_buffer_idx]; - - if (b->BufferType == SECBUFFER_STREAM_HEADER) - return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_DATA); - - if (b->BufferType == SECBUFFER_DATA) - return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_STREAM_TRAILER); - - return -1; -} - -static int send_message_get_next_buffer_token(struct schan_buffers *s) -{ - SecBuffer *b; - if (s->current_buffer_idx == -1) - return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_TOKEN); - - b = &s->desc->pBuffers[s->current_buffer_idx]; - - if (b->BufferType == SECBUFFER_TOKEN) - { - int idx = schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_TOKEN); - if (idx != s->current_buffer_idx) return -1; - return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_DATA); - } - - if (b->BufferType == SECBUFFER_DATA) - { - int idx = schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_TOKEN); - if (idx != -1) - idx = schan_find_sec_buffer_idx(s->desc, idx + 1, SECBUFFER_TOKEN); - return idx; - } - - return -1; -} - -static int recv_message_get_next_buffer(struct schan_buffers *s) -{ - if (s->current_buffer_idx != -1) + return s->desc->cBuffers ? 0 : -1; + if (s->current_buffer_idx == s->desc->cBuffers - 1) return -1; - return s->desc->cBuffers ? 0 : -1; + return s->current_buffer_idx + 1; }
static char *get_buffer(struct schan_buffers *s, SIZE_T *count) @@ -583,9 +518,9 @@ static NTSTATUS schan_handshake( void *args ) NTSTATUS status; int err;
- init_schan_buffers(&t->in, params->input, handshake_get_next_buffer); + init_schan_buffers(&t->in, params->input, common_get_next_buffer); t->in.limit = params->input_size; - init_schan_buffers(&t->out, params->output, handshake_get_next_buffer); + init_schan_buffers(&t->out, params->output, common_get_next_buffer);
while (1) { @@ -850,10 +785,7 @@ static NTSTATUS schan_send( void *args ) struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s); SSIZE_T ret, total = 0;
- 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, params->output, send_message_get_next_buffer_token); + init_schan_buffers(&t->out, params->output, common_get_next_buffer);
for (;;) { @@ -893,7 +825,7 @@ static NTSTATUS schan_recv( void *args ) ssize_t ret; SECURITY_STATUS status = SEC_E_OK;
- init_schan_buffers(&t->in, params->input, recv_message_get_next_buffer); + init_schan_buffers(&t->in, params->input, common_get_next_buffer); t->in.limit = params->input_size;
while (received < data_size)
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel_gnutls.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 44ad7c2c1da..0657f9ab064 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -147,7 +147,6 @@ struct schan_buffers SIZE_T limit; const SecBufferDesc *desc; int current_buffer_idx; - int (*get_next_buffer)(struct schan_buffers *); };
struct schan_transport @@ -226,17 +225,15 @@ static void compat_gnutls_dtls_set_timeouts(gnutls_session_t session, unsigned i FIXME("\n"); }
-static void init_schan_buffers(struct schan_buffers *s, const PSecBufferDesc desc, - int (*get_next_buffer)(struct schan_buffers *)) +static void init_schan_buffers(struct schan_buffers *s, const PSecBufferDesc desc) { s->offset = 0; s->limit = ~0UL; s->desc = desc; s->current_buffer_idx = -1; - s->get_next_buffer = get_next_buffer; }
-static int common_get_next_buffer(struct schan_buffers *s) +static int get_next_buffer(struct schan_buffers *s) { if (s->current_buffer_idx == -1) return s->desc->cBuffers ? 0 : -1; @@ -259,7 +256,7 @@ static char *get_buffer(struct schan_buffers *s, SIZE_T *count) if (s->current_buffer_idx == -1) { /* Initial buffer */ - int buffer_idx = s->get_next_buffer(s); + int buffer_idx = get_next_buffer(s); if (buffer_idx == -1) { TRACE("No next buffer\n"); @@ -280,7 +277,7 @@ static char *get_buffer(struct schan_buffers *s, SIZE_T *count) { int buffer_idx;
- buffer_idx = s->get_next_buffer(s); + buffer_idx = get_next_buffer(s); if (buffer_idx == -1) { TRACE("No next buffer\n"); @@ -518,9 +515,9 @@ static NTSTATUS schan_handshake( void *args ) NTSTATUS status; int err;
- init_schan_buffers(&t->in, params->input, common_get_next_buffer); + init_schan_buffers(&t->in, params->input); t->in.limit = params->input_size; - init_schan_buffers(&t->out, params->output, common_get_next_buffer); + init_schan_buffers(&t->out, params->output);
while (1) { @@ -785,7 +782,7 @@ static NTSTATUS schan_send( void *args ) struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s); SSIZE_T ret, total = 0;
- init_schan_buffers(&t->out, params->output, common_get_next_buffer); + init_schan_buffers(&t->out, params->output);
for (;;) { @@ -825,7 +822,7 @@ static NTSTATUS schan_recv( void *args ) ssize_t ret; SECURITY_STATUS status = SEC_E_OK;
- init_schan_buffers(&t->in, params->input, common_get_next_buffer); + init_schan_buffers(&t->in, params->input); t->in.limit = params->input_size;
while (received < data_size)
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 4508bc2f4b6..050a0a6da4c 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -961,7 +961,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW( alloc_buffer.pvBuffer = NULL; } } - else if (pOutput && pOutput->cBuffers) + else { pOutput->pBuffers[0].cbBuffer = 0; }
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel.c | 9 +-------- dlls/secur32/schannel_gnutls.c | 6 +++--- dlls/secur32/secur32_priv.h | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 050a0a6da4c..794ceff1ecf 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -1297,7 +1297,6 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle SECURITY_STATUS status; SecBuffer *buffer; SIZE_T data_size; - SIZE_T length; char *data; int output_buffer_idx = -1; ULONG output_offset = 0; @@ -1353,11 +1352,10 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle buffer_index[1] = data_idx; buffer_index[2] = trailer_idx;
- length = data_size; params.session = ctx->session; params.output = &output_desc; params.buffer = data; - params.length = &length; + params.length = data_size; params.output_buffer_idx = &output_buffer_idx; params.output_offset = &output_offset; status = GNUTLS_CALL( send, ¶ms ); @@ -1365,11 +1363,6 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle if (!status) message->pBuffers[buffer_index[output_buffer_idx]].cbBuffer = output_offset;
- TRACE("Sent %Id bytes.\n", length); - - if (length != data_size) - status = SEC_E_INTERNAL_ERROR; - free(data);
TRACE("Returning %#lx.\n", status); diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 0657f9ab064..4d7711f32a2 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -786,12 +786,12 @@ static NTSTATUS schan_send( void *args )
for (;;) { - ret = pgnutls_record_send(s, (const char *)params->buffer + total, *params->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, *params->length ); - if (total == *params->length) break; + TRACE( "sent %ld now %ld/%u\n", ret, total, (unsigned)params->length ); + if (total == params->length) break; } else if (ret == GNUTLS_E_AGAIN) { diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index 8a494309710..edbe1ccc36e 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -166,7 +166,7 @@ struct send_params schan_session session; SecBufferDesc *output; const void *buffer; - SIZE_T *length; + ULONG length; int *output_buffer_idx; ULONG *output_offset; };
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel.c | 4 ++-- dlls/secur32/secur32_priv.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c index 794ceff1ecf..bc0867ca94b 100644 --- a/dlls/secur32/schannel.c +++ b/dlls/secur32/schannel.c @@ -1436,7 +1436,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle SIZE_T data_size; char *data; unsigned expected_size; - SIZE_T received = 0; + ULONG received = 0; int idx; unsigned char *buf_ptr; SecBufferDesc input_desc = { 0 }; @@ -1494,7 +1494,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle return status; }
- TRACE("Received %Id bytes\n", received); + TRACE("Received %lu bytes\n", received);
memcpy(buf_ptr + ctx->header_size, data, received); free(data); diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index edbe1ccc36e..bbb2c527b18 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -145,7 +145,7 @@ struct handshake_params { schan_session session; SecBufferDesc *input; - SIZE_T input_size; + ULONG input_size; SecBufferDesc *output; ULONG *input_offset; int *output_buffer_idx; @@ -156,9 +156,9 @@ struct recv_params { schan_session session; SecBufferDesc *input; - SIZE_T input_size; + ULONG input_size; void *buffer; - SIZE_T *length; + ULONG *length; };
struct send_params
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel_gnutls.c | 14 +++++++++----- dlls/secur32/secur32_priv.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 4d7711f32a2..08801cef509 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -141,6 +141,11 @@ static inline gnutls_session_t session_from_handle(UINT64 handle) return (gnutls_session_t)(ULONG_PTR)handle; }
+static inline gnutls_certificate_credentials_t certificate_creds_from_handle(UINT64 handle) +{ + return (gnutls_certificate_credentials_t)(ULONG_PTR)handle; +} + struct schan_buffers { SIZE_T offset; @@ -469,8 +474,7 @@ static NTSTATUS schan_create_session( void *args ) return STATUS_INTERNAL_ERROR; }
- err = pgnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, - (gnutls_certificate_credentials_t)cred->credentials); + err = pgnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, certificate_creds_from_handle(cred->credentials)); if (err != GNUTLS_E_SUCCESS) { pgnutls_perror(err); @@ -1074,7 +1078,7 @@ static NTSTATUS schan_allocate_certificate_credentials( void *args )
if (!params->cert_blob) { - params->c->credentials = creds; + params->c->credentials = (ULONG_PTR)creds; return STATUS_SUCCESS; }
@@ -1101,14 +1105,14 @@ static NTSTATUS schan_allocate_certificate_credentials( void *args ) return STATUS_INTERNAL_ERROR; }
- params->c->credentials = creds; + params->c->credentials = (ULONG_PTR)creds; return STATUS_SUCCESS; }
static NTSTATUS schan_free_certificate_credentials( void *args ) { const struct free_certificate_credentials_params *params = args; - pgnutls_certificate_free_credentials(params->c->credentials); + pgnutls_certificate_free_credentials(certificate_creds_from_handle(params->c->credentials)); return STATUS_SUCCESS; }
diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index bbb2c527b18..5753ed47ffa 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -84,8 +84,8 @@ typedef UINT64 schan_session; typedef struct schan_credentials { ULONG credential_use; - void *credentials; DWORD enabled_protocols; + UINT64 credentials; } schan_credentials;
struct session_params
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/secur32/schannel_gnutls.c | 314 +++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+)
diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c index 08801cef509..ad319518a7a 100644 --- a/dlls/secur32/schannel_gnutls.c +++ b/dlls/secur32/schannel_gnutls.c @@ -25,6 +25,7 @@
#include "config.h"
+#include <assert.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -1286,4 +1287,317 @@ const unixlib_entry_t __wine_unix_call_funcs[] = schan_set_dtls_timeouts, };
+#ifdef _WIN64 + +typedef ULONG PTR32; + +typedef struct SecBufferDesc32 +{ + ULONG ulVersion; + ULONG cBuffers; + PTR32 pBuffers; +} SecBufferDesc32; + +typedef struct SecBuffer32 +{ + ULONG cbBuffer; + ULONG BufferType; + PTR32 pvBuffer; +} SecBuffer32; + +static NTSTATUS wow64_schan_allocate_certificate_credentials( void *args ) +{ + struct + { + PTR32 c; + ULONG cert_encoding; + ULONG cert_size; + PTR32 cert_blob; + ULONG key_size; + PTR32 key_blob; + } const *params32 = args; + struct allocate_certificate_credentials_params params = + { + ULongToPtr(params32->c), + params32->cert_encoding, + params32->cert_size, + ULongToPtr(params32->cert_blob), + params32->key_size, + ULongToPtr(params32->key_blob), + }; + return schan_allocate_certificate_credentials(¶ms); +} + +static NTSTATUS wow64_schan_create_session( void *args ) +{ + struct + { + PTR32 cred; + PTR32 session; + } const *params32 = args; + struct create_session_params params = + { + ULongToPtr(params32->cred), + ULongToPtr(params32->session), + }; + return schan_create_session(¶ms); +} + +static NTSTATUS wow64_schan_free_certificate_credentials( void *args ) +{ + struct + { + PTR32 c; + } const *params32 = args; + struct free_certificate_credentials_params params = + { + ULongToPtr(params32->c), + }; + return schan_free_certificate_credentials(¶ms); +} + +static NTSTATUS wow64_schan_get_application_protocol( void *args ) +{ + struct + { + schan_session session; + PTR32 protocol; + } const *params32 = args; + struct get_application_protocol_params params = + { + params32->session, + ULongToPtr(params32->protocol), + }; + return schan_get_application_protocol(¶ms); +} + +static NTSTATUS wow64_schan_get_connection_info( void *args ) +{ + struct + { + schan_session session; + PTR32 info; + } const *params32 = args; + struct get_connection_info_params params = + { + params32->session, + ULongToPtr(params32->info), + }; + return schan_get_connection_info(¶ms); +} + +static NTSTATUS wow64_schan_get_session_peer_certificate( void *args ) +{ + struct + { + schan_session session; + PTR32 buffer; + PTR32 bufsize; + PTR32 retcount; + } const *params32 = args; + struct get_session_peer_certificate_params params = + { + params32->session, + ULongToPtr(params32->buffer), + ULongToPtr(params32->bufsize), + ULongToPtr(params32->retcount), + }; + return schan_get_session_peer_certificate(¶ms); +} + +static NTSTATUS wow64_schan_get_unique_channel_binding( void *args ) +{ + struct + { + schan_session session; + PTR32 buffer; + PTR32 bufsize; + } const *params32 = args; + struct get_unique_channel_binding_params params = + { + params32->session, + ULongToPtr(params32->buffer), + ULongToPtr(params32->bufsize), + }; + return schan_get_unique_channel_binding(¶ms); +} + +static void secbufferdesc_32to64(const SecBufferDesc32 *desc32, SecBufferDesc *desc) +{ + unsigned int i; + + desc->ulVersion = desc32->ulVersion; + desc->cBuffers = desc32->cBuffers; + for (i = 0; i < desc->cBuffers; ++i) + { + SecBuffer32 *buffer32 = ULongToPtr(desc32->pBuffers + i * sizeof(*buffer32)); + desc->pBuffers[i].cbBuffer = buffer32->cbBuffer; + desc->pBuffers[i].BufferType = buffer32->BufferType; + desc->pBuffers[i].pvBuffer = ULongToPtr(buffer32->pvBuffer); + } +} + +static NTSTATUS wow64_schan_handshake( void *args ) +{ + SecBuffer input_buffers[3]; + SecBufferDesc input = { 0, 0, input_buffers }; + SecBuffer output_buffers[3]; + SecBufferDesc output = { 0, 0, output_buffers }; + + struct + { + schan_session session; + PTR32 input; + ULONG input_size; + PTR32 output; + PTR32 input_offset; + PTR32 output_buffer_idx; + PTR32 output_offset; + } const *params32 = args; + struct handshake_params params = + { + params32->session, + params32->input ? &input : NULL, + params32->input_size, + params32->output ? &output : NULL, + ULongToPtr(params32->input_offset), + ULongToPtr(params32->output_buffer_idx), + ULongToPtr(params32->output_offset), + }; + if (params32->input) + { + SecBufferDesc32 *desc32 = ULongToPtr(params32->input); + assert(desc32->cBuffers <= ARRAY_SIZE(input_buffers)); + secbufferdesc_32to64(desc32, &input); + } + if (params32->output) + { + SecBufferDesc32 *desc32 = ULongToPtr(params32->output); + assert(desc32->cBuffers <= ARRAY_SIZE(output_buffers)); + secbufferdesc_32to64(desc32, &output); + } + return schan_handshake(¶ms); +} + +static NTSTATUS wow64_schan_recv( void *args ) +{ + SecBuffer buffers[3]; + SecBufferDesc input = { 0, 0, buffers }; + + struct + { + schan_session session; + PTR32 input; + ULONG input_size; + PTR32 buffer; + PTR32 length; + } const *params32 = args; + struct recv_params params = + { + params32->session, + params32->input ? &input : NULL, + params32->input_size, + ULongToPtr(params32->buffer), + ULongToPtr(params32->length), + }; + if (params32->input) + { + SecBufferDesc32 *desc32 = ULongToPtr(params32->input); + assert(desc32->cBuffers <= ARRAY_SIZE(buffers)); + secbufferdesc_32to64(desc32, &input); + } + return schan_recv(¶ms); +} + +static NTSTATUS wow64_schan_send( void *args ) +{ + SecBuffer buffers[3]; + SecBufferDesc output = { 0, 0, buffers }; + + struct + { + schan_session session; + PTR32 output; + PTR32 buffer; + ULONG length; + PTR32 output_buffer_idx; + PTR32 output_offset; + } const *params32 = args; + struct send_params params = + { + params32->session, + params32->output ? &output : NULL, + ULongToPtr(params32->buffer), + params32->length, + ULongToPtr(params32->output_buffer_idx), + ULongToPtr(params32->output_offset), + }; + if (params32->output) + { + SecBufferDesc32 *desc32 = ULongToPtr(params32->output); + assert(desc32->cBuffers <= ARRAY_SIZE(buffers)); + secbufferdesc_32to64(desc32, &output); + } + return schan_send(¶ms); +} + +static NTSTATUS wow64_schan_set_application_protocols( void *args ) +{ + struct + { + schan_session session; + PTR32 buffer; + unsigned int buflen; + } const *params32 = args; + struct set_application_protocols_params params = + { + params32->session, + ULongToPtr(params32->buffer), + params32->buflen, + }; + return schan_set_application_protocols(¶ms); +} + +static NTSTATUS wow64_schan_set_session_target( void *args ) +{ + struct + { + schan_session session; + PTR32 target; + } const *params32 = args; + struct set_session_target_params params = + { + params32->session, + ULongToPtr(params32->target), + }; + return schan_set_session_target(¶ms); +} + +const unixlib_entry_t __wine_unix_call_wow64_funcs[] = +{ + process_attach, + process_detach, + wow64_schan_allocate_certificate_credentials, + wow64_schan_create_session, + schan_dispose_session, + wow64_schan_free_certificate_credentials, + wow64_schan_get_application_protocol, + wow64_schan_get_connection_info, + schan_get_enabled_protocols, + schan_get_key_signature_algorithm, + schan_get_max_message_size, + schan_get_session_cipher_block_size, + wow64_schan_get_session_peer_certificate, + wow64_schan_get_unique_channel_binding, + wow64_schan_handshake, + wow64_schan_recv, + wow64_schan_send, + wow64_schan_set_application_protocols, + schan_set_dtls_mtu, + wow64_schan_set_session_target, + schan_set_dtls_timeouts, +}; + +#endif /* _WIN64 */ + #endif /* SONAME_LIBGNUTLS */