SSL+ Java 8 + OpenJDK + SNI + HTTPClient = Handshake Failure - java

I have some code that's been working for a long time that gets data from webapps over HTTP. It uses Apache HTTPClient (v. 4.5.2) and works great for sites with and without SSL.
Recently, I've tried to use if for another site that happens to use SNI. Everything works great on my Windows machine, but if I try to run it on an AWS EC2 Linux instance, I get a handshake failure (because of the SNI).
Here's what I'm running:
Windows Java
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) Client VM (build 25.101-b13, mixed mode, sharing)
AWS Linux Java
openjdk version "1.8.0_91"
OpenJDK Runtime Environment (build 1.8.0_91-b14)
OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)
I'm not sure which component is ultimately responsible for the failure (Java 8, the runtime environment, HTTPClient).
I have seen this (https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#SNIExtension), but I'm not sure how to adapt this for HTTPClient. And besides, if I had to make code changes, why would it work on Windows?
Anyone have any idea what I should do?
Edit: As suggested, I looked into the jsse.enableSNIExtension property. This seemed wrong because it looks like it's a way to turn SSL off which isn't what I want.
I tried it turned on/off on Windows, and things only worked with it on. On Linux, when it was turned on I continue to get a handshake failure.
Here's the output:
Windows - System.setProperty("jsse.enableSNIExtension", "false");
=================================================================
pool-1-thread-1, WRITE: TLSv1.2 Handshake, length = 189
pool-1-thread-1, READ: TLSv1.2 Alert, length = 2
pool-1-thread-1, RECV TLSv1.2 ALERT: fatal, internal_error
pool-1-thread-1, called closeSocket()
pool-1-thread-1, handling exception: javax.net.ssl.SSLException: Received fatal alert: internal_error
Windows - System.setProperty("jsse.enableSNIExtension", "true");
================================================================
pool-1-thread-1, WRITE: TLSv1.2 Handshake, length = 215
pool-1-thread-1, READ: TLSv1.2 Handshake, length = 93
*** ServerHello, TLSv1.2
Linux - System.setProperty("jsse.enableSNIExtension", "true");
==============================================================
pool-1-thread-1, WRITE: TLSv1.2 Handshake, length = 143
pool-1-thread-1, READ: TLSv1.2 Alert, length = 2
pool-1-thread-1, RECV TLSv1.2 ALERT: fatal, handshake_failure
pool-1-thread-1, called closeSocket()
pool-1-thread-1, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

In our case the root cause was that the (Java) client and the server could not agree on a sufficently strong cipher suite. The solution was to install "Unlimited Strength JCE" from https://www.oracle.com/technetwork/java/javase/downloads/jce-all-download-5170447.html
This should not be a problem for Java version >= 1.8.0_161

I had the same issue, not sure if you are allowed to do this or if you noticed this in the documentation but I added the option -Djsse.enableSNIExtension=false and it worked for me.

Related

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

I am trying to create a connection to an mq manager that has ssl auth enabled. I am using Java 1.8
I have this code
TrustStrategy trustStrategy = new TrustSelfSignedStrategy();
KeyStore trustStore = KeyStore.getInstance("JKS");
try (FileInputStream fileInputStream = new FileInputStream(propertyReader.getProperty(QUEUE_KEYSTORE))) {
trustStore.load(fileInputStream, propertyReader.getProperty(QUEUE_KEYSTOREPASS).toCharArray());
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(trustStore, "changeit".toCharArray());
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
connectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
connectionFactory.setHostName(propertyReader.getProperty(QUEUE_HOST));
connectionFactory.setQueueManager(propertyReader.getProperty(QUEUE_MANAGER));
connectionFactory.setChannel(propertyReader.getProperty(QUEUE_CHANNEL));
connectionFactory.setSSLCipherSuite(propertyReader.getProperty(QUEUE_CIPHERSUITE));
connectionFactory.setPort(Integer.parseInt(propertyReader.getProperty(QUEUE_PORT)));
connectionFactory.setSSLSocketFactory(sslContext.getSocketFactory());
When I try to create the connection I get this exception:
com.ibm.mq.MQException: MQJE001: Completion Code 2, Reason 2397
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
I can see the following in the logs:
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
No available cipher suite for TLSv1
handling exception: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
SEND TLSv1.2 ALERT: fatal, description = handshake_failure
WRITE: TLSv1.2 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 03 00 02 02 28 ......(
called closeSocket()
Is this saying that it is still trying to use TLSv1 instead of TLCv1.2?
I have jce unlimited strength enabled in my security file.
Update with details:
IBM MQ Jar Version: 6.0.2.5
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b26)
You have stated you are using IBM MQ jar files from v6.0.2.5, this went out of support from IBM in September 30th 2012. See end of this question for additional details on the only CipherSuites that were supported in that old version.
You can use Maven to get the current IBM MQ v9.1.0.4 LTS support client at the following link:
MVN REPOSITORY ยป com.ibm.mq com.ibm.mq.allclient
I checked old documentation saved as PDF and MQ v6 only supported SSL and TLS1.0 ciphers, the list is below:
SSL_RSA_WITH_NULL_MD5
SSL_RSA_WITH_NULL_SHA
SSL_RSA_EXPORT_WITH_RC4_40_MD5
SSL_RSA_WITH_RC4_128_MD5
SSL_RSA_WITH_RC4_128_SHA
SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
SSL_RSA_WITH_DES_CBC_SHA
SSL_RSA_EXPORT1024_WITH_RC4_56_SHA
SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_WITH_AES_128_CBC_SHA
SSL_RSA_WITH_AES_256_CBC_SHA
SSL_RSA_WITH_DES_CBC_SHA
SSL_RSA_WITH_3DES_EDE_CBC_SHA
SSL_RSA_FIPS_WITH_DES_CBC_SHA
SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
I was facing same issue in open jdk 1.8 after spending lot of time in searching solution i have resolved it by changing below property from java.security file.
security.overridePropertiesFile=false
Change this property to false if it is true in your case.

Tomcat - Two Way SSL as Server

I'm trying to implement two way SSL on a new web service that we are building and I'm having some issues.
First some info on the environment.
Server version: Apache Tomcat/8.0.36
Server built: Jun 9 2016 13:55:50 UTC
Server number: 8.0.36.0
OS Name: Linux
OS Version: 3.10.0-514.el7.x86_64
Architecture: amd64
JVM Version: 1.8.0_111-b14
JVM Vendor: Oracle Corporation
We use an internal certificate authority to sign all of our certificates. So all the client certificates are signed by our internal root. When I trust the root certificate in the client trust store everything works. All client certificates signed by the internal root work.
However, if I remove the root certificate from the client trust store, and add individual client certificates instead I get a cert chain error.
*** ECDH ServerKeyExchange
Signature Algorithm SHA512withRSA
Server key: Sun EC public key, 256 bits
public x coord: 107108750176335210433834926983330116805775068919227166974389735341685270962458
public y coord: 93195725734236902743006469378087068209149058097948526490562555560744449337507
parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA Cert Authorities:
<CN=Client, OU=Information Technology, O=Company, L=Calgary, ST=Alberta, C=CA>
*** ServerHelloDone
http-nio2-8443-exec-4, WRITE: TLSv1.2 Handshake, length = 4482 http-nio2-8443-exec-2, READ: TLSv1.2 Handshake, length = 7
*** Certificate chain
<Empty>
***
http-nio2-8443-exec-2, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain %% Invalidated:[Session-2, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
http-nio2-8443-exec-2, SEND TLSv1.2 ALERT: fatal, description = bad_certificate http-nio2-8443-exec-2, WRITE: TLSv1.2 Alert, length = 2 http-nio2-8443-exec-2, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain http-nio2-8443-exec-2, called closeOutbound() http-nio2-8443-exec-2, closeOutboundInternal()
This is an issue for us as we can't have all the client certificates in the company granted access to this endpoint, it kind of defeats the purpose.
The company root certificate is in another trust store used on server startup. Here are my configs.
Server.xml connector:
<Connector protocol="org.apache.coyote.http11.Http11Nio2Protocol"
port="8443" maxThreads="24" minSpareThreads="4" maxSpareThreads="4" acceptCount="1000" server=" "
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="certs/servercert.jks" keystorePass=" CrazyPasswordHere"
clientAuth="true" truststoreFile="/usr/local/tomcat/certs/clienttrust.jks" truststorePass="CrazyPasswordHere"
sslEnabledProtocols="TLSv1.2" sslProtocol="TLS"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA"
useServerCipherSuitesOrder="true" compression="on" compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript" />
Systemd init:
# Systemd unit file for tomcat
[Unit]
Description=Apache Tomcat
After=syslog.target network.target
[Service]
Type=forking
Environment=JAVA_HOME=/usr/lib/jvm/jre
Environment=CATALINA_PID=/usr/local/tomcat/temp/tomcat.pid
Environment=CATALINA_HOME=/usr/local/tomcat
Environment=CATALINA_BASE=/usr/local/tomcat
Environment='CATALINA_OPTS= -Xms2048M -Xmx2048M -server -XX:+UseParallelGC \ -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=8090 \ -Dcom.sun.management.jmxremote.ssl=false \ -Dcom.sun.management.jmxremote.authenticate=true \ -Dcom.sun.management.jmxremote.password.file=/usr/local/tomcat/conf/jmxremote.password \ -Dcom.sun.management.jmxremote.access.file=/usr/local/tomcat/conf/jmxremote.access \ -Djavax.net.debug=SSL \ -Djavax.net.ssl.trustStore=/usr/local/tomcat/certs/servertrust.jks \ -Djavax.net.ssl.trustStorePassword=CrazyPasswordHere \ -Djavax.net.ssl.keyStore=/usr/local/tomcat/certs/serverclient.jks \ -Djavax.net.ssl.keyStorePassword=CrazyPasswordHere '
Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom'
ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/bin/kill -15 $MAINPID
User=tomcat
Group=tomcat
[Install]
WantedBy=multi-user.target
Any input here would be great! I can't imagine that the solution here is that every client cert signed by a specific authority is supposed to have access...
Thanks!
Classic. You are conflating authentication with authorization. It is the job of SSL to authenticate via the mechanism you have already set up, and which as you say is working perfectly. It is the job of Tomcat, or the application, to use that information to define who is authorized to use the webapp. This is done via web.xml, CMA, etc.

ssl_upgrade_error rabbitMQ

I have sucessfully configurated RabbitMQ to accept TLS-Connections(Only TLS1.1 and TLS1.2)
now I have written a Java program which connects to the rabbitMQ-Server.
The server(10.0.0.120) and the 2 clients(10.0.0.121-122) are all running on an seperate RaspberryPI which almost same configuration
I can connect to the Server using openssl
root#10.0.0.122:~# openssl s_client -connect 10.0.0.120:5671
...
SSL-Session:
Protocol : TLSv1.2
Cipher : AES256-SHA256
Session-ID: 2D1E2F6CECA4DCB3D7403E9DEF9F9DEAADF5AC15298D6CA54120F26D70D5E4A7
Session-ID-ctx:
Master-Key: 003C06F78281F23D8E2D7432E84B59EEABE586FA4472CF29259F8E7DAE4BD5F2F678A7F4FA27F9FBE6616481BAEEA131
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1422352831
Timeout : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)
---
root#10.0.0.121:~# openssl s_client -connect 10.0.0.120:5671
...
SSL-Session:
Protocol : TLSv1.2
Cipher : AES256-SHA256
Session-ID: B5538A83AE671DF2295632D02549C2E3059EED8DC73235DCE3D58FD69ABF7A62
Session-ID-ctx:
Master-Key: 86F3DDB68E5AB3796A9B762289AE7BD6D0E9A71CB549836D1A01C468180CAB98B9B819A1AF2255AE0BBF8B5911823EB8
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1422352895
Timeout : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)
---
both have the same java version
root#10.0.0.121:~# java -version
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode)
root#10.0.0.122:~# java -version
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode)
and on both is running the same jar file
root#10.0.0.121:~# md5sum rabbitReceive.jar
6df91e2e714341588908798f7e28fa10 rabbitReceive.jar
root#10.0.0.122:~# md5sum rabbitReceive.jar
6df91e2e714341588908798f7e28fa10 rabbitReceive.jar
when I start the JAR file on 10.0.0.122 (where it works!) I get this on the rabbitMQ server log
=INFO REPORT==== 27-Jan-2015::11:07:11 ===
accepting AMQP connection <0.3709.0> (10.0.0.121:52944 -> 10.0.0.120:5671)
when I start the Jar file on 10.0.0.121 I get this on the rabbitMQ server log
=INFO REPORT==== 27-Jan-2015::11:08:06 ===
accepting AMQP connection <0.3755.0> (10.0.0.122:37283 -> 10.0.0.120:5671)
=ERROR REPORT==== 27-Jan-2015::11:08:11 ===
Error on AMQP connection <0.3755.0>:
{ssl_upgrade_error,timeout}
and this exception in the Clients JVM
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1705)
at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:122 )
at sun.security.ssl.Handshaker.kickstart(Handshaker.java:909)
at sun.security.ssl.SSLSocketImpl.kickstartHandshake(SSLSocketImpl.java: 1423)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl. java:1288)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82 )
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at java.io.DataOutputStream.flush(DataOutputStream.java:123)
at com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHan dler.java:129)
at com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHan dler.java:134)
at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:278)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory .java:617)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory .java:639)
at rabbitMqTest.Test.main(Test.java:97)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl. java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces sorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoa der.java:58)
Any Ideas what the problem could be?
As you see, between the start of your jar and the error, there are exactly 5 seconds between.
By default, the ssl-handshake timeout is set to 5 seconds. Your problem is that the ssl handshake can't be done in the default 5 seconds.
You need to change the NORMAL_TIMEOUT and possible the HANDSHAKE_TIMEOUT too at the top of rabbit_reader.erl to increase the timeout.
You can find the configuration-settings are described here.

