1

What is common way of client certificate validation against CRL in Tomcat?

  1. One possible solution:
    Update server.xml, set up connector, set up key and trust store, and there is crlList parameter.

    There are 2 issues with that approach:

    1. Maintenance of the list - have to be done outside of Tomcat, Tomcat needs restart in order to pick up latest one

    2. There is no (or at least the one I could find) way to support CR Lists for multiple CA bodies, or just say - multiple CR Lists at the same time.

    I was not able to find "good" solution back few years ago with Tomcat 5. Any news on this with 7?

  2. Is there common/elegant way to override connector handler and current functionality and provide custom certificate validation?

    In a way that JBoss AS let you do it, by just extending existing class and giving you possibility to define own login-module and own verifier.

StackzOfZtuff
  • 2,534
  • 1
  • 28
  • 25
dejanmr
  • 47
  • 2
  • 8

2 Answers2

0

You can do this by implementing your own TrustManager. See the trustManagerClassName attribute in the HTTP connector docs(http://tomcat.apache.org/tomcat-8.0-doc/config/http.html#SSL_Support)

Mark Thomas
  • 16,339
  • 1
  • 39
  • 60
  • Ok, thanks. That is one way to go. I have already done similar thing with JBoss AS long time ago, but I would be happier if there is out-of-the box solution, or at least standard approach how to do it. – dejanmr Nov 29 '13 at 15:13
  • Do tomcat server caches or stores CRL lists locally for some time( expiry time) after downloading once from CA by default ? Do we need to configure more for implementing CRL cache? – harish chava Jun 20 '18 at 13:35
0

There is now a way to pick the latest CRL file without restarting the server.

They introduced 2 methods named:

  1. reloadSslHostConfig(String hostName) - to reload a specific host
  2. reloadSslHostConfigs() - reload all

They can be called in various ways:

  1. Using jmx
  2. Using manager service
  3. By making custom protocol - I found this way during my research

Details of way 1 and way 2 are easily available online.

Details of how to go about using way 3:

  1. Make a class extending the protocol of your choice for eg. Http11NioProtocol
  2. Override the required methods and just call super in them to keep default behavior
  3. Make a thread in this class to call reloadSslHostConfigs method time to time
  4. Package this class in a jar and put that jar in tomcat's lib folder
  5. Edit protocol in connector in server.xml to use this custom defined protocol

Find sample code below:

Main protocol class:

package com.myown.connector;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentMap;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.net.ssl.SSLSessionContext;

import org.apache.coyote.http11.Http11NioProtocol;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.AbstractJsseEndpoint;
import org.apache.tomcat.util.net.GetSslConfig;
import org.apache.tomcat.util.net.SSLContext;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLImplementation;
import org.apache.tomcat.util.net.SSLUtil;

public class ReloadProtocol extends Http11NioProtocol {
    
    private static final Log log = LogFactory.getLog(Http12ProtocolSSL.class);

    public ReloadProtocol() {
        super();
        RefreshSslConfigThread refresher = new 
              RefreshSslConfigThread(this.getEndpoint(), this);
        refresher.start();
    }

    @Override
    public void setKeystorePass(String s) {
        super.setKeystorePass(s);
    }

    @Override
    public void setKeyPass(String s) {
        super.setKeyPass(s);
    }

    @Override
    public void setTruststorePass(String p) {
        super.setTruststorePass(p);
    }

    class RefreshSslConfigThread extends Thread {

        AbstractJsseEndpoint<?> abstractJsseEndpoint = null;
        Http11NioProtocol protocol = null;

        public RefreshSslConfigThread(AbstractJsseEndpoint<?> abstractJsseEndpoint, Http11NioProtocol protocol) {
            this.abstractJsseEndpoint = abstractJsseEndpoint;
            this.protocol = protocol;
        }

        public void run() {
            int timeBetweenRefreshesInt = 1000000; // time in milli-seconds
            while (true) {
                try {
                        abstractJsseEndpoint.reloadSslHostConfigs();
                        System.out.println("Config Updated");
                } catch (Exception e) {
                    System.out.println("Problem while reloading.");
                }
                try {
                    Thread.sleep(timeBetweenRefreshesInt);
                } catch (InterruptedException e) {
                    System.out.println("Error while sleeping");
                }
            }
        }
   }
}

The Connector in server.xml should mention this as the protocol:

<Connector protocol="com.myown.connector.ReloadProtocol"
...

Hope this helps.

StackzOfZtuff
  • 2,534
  • 1
  • 28
  • 25
Mags
  • 86
  • 8
  • Just a 5 years too late ... thanks for the answer, will accept this, as I don't expect any new to pop up, although I am not able to test it currently – dejanmr Jan 14 '20 at 09:33