davidmoten / subethasmtp

SubEtha SMTP is a Java library for receiving SMTP mail
Other
141 stars 38 forks source link

Setting specific TLS protocols and ciphers #120

Open mcarbs opened 8 months ago

mcarbs commented 8 months ago

Hi,

I have an SMTP server that is setting TLS using an SSLContext that sets the ciphers and protocols I want to allow, but it appears that they are being overridden to supported defaults in Java in the startTlsSocketFactory() method.

For example I'm building my server like this:

X509ExtendedKeyManager keyManager = PemUtils.loadIdentityMaterial(Paths.get(certFile), Paths.get(keyFile), password.toCharArray());
X509ExtendedTrustManager trustManager = PemUtils.loadTrustMaterial(Paths.get(trustChainCerts));

String[] enabledProtocols = {"TLSv1.2", "TLSv1.3"};

String[] enabledCipherSuites = {
    "TLS_AES_256_GCM_SHA384",
    "TLS_CHACHA20_POLY1305_SHA256",
    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
    "TLS_RSA_WITH_AES_256_GCM_SHA384",
    "TLS_RSA_WITH_AES_256_CBC_SHA256",
    "TLS_AES_128_GCM_SHA256",
    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
    "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
    "TLS_RSA_WITH_AES_128_GCM_SHA256",
    "TLS_RSA_WITH_AES_128_CBC_SHA256"
};

SSLFactory sslFactory = SSLFactory.builder()
    .withIdentityMaterial(keyManager)
    .withTrustMaterial(trustManager)
    .withCiphers(enabledCipherSuites)
    .withProtocols(enabledProtocols)
    .build();

SSLContext sslContext = sslFactory.getSslContext();

smtpServer = SMTPServer
    .port(Integer.parseInt(this.props.getProperty("smtp.port")))
    .bindAddress(InetAddress.getByName(this.props.getProperty("smtp.listen")))
    .softwareName(this.props.getProperty("smtp.banner"))
    .maxConnections(Integer.parseInt(this.props.getProperty("smtp.maxconnections")))
    .hostName(this.props.getProperty("smtp.hostname"))
    .messageHandlerFactory(myFactory)
    .startTlsSocketFactory(sslContext)
    .enableTLS()
    .build();

The protocols and ciphers enabled don't reflect what I had set, looking at startTlsSocketFactory() its setting the protocols and ciphers using getSupportedProtocols() and getSupportedCipherSuites() overriding what I had set.

Would it be possible to not override the values set in the passed context or am I doing it wrong and I should be setting my parameters a different way?

Hakky54 commented 1 month ago

Hi @mcarbs

I noticed you use my ssl library for configuring smtp server. There is a trick to get around this issue. In the past I created a special ssl socket which can reload for example the cipher suite, however this ssl socket has also another capability of ignoring setting new ciphers suite via the built in methods which will do the trick for you. You can enable this option with the SSLFactory builder using the method withSwappableSslParameters(). With this option the code snippet here: https://github.com/davidmoten/subethasmtp/blob/6897a4b09f650c1263f935d7cc1b10f7ff6644ef/src/main/java/org/subethamail/smtp/server/SMTPServer.java#L581 will be ignored because of https://github.com/Hakky54/sslcontext-kickstart/blob/dbe0b37f36b49c935c8444666007d7c5a684d142/sslcontext-kickstart/src/main/java/nl/altindag/ssl/socket/FenixSSLSocket.java#L49

can you maybe try it out on your side with the latest version of 8.3.5

davidmoten commented 1 month ago

Thanks @Hakky54 for your input! @mcarbs sorry I've missed this issue, does look out of the scope of this project but I'll be happy to progress made on this.