Commit a4d69c87 authored by Alexandre Julliard's avatar Alexandre Julliard

secur32: Move the buffers initialization and callbacks to the Unix side.

parent 9894e109
......@@ -639,17 +639,6 @@ static SECURITY_STATUS SEC_ENTRY schan_FreeCredentialsHandle(
return SEC_E_OK;
}
static void init_schan_buffers(struct schan_buffers *s, const PSecBufferDesc desc,
int (*get_next_buffer)(const struct schan_transport *, struct schan_buffers *))
{
s->offset = 0;
s->limit = ~0UL;
s->desc = desc;
s->current_buffer_idx = -1;
s->allow_buffer_resize = FALSE;
s->get_next_buffer = get_next_buffer;
}
static int schan_find_sec_buffer_idx(const SecBufferDesc *desc, unsigned int start_idx, ULONG buffer_type)
{
unsigned int i;
......@@ -665,37 +654,6 @@ static int schan_find_sec_buffer_idx(const SecBufferDesc *desc, unsigned int sta
return -1;
}
static int schan_init_sec_ctx_get_next_input_buffer(const struct schan_transport *t, 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 schan_init_sec_ctx_get_next_output_buffer(const struct schan_transport *t, struct schan_buffers *s)
{
if (s->current_buffer_idx == -1)
{
int idx = schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_TOKEN);
if (t->ctx->req_ctx_attr & ISC_REQ_ALLOCATE_MEMORY)
{
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->desc->pBuffers[idx].cbBuffer = 0;
s->allow_buffer_resize = TRUE;
}
}
return idx;
}
return -1;
}
static void dump_buffer_desc(SecBufferDesc *desc)
{
unsigned int i;
......@@ -855,12 +813,8 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
ctx->req_ctx_attr = fContextReq;
init_schan_buffers(&ctx->transport.in, pInput, schan_init_sec_ctx_get_next_input_buffer);
ctx->transport.in.limit = expected_size;
init_schan_buffers(&ctx->transport.out, pOutput, schan_init_sec_ctx_get_next_output_buffer);
/* Perform the TLS handshake */
ret = schan_funcs->handshake(ctx->transport.session);
ret = schan_funcs->handshake(ctx->transport.session, pInput, expected_size, pOutput, fContextReq);
out_buffers = &ctx->transport.out;
if (out_buffers->current_buffer_idx != -1)
......@@ -1147,56 +1101,10 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesA(
}
}
static int schan_encrypt_message_get_next_buffer(const struct schan_transport *t, 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 schan_encrypt_message_get_next_buffer_token(const struct schan_transport *t, 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 SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle,
ULONG quality, PSecBufferDesc message, ULONG message_seq_no)
{
struct schan_context *ctx;
struct schan_buffers *b;
SECURITY_STATUS status;
SecBuffer *buffer;
SIZE_T data_size;
......@@ -1224,21 +1132,14 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle
data = malloc(data_size);
memcpy(data, buffer->pvBuffer, data_size);
if (schan_find_sec_buffer_idx(message, 0, SECBUFFER_STREAM_HEADER) != -1)
init_schan_buffers(&ctx->transport.out, message, schan_encrypt_message_get_next_buffer);
else
init_schan_buffers(&ctx->transport.out, message, schan_encrypt_message_get_next_buffer_token);
length = data_size;
status = schan_funcs->send(ctx->transport.session, data, &length);
status = schan_funcs->send(ctx->transport.session, message, data, &length);
TRACE("Sent %ld bytes.\n", length);
if (length != data_size)
status = SEC_E_INTERNAL_ERROR;
b = &ctx->transport.out;
b->desc->pBuffers[b->current_buffer_idx].cbBuffer = b->offset;
free(data);
TRACE("Returning %#x.\n", status);
......@@ -1246,14 +1147,6 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle
return status;
}
static int schan_decrypt_message_get_next_buffer(const struct schan_transport *t, struct schan_buffers *s)
{
if (s->current_buffer_idx == -1)
return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_DATA);
return -1;
}
static int schan_validate_decrypt_buffer_desc(PSecBufferDesc message)
{
int data_idx = -1;
......@@ -1357,11 +1250,8 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
data_size = expected_size - ctx->header_size;
data = malloc(data_size);
init_schan_buffers(&ctx->transport.in, message, schan_decrypt_message_get_next_buffer);
ctx->transport.in.limit = expected_size;
received = data_size;
status = schan_funcs->recv(ctx->transport.session, data, &received);
status = schan_funcs->recv(ctx->transport.session, message, expected_size, data, &received);
if (status != SEC_E_OK && status != SEC_I_RENEGOTIATE)
{
......
......@@ -197,6 +197,111 @@ static void compat_gnutls_dtls_set_mtu(gnutls_session_t session, unsigned int mt
FIXME("\n");
}
static void init_schan_buffers(struct schan_buffers *s, const PSecBufferDesc desc,
int (*get_next_buffer)(const struct schan_transport *, struct schan_buffers *))
{
s->offset = 0;
s->limit = ~0UL;
s->desc = desc;
s->current_buffer_idx = -1;
s->allow_buffer_resize = FALSE;
s->get_next_buffer = get_next_buffer;
}
static int schan_find_sec_buffer_idx(const SecBufferDesc *desc, unsigned int start_idx, ULONG buffer_type)
{
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(const struct schan_transport *t, 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)
{
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->desc->pBuffers[idx].cbBuffer = 0;
s->allow_buffer_resize = TRUE;
}
return idx;
}
return -1;
}
static int send_message_get_next_buffer(const struct schan_transport *t, 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(const struct schan_transport *t, 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(const struct schan_transport *t, struct schan_buffers *s)
{
if (s->current_buffer_idx != -1)
return -1;
return schan_find_sec_buffer_idx(s->desc, 0, SECBUFFER_DATA);
}
static void resize_current_buffer(const struct schan_buffers *s, SIZE_T min_size)
{
SecBuffer *b = &s->desc->pBuffers[s->current_buffer_idx];
......@@ -474,11 +579,18 @@ static void CDECL schan_set_session_target(schan_session session, const char *ta
pgnutls_server_name_set( s, GNUTLS_NAME_DNS, target, strlen(target) );
}
static SECURITY_STATUS CDECL schan_handshake(schan_session session)
static SECURITY_STATUS CDECL schan_handshake(schan_session session, SecBufferDesc *input,
SIZE_T input_size, SecBufferDesc *output, ULONG flags )
{
gnutls_session_t s = (gnutls_session_t)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, (flags & ISC_REQ_ALLOCATE_MEMORY) ?
handshake_get_next_buffer_alloc : handshake_get_next_buffer );
while(1) {
err = pgnutls_handshake(s);
switch(err) {
......@@ -723,11 +835,18 @@ static SECURITY_STATUS CDECL schan_get_session_peer_certificate(schan_session se
return SEC_E_OK;
}
static SECURITY_STATUS CDECL schan_send(schan_session session, const void *buffer, SIZE_T *length)
static SECURITY_STATUS CDECL schan_send(schan_session session, SecBufferDesc *output,
const void *buffer, SIZE_T *length)
{
gnutls_session_t s = (gnutls_session_t)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);
else
init_schan_buffers(&t->out, output, send_message_get_next_buffer_token);
for (;;)
{
ret = pgnutls_record_send(s, (const char *)buffer + total, *length - total);
......@@ -735,11 +854,10 @@ static SECURITY_STATUS CDECL schan_send(schan_session session, const void *buffe
{
total += ret;
TRACE( "sent %ld now %ld/%ld\n", ret, total, *length );
if (total == *length) return SEC_E_OK;
if (total == *length) break;
}
else if (ret == GNUTLS_E_AGAIN)
{
struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s);
SIZE_T count = 0;
if (get_buffer(t, &t->out, &count)) continue;
......@@ -751,16 +869,24 @@ static SECURITY_STATUS CDECL schan_send(schan_session session, const void *buffe
return SEC_E_INTERNAL_ERROR;
}
}
t->out.desc->pBuffers[t->out.current_buffer_idx].cbBuffer = t->out.offset;
return SEC_E_OK;
}
static SECURITY_STATUS CDECL schan_recv(schan_session session, void *buffer, SIZE_T *length)
static SECURITY_STATUS CDECL schan_recv(schan_session session, SecBufferDesc *input,
SIZE_T input_size, void *buffer, SIZE_T *length)
{
gnutls_session_t s = (gnutls_session_t)session;
struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s);
size_t data_size = *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;
while (received < data_size)
{
ret = pgnutls_record_recv(s, (char *)buffer + received, data_size - received);
......@@ -769,7 +895,6 @@ static SECURITY_STATUS CDECL schan_recv(schan_session session, void *buffer, SIZ
else if (!ret) break;
else if (ret == GNUTLS_E_AGAIN)
{
struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s);
SIZE_T count = 0;
if (!get_buffer(t, &t->in, &count)) break;
......
......@@ -128,9 +128,9 @@ struct schan_funcs
unsigned int (CDECL *get_session_cipher_block_size)(schan_session);
SECURITY_STATUS (CDECL *get_session_peer_certificate)(schan_session, struct schan_cert_list *);
SECURITY_STATUS (CDECL *get_unique_channel_binding)(schan_session, SecPkgContext_Bindings *);
SECURITY_STATUS (CDECL *handshake)(schan_session session);
SECURITY_STATUS (CDECL *recv)(schan_session, void *, SIZE_T *);
SECURITY_STATUS (CDECL *send)(schan_session, const void *, SIZE_T *);
SECURITY_STATUS (CDECL *handshake)(schan_session, SecBufferDesc *, SIZE_T, SecBufferDesc *, ULONG );
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 *);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment