What would cause SSL negotiations to succeed under .NET but fail under Java?
We have to create a web service client using Apache CXF in Java. The thing is I cannot seem to get the SSL session to properly engage. Either it fails altogether, the server fails to decipher what is sent 开发者_如何学Pythonto it once the application data is transmitted or I fail to read the responses from the server.
However when trying the same transaction using a simple soap test client built in .NET everything runs smoothly.
Server is using double authentication.
Everything is certificate based (x509) stored in the windows certificate store (windows-MY and windows-ROOT)
edit yes, double authentication is indeed client AND server authentication.
Thus far using the bountyCastle provider instead of SunMSCAPI seems to get further but still cannot get the client authentication to work.
PLatform of client CXF 2.2.9, Sun JDK 1.6_21 server IIS 6 ASP.NET unfortunately is all I could gather, I have no control over the server and must use it as-is.
update I am using a JKS keystore now but still am getting the problem. It seems the client is not sending his certificate to the server as part of the authentication process. As a result I get a 403.7 error from the server.
Funny thing is that I receive this error message as an HTML page that must first be decrypted before it is readable !
Presumably, by double authentication, you mean you're using client-certificate authentication in addition to server-certificate authentication (which is more common).
It would be useful to know which versions of the platforms are used on either side, and which patches have been applied.
It's possible that some of the problem come from the re-negotiation fix to CVE-2009-3555 (or lack of fix).
The problem is a flaw in the initial design of the re-negotiation in TLS, which is what was used to re-negotiate a client-certificate. There are two ways of getting a client-certificate: either the server asks for it during the initial TLS handshake, or it asks for it during a subsequent handshake (for example, once it has figured out what the request was aimed for and/or when trying to access a certain restricted area). The second method is the re-negotiation. Unfortunately, there was a security flaw in the design of the TLS protocol in that respect, which has since been fixed thanks to a TLS extension described in RFC 5746.
When the flaw was initially disclosed (around November 2009), some platforms and libraries such as Sun Java or OpenSSL rolled out a quick fix which simply disallowed any re-negotiation (so only initial negotiation of the client-certificate would work). Later on, once RFC 5746 was written, these libraries started to roll out implementations supporting this extension.
As far as I'm aware, Microsoft's default in IIS and its web framework was to use re-negotiation and not initial negotiation. In addition, it didn't roll out the initial fix to disable re-negotiation (effectively keeping the known vulnerability). It only rolled out a patch (still tolerant to old implementations by default) quite recently: Microsoft Security Bulletin MS10-049 - Critical.
There is also an explanation of the problem on this Microsoft security blog: http://blogs.technet.com/b/srd/archive/2010/08/10/ms10-049-an-inside-look-at-cve-2009-3555-the-tls-renegotiation-vulnerability.aspx
Essentially, if you're trying to talk to a server that only supports the old negotiation style from a stack that only has the new re-negotiation style or no renegotiation at all, it's not going to work.
If your server is running using IIS or similar environment, you might be able to turn on initial client-certificate negotiation using netsh
and its clientcertnegotiation=enable
option.
Java doesn't rely on the OS certificate store and needs to use its own.
This will import your self-signed certificates.
cd JAVA_HOME/jre/lib/security
keytool -import -file server_cert.cer -keystore cacerts
I post this as an answer though I realize now the question was not formulated properly as I got thrown in a loop because the .NET example I had was actually performing a hack to get around the problem.
The proper question should have been
How to get Java to perform Client side Authentication on a server that does not ask for Ask for certificates ?
the answer is actually under our very noses, however to get to the answer one needs the correct question !!
Great thanks to Bruno who provided some very helpful information.
the solution can pretty much be summed up in these two questions :
Java HTTPS client certificate authentication
Client SSL authentication causing 403.7 error from IIS
Although the client is "not supposed" to send a certificate if not asked I found that by tweaking the client certificate in the keystore to contain the following :
- Client certificate with all extensions
- Client Private key
- A concatenation of the client's complete certification chain.
push all this in the same certificate store and use it as keystore. Then load again the certification chain as a trust store. From there it should just work. This being said there is still a possibility for failure. the safest way to solve this particular issue is to have the server actively ask for a authentication certificate from the client by providing a list of accepted CA.
Hope this helps anyone else that can be stuck in the same problem, sure tooke me for a spin for a while before I reach the root of evil.
精彩评论