I know there are some other questions (with answers) to this topic. But no of these was helpful for me.
I have a postfix server (postfix 3.4.14 on debian 10) with 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 [email protected]{.....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 probelm?
However. On the Client side I have a Java application (openJDK 11.0.11) and every time I will send an E-Mail 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 edit the conf/security/java.security
file. I have added already ECDHE-RSA-AES256-GCM-SHA384
as jdk.tls.legacyAlgorithms
. Here 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 …
EDIT
Ok, at first I have removed my extensions from jdk.tls.legacyAlgorithms
because this 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 AUTH? 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 AUTH: use in every case TLS! 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 stdout
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 the stderr
:
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 postfix server side is openssl 1.1.1 installed:
#> openssl version OpenSSL 1.1.1d 10 Sep 2019
I don’t believe that java is using internally openssl, but may be also interesting the client side openssl version (CentOS/RHEL 7):
#> openssl version OpenSSL 1.0.2k-fips 26 Jan 2017
Answer
After upgrade 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 be also another difference on that machine. However, now it Works!
Many thanks to dave_thompson_085. You point me on the right way :-). I think your answer is a good instruction for other people with the same problem (which properties can I check and so on).