I have a trivial secure socket server-client program.
For the server certificates, I created a keystore using keytool.
When I try to connect to the server by my client I get these exceptions:
In server:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
In client:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
If my understanding is correct, these exceptions are caused due to the fact, that I am using certificates I created.
My question is the following:
If I set in the enabled cipher suites, both in server and in client, all the *_anon* cipher suites, shouldn't this solved the problem?
I mean If I enable the *_anon_*
cipher suites then no authentication would be needed hence no exceptions.
Is this correct?
Because I still get exceptions. I tried having in the enabled cipher suites all the enabled+the _anon ones. No success. I tried setting only the anon ones and got a new exception:
Exception in thread "main" java.lang.IllegalArgumentException: Name must not be null
Could someone please explain why I get these exceptions, with the anon cipher suites?
Note:
If I set on the client the system property javax.net.ssl.trustStore
pointing to the keystore I created and being used by my server, the communication is fine!
The program works with no exceptions and the data are send ok, from client to server.
UPDATE:
This is the snippet I use to enable the anon ciphers (I have done this for server and client part):
String[] supported = server.getSupportedCipherSuites();
String[] anonCipherSuitesSupported = new String[supported.length];
int count = 0;
for(int i = 0; i < supported.length; i++)
{
if(supported[i].indexOf("_anon_") > 0)
{
anonCipherSuitesSupported[count++] = supported[i];
}
}
String[] oldEnabled = server.getEnabledCipherSuites();
String[] newEnabled = new String[oldEnabled.length + count];
System.arraycopy(oldEnabled, 0, newEnabled, 0, oldEnabled.length);
System.arraycopy(anonCipherSuitesSupported, 0, newEnabled, oldEnabled.length, count);
server.setEnabledCipherSuites(newEnabled);
The stack trace is on client side:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
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.writeRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(Unknown Source)
at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
at sun.nio.cs.StreamEncoder.flush(Unknown Source)
at java.io.OutputStreamWriter.flush(Unknown Source)
at com.client.SSLClient1.main(SSLClient1.java:58)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
... 14 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
... 20 more
and on server side:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(Unknown Source)
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 com.sun.net.ssl.internal.ssl.AppInputStream.read(Unknown Source)
at com.server.SecureOrderTaker.main(SecureOrderTaker.java:92)
Now if I simply do:
server.setEnabledCipherSuites(anonCipherSuitesSupported);
So that only the anon cipher suites are enabled I get:
Exception in thread "main" java.lang.IllegalArgumentException: Name must not be null
at com.sun.net.ssl.internal.ssl.CipherSuite.valueOf(Unknown Source)
at com.sun.net.ssl.internal.ssl.CipherSuiteList.<init>(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.setEnabledCipherSuites(Unknown Source)
at com.server.SecureOrderTaker.main(SecureOrderTaker.java:82)
Thank you
You are right,
*_anon_*
ciphers are used for a complete unauthenticated connection (both server and client are anonymous). With these cipher suites no certificate is required. I wrote a small code to test:I know that this code is not perfect but I successfully exchange data between the client and the server. Maybe your server or client socket is not well configured. Can you give the full stacktrace you got?
Note that these ciphers are deprecated since there are vulnerable to man-in-the-middle attacks.
UPDATE : I found the issue. The
anonCipherSuitesSupported
array length is too long. Therefore after adding the*_anon_*
the array is ending with a bunch ofnull
values. And the implementation does not seem to acceptnull
in the enabled cipher list.