I know there are some other questions (with answers) to this topic. But none of these was helpful for me.
I have a Postfix server (postfix 3.4.14 on Debian 10 (Buster)) with the following configuration (only the interesting section):
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtpd_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA, CAMELLIA128, 3DES, CAMELLIA256, RSA+AES, eNULL smtp_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA, CAMELLIA128, 3DES, CAMELLIA256, RSA+AES, eNULL tls_preempt_cipherlist = yes tls_high_cipherlist = !aNULL:!eNULL:!CAMELLIA:HIGH:@STRENGTH
If I check the configuration with OpenSSL, I get (please note that I have made the domain name unrecognizable with “xxxxxx.de”):
#> openssl s_client -connect xxxxxx.de:25 -starttls smtp CONNECTED(00000003) depth=3 O = Digital Signature Trust Co., CN = DST Root CA X3 verify return:1 depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1 verify return:1 depth=1 C = US, O = Let's Encrypt, CN = R3 verify return:1 depth=0 CN = xxxxxx.de verify return:1 --- Certificate chain 0 s:/CN=xxxxxx.de i:/C=US/O=Let's Encrypt/CN=R3 1 s:/C=US/O=Let's Encrypt/CN=R3 i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1 2 s:/C=US/O=Internet Security Research Group/CN=ISRG Root X1 i:/O=Digital Signature Trust Co./CN=DST Root CA X3 --- Server certificate -----BEGIN CERTIFICATE----- MIIFRjCCBC6gAwIBAgISA6SNmc1MPKtxwSiNNKEvxc/EMA0GCSqGSIb3DQEBCwUA MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD ... ... ... VG2iG8sEGCcgG4w1LnWTO4tMlCYFE+tcXxAfE/7pB/VjmvRZlLCypanuwBzVRw5W bPwabUtCMRDrRlT8wI9UHAhQYTb5Hhm0F0u1hi6e/7fybK6tuFnPpWs/vgT3Z4Fj 2onoaTHk/rKlhQ== -----END CERTIFICATE----- subject=/CN=xxxxxx.de issuer=/C=US/O=Let's Encrypt/CN=R3 --- No client certificate CA names sent Peer signing digest: SHA256 Server Temp Key: ECDH, P-256, 256 bits --- SSL handshake has read 4950 bytes and written 450 bytes --- New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-GCM-SHA384 Session-ID: B20E725616C98083988847B90FB42BFDCAEED745129C53E79E723692C641F6F5 Session-ID-ctx: Master-Key: A3D2C497E11E47C6260C119E47DC3B4CAA119485EAFA5BCF6CDA882F115D80E78960C802A48E375DAA293A3A2C1DAE35 Key-Arg : None Krb5 Principal: None PSK identity: None PSK identity hint: None TLS session ticket lifetime hint: 7200 (seconds) TLS session ticket: 0000 - ec 40 39 d6 f4 94 ac 7b-d8 f8 ef 94 98 62 d7 35 .@9....{.....b.5 0010 - de fb c3 f5 f3 b1 3a d1-24 3e 62 57 fb 06 56 eb ......:.$>bW..V. 0020 - 84 61 2a 0d 30 7d 9f ac-70 e7 a8 a3 23 4a c6 57 .a*.0}..p...#J.W 0030 - dc 21 7c d3 5d f4 e8 14-c5 4c 18 da 35 1d 32 49 .!|.]....L..5.2I 0040 - f0 19 de 75 77 22 25 f9-74 4d a2 47 39 0d ce 75 ...uw"%.tM.G9..u 0050 - 0a 04 41 85 0d 67 05 fe-a4 09 ec 72 4b a5 ad f4 ..A..g.....rK... 0060 - 8b 73 a2 a3 2e 28 46 b8-2a 60 4b ed ce 75 09 fb .s...(F.*`K..u.. 0070 - ef 95 e3 e2 6e 6a 90 bd-9e 46 e8 c9 aa 52 c3 ae ....nj...F...R.. 0080 - 72 6f 9f 37 fd 6c 12 e9-bb 60 83 c6 c4 44 ca 85 ro.7.l...`...D.. 0090 - cb ee 1d bd 69 29 77 31-4f 96 d5 4d 93 8e 63 d2 ....i)w1O..M..c. Start Time: 1623221077 Timeout : 300 (sec) Verify return code: 0 (ok) --- 250 CHUNKING
Here I’m wondering about the line
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
because TLSv1/SSLv3 should be disabled by the postfix configuration. Could be that the problem?
However. On the client side I have a Java application (OpenJDK 11.0.11) and every time I will send an email I get:
javax.mail.MessagingException: Could not convert socket to TLS; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666) at javax.mail.Service.connect(Service.java:295) ...
Of course, I have already edited the conf/security/java.security
file. I have added already ECDHE-RSA-AES256-GCM-SHA384
as jdk.tls.legacyAlgorithms
. Here are the interesting settings from java.securtity
:
jdk.tls.legacyAlgorithms= K_NULL, C_NULL, M_NULL, DH_anon, ECDH_anon, RC4_128, RC4_40, DES_CBC, DES40_CBC, 3DES_EDE_CBC, ECDHE-RSA-AES256-GCM, ECDHE-RSA-AES256-GCM-SHA384 jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, include jdk.disabled.namedCurves jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, include jdk.disabled.namedCurves
May be I’m blind, but I don’t see where my problem is …
Ok, at first I have removed my extensions from jdk.tls.legacyAlgorithms
, because these are not helpful and wrong (thanks to dave_thompson_085 for the hint).
Here are the Java code for sending the emails (the code has a “long” history, so please don’t wonder why there are Vector
instead of ArrayList
or so was used…)
// Create some properties and get the default Session Properties props = new Properties(); props.put("mail.smtp.host", smtpServer); props.put("mail.smtp.port", "25"); props.put("mail.debug", "true"); // SMTP authentication? Session session; if (username != null && pwd != null && username.length() > 0 && pwd.length() > 0) { props.put("mail.smtp.auth", "true"); //props.put("mail.smtp.user", username); //props.put("mail.password", pwd); // if SMTP authentication: use TLS in every case! tls = true; session = Session.getInstance(props, new MyPasswordAuthenticator(username, pwd)); } else { session = Session.getDefaultInstance(props, null); } // TLS? if (tls) { props.put("mail.smtp.starttls.enable", "true"); //props.put("mail.smtp.tls", "true"); } // create a message SMTPMessage mimeMsg = new SMTPMessage(session); InternetAddress addressFrom = new InternetAddress(sender); mimeMsg.setFrom(addressFrom); mimeMsg.setEnvelopeFrom(sender); // Set recipients ... InternetAddress[] tos = new InternetAddress[receivers.size()]; int i = 0; for (String addr : receivers) { tos[i++] = new InternetAddress(addr, extractPersonalNameFromEMailAddr(addr)); } // Set CC recipients ... InternetAddress[] ccAddrs = new InternetAddress[0]; if (ccs != null) { ccAddrs = new InternetAddress[ccs.size()]; i = 0; for (String addr : ccs) { ccAddrs[i++] = new InternetAddress(addr, extractPersonalNameFromEMailAddr(addr)); } } mimeMsg.setRecipients(Message.RecipientType.TO, tos); mimeMsg.setRecipients(Message.RecipientType.CC, ccAddrs); // Set return notifications if (readNotificationRequest) { String notifyAddr = replyTo; if (notifyAddr == null || notifyAddr.trim().length() == 0) notifyAddr = sender; mimeMsg.addHeader("Disposition-Notification-To", "<" + notifyAddr + ">"); mimeMsg.addHeader("Return-Receipt-To", "<" + notifyAddr + ">"); } mimeMsg.addHeader("Date", mailDateFormat.format(new Date())); mimeMsg.setNotifyOptions(deliverNotificationRequest); mimeMsg.setReturnOption(deliverNotificationContent); if (replyTo != null) { Address[] replyToAddrs = new Address[1]; replyToAddrs[0] = new InternetAddress(this.replyTo); mimeMsg.setReplyTo(replyToAddrs); mimeMsg.setFrom(replyToAddrs[0]); } mimeMsg.setSentDate(new Date()); mimeMsg.setSubject(subject); //mimeMsg.setContent(msg, msgType); // Set the text content: MimeBodyPart msgPart = new MimeBodyPart(); msgPart.setContent(msg, msgType + "; charset=" + charset); Multipart multipart = new MimeMultipart(); multipart.addBodyPart(msgPart); // Add the attachments: String attFile; MimeBodyPart attachment; Iterator<String> it = new Vector<String>(attachments).iterator(); while (it.hasNext()) { attFile = it.next(); attachment = new MimeBodyPart(); attachment.setDataHandler(new DataHandler(new AppOctetStreamFileDataSource(attFile))); attachment.setFileName(FileUtil.extractFilename(attFile)); multipart.addBodyPart(attachment); } mimeMsg.setContent(multipart); System.out.println("mail.smtp.ssl.trust: <<" + System.getProperty("mail.smtp.ssl.trust") + ">>"); System.out.println("mail.smtp.ssl.socketfactory.class: <<" + System.getProperty("mail.smtp.ssl.socketfactory.class") + ">>"); System.out.println("mail.smtp.socketfactory.class: <<" + System.getProperty("mail.smtp.socketfactory.class") + ">>"); System.out.println("mail.smtp.ssl.protocols: <<" + System.getProperty("mail.smtp.ssl.protocols") + ">>"); System.out.println("mail.smtp.ssl.ciphersuites: <<" + System.getProperty("mail.smtp.ssl.ciphersuites") + ">>"); System.out.println("SSLContext.getDefault().getDefaultSSLParameters().getProtocols(): " + Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getProtocols())); System.out.println("Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites(): " + Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites())); session.setDebug(debug); Transport transport = session.getTransport("smtp"); transport.connect(smtpServer, 25, username, pwd); //System.out.println("#########" + System.getProperty("mail.smtp.localhost")); transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients()); transport.close();
For debugging I have add some System.out’s for output the some interesting values.
Here the standard output:
DEBUG: JavaMail version 1.4.7 DEBUG: successfully loaded resource: /META-INF/javamail.default.providers DEBUG: Tables of loaded providers DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]} DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]} DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map mail.smtp.ssl.trust: <<null>> mail.smtp.ssl.socketfactory.class: <<null>> mail.smtp.socketfactory.class: <<null>> mail.smtp.ssl.protocols: <<null>> mail.smtp.ssl.ciphersuites: <<null>> SSLContext.getDefault().getDefaultSSLParameters().getProtocols(): [TLSv1.3, TLSv1.2] Arrays.toString(SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites(): [TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
And standard error:
javax.net.ssl|DEBUG|01|main|2021-06-10 08:28:39.042 CEST|SSLCipher.java:438|jdk.tls.keyLimits: entry = AES/GCM/NoPadding KeyUpdate 2^37. AES/GCM/NOPADDING:KEYUPDATE = 137438953472 javax.net.ssl|ERROR|01|main|2021-06-10 08:28:39.306 CEST|TransportContext.java:341|Fatal (HANDSHAKE_FAILURE): Couldn't kickstart handshaking ( "throwable" : { javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) at java.base/sun.security.ssl.HandshakeContext.(HandshakeContext.java:170) at java.base/sun.security.ssl.ClientHandshakeContext.(ClientHandshakeContext.java:98) at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:221) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:433) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411) at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549) at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:486) at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1902) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666) at javax.mail.Service.connect(Service.java:295) at com.coco_on.tools.general.useCases.net.UCSendEMail.start(UCSendEMail.java:470) at com.tetrixSystems.tHiddenExecuter.Executer.start(Executer.java:233) at com.tetrixSystems.tHiddenExecuter.UCMain.start(UCMain.java:83) at com.tetrixSystems.tHiddenExecuter.UCMain.main(UCMain.java:49)} ) javax.net.ssl|DEBUG|01|main|2021-06-10 08:28:39.306 CEST|SSLSocketImpl.java:1638|close the underlying socket javax.net.ssl|DEBUG|01|main|2021-06-10 08:28:39.306 CEST|SSLSocketImpl.java:1657|close the SSL connection (initiative) javax.mail.MessagingException: Could not convert socket to TLS; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666) at javax.mail.Service.connect(Service.java:295) at com.coco_on.tools.general.useCases.net.UCSendEMail.start(UCSendEMail.java:470) at com.tetrixSystems.tHiddenExecuter.Executer.start(Executer.java:233) at com.tetrixSystems.tHiddenExecuter.UCMain.start(UCMain.java:83) at com.tetrixSystems.tHiddenExecuter.UCMain.main(UCMain.java:49) Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) at java.base/sun.security.ssl.HandshakeContext.(HandshakeContext.java:170) at java.base/sun.security.ssl.ClientHandshakeContext.(ClientHandshakeContext.java:98) at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:221) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:433) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:411) at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549) at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:486) at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1902) ... 6 more
On the Postfix server side, OpenSSL 1.1.1 is installed:
#> openssl version OpenSSL 1.1.1d 10 Sep 2019
I don’t believe that Java is using OpenSSL internally, but the client side openssl version (CentOS/RHEL 7) may be also interesting:
#> openssl version OpenSSL 1.0.2k-fips 26 Jan 2017
Advertisement
Answer
After upgrading JavaMail from 1.4.7 to 1.6.2, the error is gone! I’m sure there are also other clients which use JavaMail 1.4.7 and which works. So there must also be another difference on that machine. However, now it works!