Beispiel #1
0
NegotiateAuth::~NegotiateAuth()
{
    if (SecIsValidHandle(&m_creds)) {
        FreeCredentialHandle(&m_creds);
        SecInvalidateHandle(&m_creds);
    }
    if (SecIsValidHandle(&m_secCtx)) {
        FreeCredentialHandle(&m_secCtx);
        SecInvalidateHandle(&m_secCtx);
    }
}
Beispiel #2
0
SSL_SOCKET :: ~SSL_SOCKET()
	{
	if (Type == 0)
		ClientOff();
	else
		ServerOff();

	if (hCtx.dwLower || hCtx.dwLower)
		{
		DeleteSecurityContext(&hCtx);
		}

	if (hCred.dwLower || hCred.dwLower)
		{
		FreeCredentialHandle(&hCred);
		}

	if (OurCertificate && !IsExternalCert)
		{
		CertFreeCertificateContext(OurCertificate);
		OurCertificate = 0;
		}

	if (hCS)
		CertCloseStore(hCS,0);
	hCS = 0;
	}
void tlsio_schannel_destroy(CONCRETE_IO_HANDLE tls_io)
{
    if (tls_io != NULL)
    {
        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
        if (tls_io_instance->credential_handle_allocated)
        {
            (void)FreeCredentialHandle(&tls_io_instance->credential_handle);
            tls_io_instance->credential_handle_allocated = false;
        }

        if (tls_io_instance->received_bytes != NULL)
        {
            free(tls_io_instance->received_bytes);
        }

        if (tls_io_instance->x509_schannel_handle != NULL)
        {
            x509_schannel_destroy(tls_io_instance->x509_schannel_handle);
        }

        xio_destroy(tls_io_instance->socket_io);
        free(tls_io_instance->host_name);
        free(tls_io);
    }
}
Beispiel #4
0
static long ssl_abort (SSLSTREAM *stream)
{
  if (stream->tcpstream) {	/* close TCP stream */
    DeleteSecurityContext (&stream->context);
    FreeCredentialHandle (&stream->cred);
    tcp_close (stream->tcpstream);
    stream->tcpstream = NIL;
  }
  if (stream->ibuf) fs_give ((void **) &stream->ibuf);
  if (stream->obuf) fs_give ((void **) &stream->obuf);
  return NIL;
}
Beispiel #5
0
static int DoSchannelNegotiation(SocketClass *self, const char *opt)
{
	CSTR func = "DoSchannelNegotiation";
	SecBuffer	ExtraData;
	BOOL		ret = 0, cCreds = FALSE, cCtxt = FALSE;
	SchannelSpec	*ssd = NULL;

	if (NULL == (ssd = calloc(sizeof(SchannelSpec), 1)))
	{
		return 0;
	}
	if (SEC_E_OK != CreateSchannelCredentials(NULL, NULL, &ssd->hCred))
	{
		mylog("%s:CreateSchannel failed\n", func);
		goto cleanup;
	}
	cCreds = TRUE;
	if (SEC_E_OK != PerformSchannelClientHandshake(self->socket, &ssd->hCred, NULL, &ssd->hCtxt, &ExtraData))
	{
		mylog("%s:PerformSchannelClientHandshake failed\n", func);
		goto cleanup;
	}
	cCtxt = TRUE;
	if (NULL != ExtraData.pvBuffer && 0 != ExtraData.cbBuffer)
	{
		ssd->iobuf = malloc(ExtraData.cbBuffer);
		ssd->iobuflen =
		ssd->ioread = ExtraData.cbBuffer;
		memcpy(ssd->iobuf, ExtraData.pvBuffer, ssd->ioread);
		free(ExtraData.pvBuffer);
	}
	ret = TRUE;
cleanup:
	if (ret)
	{
		self->sspisvcs |= SchannelService;
		self->ssd = ssd;
	}
	else
	{
		if (cCreds)
			FreeCredentialHandle(&ssd->hCred);
		if (cCtxt)
			DeleteSecurityContext(&ssd->hCtxt);
		if (ssd->iobuf)
			free(ssd->iobuf);
		free(ssd);
	}
	return ret;
}
Beispiel #6
0
static void test_kerberos(void)
{
    SecPkgInfoA *info;
    TimeStamp ttl;
    CredHandle cred;
    SECURITY_STATUS status;

    SEC_CHAR provider[] = {'K','e','r','b','e','r','o','s',0};

    static const ULONG expected_flags =
          SECPKG_FLAG_INTEGRITY
        | SECPKG_FLAG_PRIVACY
        | SECPKG_FLAG_TOKEN_ONLY
        | SECPKG_FLAG_DATAGRAM
        | SECPKG_FLAG_CONNECTION
        | SECPKG_FLAG_MULTI_REQUIRED
        | SECPKG_FLAG_EXTENDED_ERROR
        | SECPKG_FLAG_IMPERSONATION
        | SECPKG_FLAG_ACCEPT_WIN32_NAME
        | SECPKG_FLAG_NEGOTIABLE
        | SECPKG_FLAG_GSS_COMPATIBLE
        | SECPKG_FLAG_LOGON
        | SECPKG_FLAG_MUTUAL_AUTH
        | SECPKG_FLAG_DELEGATION
        | SECPKG_FLAG_READONLY_WITH_CHECKSUM;
    static const ULONG optional_mask =
          SECPKG_FLAG_RESTRICTED_TOKENS
        | SECPKG_FLAG_APPCONTAINER_CHECKS;

    status = QuerySecurityPackageInfoA(provider, &info);
    ok(status == SEC_E_OK, "Kerberos package not installed, skipping test\n");
    if(status != SEC_E_OK)
        return;

    ok( (info->fCapabilities & ~optional_mask) == expected_flags, "got %08x, expected %08x\n", info->fCapabilities, expected_flags );
    ok( info->wVersion == 1, "got %u\n", info->wVersion );
    ok( info->wRPCID == RPC_C_AUTHN_GSS_KERBEROS, "got %u\n", info->wRPCID );
    ok( info->cbMaxToken >= 12000, "got %u\n", info->cbMaxToken );
    ok( !lstrcmpA( info->Name, "Kerberos" ), "got %s\n", info->Name );
    ok( !lstrcmpA( info->Comment, "Microsoft Kerberos V1.0" ), "got %s\n", info->Comment );
    FreeContextBuffer( info );

    status = AcquireCredentialsHandleA( NULL, provider, SECPKG_CRED_OUTBOUND, NULL,
                                        NULL, NULL, NULL, &cred, &ttl );
    todo_wine ok( status == SEC_E_OK, "AcquireCredentialsHandleA returned %08x\n", status );
    if(status == SEC_E_OK)
        FreeCredentialHandle( &cred );
}
/* {{{ my_bool ma_tls_close(MARIADB_PVIO *pvio) */
my_bool ma_tls_close(MARIADB_TLS *ctls)
{
  SC_CTX *sctx= (SC_CTX *)ctls->ssl; 
  
  if (sctx)
  {
    if (sctx->IoBufferSize)
      LocalFree(sctx->IoBuffer);
    if (sctx->client_cert_ctx)
      CertFreeCertificateContext(sctx->client_cert_ctx);
    FreeCredentialHandle(&sctx->CredHdl);
    DeleteSecurityContext(&sctx->ctxt);
  }
  LocalFree(sctx);
  return 0;
}
static void on_underlying_io_close_complete(void* context)
{
    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
    if (tls_io_instance->tlsio_state == TLSIO_STATE_CLOSING)
    {
        tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
        if (tls_io_instance->on_io_close_complete != NULL)
        {
            tls_io_instance->on_io_close_complete(tls_io_instance->on_io_close_complete_context);
        }

        /* Free security context resources corresponding to creation with open */
        DeleteSecurityContext(&tls_io_instance->security_context);

        if (tls_io_instance->credential_handle_allocated)
        {
            (void)FreeCredentialHandle(&tls_io_instance->credential_handle);
            tls_io_instance->credential_handle_allocated = false;
        }
    }
}
Beispiel #9
0
void ReleaseSvcSpecData(SocketClass *self)
{
	if (!self->ssd)
		return;
	if (0 != (self->sspisvcs & SchannelService))
	{
		SchannelSpec *ssd = (SchannelSpec *) self->ssd;

		if (ssd->iobuf)
		{
			free(ssd->iobuf);
			ssd->iobuf = NULL;
		}
		if (ssd->ioovrbuf)
		{
			free(ssd->ioovrbuf);
			ssd->ioovrbuf = NULL;
		}
		FreeCredentialHandle(&ssd->hCred);
		DeleteSecurityContext(&ssd->hCtxt);
		self->sspisvcs &= (~SchannelService);
	}
}
Beispiel #10
0
void main()
{

	SOCKET            Client_Socket;
	BYTE              Data[BIG_BUFF];
	PCHAR             pMessage;
	WSADATA           wsaData;
	CredHandle        hCred;
	struct _SecHandle hCtxt;
	SECURITY_STATUS   ss;
	DWORD             cbRead;
	ULONG             cbMaxSignature;
	ULONG             cbSecurityTrailer;
	SecPkgContext_Sizes            SecPkgContextSizes;
	SecPkgContext_NegotiationInfo  SecPkgNegInfo;
	BOOL DoAuthentication (SOCKET s);

	//-------------------------------------------------------------------
	//  Initialize the socket and the SSP security package.

	if(WSAStartup (0x0101, &wsaData))
	{
		MyHandleError("Could not initialize winsock ");
	}

	//--------------------------------------------------------------------
	//  Connect to a server.

	if (!ConnectAuthSocket (
				&Client_Socket,
				&hCred,
				&hCtxt))
	{
		MyHandleError("Authenticated server connection ");
	}

	//--------------------------------------------------------------------
	//   An authenticated session with a server has been established.
	//   Receive and manage a message from the server.
	//   First, find and display the name of the negotiated
	//   SSP and the size of the signature and the encryption 
	//   trailer blocks for this SSP.

	ss = QueryContextAttributes(
	&hCtxt,
	SECPKG_ATTR_NEGOTIATION_INFO,
	&SecPkgNegInfo );

	if (!SEC_SUCCESS(ss))  
	{
		MyHandleError("QueryContextAttributes failed ");
	}
	else
	{
		printf("Package Name: %s\n", SecPkgNegInfo.PackageInfo->Name);
	}

	ss = QueryContextAttributes(
	&hCtxt,
	SECPKG_ATTR_SIZES,
	&SecPkgContextSizes );

	if (!SEC_SUCCESS(ss))  
	{
		MyHandleError("Query context ");
	}

	cbMaxSignature = SecPkgContextSizes.cbMaxSignature;
	cbSecurityTrailer = SecPkgContextSizes.cbSecurityTrailer;

	printf("InitializeSecurityContext result = 0x%08x\n", ss);

	//--------------------------------------------------------------------
	//   Decrypt and display the message from the server.

	if (!ReceiveBytes(
				Client_Socket, 
				Data, 
				BIG_BUFF, 
				&cbRead))
	{
		MyHandleError("No response from server ");
	}

	if (0 == cbRead)
	{
		MyHandleError("Zero bytes received ");
	}

	pMessage = (PCHAR) DecryptThis(
	Data, 
	&cbRead,
	&hCtxt,
	cbSecurityTrailer);

	printf ("The message from the server is \n ->  %.*s \n",
	cbRead, pMessage);

	//--------------------------------------------------------------------
	//  Terminate socket and security package.

	DeleteSecurityContext (&hCtxt);
	FreeCredentialHandle (&hCred); 
	shutdown (Client_Socket, 2);
	closesocket (Client_Socket);
	if (SOCKET_ERROR == WSACleanup ())
	{
		MyHandleError("Problem with socket cleanup ");
	}

	exit (EXIT_SUCCESS);
}  // end main
Beispiel #11
0
	~SchannelCredential()
	{
		FreeCredentialHandle(&credentialHandle_);
	}
