0

Good day! I have a simple chat application with websocket (STOMP). I have configured ssl connection with mutal auth.

Server side:

server.port=8443
server.ssl.key-store=path/to/server.jks
server.ssl.trust-store=path/to/trusted.jks
server.ssl.key-store-password=22222222
server.ssl.trust-store-password=22222222
server.ssl.client-auth=need

client :

System.setProperty("javax.net.ssl.keyStore","path/to/client.jks");
System.setProperty("javax.net.ssl.keyStorePassword","22222222");
System.setProperty("javax.net.ssl.trustStore","path/to/trusted.jks");  
System.setProperty("javax.net.ssl.trustStorePassword","22222222");

server trusted.jks and client trusted.jks are the same.

so when I try to connect with

-Djavax.net.debug=ssl

I get lots of output and some strange situation - I can see two(?) key-agreements. The first one goes ok -

  trustStore is: /path/to/trusted.jks

adding as trusted cert:
  Subject: [email protected], CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
  Issuer:  [email protected], CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
  Algorithm: RSA; Serial number: 0x9952f188496b2545
  Valid from Wed Jun 28 15:39:04 MSK 2017 until Sat Jun 26 15:39:04 MSK 2027

So my CA cert is added as trusted. Then

*** ClientHello, TLSv1.2
//ok
*** ServerHello, TLSv1.2
//ok
*** Certificate chain
//my localhost server cert
***
Found trusted certificate:

 Version: V3
 Subject: [email protected], CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
 Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

So my client found trusted certificate for this server certificate.

*** ECDH ServerKeyExchange
//ok
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:

*** ServerHelloDone

And I can find my CHAIN -

*** Certificate chain
chain [0] = [
[
  Version: V3
  Subject: [email protected], CN=client3, OU=client3, O=client3, L=client3, ST=client3, C=RU
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

chain [1] = [
[
  Version: V3
  Subject: [email protected], CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
*** ECDHClientKeyExchange
*** CertificateVerify
*** Finished

As far as I know - this is ok. Then I can see:

DEBUG org.springframework.web.client.RestTemplate - GET request for "https://localhost:8443/chat/info" resulted in 200 (null)
DEBUG org.springframework.web.socket.sockjs.client.WebSocketTransport - Starting WebSocket session on wss://localhost:8443/chat/437/f6158d1ee84b4c53ba55a6810b2f92a8/websocket
DEBUG org.springframework.web.socket.client.standard.StandardWebSocketClient - 
Connecting to wss://localhost:8443/chat/437/f6158d1ee84b4c53ba55a6810b2f92a8/websocket

Again adding trust store certificate and so on, all is the same, but

*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA
Cert Authorities:
<[email protected], CN=ca, OU=ca, O=ca, L=ca, ST=ca, C=RU>
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***

So the server says to me

ttps-jsse-nio-8443-exec-9, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain

Any thoughts about problem? If it is needed I can post my keystores and client implementation here. Thank you for help!

UPDATE with curl output

 env -i curl -E ./chain.pem --key ./client.key --cacert ca.crt --verbose --user test:test  https://localhost:8443/

*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8443 (#0)
* found 1 certificates in ca.crt
* found 704 certificates in /etc/ssl/certs 
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
*    server certificate verification OK
*    server certificate status verification SKIPPED
*    common name: localhost (matched)
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #3
*    subject: 

C=RU,ST=localhost, 
L=localhost,O=localhost,OU=localhost, 
CN=localhost,[email protected]
*    start date: Wed, 28 Jun 2017 13:07:14 GMT
*    expire date: Thu, 28 Jun 2018 13:07:14 GMT
*    issuer: C=RU,ST=ca,L=ca,O=ca,OU=ca,CN=ca,[email protected]
*    compression: NULL
* ALPN, server did not agree to a protocol
* Server auth using Basic with user 'kitcpp'
> GET / HTTP/1.1
> Host: localhost:8443
> Authorization: Basic a2l0Y3BwOmtpdGNwcA==
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 200 
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains
< X-Frame-Options: DENY
< Set-Cookie: JSESSIONID=67BACDE78AF68627516075B29C987C86; Path=/; Secure; HttpOnly
< Last-Modified: Wed, 28 Jun 2017 16:29:53 GMT
 < Accept-Ranges: bytes
< Content-Type: text/html;charset=UTF-8
< Content-Language: en-US
< Content-Length: 6935
< Date: Fri, 30 Jun 2017 09:30:02 GMT
< 
<!DOCTYPE html>
<html>
<head>
//and so on (my web chat page)
10
  • Have you tried taking WebSockets out of the picture and seeing if you can establish an HTTPS connection with mutual auth? Commented Jun 30, 2017 at 8:19
  • Andy Wilkinson, if I may say so - I installed my user certificates to chrome and connected to the chat via web client. Commented Jun 30, 2017 at 8:31
  • I'm not sure if that answers my question or not. What does "web client" mean? To keep things simple, I'd use something like curl to verify that mutual auth works with HTTPS. That will either show that the problem is pretty fundamental, or that it's something specific to WebSockets. Commented Jun 30, 2017 at 8:41
  • Andy Wilkinson, I have updated my answer with curl output Commented Jun 30, 2017 at 9:39
  • Ok, so the basic SSL configuration is fine. Looking at your code: firstly, there's quite a lot of it. A minimal sample would make it a lot easier for people to help you. Secondly, your SSL configuration on the client-side looks a bit suspect to me. You have set various system properties, but you've done so after initialising the SSLContext. Furthermore, you've initialised it with no key and trust managers. I'm not sure that will work. Commented Jul 2, 2017 at 16:54

1 Answer 1

3

You are using Tomcat's WebSocket client. Its documentation describes how it should be configured to use SSL:

When using the WebSocket client to connect to secure server endpoints, the client SSL configuration is controlled by the userProperties of the provided javax.websocket.ClientEndpointConfig. The following user properties are supported:

  • org.apache.tomcat.websocket.SSL_CONTEXT
  • org.apache.tomcat.websocket.SSL_PROTOCOLS
  • org.apache.tomcat.websocket.SSL_TRUSTSTORE
  • org.apache.tomcat.websocket.SSL_TRUSTSTORE_PWD

If the org.apache.tomcat.websocket.SSL_CONTEXT property is set then the org.apache.tomcat.websocket.SSL_TRUSTSTORE and org.apache.tomcat.websocket.SSL_TRUSTSTORE_PWD properties will be ignored.

You're using Spring's WebSocket and it is creating the ClientEndpointConfig for you. To configure its user properties you set them on the StandardWebSocketClient and it will then use them when it creates the ClientEndpointConfig. For example, assuming that the default SSL context is sufficient:

StandardWebSocketClient simpleWebSocketClient =
        new StandardWebSocketClient();
Map<String, Object> userProperties = new HashMap<>();
userProperties.put("org.apache.tomcat.websocket.SSL_CONTEXT", SSLContext.getDefault());
simpleWebSocketClient.setUserProperties(userProperties);
Sign up to request clarification or add additional context in comments.

1 Comment

@Furetto, this question and answer are about Tomcat. If you're interested in how to do something similar with Jetty, please ask a new question with more context so that potential answerers can see exactly what you're trying to do.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.