in adapters/tlsio_openssl.c [1059:1233]
static int create_openssl_instance(TLS_IO_INSTANCE* tlsInstance)
{
int result;
const SSL_METHOD* method = NULL;
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
if (tlsInstance->tls_version == VERSION_1_2)
{
method = TLSv1_2_method();
}
else if (tlsInstance->tls_version == VERSION_1_1)
{
method = TLSv1_1_method();
}
else
{
method = TLSv1_method();
}
#else
{
method = TLS_method();
}
#endif
tlsInstance->ssl_context = SSL_CTX_new(method);
if (tlsInstance->ssl_context == NULL)
{
log_ERR_get_error("Failed allocating OpenSSL context.");
result = MU_FAILURE;
}
#ifndef OPENSSL_NO_ENGINE
else if ((tlsInstance->engine_id != NULL) &&
(engine_load(tlsInstance) != 0))
{
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
result = MU_FAILURE;
}
#endif // OPENSSL_NO_ENGINE
else if ((tlsInstance->cipher_list != NULL) &&
(SSL_CTX_set_cipher_list(tlsInstance->ssl_context, tlsInstance->cipher_list)) != 1)
{
engine_destroy(tlsInstance);
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
log_ERR_get_error("unable to set cipher list.");
result = MU_FAILURE;
}
else if (add_certificate_to_store(tlsInstance, tlsInstance->certificate) != 0)
{
engine_destroy(tlsInstance);
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
log_ERR_get_error("unable to add_certificate_to_store.");
result = MU_FAILURE;
}
/*x509 authentication can only be build before underlying connection is realized*/
else if (
(tlsInstance->x509_certificate != NULL) &&
(tlsInstance->x509_private_key != NULL) &&
(x509_openssl_add_credentials(
tlsInstance->ssl_context,
tlsInstance->x509_certificate,
tlsInstance->x509_private_key,
#ifndef OPENSSL_NO_ENGINE
tlsInstance->x509_private_key_type,
tlsInstance->engine) != 0)
#else // OPENSSL_NO_ENGINE
tlsInstance->x509_private_key_type) != 0)
#endif // OPENSSL_NO_ENGINE
)
{
engine_destroy(tlsInstance);
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
log_ERR_get_error("unable to use x509 authentication");
result = MU_FAILURE;
}
else
{
SSL_CTX_set_cert_verify_callback(tlsInstance->ssl_context, tlsInstance->tls_validation_callback, tlsInstance->tls_validation_callback_data);
tlsInstance->in_bio = BIO_new(BIO_s_mem());
if (tlsInstance->in_bio == NULL)
{
engine_destroy(tlsInstance);
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
log_ERR_get_error("Failed BIO_new for in BIO.");
result = MU_FAILURE;
}
else
{
tlsInstance->out_bio = BIO_new(BIO_s_mem());
if (tlsInstance->out_bio == NULL)
{
(void)BIO_free(tlsInstance->in_bio);
engine_destroy(tlsInstance);
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
log_ERR_get_error("Failed BIO_new for out BIO.");
result = MU_FAILURE;
}
else
{
if ((BIO_set_mem_eof_return(tlsInstance->in_bio, -1) <= 0) ||
(BIO_set_mem_eof_return(tlsInstance->out_bio, -1) <= 0))
{
(void)BIO_free(tlsInstance->in_bio);
(void)BIO_free(tlsInstance->out_bio);
engine_destroy(tlsInstance);
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
LogError("Failed BIO_set_mem_eof_return.");
result = MU_FAILURE;
}
else
{
SSL_CTX_set_verify(tlsInstance->ssl_context, SSL_VERIFY_PEER, NULL);
// Specifies that the default locations for which CA certificates are loaded should be used.
if (SSL_CTX_set_default_verify_paths(tlsInstance->ssl_context) != 1)
{
// This is only a warning to the user. They can still specify the certificate via SetOption.
LogInfo("WARNING: Unable to specify the default location for CA certificates on this platform.");
}
tlsInstance->ssl = SSL_new(tlsInstance->ssl_context);
if (tlsInstance->ssl == NULL)
{
(void)BIO_free(tlsInstance->in_bio);
(void)BIO_free(tlsInstance->out_bio);
engine_destroy(tlsInstance);
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
log_ERR_get_error("Failed creating OpenSSL instance.");
result = MU_FAILURE;
}
else if (SSL_set_tlsext_host_name(tlsInstance->ssl, tlsInstance->hostname) != 1)
{
SSL_free(tlsInstance->ssl);
tlsInstance->ssl = NULL;
(void)BIO_free(tlsInstance->in_bio);
(void)BIO_free(tlsInstance->out_bio);
engine_destroy(tlsInstance);
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
log_ERR_get_error("Failed setting SNI hostname hint.");
result = MU_FAILURE;
}
else if (enable_domain_check(tlsInstance))
{
SSL_free(tlsInstance->ssl);
tlsInstance->ssl = NULL;
(void)BIO_free(tlsInstance->in_bio);
(void)BIO_free(tlsInstance->out_bio);
SSL_CTX_free(tlsInstance->ssl_context);
tlsInstance->ssl_context = NULL;
log_ERR_get_error("Failed to configure domain name verification.");
result = MU_FAILURE;
}
else
{
SSL_set_bio(tlsInstance->ssl, tlsInstance->in_bio, tlsInstance->out_bio);
SSL_set_connect_state(tlsInstance->ssl);
result = 0;
}
}
}
}
}
return result;
}