1

(1 replies, posted in wolfSSL)

I am writing an SSL client based on non-blocking sockets.
I have 2 functions Connect and checkkConnect
On some domains, everything works fine, and on some domains it does not connect for several reasons:
vk.com - OK
gateway.discord.gg - OK
forum.garena.games - ASN no signer error to confirm failure
vkapps.ru - peer subject name mismatch

All sites success open in browser, and not trigger errors

bool CSecureTCPClient::CheckConnect( )
{
    if ( m_Socket == INVALID_SOCKET || m_HasError || !m_Connecting )
        return false;

    if ( m_SSLAuth )
    {

        /* Connect to wolfSSL on the server side */
        if ( wolfSSL_connect( m_SSL ) != SSL_SUCCESS ) {
            if ( wolfSSL_want_read( m_SSL ) )
                return false; //Connecting

            // Error
            char errorString[80];

            int err = wolfSSL_get_error( m_SSL, 0 );

            wolfSSL_ERR_error_string( err, errorString );

            CONSOLE_Print( "[SECURETCPCLIENT] error ( " + string( errorString ) + " )"  );
            m_HasError = true;
            return false;
        }

        m_Connected = true;
        m_Connecting = false;
        return true;
    }

    fd_set fd;
    FD_ZERO( &fd );
    FD_SET( m_Socket, &fd );

    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 0;

    // check if the socket is connected

#ifdef WIN32
    if ( select( 1, nullptr, &fd, nullptr, &tv ) == SOCKET_ERROR )
#else
    if ( select( m_Socket + 1, nullptr, &fd, nullptr, &tv ) == SOCKET_ERROR )
#endif
    {
        m_HasError = true;
        m_Error = GetLastError( );
        return false;
    }

    if ( FD_ISSET( m_Socket, &fd ) )
    {
        /* Create a WOLFSSL object */
        if ( ( m_SSL = wolfSSL_new( m_CTX ) ) == NULL ) {
            CONSOLE_Print( "[SECURETCPCLIENT] error (wolfSSL_new)" );
            m_HasError = true;
            return false;
        }

        wolfSSL_check_domain_name( m_SSL, m_Host.c_str( ) );

        /* Attach wolfSSL to the socket */
        wolfSSL_set_fd( m_SSL, m_Socket );

        /* make wolfSSL object nonblocking */
        wolfSSL_set_using_nonblock( m_SSL, 1 );

        m_SSLAuth = true;
        return false;
    }

    return false;
}

void CSecureTCPClient::Reset( )
{
    CSocket::Reset( );
    Allocate( SOCK_STREAM );

    m_Connecting = false;
    m_LastRecv = GetTime( );
    m_Connected = false;
    m_SSLAuth = false;

    if ( m_SSL )
        wolfSSL_free( m_SSL );
    if ( m_CTX )
        wolfSSL_CTX_free( m_CTX );

    m_CTX = NULL;
    m_SSL = NULL;
}

