44

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Steffen
  • 2,500
  • 4
  • 31
  • 47

7 Answers7

41

I was facing the same issue using JDK 11. But I resolved it by commenting this line in the java.security file:

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zeenat Hussain
  • 421
  • 1
  • 3
  • 3
  • 1
    This answer help me when I run an application with open JDK 11 installation in my Linux machine – Prasanth Rajendran Aug 17 '21 at 19:10
  • This answer helped me when trying to get Elasticsearch to work with a SQL Server instance by using the JDBC drivers. – Ryan Harris Aug 23 '21 at 15:14
  • 1
    used for `1.8.0_301` – l33tHax0r Oct 11 '21 at 23:10
  • 2
    This solved my problem. The path of the file was `/usr/lib/jvm/java-11-openjdk-amd64/conf/security/java.security` for me. – Asocia Oct 19 '21 at 07:54
  • 3
    This is dangerous! You then allow insecure algorithms to be used. – Georg Schölly Nov 18 '21 at 10:23
  • 3
    Tuning these setting may be a security risk, but at least you can get 'old' libraries working again. See it as workaround if you cannot update old legacy code. At least you can update the java version. – TMS Nov 30 '21 at 09:24
  • I've removed from the list only the first few (SSLv3, TLSv1, TLSv1.1) and it was sufficient in my case. – Igor Dec 29 '21 at 18:37
  • I have removed only TLSv1 and TLSv1.1, it was sufficient in my case for sending emails (1.8.0_291) – Ghost Rider Jan 05 '22 at 08:51
  • Removing TLSv1 and TLSv1.1 is more than enough if you face any connectivity issue with MySql such as `Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) ` – Prasanth Rajendran Apr 26 '22 at 11:17
  • commenting this out enables `SSLv3`! What is the point in encrypting a connection if you use `SSLv3` ???? Take out `TLSv1.1`, check if it works, if not `TLSv1` ... – thecarpy Oct 10 '22 at 17:59
