0

Im using java-websocket in java for testing a websocket server messages from and to the client, and i need to know how to implement a way for the client to not validate SSL certificates in our testing environment, because i don't have the code or any way to disable on the server, we need to only tests the server and make automated tests for the messages to and from the server. But all examples i found are to disable in the server, not in the client, or they disable in other protocols but not websocket client.

This is the error im receiving:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

What i want is to be able to establish a connection to a WebSocket testing server inside our test methods using junit.

This is the client class:

package application.apiClasses.apiEndpoint;

import javax.mail.Session;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.logging.Logger;

public class ApiWebSocketClient extends WebSocketClient {

    private final Logger logger = Logger.getLogger(String.valueOf(this.getClass()));

    public ApiWebSocketClient(URI serverUri, Draft draft) {
        super(serverUri, draft);
    }

    public ApiWebSocketClient(URI serverURI) {
        super(serverURI);
    }

    public ApiWebSocketClient(URI serverUri, Map<String, String> httpHeaders) {
        super(serverUri, httpHeaders);
    }

    @Override
    public void connect() {
        logger.info("Starting connection...");
        super.connect();
    }

    @Override
    public void onOpen(ServerHandshake handshakeData) {
        send("Hello, it is me. Mario :)");
        logger.info("Opened connection");
    }

    @Override
    public void onMessage(String message) {
        logger.info("received: " + message);
    }

    @Override
    public void onMessage(ByteBuffer message) {
        logger.info("received ByteBuffer: " + message);
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        logger.info("Connection closed by " + (remote ? "remote peer" : "us") + " Code: " + code + " Reason: "
                + reason);
    }

    @Override
    public void onError(Exception e) {
        logger.info("An error ocurred: " + e.toString());
    }
}

This is the code of the test method:

    Map<String, String> headers = new HashMap<>();
    String webSocketProtocol = responseProvisionSession.getHeader("Authorization")
            .replaceAll("Bearer " , "") + "XXXXXXXXXXXXXXXXXX";

    headers.put("Sec-WebSocket-Protocol", webSocketProtocol);
    logger.info("WebSocket protocol string: " + webSocketProtocol);

    //headers.put("Sec-WebSocket-Version", "13");
    //headers.put("Sec-WebSocket-Key", "XXXXXXXXXXXXXXXXXXXXX");
    //headers.put("Connection", "Upgrade");
    //headers.put("Upgrade", "websocket");
    //headers.put("Sec-WebSocket-Extensions", "permessage-deflate; client_max_window_bits");
    this.apiWebSocketClient = new ApiWebSocketClient(urlWebSocket,headers);
    logger.info("Has SSL support: " + this.apiWebSocketClient.hasSSLSupport());

    this.apiWebSocketClient.connect();

I tried to disable using the following snippets of code before instantiating the client, with no luck:

    sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, new TrustManager[]{UnsafeX509ExtendedTrustManager.INSTANCE}, null);

And this, but failed to understand if i can use that SSLContext in the client:

    /* Start of Fix */
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
        public void checkClientTrusted(X509Certificate[] certs, String authType) { }
        public void checkServerTrusted(X509Certificate[] certs, String authType) { }

    } };

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

    // Create all-trusting host name verifier
    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) { return true; }
    };
    // Install the all-trusting host verifier
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    /* End of the fix*/

I also tried to add a custom unsafeTrustManager but this is also for the server i think:

import javax.net.ssl.SSLEngine;
import javax.net.ssl.X509ExtendedTrustManager;
import java.net.Socket;
import java.security.cert.X509Certificate;

public final class UnsafeX509ExtendedTrustManager extends X509ExtendedTrustManager {

    public static final X509ExtendedTrustManager INSTANCE = new UnsafeX509ExtendedTrustManager();
    public static final X509Certificate[] EMPTY_CERTIFICATES = new X509Certificate[0];

    private UnsafeX509ExtendedTrustManager() {}

    public static X509ExtendedTrustManager getInstance() {
        return INSTANCE;
    }

    @Override
    public void checkClientTrusted(X509Certificate[] certificates, String authType) {
        // ignore certificate validation
    }

    @Override
    public void checkClientTrusted(X509Certificate[] certificates, String authType, Socket socket) {
        // ignore certificate validation
    }

    @Override
    public void checkClientTrusted(X509Certificate[] certificates, String authType, SSLEngine sslEngine) {
        // ignore certificate validation
    }

    @Override
    public void checkServerTrusted(X509Certificate[] certificates, String authType) {
        // ignore certificate validation
    }

    @Override
    public void checkServerTrusted(X509Certificate[] certificates, String authType, Socket socket) {
        // ignore certificate validation
    }

    @Override
    public void checkServerTrusted(X509Certificate[] certificates, String authType, SSLEngine sslEngine) {
        // ignore certificate validation
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return EMPTY_CERTIFICATES;
    }

}

Any help will be ver appreciated! also anything about testing websocket messages in java. thanks!

Lea2501
  • 311
  • 6
  • 22
  • Does this answer your question? [Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?](https://stackoverflow.com/questions/9619030/resolving-javax-net-ssl-sslhandshakeexception-sun-security-validator-validatore) – Nagaraj Tantri Oct 28 '21 at 14:38
  • Sadly no, i tried almost any solution depicted here, but all fails, now, after tried to import the certificates downloaded with openssl with "echo -n | openssl s_client -connect DOMAIN:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > DOMAIN.crt" and imported with "keytool -import -noprompt -trustcacerts ..." but now im getting a "javax.net.ssl.SSLHandshakeException: No name matching DOMAIN found" – Lea2501 Oct 28 '21 at 16:00

0 Answers0