libcurl has timeout options like these:
CURLOPT_CONNECTTIMEOUT - maximum time in seconds that you allow the connection to the server to take.
CURLOPT_TIMEOUT - maximum time in seconds that you allow the libcurl transfer operation to take.
I'd like to implement a similar timeout mechanism in OpenSSL.
What changes would be required in the code below so that a timeout value is applied to BIO_do_connect(), BIO_write() and BIO_read()?
I'm connecting to a server and sending/receiving data to/from the server using BIO_write()/BIO_read() that OpenSSL provides. My code is based on the following sample code available from here.
int main()
{
BIO * bio;
SSL * ssl;
SSL_CTX * ctx;
int p;
char * request = "GET / HTTP/1.1\x0D\x0AHost: www.verisign.com\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A";
char r[1024];
/* Set up the library */
ERR_load_BIO_strings();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
/* Set up the SSL context */
ctx = SSL_CTX_new(SSLv23_client_method());
/* Load the trust store */
if(! SSL_CTX_load_verify_locations(ctx, "TrustStore.pem", NULL))
{
fprintf(stderr, "Error loading trust store\n");
ERR_print_errors_fp(stderr);
SSL_CTX_free(ctx);
return 0;
}
/* Setup the connection */
bio = BIO_new_ssl_connect(ctx);
/* Set the SSL_MODE_AUTO_RETRY flag */
BIO_get_ssl(bio, & ssl);
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
/* Create and setup the connection */
BIO_set_conn_hostname(bio, "www.verisign.com:https");
if(BIO_do_connect(bio) <= 0)
{
fprintf(stderr, "Error attempting to connect\n");
ERR_print_errors_fp(stderr);
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
/* Check the certificate */
if(SSL_get_verify_result(ssl) != X509_V_OK)
{
fprintf(stderr, "Certificate verification error: %i\n", SSL_get_verify_result(ssl));
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
/* Send the request */
BIO_write(bio, request, strlen(request));
/* Read in the response */
for(;;)
{
p = BIO_read(bio, r, 1023);
if(p <= 0) break;
r[p] = 0;
printf("%s", r);
}
/* Close the connection and free the context */
BIO_free_all(bio);
SSL_CTX_free(ctx);
return 0;
}
I'm cross-compiling for ARM on Ubuntu (Eclipse with CodeSourcery Lite).
There are some timeout functions in openssl -SSL_CTX_set_timeout , SSL_SESSION_set_timeout but these have no effect on SSL_connect. Is there really no way of setting timeout for SSL_connect when e.g. ssl server is buggy and goes into loop before doing SSL handshake?
Setting the ‘Connect Timeout’ to 0 gives the SSIS package an unlimited amount of time to attempt connection. This should have displayed in the connection string and prevented the error they received.
In summary, a few extra steps are needed to set ‘Connect Timeout’ through the configuration manager: Now ‘Connect Timeout’ should be set to “Unlimited” in the connection string. The connection string is overridden when a configuration file is added. This also allows ‘Connect Timeout’ to be set to 0 by altering an XML file.
If the delay is higher than what you would like to wait, you can specify a 'timeout' duration. The best method of achieving this is by using the --connect-timeout option.
For connecting, @jpen gave the best answer there. You have to mark the BIO as non-blocking and use select
for determining whether it connected and/or timed out.
Reads are a little different. Because OpenSSL may buffer decrypted data (depending on the TLS cipher suite used), select
may timeout when you are trying to read - even if data actually is available. The proper way to handle read timeouts is to first check SSL_pending
or BIO_pending
. If the pending function returns zero, then use select to set a timeout. If the pending function returns greater than zero, then just call SSL_read
or BIO_read
or any other read function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With