1

I am trying to solve an issue with my Jetty servlet running over HTTPS.

This is an error in the browser:

enter image description here

This is an error in the curl:

enter image description here

What I did:

  1. I created my Keystore and Truststore as is described here: How to generate keystore and truststore and here https://serverfault.com/questions/488003/keytool-subjectalternativename

    This is my batch script to create Keystore and Truststore:

keytool -keystore keystore.jks -storepass P4ssW0rd -keypass P4ssW0rd -genkey -alias example -validity 365 -dname "CN=example,OU=Example,O=Example,L=Bratislava,ST=Slovakia,C=SK" -ext "SAN=DNS:example.com,DNS:www.example.com,DNS:test.example.com"
"C:\Program Files\Git\usr\bin\openssl.exe" req -new -x509 -subj "/C=SK/ST=Slovakia/L=Bratislava/O=Example/OU=Example/CN=Root-CA" -keyout ca-key -out ca-cert -days 365 -passout pass:P4ssW0rd
keytool -keystore truststore.jks -storepass P4ssW0rd -import -alias ca-root -file ca-cert -noprompt
keytool -keystore keystore.jks -storepass P4ssW0rd -certreq -alias exmaple -file cert-file
echo [SAN] > extFile
echo subjectAltName=DNS:example.com,DNS:www.example.com,DNS:test.example.com >> extFile
"C:\Program Files\Git\usr\bin\openssl.exe" x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out test.pem -days 365 -CAcreateserial -passin pass:P4ssW0rd -extensions SAN -extfile extFile
keytool -keystore keystore.jks -storepass P4ssW0rd -import -alias ca-root -file ca-cert -noprompt
keytool -keystore keystore.jks -storepass P4ssW0rd -import -alias metahost -file test.pem
pause
  1. keystore.jks and truststore.jks were copied to the directory of my project and code was written up to load these files.
package sk.cood.metahost.server;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;

import java.io.*;

@WebServlet(displayName = "MetaHostServlet", urlPatterns = { "/*" })
public class MetaHostServlet extends HttpServlet {
    private static File keyStoreFile;
    private static File trustStoreFile;

    public static void main(String[] args) throws Exception {
        loadKeyStores();

        Server server = new Server(443);
        ServerConnector connector = createSSLConnector(server, "P4ssW0rd", "P4ssW0rd", false);
        server.addConnector(connector);

        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.addServlet(new ServletHolder(new MetaHostServlet()),"/*");
        context.setContextPath("/");
        server.setHandler(context);

        server.start();
        server.join();
    }

    private static void loadKeyStores() {
        keyStoreFile = new File("keystore.jks");
        trustStoreFile = new File("truststore.jks");
        if (!keyStoreFile.exists()) {
            throw new RuntimeException("Key store file does not exist on path '"+keyStoreFile.getAbsolutePath()+"'");
        }
        if (!trustStoreFile.exists()) {
            throw new RuntimeException("Trust store file does not exist on path '"+trustStoreFile.getAbsolutePath()+"'");
        }
    }

    private static ServerConnector createSSLConnector(Server server, String keyStorePassword, String trustStorePassword, boolean isClientAuthNeeded) {
        SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
        sslContextFactory.setKeyStorePath(keyStoreFile.getAbsolutePath());
        sslContextFactory.setKeyStorePassword(keyStorePassword);
        sslContextFactory.setTrustStorePath(trustStoreFile.getAbsolutePath());
        sslContextFactory.setTrustStorePassword(trustStorePassword);
        sslContextFactory.setNeedClientAuth(isClientAuthNeeded);

        HttpConfiguration https_config = new HttpConfiguration();
        https_config.setSendServerVersion(false);
        https_config.setRequestHeaderSize(512 * 1024);
        https_config.setResponseHeaderSize(512 * 1024);

        SecureRequestCustomizer src = new SecureRequestCustomizer();
        https_config.addCustomizer(src);

        return new ServerConnector(server, sslContextFactory, new HttpConnectionFactory(https_config));
    }

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
        res.setContentType("text/html");
        res.setStatus(HttpServletResponse.SC_OK);
        res.getWriter().println("<h1>Hello World!</h1>");
        res.getWriter().println("session=" + req.getSession(true).getId());
    }
}
  1. I started my servlet with jetty and tried to connect to https://example.com/ and mentioned error appears.

I don't know what is wrong in my case, maybe someone more experienced with jetty and certificates will help.

Thank you so much!

CooderSK
  • 147
  • 1
  • 2
  • 8

1 Answers1

0

Your ServerConnector doesn't do anything with the SSL, at least not directly.

This line ...

return new ServerConnector(server, sslContextFactory, 
    new HttpConnectionFactory(https_config));

It merely supports HTTP/1.1 normal plaintext, no SSL, and relies on the JVM ServiceLoader to find the appropriate SslConnectionFactory based on your SslContextFactory.Server.

Since you didn't specify what the classloader/classpath is for your environment, nor the specific version of Jetty, I would encourage you to be more direct with your ServerConnector and your SSL/TLS desires, don't rely on the ServiceLoader if you don't have to.

Like this ...

return new ServerConnector(server, 
    new SslConnectionFactory(slContextFactory, "http/1.1"),
    new HttpConnectionFactory(https_config));

This will likely improve things for you, but without more details I cannot tell you exactly what happened or how to fix it.

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
  • Thank you, now it is showing me this error in curl: curl: (35) schannel: next InitializeSecurityContext failed: SEC_E_ILLEGAL_MESSAGE (0x80090326) - This error usually occurs when a fatal SSL/TLS alert is received (e.g. handshake failed). More detail may be available in the Windows System event log. – CooderSK Nov 13 '21 at 19:21
  • What details can I attach to this question to help with resolving this issue? – CooderSK Nov 13 '21 at 19:26