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