I am currently developing serverside code that is support SMTP and am now looking at the STARTTLS command. I have setup a java keystore file that contains the server side certificate that we also use in nginx. For debugging purposes, my code is now logging info of the keystore file (see below):
[2022-04-11 07:49:58:224] ( INFO): Loading keystore from path: /opt/linkedstrategies/config.infinity/smtptls.jks
[2022-04-11 07:49:58:825] ( FINE): X509Certificate: Alg:SHA384withRSA, Serial:6c55abdbd00792c79d070cd8119ed6bf, Subject:CN=ZeroSSL RSA Domain Secure Site CA, O=ZeroSSL, C=AT, Issuer:CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US, Key type:RSA, Length:4096, Cert Id:-819270611, Valid from:1/29/20, 7:00 PM, Valid until:1/29/30, 6:59 PM
[2022-04-11 07:49:58:832] ( FINE): X509Certificate: Alg:SHA384withRSA, Serial:2eb636ed2d9e2bcaac04061a406f94d4, Subject:CN=connect-infinity.com, Issuer:CN=ZeroSSL RSA Domain Secure Site CA, O=ZeroSSL, C=AT, Key type:RSA, Length:2048, Cert Id:-1599950318, Valid from:7/11/21, 8:00 PM, Valid until:7/12/22, 7:59 PM
[2022-04-11 07:49:59:112] ( INFO): Keystore alias: smtptls
[2022-04-11 07:49:59:124] ( INFO): certificate type: X.509
[2022-04-11 07:49:59:125] ( INFO): Keystore alias: mykey
[2022-04-11 07:49:59:125] ( INFO): certificate type: X.509
[2022-04-11 07:49:59:248] ( INFO): Number of enabled protocols: 1
[2022-04-11 07:49:59:268] ( INFO): TLSv1.2
[2022-04-11 07:49:59:269] ( INFO): Number of enabled cipher suites: 46
[2022-04-11 07:49:59:269] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:274] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:274] ( INFO): TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
[2022-04-11 07:49:59:274] ( INFO): TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:275] ( INFO): TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
[2022-04-11 07:49:59:275] ( INFO): TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:275] ( INFO): TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:275] ( INFO): TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
[2022-04-11 07:49:59:276] ( INFO): TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:276] ( INFO): TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:276] ( INFO): TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:276] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
[2022-04-11 07:49:59:277] ( INFO): TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
[2022-04-11 07:49:59:277] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:277] ( INFO): TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:277] ( INFO): TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
[2022-04-11 07:49:59:278] ( INFO): TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
[2022-04-11 07:49:59:278] ( INFO): TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:278] ( INFO): TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:278] ( INFO): TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:279] ( INFO): TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:279] ( INFO): TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:279] ( INFO): TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:279] ( INFO): TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
[2022-04-11 07:49:59:279] ( INFO): TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
[2022-04-11 07:49:59:288] ( INFO): TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:288] ( INFO): TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:288] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:288] ( INFO): TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:289] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:289] ( INFO): TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:289] ( INFO): TLS_DHE_RSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:289] ( INFO): TLS_DHE_DSS_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:289] ( INFO): TLS_DHE_RSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:294] ( INFO): TLS_DHE_DSS_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:295] ( INFO): TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:295] ( INFO): TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:296] ( INFO): TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:296] ( INFO): TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:296] ( INFO): TLS_RSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:296] ( INFO): TLS_RSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:297] ( INFO): TLS_RSA_WITH_AES_256_CBC_SHA256
[2022-04-11 07:49:59:297] ( INFO): TLS_RSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:297] ( INFO): TLS_RSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:297] ( INFO): TLS_RSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:298] ( INFO): TLS_EMPTY_RENEGOTIATION_INFO_SCSV
[2022-04-11 07:49:59:312] ( INFO): Number of cipher suites: 46
[2022-04-11 07:49:59:312] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:313] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:313] ( INFO): TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
[2022-04-11 07:49:59:313] ( INFO): TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:313] ( INFO): TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
[2022-04-11 07:49:59:313] ( INFO): TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:313] ( INFO): TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:313] ( INFO): TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
[2022-04-11 07:49:59:313] ( INFO): TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:314] ( INFO): TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:314] ( INFO): TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:314] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
[2022-04-11 07:49:59:314] ( INFO): TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
[2022-04-11 07:49:59:314] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:314] ( INFO): TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:314] ( INFO): TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
[2022-04-11 07:49:59:314] ( INFO): TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
[2022-04-11 07:49:59:315] ( INFO): TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:315] ( INFO): TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:315] ( INFO): TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:316] ( INFO): TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:316] ( INFO): TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:316] ( INFO): TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:316] ( INFO): TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
[2022-04-11 07:49:59:316] ( INFO): TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
[2022-04-11 07:49:59:316] ( INFO): TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:318] ( INFO): TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:318] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:318] ( INFO): TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:318] ( INFO): TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:319] ( INFO): TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:319] ( INFO): TLS_DHE_RSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:319] ( INFO): TLS_DHE_DSS_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:320] ( INFO): TLS_DHE_RSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:320] ( INFO): TLS_DHE_DSS_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:320] ( INFO): TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:321] ( INFO): TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:321] ( INFO): TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:321] ( INFO): TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:335] ( INFO): TLS_RSA_WITH_AES_256_GCM_SHA384
[2022-04-11 07:49:59:340] ( INFO): TLS_RSA_WITH_AES_128_GCM_SHA256
[2022-04-11 07:49:59:340] ( INFO): TLS_RSA_WITH_AES_256_CBC_SHA256
[2022-04-11 07:49:59:340] ( INFO): TLS_RSA_WITH_AES_128_CBC_SHA256
[2022-04-11 07:49:59:340] ( INFO): TLS_RSA_WITH_AES_256_CBC_SHA
[2022-04-11 07:49:59:341] ( INFO): TLS_RSA_WITH_AES_128_CBC_SHA
[2022-04-11 07:49:59:341] ( INFO): TLS_EMPTY_RENEGOTIATION_INFO_SCSV
[2022-04-11 07:49:59:341] ( INFO): Succesfully loaded keystore from path: /opt/linkedstrategies/config.infinity/smtptls.jks, enabling support for the STARTTLS command
Here is the code that does that:
this.logger.info(() -> "Loading keystore from path: " + this.keyStorePath);
try (InputStream inputStream = Files.newInputStream(keyStorePath);) {
char[] password = this.keyStorePassword.toCharArray();
keyStore.load(inputStream, password);
keyManagerFactory.init(keyStore, password);
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
if (this.logger.isLoggable(Level.INFO)) {
this.verboseSSLInfo(keyStore, sslContext);
}
}
this.logger.info(() -> "Succesfully loaded keystore from path: " + this.keyStorePath + ", enabling support for the STARTTLS command");
this.socketFactory = sslContext.getSocketFactory();
And:
private void verboseSSLInfo(KeyStore keyStore, SSLContext sslContext) throws KeyStoreException {
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
this.logger.info(() -> " Keystore alias: " + alias);
Certificate certificate = keyStore.getCertificate(alias);
this.logger.info(() -> " certificate type: " + certificate.getType());
}
SSLEngine sslEngine = sslContext.createSSLEngine();
String[] enabledProtocols = sslEngine.getEnabledProtocols();
this.logger.info(() -> " Number of enabled protocols: " + enabledProtocols.length);
for (String enabledProtocol : enabledProtocols) {
this.logger.info(() -> " " + enabledProtocol);
}
String[] enabledCipherSuites = sslEngine.getEnabledCipherSuites();
this.logger.info(() -> " Number of enabled cipher suites: " + enabledCipherSuites.length);
for (String enabledCipherSuite : enabledCipherSuites) {
this.logger.info(() -> " " + enabledCipherSuite);
}
String[] cipherSuites = sslEngine.getSSLParameters().getCipherSuites();
this.logger.info(() -> " Number of cipher suites: " + enabledCipherSuites.length);
for (String cipherSuite : cipherSuites) {
this.logger.info(() -> " " + cipherSuite);
}
}
Then, when the client code issues the STARTTLS command, I execute the following code:
this.sslSocket = (SSLSocket) socketFactory.createSocket(this.socket, null, false);
this.sslSocket.addHandshakeCompletedListener(
event -> {
logger.info(() -> "[SMTP][" + this.socketInetAddress + "] - TLS handlshake completed");
logger.info(() -> "[SMTP][" + this.socketInetAddress + "] - CipherSuite:" + event.getCipherSuite());
logger.info(() -> "[SMTP][" + this.socketInetAddress + "] - SessionId " + event.getSession());
logger.info(() -> "[SMTP][" + this.socketInetAddress + "] - PeerHost " + event.getSession().getPeerHost());
}
);
this.sslSocket.setUseClientMode(false); // We are the server
this.sslSocket.startHandshake();
But that produces the following error:
javax.net.ssl.SSLHandshakeException: no cipher suites in common
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:356)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:312)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:303)
at java.base/sun.security.ssl.ServerHello$T12ServerHelloProducer.chooseCipherSuite(ServerHello.java:471)
at java.base/sun.security.ssl.ServerHello$T12ServerHelloProducer.produce(ServerHello.java:297)
at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:440)
at java.base/sun.security.ssl.ClientHello$T12ClientHelloConsumer.consume(ClientHello.java:1120)
at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:853)
at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:812)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:458)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:199)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1488)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1394)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:441)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:412)
at com.linkedstrategies.infinity.mailserver.impl.MessageTransferAgent$SMTPCommandHandler.startTLS(MessageTransferAgent.java:632)
at com.linkedstrategies.infinity.mailserver.impl.MessageTransferAgent$SMTPCommandHandler.handle(MessageTransferAgent.java:611)
at com.linkedstrategies.infinity.mailserver.impl.MessageTransferAgent$SMTPCommandHandler.run(MessageTransferAgent.java:435)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:832)
I have my logging.properties set at FINEST for all loggers and handlers. I have enabled javax.net.debug=all when I start the VM, hoping that it would tell me more about the certificates and ciphers it tried and failed but there is not much to go on.
Any any ideas or suggestions where I should start looking?