ConnectionException when connecting to Cassandra with DataStax Java driver 1.0.5

I have a 3 cassandra nodes (db-stats-01, db-stats-02, db-stats-03), which are all Up and Normal according to nodetool status.
The client is essentially doing this:
Builder builder = Cluster.builder();
builder.addContactPoint(node);
context = getSSLContext();
String[] cipherSuites = SSLOptions.DEFAULT_SSL_CIPHER_SUITES;
builder.withSSL(new SSLOptions(context, cipherSuites)).build();
and failing on the last line with the following exception:
Sep 12 14:31:26 localhost daemon: Defuncting connection to db-stats-01/192.168.105.1
Sep 12 14:31:26 localhost com.datastax.driver.core.ConnectionException: [db-stats-01/192.168.105.1] Unexpected error during transport initialization (com.datastax.driver.core.ConnectionException: [db-stats-01/192.168.105.1] Operation Timeouted)
Sep 12 14:31:26 localhost at com.datastax.driver.core.Connection.initializeTransport(Connection.java:182)
Sep 12 14:31:26 localhost at com.datastax.driver.core.Connection.<init>(Connection.java:132)
Sep 12 14:31:26 localhost at com.datastax.driver.core.Connection.<init>(Connection.java:60)
Sep 12 14:31:26 localhost at com.datastax.driver.core.Connection$Factory.open(Connection.java:419)
Sep 12 14:31:26 localhost at com.datastax.driver.core.ControlConnection.tryConnect(ControlConnection.java:205)
Sep 12 14:31:26 localhost at com.datastax.driver.core.ControlConnection.reconnectInternal(ControlConnection.java:168)
Sep 12 14:31:26 localhost at com.datastax.driver.core.ControlConnection.connect(ControlConnection.java:81)
Sep 12 14:31:26 localhost at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:794)
Sep 12 14:31:26 localhost at com.datastax.driver.core.Cluster$Manager.access$100(Cluster.java:721)
Sep 12 14:31:26 localhost at com.datastax.driver.core.Cluster.<init>(Cluster.java:82)
Sep 12 14:31:26 localhost at com.datastax.driver.core.Cluster.<init>(Cluster.java:67)
Sometimes, but not everytime, I get the following error on the server side:
DEBUG [New I/O worker #1] 2014-09-12 14:36:14,337 Slf4JLogger.java (line 36) SSLEngine.closeInbound() raised an exception after a handshake failure.
javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1619)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1587)
at sun.security.ssl.SSLEngineImpl.closeInbound(SSLEngineImpl.java:1517)
at org.jboss.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:1407)
at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1293)
at org.jboss.netty.handler.ssl.SslHandler.decode(SslHandler.java:913)
at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:425)
at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:303)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
DEBUG [New I/O worker #1] 2014-09-12 14:36:14,342 Slf4JLogger.java (line 36) Swallowing an exception raised while writing non-app data
java.nio.channels.ClosedChannelException
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.cleanUpWriteBuffer(AbstractNioWorker.java:434)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.writeFromUserCode(AbstractNioWorker.java:129)
at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:99)
at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:36)
at org.jboss.netty.channel.Channels.write(Channels.java:725)
at org.jboss.netty.channel.Channels.write(Channels.java:686)
at org.jboss.netty.handler.ssl.SslHandler.wrapNonAppData(SslHandler.java:1153)
at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1246)
at org.jboss.netty.handler.ssl.SslHandler.channelDisconnected(SslHandler.java:656)
at org.jboss.netty.channel.Channels.fireChannelDisconnected(Channels.java:396)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.close(AbstractNioWorker.java:361)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:93)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109)
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
However, most of the time I don't even see this error on the server, dispite the server being set to DEBUG.
I don't suspect a connectivity issue, because I have watched tcpdump and I see packets going to and from the client and server. Also, there is briefly an ESTABLISHED connection up on port 9042 when I look at netstat -anp.
Using telnet, I can verify that the server is listening on 9042, and when I send junk through telnet I get a nice error on the server side complaining about a non-SSL record:
ERROR [Native-Transport-Requests:85] 2014-09-12 14:40:23,747 ErrorMessage.java (line 222) Unexpected exception during request
org.jboss.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 640d0a64660d0a
Not sure what else to check or where I may have gone wrong. Before implementing SSL in my client, I didn't see this issue at all, so my thought is it is probably related. Other misc info:
[root#db-stats-01 ~]# rpm -qa | grep cassandra
cassandra20-2.0.9-1.noarch
[root#db-stats-01 ~]# java -version
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
The SSL setup was wrong in some way. I regenerated all my key and trust stores according to http://techdocs.acunu.com.s3.amazonaws.com/v5.0/admin/security/ssl.html and everything worked as expected.

OpenLDAP and SSL

I am having trouble trying to connect to a secure OpenLDAP server which I have set up. On running my LDAP client code
java -Djavax.net.debug=ssl LDAPConnector
I get the following exception trace (java version 1.6.0_17)
trigger seeding of SecureRandom
done seeding SecureRandom
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: GMT: 1256110124 bytes = { 224, 19, 193, 148, 45, 205, 108, 37, 101, 247, 112, 24, 157, 39, 111, 177, 43, 53, 206, 224, 68, 165, 55, 185, 54, 203, 43, 91 }
Session ID: {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_W
ITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SH
A, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA]
Compression Methods: { 0 }
***
Thread-0, WRITE: TLSv1 Handshake, length = 73
Thread-0, WRITE: SSLv2 client hello message, length = 98
Thread-0, received EOFException: error
Thread-0, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Thread-0, SEND TLSv1 ALERT: fatal, description = handshake_failure
Thread-0, WRITE: TLSv1 Alert, length = 2
Thread-0, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
javax.naming.CommunicationException: simple bind failed: ldap.natraj.com:636 [Root exception is javax.net.ssl.SSLHandshakeException: Remote host closed connection during hands
hake]
at com.sun.jndi.ldap.LdapClient.authenticate(Unknown Source)
at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source)
at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source)
at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.init(Unknown Source)
at javax.naming.InitialContext.<init>(Unknown Source)
at javax.naming.directory.InitialDirContext.<init>(Unknown Source)
at LDAPConnector.CallSecureLDAPServer(LDAPConnector.java:43)
at LDAPConnector.main(LDAPConnector.java:237)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read1(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at com.sun.jndi.ldap.Connection.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)
... 9 more
I am able to connect to the same secure LDAP server however if I use another version of java (1.6.0_14)
I have created and installed the server certificates in the cacerts of both the JRE's as mentioned in this guide --> OpenLDAP with SSL
When I run ldapsearch -x on the server I get
# extended LDIF
#
# LDAPv3
# base <dc=localdomain> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# localdomain
dn: dc=localdomain
objectClass: top
objectClass: dcObject
objectClass: organization
o: localdomain
dc: localdomain
# admin, localdomain
dn: cn=admin,dc=localdomain
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
# search result
search: 2
result: 0 Success
# numResponses: 3
# numEntries: 2
On running openssl s_client -connect ldap.natraj.com:636 -showcerts , I obtain the self signed certificate.
My slapd.conf file is as follows
#######################################################################
# Global Directives:
# Features to permit
#allow bind_v2
# Schema and objectClass definitions
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/inetorgperson.schema
# Where the pid file is put. The init.d script
# will not stop the server if you change this.
pidfile /var/run/slapd/slapd.pid
# List of arguments that were passed to the server
argsfile /var/run/slapd/slapd.args
# Read slapd.conf(5) for possible values
loglevel none
# Where the dynamically loaded modules are stored
modulepath /usr/lib/ldap
moduleload back_hdb
# The maximum number of entries that is returned for a search operation
sizelimit 500
# The tool-threads parameter sets the actual amount of cpu's that is used
# for indexing.
tool-threads 1
#######################################################################
# Specific Backend Directives for hdb:
# Backend specific directives apply to this backend until another
# 'backend' directive occurs
backend hdb
#######################################################################
# Specific Backend Directives for 'other':
# Backend specific directives apply to this backend until another
# 'backend' directive occurs
#backend <other>
#######################################################################
# Specific Directives for database #1, of type hdb:
# Database specific directives apply to this databasse until another
# 'database' directive occurs
database hdb
# The base of your directory in database #1
suffix "dc=localdomain"
# rootdn directive for specifying a superuser on the database. This is needed
# for syncrepl.
rootdn "cn=admin,dc=localdomain"
# Where the database file are physically stored for database #1
directory "/var/lib/ldap"
# The dbconfig settings are used to generate a DB_CONFIG file the first
# time slapd starts. They do NOT override existing an existing DB_CONFIG
# file. You should therefore change these settings in DB_CONFIG directly
# or remove DB_CONFIG and restart slapd for changes to take effect.
# For the Debian package we use 2MB as default but be sure to update this
# value if you have plenty of RAM
dbconfig set_cachesize 0 2097152 0
# Sven Hartge reported that he had to set this value incredibly high
# to get slapd running at all. See http://bugs.debian.org/303057 for more
# information.
# Number of objects that can be locked at the same time.
dbconfig set_lk_max_objects 1500
# Number of locks (both requested and granted)
dbconfig set_lk_max_locks 1500
# Number of lockers
dbconfig set_lk_max_lockers 1500
# Indexing options for database #1
index objectClass eq
# Save the time that the entry gets modified, for database #1
lastmod on
# Checkpoint the BerkeleyDB database periodically in case of system
# failure and to speed slapd shutdown.
checkpoint 512 30
# Where to store the replica logs for database #1
# replogfile /var/lib/ldap/replog
# The userPassword by default can be changed
# by the entry owning it if they are authenticated.
# Others should not be able to see it, except the
# admin entry below
# These access lines apply to database #1 only
access to attrs=userPassword,shadowLastChange
by dn="cn=admin,dc=localdomain" write
by anonymous auth
by self write
by * none
# Ensure read access to the base for things like
# supportedSASLMechanisms. Without this you may
# have problems with SASL not knowing what
# mechanisms are available and the like.
# Note that this is covered by the 'access to *'
# ACL below too but if you change that as people
# are wont to do you'll still need this if you
# want SASL (and possible other things) to work
# happily.
access to dn.base="" by * read
# The admin dn has full write access, everyone else
# can read everything.
access to *
by dn="cn=admin,dc=localdomain" write
by * read
# For Netscape Roaming support, each user gets a roaming
# profile for which they have write access to
#access to dn=".*,ou=Roaming,o=morsnet"
# by dn="cn=admin,dc=localdomain" write
# by dnattr=owner write
#######################################################################
# Specific Directives for database #2, of type 'other' (can be hdb too):
# Database specific directives apply to this databasse until another
# 'database' directive occurs
#database <other>
# The base of your directory for database #2
#suffix "dc=debian,dc=org"
#######################################################################
# SSL:
# Uncomment the following lines to enable SSL and use the default
# snakeoil certificates.
#TLSCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
#TLSCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
TLSCipherSuite TLS_RSA_AES_256_CBC_SHA
TLSCACertificateFile /etc/ldap/ssl/server.pem
TLSCertificateFile /etc/ldap/ssl/server.pem
TLSCertificateKeyFile /etc/ldap/ssl/server.pem
My ldap.conf file is
#
# LDAP Defaults
#
# See ldap.conf(5) for details
# This file should be world readable but not world writable.
HOST ldap.natraj.com
PORT 636
BASE dc=localdomain
URI ldaps://ldap.natraj.com
TLS_CACERT /etc/ldap/ssl/server.pem
TLS_REQCERT allow
#SIZELIMIT 12
#TIMELIMIT 15
#DEREF never
Why is it that I can connect to the same server using one version of JRE while I cannot with another ?
Fixed the problem. The issue was arising because the CipherSuites which were being sent by the JRE (version 1.6.0_17) did not match with the CipherSuites accepted by the server.
The server's slapd.conf contained the line
TLSCipherSuite TLS_RSA_AES_256_CBC_SHA
while this particular Java client was sending a set of suites which included TLS_RSA_AES_128_CBC_SHA. The problem was solved by simply commenting out the above mentioned line in slapd.conf. The confusion was because the server returned an EOF exception when the problem was invloving CipherSuites.
JRE (version 1.6.0_14) however, was sending TLS_RSA_AES_256_CBC_SHA as part of the CipherSuites it was accepting and thus the same code worked with this version.
As you got this straight after sending the SSLv2 ClientHello, you should try disabling SSlv2ClientHello. See the JSSE Reference Guide.

Categories

Resources