static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
{
    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;

    if (resize_receive_buffer(tls_io_instance, tls_io_instance->received_byte_count + size) == 0)
    {
        memcpy(tls_io_instance->received_bytes + tls_io_instance->received_byte_count, buffer, size);
        tls_io_instance->received_byte_count += size;

        if (size > tls_io_instance->needed_bytes)
        {
            tls_io_instance->needed_bytes = 0;
        }
        else
        {
            tls_io_instance->needed_bytes -= size;
        }

        switch (tls_io_instance->tlsio_state)
        {
        default:
            break;

        case TLSIO_STATE_ERROR:
            break;

        case TLSIO_STATE_HANDSHAKE_CLIENT_HELLO_SENT:
        {
            if (tls_io_instance->needed_bytes == 0)
            {
                SecBuffer input_buffers[2];
                SecBuffer output_buffers[2];
                ULONG context_attributes;

                /* we need to try and perform the second (next) step of the init */
                input_buffers[0].cbBuffer = tls_io_instance->received_byte_count;
                input_buffers[0].BufferType = SECBUFFER_TOKEN;
                input_buffers[0].pvBuffer = (void*)tls_io_instance->received_bytes;
                input_buffers[1].cbBuffer = 0;
                input_buffers[1].BufferType = SECBUFFER_EMPTY;
                input_buffers[1].pvBuffer = 0;

                SecBufferDesc input_buffers_desc;
                input_buffers_desc.cBuffers = 2;
                input_buffers_desc.pBuffers = input_buffers;
                input_buffers_desc.ulVersion = SECBUFFER_VERSION;

                output_buffers[0].cbBuffer = 0;
                output_buffers[0].BufferType = SECBUFFER_TOKEN;
                output_buffers[0].pvBuffer = NULL;
                output_buffers[1].cbBuffer = 0;
                output_buffers[1].BufferType = SECBUFFER_EMPTY;
                output_buffers[1].pvBuffer = 0;

                SecBufferDesc output_buffers_desc;
                output_buffers_desc.cBuffers = 2;
                output_buffers_desc.pBuffers = output_buffers;
                output_buffers_desc.ulVersion = SECBUFFER_VERSION;

                SECURITY_STATUS status = InitializeSecurityContext(&tls_io_instance->credential_handle,
                    &tls_io_instance->security_context, (SEC_CHAR*)tls_io_instance->host_name, ISC_REQ_EXTENDED_ERROR | ISC_REQ_STREAM | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_USE_SUPPLIED_CREDS, 0, 0, &input_buffers_desc, 0,
                    &tls_io_instance->security_context, &output_buffers_desc,
                    &context_attributes, NULL);

                switch (status)
                {
                case SEC_E_INCOMPLETE_MESSAGE:
                    if (input_buffers[1].BufferType != SECBUFFER_MISSING)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                        }
                    }
                    else
                    {
                        tls_io_instance->needed_bytes = input_buffers[1].cbBuffer;
                        tls_io_instance->consumed_bytes += tls_io_instance->needed_bytes;
                        if (resize_receive_buffer(tls_io_instance, tls_io_instance->received_byte_count + tls_io_instance->needed_bytes) != 0)
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                            if (tls_io_instance->on_io_open_complete != NULL)
                            {
                                tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                            }
                        }
                    }
                    break;
                case SEC_E_OK:
                    memmove(tls_io_instance->received_bytes, tls_io_instance->received_bytes + tls_io_instance->consumed_bytes, tls_io_instance->received_byte_count - tls_io_instance->consumed_bytes);
                    tls_io_instance->received_byte_count -= tls_io_instance->consumed_bytes;

                    tls_io_instance->needed_bytes = 1;
                    tls_io_instance->consumed_bytes = tls_io_instance->needed_bytes;

                    if (set_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;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                        }
                    }
                    else
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_OK);
                        }
                    }

                    break;

                case SEC_I_COMPLETE_NEEDED:
                case SEC_I_CONTINUE_NEEDED:
                case SEC_I_COMPLETE_AND_CONTINUE:
                    if ((output_buffers[0].cbBuffer > 0) && xio_send(tls_io_instance->socket_io, output_buffers[0].pvBuffer, output_buffers[0].cbBuffer, NULL, NULL) != 0)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        if (tls_io_instance->on_io_open_complete != NULL)
                        {
                            tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                        }
                    }
                    else
                    {
                        (void)memmove(tls_io_instance->received_bytes, tls_io_instance->received_bytes + tls_io_instance->consumed_bytes, tls_io_instance->received_byte_count - tls_io_instance->consumed_bytes);
                        tls_io_instance->received_byte_count -= tls_io_instance->consumed_bytes;

                        /* set the needed bytes to 1, to get on the next byte how many we actually need */
                        tls_io_instance->needed_bytes = 1;
                        tls_io_instance->consumed_bytes = tls_io_instance->needed_bytes;
                        if (set_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
                        {
                            FreeCredentialHandle(&tls_io_instance->credential_handle);
                            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                            if (tls_io_instance->on_io_open_complete != NULL)
                            {
                                tls_io_instance->on_io_open_complete(tls_io_instance->open_callback_context, IO_OPEN_ERROR);
                            }
                        }
                        else
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_HANDSHAKE_CLIENT_HELLO_SENT;
                        }
                    }
                    break;
                }
            }

            break;

        case TLSIO_STATE_OPEN:
        {
            if (tls_io_instance->needed_bytes == 0)
            {
                SecBuffer security_buffers[4];
                SecBufferDesc security_buffers_desc;

                security_buffers[0].BufferType = SECBUFFER_DATA;
                security_buffers[0].pvBuffer = tls_io_instance->received_bytes;
                security_buffers[0].cbBuffer = tls_io_instance->received_byte_count;
                security_buffers[1].BufferType = SECBUFFER_EMPTY;
                security_buffers[2].BufferType = SECBUFFER_EMPTY;
                security_buffers[3].BufferType = SECBUFFER_EMPTY;

                security_buffers_desc.cBuffers = sizeof(security_buffers) / sizeof(security_buffers[0]);
                security_buffers_desc.pBuffers = security_buffers;
                security_buffers_desc.ulVersion = SECBUFFER_VERSION;

                SECURITY_STATUS status = DecryptMessage(&tls_io_instance->security_context, &security_buffers_desc, 0, NULL);
                switch (status)
                {
                case SEC_E_INCOMPLETE_MESSAGE:
                    if (security_buffers[1].BufferType != SECBUFFER_MISSING)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        indicate_error(tls_io_instance);
                    }
                    else
                    {
                        tls_io_instance->needed_bytes = security_buffers[1].cbBuffer;
                        tls_io_instance->consumed_bytes += tls_io_instance->needed_bytes;
                        if (resize_receive_buffer(tls_io_instance, tls_io_instance->received_byte_count + tls_io_instance->needed_bytes) != 0)
                        {
                            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                            indicate_error(tls_io_instance);
                        }
                    }
                    break;

                case SEC_E_OK:
                    if (security_buffers[1].BufferType != SECBUFFER_DATA)
                    {
                        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
                        indicate_error(tls_io_instance);
                    }
                    else
                    {
                        size_t i;
                        for (i = 0; i < security_buffers[1].cbBuffer; i++)
                        {
                            LOG(tls_io_instance->logger_log, 0, "<-%02x ", ((unsigned char*)security_buffers[1].pvBuffer)[i]);
                        }

                        /* notify of the received data */
                        if (tls_io_instance->on_bytes_received != NULL)
                        {
                            tls_io_instance->on_bytes_received(tls_io_instance->open_callback_context, security_buffers[1].pvBuffer, security_buffers[1].cbBuffer);
                        }

                        (void)memmove(tls_io_instance->received_bytes, tls_io_instance->received_bytes + tls_io_instance->consumed_bytes, tls_io_instance->received_byte_count - tls_io_instance->consumed_bytes);
                        tls_io_instance->received_byte_count -= tls_io_instance->consumed_bytes;

                        tls_io_instance->needed_bytes = 1;
                        tls_io_instance->consumed_bytes = tls_io_instance->needed_bytes;

                        if (set_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);
                        }
                    }
                    break;
                }
            }

            break;
        }
        }
        }
    }
}
static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT io_open_result)
{
    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
    if (tls_io_instance->tlsio_state != TLSIO_STATE_OPENING_UNDERLYING_IO)
    {
        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
        indicate_error(tls_io_instance);
    }
    else
    {
        SecBuffer init_security_buffers[2];
        ULONG context_attributes;
        SECURITY_STATUS status;
        SCHANNEL_CRED auth_data;

        auth_data.dwVersion = SCHANNEL_CRED_VERSION;
        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;
        auth_data.dwFlags = SCH_USE_STRONG_CRYPTO;
        auth_data.dwCredFormat = 0;

        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
        {
            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;

            SecBufferDesc security_buffers_desc;
            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, (SEC_CHAR*)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, NULL, NULL) != 0)
                {
                    FreeCredentialHandle(&tls_io_instance->credential_handle);
                    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;
                    tls_io_instance->consumed_bytes = tls_io_instance->needed_bytes;
                    if (resize_receive_buffer(tls_io_instance, tls_io_instance->needed_bytes + tls_io_instance->received_byte_count) != 0)
                    {
                        FreeCredentialHandle(&tls_io_instance->credential_handle);
                        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;
                    }
                }
            }
        }
    }
}
void tls_server_io_schannel_destroy(CONCRETE_IO_HANDLE tls_io)
{
    if (tls_io != NULL)
    {
        LIST_ITEM_HANDLE first_pending_io;
        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;
        if (tls_io_instance->credential_handle_allocated)
        {
            (void)FreeCredentialHandle(&tls_io_instance->credential_handle);
            tls_io_instance->credential_handle_allocated = false;
        }

        if (tls_io_instance->received_bytes != NULL)
        {
            free(tls_io_instance->received_bytes);
        }

        if (tls_io_instance->x509_schannel_handle != NULL)
        {
            x509_schannel_destroy(tls_io_instance->x509_schannel_handle);
        }

        if (tls_io_instance->x509certificate != NULL)
        {
            free(tls_io_instance->x509certificate);
        }

        if (tls_io_instance->x509privatekey != NULL)
        {
            free(tls_io_instance->x509privatekey);
        }

        xio_destroy(tls_io_instance->socket_io);
        free(tls_io_instance->host_name);

        first_pending_io = singlylinkedlist_get_head_item(tls_io_instance->pending_io_list);
        while (first_pending_io != NULL)
        {
            PENDING_SEND* pending_send = (PENDING_SEND*)singlylinkedlist_item_get_value(first_pending_io);
            if (pending_send == NULL)
            {
                LogError("Failure: retrieving socket from list");
                indicate_error(tls_io_instance);
                break;
            }
            else
            {
                if (pending_send->on_send_complete != NULL)
                {
                    pending_send->on_send_complete(pending_send->on_send_complete_context, IO_SEND_CANCELLED);
                }

                if (singlylinkedlist_remove(tls_io_instance->pending_io_list, first_pending_io) != 0)
                {
                    LogError("Failure: removing pending IO from list");
                }
            }
        }

        if (tls_io_instance->cert_context != NULL)
        {
            if (!CertFreeCertificateContext(tls_io_instance->cert_context))
            {
                LogError("Failure freeing certificate context");
            }
        }

        singlylinkedlist_destroy(tls_io_instance->pending_io_list);
        free(tls_io);
    }
}