I am using one of the example jetty embedded projects from here
I added a SelectChannelConnect, SslSelectChannelConnect and SslSocketConnector as shown in the link above.
Here is a snippet from my code:
// Create the server
Server server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(80);
connector.setMaxIdleTime(30000);
connector.setConfidentialPort(8443);
connector.setStatsOn(false);
connector.setAcceptors(4);
server.setConnectors(new Connector[]
{ connector });
SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector();
ssl_connector.setPort(443);
SslContextFactory cf = ssl_connector.getSslContextFactory();
cf.setKeyStorePath("/path/to/keystore");
cf.setKeyStorePassword("password");
cf.setKeyManagerPassword("password");
cf.setTrustStore("/path/to/keystore");
cf.setTrustStorePassword("password");
cf.setExcludeCipherSuites(
"SSL_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_RSA_WITH_DES_CBC_SHA",
"SSL_DHE_DSS_WITH_DES_CBC_SHA",
"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");
ssl_connector.setStatsOn(false);
server.addConnector(ssl_connector);
ssl_connector.open();
SslSocketConnector ssl2_connector = new SslSocketConnector(cf);
ssl2_connector.setPort(443);
ssl2_connector.setStatsOn(false);
server.addConnector(ssl2_connector);
ssl2_connector.open();
server.start()
HTTP works fine but I am not able to get it to work on HTTPS. It gives me an initial warning in the browser about untrusted certificate blah blah. I added an exception but then it displays this message: "This might be because the site uses outdated or unsafe TLS security settings. If this keeps happening, try contacting the website’s owner." on IE. My settings on IE are alright with TLS 1.0, 1.1 and 1.2 checked and SSL 3.0 unchecked.
Am I missing something? I believe I followed everything from the example project.
Also I generated the keystore and built the project from jdk SE 6u45. I do not think there are any issues the keystore file as it works perfectly in another application.
Most browser no longer support SSLv3, TLS/1.0 and TLS/1.1.
Chrome Announcement
https://developers.google.com/web/updates/2020/05/chrome-84-deps-rems
Firefox Announcement
https://blog.mozilla.org/security/2018/10/15/removing-old-versions-of-tls/
Apple Safari Announcement
https://webkit.org/blog/8462/deprecation-of-legacy-tls-1-0-and-1-1-versions/
Microsoft Announcement
https://blogs.windows.com/msedgedev/2018/10/15/modernizing-tls-edge-ie11/#OkGpBsuyj6XwhUEQ.97
You should be using TLS/1.2 or better (eg: TLS/1.3)
Java 6u45 does not support TLS/1.2, you have to upgrade your JVM at a minimum.
You need to be on Java 7u95 or newer for decent TLS/1.2 support.
For TLS/1.3 support you need to be on Java 8u262 or newer.
Pay attention to JVM expiration dates.
This is important for long term success with SSL/TLS, as the expiration exist because of various databases and configurations within the JVM need to be kept up to date for SSL/TLS to function reliably with the general internet.
Finally, get rid of the entire setExcludeCipherSuites you have, as every one of those cipher suites are excluded by the JVM itself now (see security.properties on a modern JVM)
Related
I've written a java application using an API given to me by a vendor, which accesses that vendor's webapp to download files. The vendor's webapp is dropping support for TLS 1.0/1.1 soon and I want to verify that my application will continue to run. The application runs on a CentOS server with Java 8 installed and I keep reading that Java 8 supports TLS1.2 by default, but I'm curious if it actually FORCES applications to use TLS1.2 or if an application can override the default. I do see references to TLSv1 in the API's code that has me concerned.
I don't think there's much I can do, other than ask the vendor to update their API, but I'm just trying to find out if that's even necessary or if I should expect the application to run with TLS 1.2 right now
//auth/AuthProxyClient.class
Socket socket = null;
if (authProxySSLEnabled) {
SSLSocketFactory factory = this.getSSLSocketFactory(authProxySSLTrustStore, authProxySSLTrustStorePassword, authProxySSLKeyStore, authProxySSLKeyStorePassword, authProxySSLClientAuth, authProxySSLKeyStoreClientKeyAlias, authProxySSLKeyStoreClientKeyPassword);
socket = factory.createSocket(host, port);
((SSLSocket)socket).setEnabledProtocols(new String[]{"TLSv1"});
((SSLSocket)socket).setUseClientMode(true);
((SSLSocket)socket).startHandshake();
this.logSSLSocketInfo((SSLSocket)socket);
} else {
socket = new Socket(host, port);
}
//
try {
SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(keyManagers, trustManagers, (SecureRandom)null);
factory = sslContext.getSocketFactory();
return factory;
} catch (GeneralSecurityException var13) {
this.logException(var13);
throw new IllegalStateException(var13);
}
I'm expecting (hoping) that the application will utilize TLS1.2 by virtue of running in Java 8 alone, but I don't know if that's the case.
TLDR: You need to enable it but not force it because TLS version is negotiated.
Through 1.2, this is fairly simple. Each endpoint normally supports a range of versions and the ClientHello specifies (only) the highest version the client supports. The ServerHello responds with the highest version it supports or the client max if that is lower, but if the client max is too low for the server (below server min) server aborts the handshake instead, and if the server's selection is too low for the client the client aborts the handshake. 1.3 makes this negotiation more complicated, but since only Java 11 up supports 1.3 I ignore it here.
Thus as long as the client offers "up to" 1.2, the server can and will select 1.2 and it will work. The client does not need to actively prevent using protocols lower than 1.2, although it may if you wish.
The difference between Java 7 and Java 8 is that both implement up to 1.2, but j7 client by default only offers "up to" 1.0. (Since SSL3 is now broken and prohibited, and Java never implemented SSL2 at all, "up to" 1.0 is the same as "only" 1.0.) You can override this default in the code, and if using HttpsURLConnection (which you aren't) you can use sysprop https.protocols to change it. In j8 the default is "up to 1.2" or sysprop jdk.tls.client.protocols as stated by Jonathan but can be overridden just like j7.
And the code you posted DOES override. That code will support only TLS 1.0 in either j7 or j8, and as a result will be rejected by a server that insists on 1.2 (or even 1.1). You need to change that code, either to explicitly allow 1.2 -- and it's up to you whether to allow 1.0 and 1.1 because even if you do the server won't select them -- or to use and not override the default which for j8 will be suitable. SSLContext.getInstance("TLS") gets you the (different) default in either Java version. (SSLContext.getDefault() also uses the default but that doesn't allow you to customize keymgr and trustmgr directly, as your code does.)
(For completeness: if you couldn't or can't change the code, a workaround is to interpose some kind of proxy that on one side accepts the outdated and yucky protocol -- 1.0 -- and on the other side relays the data to the real host using the now fashionable protcol -- 1.2. But I don't think you need that.)
Our company has upgraded from TLS 1.0 to TLS 1.2. Before this, we used to download files using org.apache.commons.net.ftp.FTPClient.
Now we cannot connect to the server using FTPSclent and we get an exception:
org.apache.commons.net.ftp.FTPConnectionClosedException: Connection closed without indication
How can I correctly connect to the server.
Full stack trace:
First of all, turn on the SSL debug as the javadoc sugests and try to connect, then check the output (it logs by default to std out, you should redirect it to a file).
The sorter answer
Give a try to the -Dhttps.protocols=TLSv1.2 JVM argument (this should be passed to every java code that you are using during your investigation and you have to use the same JRE of course too).
If does not work, check the server certificate, that should be installed to the JRE's default keystore (cacerts) or your custom keystore that you may use.
If this does not help, install the JCE extensions (JRE could not handle a cert that has at least 2048 bit key without JCE).
If all of these steps are useless, you may have the same problem than this guy.
The longer version
I hope that you are using at least Java7 (see the table of the available protocols on each platform).
The first thing is, that the TLS protocols supported by the server and supported by your application have to have an intersect.
In this table you can find the default TLS protocols of the different JRE versions, this is important because your client uses very probably the default TLS of the JRE.
So after you have checked your JRE and found the supported TLS versions, you should check the applied cyphers.
You should test your connection using nmap:
nmap.exe --script ssl-enum-ciphers -p <port> <ftp host>
with this tool, you can list the TLS version and the used cyphers. The cypher list can be compared with the list provided by this small java code. This two lists have to have at least one common point in order to be able to communicate.
You can download the server's certificate using Portecle, that certificate should be installed in the keystore of your client JRE.
If you have found that they have intersection in TLS protocols and in cyphers too, you have the right cert in your keystore, you can test that they can communicate with
SSLPoke
If this works too, then the problem should be in FTPClient.
Note: Same url is working successfully in browser, but it’s not working through java program same url.
Java code:
String urlString= "https://<host>:<port>/TestProject";
URL url = new URL(urlString);
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
InputStream ins = con.getInputStream();
InputStreamReader isr = new InputStreamReader(ins);
BufferedReader in = new BufferedReader(isr);
String inputLine;
while ((inputLine = in.readLine()) != null) System.out.println(inputLine);
in.close();
Exception:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1720)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
Please give the solutions as early as possible for this. Please give the possibilities to get this scenario if knows, it will very useful for me.
Finally i got solution:
Please look into http://myjavacafe.blogspot.in/2015/01/exception-received-fatal-alert.html
First: the server probably logged more detailed information about the problem, which could allow determining and fixing the actual problem. But since you want an early and "possible" answer rather than an accurate one, causes I've seen are:
Version too old: The server requires a newer protocol than your Java client offers. You appear to be running Java6, which only implements up to TLSv1.0. If the server demands higher, it will fail the handshake, although requiring above 1.0 is somewhat controversial for now (it likely will become accepted and common over the next several years). Solution: use Java8 (in its default configuration), or at least Java7 and override its default configuration which only offers up to TLSv1.0 for client.
Version too new: TLS specs (all) call for servers to negotiate a newer-version or otherwise more-capable client down to the server capabilities, but some servers apparently have bugs and instead fail the handshake. (Browsers/clients often handle this by falling back to older protocols, which caused the recent "POODLE" attack. See for example https://security.stackexchange.com/questions/71427/is-java-client-vulnerable-by-poodle and https://security.stackexchange.com/questions/70719/ssl3-poodle-vulnerability .) However, Java6 client is unlikely to trigger such a problem, and if a recent browser and especially several recent browsers can connect this is very unlikely. But if this is the problem Solution: use older Java (poor), or configure to use old protocol version(s) and possibly few(er) ciphers.
Extensions: Similarly it is possible a buggy server fails to skip unimplemented extensions as the specs say it should. Again if modern browsers can connect this is very unlikely. But if it does you can't control the extensions Java uses so Solution: none. (At least none in Java. You could use an external adapter such as stunnel, or an application-level proxy or relay.)
No shared cipher: The server does not support any of the ciphersuites your client offers. This is unlikely unless your JRE/JVM is configured badly. Java implements nearly all the defined ciphersuites, and by default enables all the ones that are not badly insecure, except that Java6 only enables Elliptic Curve Cryptography suites if an ECC crypto provider is installed which it is not by default. A server admin might reasonably want and prefer EC, but to require it today would be imprudent. If ECC is the problem Solution: use Java7 or 8 or add an EC provider to Java6. If your JRE/JVM is configured badly to use insecure ciphersuites that the server should not agree to Solution: don't do that.
SNI: The server may fail the handshake if it requires Server Name Indication, an extension commonly required nowadays for virtual hosting, but your client does not provide it with the right value. However, Java6 URLConnection(https) derives SNI automatically from the URL, the same way browsers do, so if the same URL works in a recent browser that is not the problem.
Client auth: The server may require client authentication using a certificate, often abbreviated as requiring (a) client cert, and fail if your client doesn't provide one, or perhaps not the correct one. Your browser(s) may be configured to supply the correct cert&key automatically, although if you use multiple browsers that don't share a keystore (as for example IE and Chrome on Windows do) that may be less likely. Solution: configure your JVM/JRE (or for limited scope a customized SSLSocketFactory) to use a keystore that contains the correct privateKeyEntry (key and cert or chain) or if a keystore is already configured put the correct privateKeyEntry in that keystore.
Background:
I am working on a project that involves the client to authenticate itself (via client certificate). We are trying to launch a third party app which first authenticates the client cert and then launches its app.
We are using Java and SSL hanshake, and our client server is Weblogic 10.x. The client certificate is in PKCS12 format (cannot change this)
This is the piece of code for presenting the certificate:
System.setProperty("javax.net.ssl.keyStore","MyPath/cert.pfx");
System.setProperty("javax.net.ssl.keyStorePassword","MyPwd");
System.setProperty("javax.net.ssl.keyStoreType","PKCS12");
url.openConnection();
Now all this works pretty well from a standalone. The problem starts when we put this on weblogic. Sometimes it works, sometimes 'Client certificate not present' (http 403.7) is returned. I have tried various combinations (including configuring custome keystore on weblogic console) but nothing seems to work. Any idea why would weblogic altogether ignore the SSL settings (it doesnt throw an error even if I set keystore to a non-existent file)? System.setProperty for SSL just appears useless on weblogic!
In Weblogic 12c you also need add the parameter -DUseSunHttpHandler=true in order to tell the weblogic server to use the Sun Http Handlers instead of its own. Therefore you need the following Java VM parameters:
-Djavax.net.ssl.keyStore=MyPath/cert.pfx
-Djavax.net.ssl.keyStoreType=PKCS12
-Djavax.net.ssl.keyStorePassword=MyPwd
-DUseSunHttpHandler=true
Finally found the solution! Weblogic seems to over-ride the keystore configurations if it is done through Java as above. The thing that worked for me was to configure the SSL settings on JVM level, at web-logic start-up.
To make it work, I just added these Java options in the start-script for weblogic:
-Djavax.net.ssl.keyStore=MyPath/cert.pfx
-Djavax.net.ssl.keyStoreType=MyPwd
-Djavax.net.ssl.keyStorePassword=PKCS12
Restarted web-logic and SSL has been working great since then :)
I'm trying to upgrade from BouncyCastle bcprov-jdk14-124.jar (oooold) to bcprov-jdk14-143.jar. When I replace the old jar with the new jar and build everything, my software will no longer establish an SSL connection, failing with a javax.net.ssl.SSLException: Received fatal alert: illegal_parameter. Googling for "bouncycastle javax.net.ssl.SSLException illegal_parameter" yields a whopping 4 results.
Any suggestions on where to start debugging this?
Additional context:
client is on WinXP
server on CentOS, using Oracle Application Server
The client is attempting to establish an SSL connection for an AXIS2 POST.
When the server uses bcprov-jdk14-143 and the client uses bcprov-jdk14-124, the POST succeeds, but when the client is upgraded to 143, I get this error
I am a little bit confused about your setup. Your error is from JSSE but BC doesn't provide JSSE. I assume the error is from server, which uses SunJSSE. You probably use BC's TLS API from client to make the TLS connection (check if you have TlsProtocolHandler).
If this is the case, getting everything working is already a miracle on Java 1.4, I wouldn't upgrade anything. Before Java 5, Sun's JSSE is partially hard-wired to SunJCE so you are practically using 2 JCEs at the same time on the server. I played with TLS from BC before and I never got it working so you are way ahead of me :)
Why do you need to upgrade BC? In my opinion, there is no reason to use BC at all if you are on Java 1.4 or later. However, it requires code changes to remove it if you use TlsProtocolHandler.
The specific error is caused by server sending down a list of compression methods. There is no way to get around that. Nobody supports compression but they all send down a list with only Null method.