int tlsio_openssl_setoption()

in adapters/tlsio_openssl.c [1636:1871]


int tlsio_openssl_setoption(CONCRETE_IO_HANDLE tls_io, const char* optionName, const void* value)
{
    int result;

    if (tls_io == NULL || optionName == NULL)
    {
        result = MU_FAILURE;
    }
    else
    {
        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)tls_io;

        if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
        {
            const char* cert = (const char*)value;
            size_t len;

            if (tls_io_instance->certificate != NULL)
            {
                // Free the memory if it has been previously allocated
                free(tls_io_instance->certificate);
                tls_io_instance->certificate = NULL;
            }

            // Store the certificate
            len = strlen(cert);
            size_t malloc_size = safe_add_size_t(len, 1);
            if (malloc_size == SIZE_MAX ||
                (tls_io_instance->certificate = malloc(malloc_size)) == NULL)
            {
                LogError("malloc failure, size:%zu", malloc_size);
                result = MU_FAILURE;
            }
            else
            {
                strcpy(tls_io_instance->certificate, cert);
                result = 0;
            }

            // If we're previously connected then add the cert to the context
            if (tls_io_instance->ssl_context != NULL)
            {
                result = add_certificate_to_store(tls_io_instance, cert);
            }
        }
        else if (strcmp(OPTION_OPENSSL_CIPHER_SUITE, optionName) == 0)
        {
            if (tls_io_instance->cipher_list != NULL)
            {
                // Free the memory if it has been previously allocated
                free(tls_io_instance->cipher_list);
                tls_io_instance->cipher_list = NULL;
            }

            // Store the cipher suites
            if (mallocAndStrcpy_s((char**)&tls_io_instance->cipher_list, value) != 0)
            {
                LogError("unable to mallocAndStrcpy_s %s", optionName);
                result = MU_FAILURE;
            }
            else
            {
                result = 0;
            }
        }
        else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0 || strcmp(OPTION_X509_ECC_CERT, optionName) == 0)
        {
            if (tls_io_instance->x509_certificate != NULL)
            {
                LogError("unable to set x509 options more than once");
                result = MU_FAILURE;
            }
            else
            {
                /*let's make a copy of this option*/
                if (mallocAndStrcpy_s((char**)&tls_io_instance->x509_certificate, value) != 0)
                {
                    LogError("unable to mallocAndStrcpy_s %s", optionName);
                    result = MU_FAILURE;
                }
                else
                {
                    result = 0;
                }
            }
        }
        else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0 || strcmp(OPTION_X509_ECC_KEY, optionName) == 0)
        {
            if (tls_io_instance->x509_private_key != NULL)
            {
                LogError("unable to set more than once x509 options");
                result = MU_FAILURE;
            }
            else
            {
                /*let's make a copy of this option*/
                if (mallocAndStrcpy_s((char**)&tls_io_instance->x509_private_key, value) != 0)
                {
                    LogError("unable to mallocAndStrcpy_s %s", optionName);
                    result = MU_FAILURE;
                }
                else
                {
                    result = 0;
                }
            }
        }
        #ifndef OPENSSL_NO_ENGINE
        else if (strcmp(OPTION_OPENSSL_ENGINE, optionName) == 0)
        {
            ENGINE_load_builtin_engines();

            if (mallocAndStrcpy_s((char**)&tls_io_instance->engine_id, value) != 0)
            {
                LogError("unable to mallocAndStrcpy_s %s", optionName);
                result = MU_FAILURE;
            }
            else
            {
                result = 0;
            }
        }
        #endif // OPENSSL_NO_ENGINE
        else if (strcmp(OPTION_OPENSSL_PRIVATE_KEY_TYPE, optionName) == 0)
        {
            const OPTION_OPENSSL_KEY_TYPE type = *(const OPTION_OPENSSL_KEY_TYPE*)value;
            switch (type)
            {
            case KEY_TYPE_DEFAULT:
            case KEY_TYPE_ENGINE:
                tls_io_instance->x509_private_key_type = type;
                result = 0;
                break;

            default:
                LogError("Unknown x509PrivatekeyType type %d", type);
                result = MU_FAILURE;
            }
        }
        else if (strcmp("tls_validation_callback", optionName) == 0)
        {
#ifdef WIN32
#pragma warning(push)
#pragma warning(disable:4055)
#endif // WIN32
            tls_io_instance->tls_validation_callback = (TLS_CERTIFICATE_VALIDATION_CALLBACK)value;
#ifdef WIN32
#pragma warning(pop)
#endif // WIN32

            if (tls_io_instance->ssl_context != NULL)
            {
                SSL_CTX_set_cert_verify_callback(tls_io_instance->ssl_context, tls_io_instance->tls_validation_callback, tls_io_instance->tls_validation_callback_data);
            }

            result = 0;
        }
        else if (strcmp("tls_validation_callback_data", optionName) == 0)
        {
            tls_io_instance->tls_validation_callback_data = (void*)value;

            if (tls_io_instance->ssl_context != NULL)
            {
                SSL_CTX_set_cert_verify_callback(tls_io_instance->ssl_context, tls_io_instance->tls_validation_callback, tls_io_instance->tls_validation_callback_data);
            }

            result = 0;
        }
        else if (strcmp(OPTION_TLS_VERSION, optionName) == 0)
        {
            if (tls_io_instance->ssl_context != NULL)
            {
                LogError("Unable to set the tls version after the tls connection is established");
                result = MU_FAILURE;
            }
            else
            {
                const int version_option = *(const int*)value;
                if (version_option == 0 || version_option == 10)
                {
                    tls_io_instance->tls_version = VERSION_1_0;
                }
                else if (version_option == 11)
                {
                    tls_io_instance->tls_version = VERSION_1_1;
                }
                else if (version_option == 12)
                {
                    tls_io_instance->tls_version = VERSION_1_2;
                }
                else
                {
                    LogInfo("Value of TLS version option %d is not found shall default to version 1.2", version_option);
                    tls_io_instance->tls_version = VERSION_1_2;
                }
                result = 0;
            }
        }
        else if (strcmp(optionName, OPTION_UNDERLYING_IO_OPTIONS) == 0)
        {
            if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, (void*)tls_io_instance->underlying_io) != OPTIONHANDLER_OK)
            {
                LogError("failed feeding options to underlying I/O instance");
                result = MU_FAILURE;
            }
            else
            {
                result = 0;
            }
        }
        else if (strcmp(optionName, OPTION_SET_TLS_RENEGOTIATION) == 0)
        {
            // No need to do anything for Openssl
            result = 0;
        }
        else if (strcmp("ignore_host_name_check", optionName) == 0)
        {
            bool* server_name_check = (bool*)value;
            tls_io_instance->ignore_host_name_check = *server_name_check;
            result = 0;
        }
        else
        {
            if (tls_io_instance->underlying_io == NULL)
            {
                result = MU_FAILURE;
            }
            else
            {
                result = xio_setoption(tls_io_instance->underlying_io, optionName, value);
            }
        }
    }

    return result;
}