37

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!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Steffen
  • 2,500
  • 4
  • 31
  • 47
  • Other clients with old javamail connect _to this server which only allows TLS1.2 and 1.3_? Are you sure? Can you confirm what protocol is in the ServerHello, either using javax.net.debug or an external trace like wireshark? – dave_thompson_085 Jun 15 '21 at 08:26
  • @dave_thompson_085: I have found another Client with JavaMail 1.4.7 and you are right. The error is also there (but was not reported because of a "... > /dev/null 2>&1" arrgh!). But I have found two other clients on which JavaMail 1.3 like it was stored in MANIFEST of the jar (oohhh fucking hell, that's too old!!!). And on that clients it works! The javax.net.debug property didn't work (may be it's not implemented in 1.3...). Before updating the JavaMail I will try to create (may be tomorrow) a tcpdump – Steffen Jun 15 '21 at 15:50
  • javax.net.debug is in the JRE (specifically JSSE) not Javamail -- though older JREs write to stdout and newer ones to stderr, which may make a difference for capturing it. AFAICS the online repository for Javamail doesn't go back to 1.3, but I can imagine something that old doesn't do SSL/TLS or at least STARTTLS at all. – dave_thompson_085 Jun 15 '21 at 21:35
  • Today I also encountered this problem, running javax.mail 1.4.7 on a very recent Java 8 JRE. The exact same code works perfectly fine on another server with a less recent Java 8 JRE and the same 1.4.7 JavaMail JAR. I fixed this on the first system by upgrading to JavaMail 1.6.7, as you suggested. Then I upgraded the other server as well, so now the application is running with JavaMail 1.6.7 successfully on both servers. Perhaps something has changed in very recent Java 8 releases that broke JavaMail 1.4.7 with some SMTP servers... – Mauro Molinari Aug 06 '21 at 16:50
  • Worked for me (at least after finding the correct replacement for the old Oracle builds ofjava.mail). I finally used: com.sun.mail / jakarta.mail Verison 1.6.7 – McIntosh Feb 10 '22 at 07:37
18

In my case, Postfix supports TLS 1.0, TLS 1.1, TLS 1.2 and TLS 1.3. I prepared some tests, using different OpenJDKs.

  • Using OpenJDK 11.0.9 (2020-10-20)

    I was able to send email without any exceptions

  • Using OpenJDK 11.0.10 (2021-01-19)

    I was able to send email without any exceptions

  • Using OpenJDK 11.0.11 (2021-04-20)

    I was getting the exception,

    SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

  • Using OpenJDK 11.0.12 (2021-07-20)

    I was getting the same exception,

    SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

As far as I am concerned, the cause of the issue is that OpenJDK requires TLSv1.2 or TLSv1.3, starting from version 11.0.11. The change will apply to at least OpenJDK 8u292 onward, OpenJDK 11.0.11 onward, and all versions of OpenJDK 16, following the JRE and JDK Crypto Roadmap published by an Oracle reference.

How to fix the problem,

  1. Go back to OpenJDK 11.0.10, you can find binaries here. More OpenJDK versions here.
  2. (Preferred) Set the TLS version to TLS 1.2 for sending emails. You can do it by setting a system property like below, before you configure the Java SMTP client.

System.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");

I use Apache Commons email and setting the aforementioned property before initializing my HtmlEmail object, I was able to send using the current OpenJDK version 11.0.12.

In any case you use a POP3 Java client, the same there,

System.setProperty("mail.pop3s.ssl.protocols", "TLSv1.2");

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Georgios Syngouroglou
  • 18,813
  • 9
  • 90
  • 92
9

I got rid of the above exception by adding this to my connection string.

jdbc:mysql://localhost:3306/Peoples?autoReconnect=true&useSSL=false
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Usama
  • 411
  • 4
  • 6
4

Here I'm wondering about the line [in s_client]
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384

You're apparently using OpenSSL 1.0.2, where that's a basically useless relic. Back in the days when OpenSSL supported SSLv2 (mostly until 2010, although almost no one used it much after 2000), the ciphersuite values used for SSLv3 and up (including all TLS, but before 2014 OpenSSL didn't implement higher than TLS 1.0) were structured differently than those used for SSL 2.0, so it was important to qualify the ciphersuite by the 'universe' it existed in. It has almost nothing to do with the protocol version actually used, which appears later in the session-param decode:

SSL-Session:
    Protocol  : TLSv1.2
...

-- although you already know this from the ciphersuite, because ECDHE-RSA-AES256-GCM-SHA384 cannot be used in any protocol version other than TLS 1.2.

In OpenSSL 1.1.0 up, the protocol state machine is redesigned and among other things this field is changed to display the minimum protocol version compatible with the ciphersuite, which is no longer totally useless, but still may be different from the actual protocol used.

In any case your exception occurs before JSSE client even sends the ClientHello to the server to start the handshake, so it is physically impossible for it to be be caused by anything wrong in the server. It is instead caused by something wrong in the coding or configuration on the (Java) client, about which you have provided almost no information.

It may help to run with sysprop javax.net.debug=ssl:handshake although this problem occurs early and may be before anything usefully traceable.

Make sure you don't have sysprops mail.smtp.ssl.{protocols,ciphersuites} set to something unsuitable. See e.g. com.sun.mail.util.SocketFetcher.configureSSLSocket) and Docker container error: "javax.mail.MessagingException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate);" and links there. Also check for any settings of mail.smtp.ssl.trust mail.smtp.ssl.socketfactory.class mail.smtp.socketfactory.class, and any code that alters the SSLSocketFactory default and maybe (Edit) alteration to the SSLContext default i.e. at or near the point you try to connect with javamail print or otherwise get Arrays.toString(SSLContext.getDefaultSSLParameters().getProtocols()) and the same for getCipherSuites.

Edit 2: it's version dependent. Older Sun/Oracle (i.e., pre-Jakarta) versions below 1.5.3 (2015-04-15) had the default (if mail.smtp.ssl.protocols is not configured) hardcoded to TLSv1 meaning 1.0 only. As a result the connection will fail with the exception in the question on a Java that has TLS 1.0 disabled, as 11.0.11 does when installed, and also 16.0.0 up and 8u291 (presumably up). On Java instances without TLS 1.0 disabled it will attempt the connection, but if the server refuses TLS 1.0 -- which the one in this question should -- the connection will still fail with a different exception.

I have added already ECDHE-RSA-AES256-GCM-SHA384 as jdk.tls.legacyAlgorithms.

That's backwards. Legacy algorithms are ones you prefer not to use and accept only as fallback; this ciphersuite is among the best currently available and should be preferred (and is by default, so you shouldn't change it). Plus, although the doc and comments in the file don't make this clear, the legacy constraint only applies server-side anyway -- because that's where ciphersuite selection, and for 1.3 related algorithm selection, is done.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70
  • Thanks. I have edit my question and add more detailed information – Steffen Jun 09 '21 at 10:49
  • Steffen: (1) as I feared, JSSE tracing didn't help (2) you checked 3 sysprops but not the other 2 (3) on checking I am reminded SSLSocketFactory doesn't have its own default, so we don't need to check that, but SSLContext does, so do check that -- see edit (4) _Java_ doesn't use openssl, but when you did `openssl s_client` on the client machine you used OpenSSL 1.0.2, that's what I was explaining about – dave_thompson_085 Jun 10 '21 at 05:46
  • So as not to let my question get too long I have only update my EDIT section (instead adding a new EDIT section). To (4): Yes, you are right. The "TLSv1/SSLv3" output is comming while I call openssl from command line (which have nothing todo with java) :-) – Steffen Jun 10 '21 at 07:35
  • Okay, I am now baffled -- with sysprops not set and those JSSE defaults AFAICS it should work. I don't currently have an environment that can debug this; I will set one up, but it may take a while. In case it matters, please identify the version of javamail you are using. – dave_thompson_085 Jun 12 '21 at 08:30
  • I have another idea which can be the problem. May be anything was changing with the letsencrypt certificate of the mail server. I will retry to add the root certificates of letsencrypt into a truststore and check it again. But I'm also not sure if I can do this in the next few days (because of some time troubles in a private and on other side an other business project ...): However, if in Java some fails with SSL encryption I would wish more error details. Currently it's like the error message "Anything is wrong" ... :-( – Steffen Jun 13 '21 at 12:07
  • I took the time too look into this stuff again. At first: The certificate should be not the problem. I have import the certificate of the mail server into a truststore, but the error is still there. Another idea you gave me is to update JavaMail. Past JavaMail version was 1.4.7 and I updated now to 1.6.2. The problem is still there, BUT I get a lot of more informations on stderr. I have updated my EDIT section. But please note, that I had to cut some Information with "..." so as not to exceed the limit of 30000 characters for stackoverflow posts ... I tell you my thanks for your efforts! – Steffen Jun 13 '21 at 16:45
  • IT WORKS! Seems that the update from JavaMail 1.4.7 to 1.6.2 was the solution. The messages I see was only debug messages ond no error messages. The E-Mail was successfully sent, but received in my SPAM folder, so I haven't see the mail. Many thanks to you! You point me on the right way :-) – Steffen Jun 14 '21 at 05:40
  • I could have told you it wasn't the cert/truststore -- as I said the exception occurs before sending ClientHello, thus before receiving and validating the server cert. But on checking the older repository yes this _was_ a change in 1.5.3. See edit2. – dave_thompson_085 Jun 15 '21 at 08:28
  • Please don't use "edit" and strike out (that is what the revision history is for). The answer should be as if it written today. – Peter Mortensen Aug 19 '22 at 19:54
4

If you using Java 1.8, go to directory

..\Java\jre1.8.0_261\lib\security

If you using Java 11 or 17,

..\Java\jdk-11.0.15\conf\security\

Find the file java.security.

Find the lines

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL

And put # before each line, and save it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vladi
  • 1,662
  • 19
  • 30
0

For Java

openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment (build 11.0.13+8-Ubuntu-0ubuntu1.20.04)
OpenJDK 64-Bit Server VM (build 11.0.13+8-Ubuntu-0ubuntu1.20.04, mixed mode, sharing)

I had the same problem. The smpt server used Tls1.2, which was proved by openssl test like that:

 openssl s_client  smtp -connect ourhost:587

and this output clearly shown me that SMTP server uses Tls1.2:

---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 2412 bytes and written 442 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated

But with all settings like

mail.properties.mail.smtp.auth=true
mail.properties.mail.smtp.starttls.enable=true
mail.properties.mail.smtp.ssl.protocols=TLSv1.2
jdk.tls.client.protocols=TLSv1.2
mail.properties.mail.smtp.ssl.trust=*

it still was the error

Mail server connection failed; nested exception is 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). Failed messages: 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)

And the only stuff that helped was removing Tls parts from java.security file as was said above:

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \

to

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves
Eljah
  • 4,188
  • 4
  • 41
  • 85