in adapters/tlsio_schannel.c [297:403]
static void send_client_hello(TLS_IO_INSTANCE* tls_io_instance)
{
SecBuffer init_security_buffers[2];
ULONG context_attributes;
SECURITY_STATUS status;
SCHANNEL_CRED auth_data;
PCCERT_CONTEXT certContext;
auth_data.dwVersion = SCHANNEL_CRED_VERSION;
if (tls_io_instance->x509_schannel_handle != NULL)
{
certContext = x509_schannel_get_certificate_context(tls_io_instance->x509_schannel_handle);
auth_data.cCreds = 1;
auth_data.paCred = &certContext;
}
else
{
auth_data.cCreds = 0;
auth_data.paCred = NULL;
}
auth_data.hRootStore = NULL;
auth_data.cSupportedAlgs = 0;
auth_data.palgSupportedAlgs = NULL;
auth_data.grbitEnabledProtocols = 0;
auth_data.dwMinimumCipherStrength = 0;
auth_data.dwMaximumCipherStrength = 0;
auth_data.dwSessionLifespan = 0;
#if defined(SCH_USE_STRONG_CRYPTO)
auth_data.dwFlags = SCH_USE_STRONG_CRYPTO | SCH_CRED_NO_DEFAULT_CREDS;
#else
auth_data.dwFlags = SCH_CRED_NO_DEFAULT_CREDS;
#endif
if (tls_io_instance->ignore_server_name_check)
{
auth_data.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
}
auth_data.dwCredFormat = 0;
if (tls_io_instance->trustedCertificate != NULL)
{
// SCH_CRED_MANUAL_CRED_VALIDATION flag signals to schannel to NOT use
// the Windows certificate store, but instead have application verify
// certificate.
auth_data.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
}
status = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL,
&auth_data, NULL, NULL, &tls_io_instance->credential_handle, NULL);
if (status != SEC_E_OK)
{
tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
indicate_error(tls_io_instance);
}
else
{
SecBufferDesc security_buffers_desc;
tls_io_instance->credential_handle_allocated = true;
init_security_buffers[0].cbBuffer = 0;
init_security_buffers[0].BufferType = SECBUFFER_TOKEN;
init_security_buffers[0].pvBuffer = NULL;
init_security_buffers[1].cbBuffer = 0;
init_security_buffers[1].BufferType = SECBUFFER_EMPTY;
init_security_buffers[1].pvBuffer = 0;
security_buffers_desc.cBuffers = 2;
security_buffers_desc.pBuffers = init_security_buffers;
security_buffers_desc.ulVersion = SECBUFFER_VERSION;
status = InitializeSecurityContext(&tls_io_instance->credential_handle,
NULL, tls_io_instance->host_name, ISC_REQ_EXTENDED_ERROR | ISC_REQ_STREAM | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_USE_SUPPLIED_CREDS, 0, 0, NULL, 0,
&tls_io_instance->security_context, &security_buffers_desc,
&context_attributes, NULL);
if ((status == SEC_I_COMPLETE_NEEDED) || (status == SEC_I_CONTINUE_NEEDED) || (status == SEC_I_COMPLETE_AND_CONTINUE))
{
if (xio_send(tls_io_instance->socket_io, init_security_buffers[0].pvBuffer, init_security_buffers[0].cbBuffer, unchecked_on_send_complete, NULL) != 0)
{
tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
indicate_error(tls_io_instance);
}
else
{
/* set the needed bytes to 1, to get on the next byte how many we actually need */
tls_io_instance->needed_bytes = 1;
if (resize_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
{
tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
indicate_error(tls_io_instance);
}
else
{
tls_io_instance->tlsio_state = TLSIO_STATE_HANDSHAKE_CLIENT_HELLO_SENT;
}
}
}
if (init_security_buffers[0].pvBuffer != NULL)
{
FreeContextBuffer(init_security_buffers[0].pvBuffer);
}
if (init_security_buffers[1].pvBuffer != NULL)
{
FreeContextBuffer(init_security_buffers[1].pvBuffer);
}
}
}