void CSecureTCPClient::Connect( const std::string & localaddress, const std::string & address, uint16_t port )
{
    wolfSSL_Init( );

    m_Host = address;

    if ( m_Socket == INVALID_SOCKET || m_HasError || m_Connecting || m_Connected )
        return;

    if ( !localaddress.empty( ) )
    {
        struct sockaddr_in LocalSIN;
        memset( &LocalSIN, 0, sizeof( LocalSIN ) );
        LocalSIN.sin_family = AF_INET;

        if ( ( LocalSIN.sin_addr.s_addr = inet_addr( localaddress.c_str( ) ) ) == INADDR_NONE )
            LocalSIN.sin_addr.s_addr = INADDR_ANY;

        LocalSIN.sin_port = htons( 0 );

        if ( ::bind( m_Socket, reinterpret_cast<struct sockaddr*>( &LocalSIN ), sizeof( LocalSIN ) ) == SOCKET_ERROR )
        {
            m_HasError = true;
            m_Error = GetLastError( );
            CONSOLE_Print( "[TCPCLIENT] error (bind) - " + GetErrorString( ) );
            return;
        }
    }

    // get IP address

    struct hostent* HostInfo;
    uint32_t        HostAddress;
    HostInfo = gethostbyname( address.c_str( ) );

    if ( !HostInfo )
    {
        m_HasError = true;
        // m_Error = h_error;
        CONSOLE_Print( "[TCPCLIENT] error (gethostbyname)" );
        return;
    }

    memcpy( &HostAddress, HostInfo->h_addr, HostInfo->h_length );

    // connect

    m_SIN.sin_family = AF_INET;
    m_SIN.sin_addr.s_addr = HostAddress;
    m_SIN.sin_port = htons( port );

#ifdef WIN32
    int32_t iMode = 1;
    ioctlsocket( m_Socket, FIONBIO, ( u_long FAR* )&iMode );
#else
    fcntl( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK );
#endif

    /* Create and initialize WOLFSSL_CTX */
    if ( ( m_CTX = wolfSSL_CTX_new( wolfTLSv1_2_client_method( ) ) ) == NULL ) {
        m_HasError = true;
        CONSOLE_Print( "[SECURETCPCLIENT] error (wolfSSL_CTX_new)" );
    }

    /* Load client certificates into WOLFSSL_CTX */
    if ( wolfSSL_CTX_load_verify_locations( m_CTX, "cacert.pem", NULL ) != SSL_SUCCESS ) {
        m_HasError = true;
        CONSOLE_Print( "[SECURETCPCLIENT] error (wolfSSL_CTX_load_verify_locations)" );
    }

    if ( connect( m_Socket, reinterpret_cast<struct sockaddr*>( &m_SIN ), sizeof( m_SIN ) ) == SOCKET_ERROR )
    {
        if ( GetLastError( ) != EINPROGRESS && GetLastError( ) != EWOULDBLOCK )
        {
            // connect error

            m_HasError = true;
            m_Error = GetLastError( );
            CONSOLE_Print( "[TCPCLIENT] error (connect) - " + GetErrorString( ) );
            return;
        }
    }

    m_Connecting = true;
}

2

(1 replies, posted in wolfSSL)

I am writing an SSL client based on non-blocking sockets. I could connect, but I can’t understand how to detect socket errors? I have the code:

void CSecureTCPClient::DoRecv( )
{
    if ( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected )
        return;

    char buffer[1024];
    int c = wolfSSL_read( m_SSL, buffer, sizeof( buffer ) - 1 );

    CONSOLE_Print( UTIL_ToString( GetLastError( ) ) );

    if ( c > 0 )
    {
        m_RecvBuffer += string( buffer, c );
        m_LastRecv = GetTime( );
    }
    else if ( c == 0 )
        return;
    else
    {
        int ss = wolfSSL_want_read( m_SSL );
        int err = wolfSSL_get_error( m_SSL, 0 );

        if ( err == EWOULDBLOCK )
            return;

        m_HasError = true;
        m_Error = err;

        char errorString[80];
        wolfSSL_ERR_error_string( err, errorString );
        CONSOLE_Print( "[SECURETCPCLIENT] error read ( " + string( errorString ) + " )" );
    }



}

void CSecureTCPClient::DoSend( )
{
    if ( m_Socket == INVALID_SOCKET || m_HasError || !m_Connected )
        return;

    if ( wolfSSL_write( m_SSL, m_SendBuffer.c_str( ), m_SendBuffer.size( ) ) == m_SendBuffer.size( ) ) {

        int c = wolfSSL_want_write( m_SSL );

        if ( c >= 0 )
        {
            m_SendBuffer = m_SendBuffer.substr( c );
            return;
        }

        int err = wolfSSL_get_error( m_SSL, 0 );

        if ( err == EWOULDBLOCK )
            return;

        char errorString[80];
        m_Error = err;
        wolfSSL_ERR_error_string( err, errorString );

        CONSOLE_Print( "[SECURETCPCLIENT] error send ( " + string( errorString ) + " )" );
        m_HasError = true;
        return;
    }
}

How to understand where the remote party closed the connection? And where did the socket error go? Does the EWOULDBLOCK library itself handle, or should its case also be taken into account?