Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getAttribute("javax.servlet.request.X509Certificate") not set (Spring,CXF,Jetty,JAX-RSv1.1)

My client implements Two-Way SSL in the following way:


    private final static String KEYSTORE = "/security/client.jks";
    private final static String KEYSTORE_PASSWORD = "secret";
    private final static String KEYSTORE_TYPE = "JKS";
    private final static String TRUSTSTORE = "/security/certificates.jks";
    private final static String TRUSTSTORE_PASSWORD = "secret";
    private final static String TRUSTSTORE_TYPE = "JKS";
    ...
    KeyStore keystore = KeyStore.getInstance(KEYSTORE_TYPE);
    FileInputStream keystoreInput = new FileInputStream(new File(KEYSTORE));
    keystore.load(keystoreInput, KEYSTORE_PASSWORD.toCharArray());
    KeyStore truststore = KeyStore.getInstance(TRUSTSTORE_TYPE);
    FileInputStream truststoreIs = new FileInputStream(new File(TRUSTSTORE));
    truststore.load(truststoreIs, TRUSTSTORE_PASSWORD.toCharArray());
    SSLSocketFactory socketFactory = new SSLSocketFactory(keystore, KEYSTORE_PASSWORD, truststore);
    Scheme scheme = new Scheme("https", 8543, socketFactory);
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(scheme);
    ClientConnectionManager ccm = new PoolingClientConnectionManager(registry);
    httpclient = new DefaultHttpClient(ccm);
    HttpResponse response = null;
    HttpGet httpget = new HttpGet("https://mylocalhost.com:8543/test");
    response = httpclient.execute(httpget);
    ...

And I try to retrieve the X.509 certificate on the server's side from the client via javax.servlet.http.HttpServletRequest.getAttribute("javax.servlet.request.X509Certificate") as it is decribed here: http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/ServletRequest.html#getAttribute%28java.lang.String%29.

I get the HttpServletRequest on the server's side via:
HttpServletRequest servletRequest = (HttpServletRequest) msg.get("HTTP.REQUEST"); via the handleMessage(Message msg) method of my interceptor class which extends AbstractPhaseInterceptor<Message>. I have to use JAX-RS 1.1.1 on the server's side because of some Maven dependencies which I am not allowed to change and so I cannot use ContainerRequestFilter (supported from JAX-RS 2.0 on).

My problem is that getAttribute("javax.servlet.request.X509Certificate") on the server's side returns null all the time. If I verify the traffic between server and client, I can see that the certificate from the server is sent to the client, that handshake works. But I cannot see that the client certificate is sent to the server and I think it is the reason why getAttribute("javax.servlet.request.X509Certificate") returns null. Does someone know how I can solve that problem? I tried some other implementations on the client's side already, but with no change.

What am I doing wrong? Many thanks in advance!

Additional information: I have seen on the server's side that javax.servlet.request.ssl_session_id, javax.servlet.request.key_size and javax.servlet.request.cipher_suite are set, but the key javax.servlet.request.X509Certificate is not set. I'm using Jetty Server 8.1.15, Apache CXF 2.7.x and JAX-RS 1.1.1. I tried with Jetty configuration via http://cxf.apache.org/docs/jetty-configuration.html and http://cxf.apache.org/docs/secure-jax-rs-services.html#SecureJAX-RSServices-Configuringendpoints, the attribute still isn't set.

like image 566
Jana Weschenfelder Avatar asked Jun 22 '14 12:06

Jana Weschenfelder


1 Answers

Problem is solved. It wasn't a problem in the code, it was a certificate problem only. My problem was that I was a beginner regarding X509 certificates as well, it was a handshake problem between server and client. In this case, only the SSL/Handshake debug helped me. The debug log told that the server only accepted client certificates from a specific CA, the server told the client the required CA in a certificate request during the ServerHello message. Since the Client didn't have a certificate from that CA, it didn't send something and the connection between client and server was closed then, with the result that javax.servlet.request.X509Certificate was not set.

For all others who might join the same problem sometime (which seems to be a common SSL configuration problem regarding to IBM as it is mentioned in the first link below), the following sources helped me a lot:
- http://www-01.ibm.com/support/docview.wss?uid=swg27038122&aid=1 (pages 16 and 17)
- http://java.dzone.com/articles/how-analyze-java-ssl-errors (shows as the handshake should look)
- need help Debugging SSL handshake in tomcat (shows how to debug ssl errors in Java)
- https://thomas-leister.de/internet/eigene-openssl-certificate-authority-ca-erstellen-und-zertifikate-signieren/ (in German, but maybe you can find an English equivalent)
- https://access.redhat.com/site/documentation/en-US/Red_Hat_JBoss_Fuse/6.0/html/Web_Services_Security_Guide/files/i382674.html (continuation of the German article)
- http://www.webfarmr.eu/2010/04/import-pkcs12-private-keys-into-jks-keystores-using-java-keytool/ (how to create keystore and truststore)

After creating an own CA, a server and client certificate and after creating the keystore and truststore for both, the attribute was set now:
- Here15_1: javax.servlet.request.X509Certificate
- Here16_2: class [Ljava.security.cert.X509Certificate;
- Here16_3: [Ljava.security.cert.X509Certificate;@43b8f002
The server code is able to extract the client certificate information now, too.

like image 175
Jana Weschenfelder Avatar answered Sep 29 '22 04:09

Jana Weschenfelder