Bug #110463 Add posiblity to supply custom SSLContext for a SSL connection
Submitted: 22 Mar 2023 10:40 Modified: 7 Mar 2024 8:26
Reporter: Hakan Altindag Email Updates:
Status: Verified Impact on me:
None 
Category:Connector / J Severity:S4 (Feature request)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any

[22 Mar 2023 10:40] Hakan Altindag
Description:
Hi,

MySQL Connector J currently has the capability of creating a SSLContext. It will create it based on the following properties: 
- trustCertificateKeyStoreUrl
- trustCertificateKeyStorePassword
- clientCertificateKeyStoreUrl
- clientCertificateKeyStorePassword

I have analysed the builder of the sslcontext, see here for the source code https://github.com/mysql/mysql-connector-j/blob/fa4912a849140828e48162a2c396c8df0091bed7/s... and noticed that there is no way to configure the connector with a custom SSLContext.

I made a library for configuring an SSLContext based on different input values, see here for the documentation and the library itself: https://github.com/Hakky54/sslcontext-kickstart

A developer mentioned the limitation of the connector and that is why I am raising a feature request. See here for the original issue: https://github.com/Hakky54/sslcontext-kickstart/issues/298

The connector will built internally a SSLContext at this place: https://github.com/mysql/mysql-connector-j/blob/fa4912a849140828e48162a2c396c8df0091bed7/s... and there is no way around it if you want to configure your own. 

So why would anyone want to have a custom SSLContext?
- Using pem files without converting it to a jks file
- Using binary / DER files without converting it to a jks file
- Hot reload / update ssl if the certificates have expired while the connection is still being used
- Get the ssl material from different sources, like from inputstream, database..
- Having custom validations with a custom X509ExtendedTrustManager
- Combining multiple trust materials from different files.

How to repeat:
It is not a bug, but a feature request. So it is not possible to repeat it.

Suggested fix:
I would suggest a new sslMode value custom or something else which would make sense. If the value is present the connector could get the default SSLContext.

The developer can construct a custom SSLContext and set it as default:

SSLContext mySslContext = ... // my initialized ssl context
SSLContext.setDefault(mySslContext);

jdbc:mysql://localhost:3306/test_db?sslMode=custom

If the value custom is present for key sslMode then get the Default SSLContext with the method SSLContext.getDefault() and use it here: https://github.com/mysql/mysql-connector-j/blob/fa4912a849140828e48162a2c396c8df0091bed7/s...
[22 Mar 2023 11:18] MySQL Verification Team
Hello Hakan Altindag,

Thank you for the report and feature request.

regards,
Umesh
[1 Mar 2024 17:09] Hakan Altindag
Hi dev team, did you get the chance to work on this topic? Almost one year has passed, and I am curious whether there is a discussion on this topic whether mysql will add the possibility to customize the ssl configuration programatically.
[7 Mar 2024 8:26] Hakan Altindag
As there is no responds yet from the dev team, I would like to provide my solution to this technical challange. So the limitation is that it is not possible adjust the ssl configuration programatically because it is constructed by the library itself based on a property file. Which is not bad, it is just an api design decision.

I have made a solution which makes it possible to override/bypass the ssl configuration with a custom one without the need of adjusting the mysql-connectorj library.

Here is a working POC: https://github.com/Hakky54/java-tutorials/tree/main/bypassing-overruling-ssl-configuration

I am using the following configuration: https://github.com/Hakky54/sslcontext-kickstart?tab=readme-ov-file#global-ssl-configuratio...

The code to get it working looks like:

```
import nl.altindag.ssl.util.ProviderUtils;

import java.security.Provider;
import java.security.Security;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class App {

    public static void main(String[] args) {
        SSLFactory sslFactory = SSLFactory.builder()
                .withIdentityMaterial(Paths.get("/path/to/your/identity.jks"), "password".toCharArray())
                .withTrustMaterial(Paths.get("/path/to/your/truststore.jks"), "password".toCharArray())
                .withSwappableIdentityMaterial()
                .withSwappableTrustMaterial()
                .build();

        Provider provider = ProviderUtils.create(sslFactory);
        Security.insertProviderAt(provider, 1);

        String url = "jdbc:mysql://localhost:33060/mysql?verifyServerCertificate=true&useSSL=true&requireSSL=true";
        try (Connection connection = DriverManager.getConnection(url, "root", "secret")) {
            System.out.println("Database connected!");
        } catch (SQLException e) {
            throw new IllegalStateException("Cannot connect the database!", e);
        } finally {
            Security.removeProvider("Fenix");
        }
    }

}
```

I am not sure whether this feature requests needs to be closed as I think it will still be good to have a solution from mysql dev team, but if there is no plan to add that kind of feature then we can close it and I will continue to use the workaround code snippet above.

Looking forward to your responds.