I want to record things like client sent tls version, server preferred version, server preferred cipher suite in JSSE. how to do this?
Note that I can only use Java code to do this.Parsing log files are not accepted.
You can add -Djavax.net.debug=all flag to your java execution string and it will dump all that info into the console.
http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/ReadDebug.html
The only way this information is available is via the javax.net.debug system property. If you can't parse that output all you can get is the data in the resulting SSLSession, which consists of what the negotiated protocol and cipher suite were, and the peer certificates. You can also have a look at your own SSLSocket's enabled protocols and cipher suites, but I don't see where it's going to get you.
Related
Two-Way SSL - or mutual authentication - is typically dictated in HTTPS by the server. For example, this tutorial explains how to set up WildFly application server to require webservice clients to present a certificate during communication.
However, in our case we need to enforce Two-Way SSL on the client side. That means our client is configured with a client certificate so that it can supply the certificate during handshake. If a server we are connecting to does not ask for the certificate, we want to abort communication.
Descriptions of the SSL handshake like the diagram in the section titled "The SSL Protocol" here (a bit further down) explain how the first thing happening is selection of a cipher suite:
"1. Client hello - The client sends the server information including the
highest version of SSL it supports and a list of the cipher suites it
supports. (TLS 1.0 is indicated as SSL 3.1.) The cipher suite
information includes cryptographic algorithms and key sizes."
On Java side (more specifically: CXF in my case) , it's possible to filter cipher suites("cipherSuitesFilter") - so I thought it would be possible to limit cipher suites to those requiring mutual authentication. But I don't find any links between cipher suites and two-way SSL. For example, this page notes:
authentication algorithm - dictates how server authentication and (if
needed) client authentication will be carried out.
I'm starting to think that means the cipher suite only dictates how client authentication is done, not if client authentication is required.
That leaves me at a dead end. Is there any other way to enforce client authentication on the client side?
Right now the only solution I can think of is finding the right hook method to implement for SSL communication after the handshake has been done, checking if the connection uses client authentication and aborting if it's not. But I'd like to use any kind of common approach for, if such a thing exists.
We didn't find a better solution than the one I already mentioned in my question.
As a client, we can only check whether a connection was established using a client certificate. That does not guarantee that the server thoroughly verified the certificate, just that it requested a certificate.
Our implementation is a custom javax.net.ssl.SSLSocketFactory that extends createSocket methods to check whether javax.net.ssl.SSLSession.getLocalCertificates() returns something. If not, an exception subclass of javax.net.ssl.SSLException is thrown to abort communication.
The socket factory is set via org.apache.cxf.configuration.jsse.TLSClientParameters.setSSLSocketFactory(SSLSocketFactory).
I have https integration with two host server and I am using java 1.6 and provided cipher using the -Dhttp.ciphers list. we have added Strong cipher first and then added the weaker once. Assuming the order is been followed when we make the SSL connection.
What i observed in the SSL debug log whenever java application is making the connection to host A
Cipher list order is maintain as given in -D option in client Hello message.
Here we are using httpsURLconnection to make a connection.
But when we make the SSL connection to host B cipher list in client hello message is getting changed. Weak cipher is coming before Strong cipher and as a result weak cipher is selected by the Server host B. Here we are making an use of Apache Default httpclient 3.1 to make https connection.
Any idea about why the order of weak ciphers is getting changed ?
My client java -version is 1.7.0_85 and the server version is lower than that. the communication takes place fine when the client was a version lower. But since the update i get the handshake_failure error. Upon firing openssl command for the server it said that the cipher was RC4-SHA in the latest update RC4 were disabled by default. Cant update the server not in my control, how should i establish the communication using properties in the java.security
file
You can look at the value for the jdk.tls.disabledAlgorithms parameter in java.security and remove RC4 from that values list.
Rather than retain this change and make clients insecure, it would be a better option if a parallel thread is opened with the server operator(s) to have them fix their SSL setup.
I'd like to repeat what the JRE release notes states about the usage of RC4 (emphasis mine).
Area: security-libs/javax.net.ssl
Synopsis: Prohibit RC4 cipher suites
RC4 is now considered as a compromised cipher. RC4 cipher suites have
been removed from both client and server default enabled cipher suite
list in Oracle JSSE implementation. These cipher suites can still be
enabled by SSLEngine.setEnabledCipherSuites() and
SSLSocket.setEnabledCipherSuites() methods.
See JDK-8077110 (not public).
I have configured Jetty embedded server to include/exclude some protocols and cipher suites. Is there way to report those on working service? I think about something like getSupportedCipherSuites() and getSupportedProtocols() of javax.net.ssl.SSLServerSocket but for Jetty server objects. My code already shows things from configration:
HTTPSPDYServerConnector SSLconnector = new HTTPSPDYServerConnector(server, sslContextFactory);
SSLconnector.setPort(PortHTTPS);
...
server.setConnectors(new Connector[] { SSLconnector });
...
showInfo(sslContextFactory.getIncludeCipherSuites());
showInfo(sslContextFactory.getExcludeCipherSuites());
showInfo(sslContextFactory.getIncludeProtocols());
showInfo(sslContextFactory.getExcludeProtocols());
...
server.start();
Now I want to see what protocols and cipher suites are available for clients.
EDIT (more info):
My environment can work with those protocols:
SSLv2Hello
SSLv3
TLSv1
TLSv1.1
TLSv1.2
This is result of SSLServerSocket.getSupportedProtocols() that is reported by http://www.java2s.com/Code/JavaAPI/javax.net.ssl/SSLServerSocketgetSupportedProtocols.htm
But with Jetty environment I do not know how to get such list. I excluded some protocols by calling
sslContextFactory.addExcludeProtocols() (I disabled TLSv1.2 because of Chrome bug ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED in Google Chrome)
How can I get list of protocols available (not excluded) for Jetty server?
I suppose that for my environment such result will be:
SSLv2Hello
SSLv3
TLSv1
TLSv1.1
(TLSv1.2 was disabled)
I've just gone through a similar problem.
The way Jetty works, it instantiates a default SSLEngine and then it applies exclusions and other preferences. By default, Jetty 9.4 excludes the following protocols:
this.addExcludeProtocols("SSL", "SSLv2", "SSLv2Hello", "SSLv3");
Ciphers are managed in a similar way, but you can uge regexes. By default, Jetty 9.4 excludes the following:
this.setExcludeCipherSuites("^.*_(MD5|SHA|SHA1)$");
this.addExcludeCipherSuites("^TLS_RSA_.*$");
this.addExcludeCipherSuites("^SSL_.*$");
this.addExcludeCipherSuites("^.*_NULL_.*$");
this.addExcludeCipherSuites("^.*_anon_.*$");
If you call the include/exclude methods yourselp, you will have to deal with the particular sequence of processing that Jetty performs, which is potentially confusing. So I recommend you use the setter methods first with empty arrays, in order to clear anything Jetty put in place by default, and then add your preferred items. Example:
// empty the collections, we don't need no education
sslContextFactory.setExcludeProtocols(new String[]{});
sslContextFactory.setExcludeCipherSuites(new String[]{});
// tell me what you want, what you really really want
sslContextFactory.setIncludeProtocols("TLSv1","TLSv1.1","TLSv1.2");
sslContextFactory.setIncludeCipherSuites(omgIveNeverSeenSuchABigArrayOfCiphers);
If you need a list of ciphers that a specific Java client supports, run that client with -Djavax.net.debug=ssl:handshake:verbose and look for ClientHello messages.
How can I obtain a list of ciphers supported by a remote server via a Java JSSE environment.
I want to get a list of weak ciphers supported by the remote server, so that they can be fixed.
I am using SSLSocket, which has a method called getSupportedCipherSuites, but this method returns ciphers that are supported by the client, not a remote server.
You can't get a list of the supported cipher suites, but you can get the server's enabled weak cipher suites, as follows:
Enable all the weak cipher suites at your client, and none of the strong ones.
Have your client connect and call startHandshake().
If that succeeds, the server has chosen a weak cipher suite, which you can get from the SSLSession. Remove that from the enabled cipher suites and repeat.
All the handshakes at (2) which succeed indicate that the corresponding weak cipher suite is enabled at the server. If there are zero, good. Otherwise print out the succeeding cipher suites and act accordingly.
You can try gnutls-cli