Alex,

On 5/21/25 9:01 PM, My Subs wrote:
Chris,



Is the client sending just their own cert, or also the chain?
It would
  be unusual for the client to send a chain, but instead
just sends their
  own leaf certificate. I'm assuming that both
the root and the
  intermediate / subordinate cert are both in
the trust store. Is that
  correct?


The client is
sending both the leaf and the intermediate certificates (both are in
the PKCS12 file imported into Firefox).  That's the only way for the
chain of trust to work, because only the root certificate is in the
trust store (well, that's how it's supposed to be, as far as I
understand).  And it works fine until the CRL comes into play.



I also tested adding
the subordinate CA's certificate to the trust store.  No change.
With no CRL configured, works alright; but when it is configured, I
get the same errors.  Revoked client cert is rejected as such, and
valid client cert is rejected with SSL_ERROR_UNKNOWN_CA_ALERT.




Can
you please try one more thing for me?
> Can
you create a self-signed certificate, and use ONLY that self-signed
  certificate in your trust store, and have the client send that
to the
  server?
> It will be easier
for me if I just have to deal with a single cert on
  either side
of the connection rather than set up a whole signing
  authority,
etc. before I'm able to reproduce it.

Done.  Removed root CA certificate from trust store, and left only a
self-signed certificate.  The result is exactly the same.  With no
CRL checking, it works fine.  Add CRL checking, and I get: "Peer
does not recognize and trust the CA that issued your certificate.
Error code: SSL_ERROR_UNKNOWN_CA_ALERT"

Perfect. That will make it a lot easier for me to duplicate your setup.

Guess the finger
increasingly points to the CRL checking code.

Agreed, at least in theory.

-chris

---- On Wed, 21 May 2025 16:29:10 -0500 Christopher Schultz 
<ch...@christopherschultz.net> wrote ---



Alex,
On 5/21/25 1:26 PM, My Subs wrote:
To test this, I set
certificateRevocationListPath to the directory having the CRL file;
changed to certificateVerification="optional"; and
downgraded to HTTP 1.1 (as mentioned, "optional" does not
work with HTTP 2).  The result is that requests without a client
certificate get a 200 OK response.
Good.
However, *all* requests having a client certificate (valid or
revoked) are rejected.
Okay.
If the client certificate is revoked, it is correctly identified as
such.  Firefox displays message "SSL peer rejected your
certificate as revoked.  Error code: SSL_ERROR_REVOKED_CERT_ALERT".
Good!
If the client certificate is not revoked, the connection fails with
Firefox displaying an unexpected message: "Peer does not
recognize and trust the CA that issued your certificate.  Error code:
SSL_ERROR_UNKNOWN_CA_ALERT".
Obviously, not good. But I wonder if this is a problem with adding the CRL (which looks like
it's working) versus the trust store. But...
But that same issuing CA is perfectly recognized when the
certificateRevocationListPath attribute is removed from the
connector.
Yeah, I was afraid you'd say that.
Requests with a non-revoked client certificate get a 200 OK
response, and that certificate is made visible to servlets as a
java.security.cert.X509Certificate object. This holds both for
"optional" and> "required" verification.
  > > It's CRL checking what triggers the error.

I'm
not sure whether the message "No client certificate
CA names sent" means a problem with the trust store.  As you can
see from my connector, caCertificatePath is set to the trust store directory. It
contains the certificate of the root CA, which signed the certificate
of the subordinate CA.  The client certificates used in the above
test are signed by that subordinate CA.  And as
shown, those are correctly verified when no CRL is configured.
Is the client sending just their own cert, or also the chain? It would
be unusual for the client to send a chain, but instead just sends their
own leaf certificate. I'm assuming that both the root and the
intermediate / subordinate cert are both in the trust store. Is that
correct?
   > If you do not configure the CRL, are any CA certs listed in
this output?

No.  Message "No client certificate CA names sent" is still there.
The full output is:
  > > [snip]
  >
---

No client certificate CA names sent
Okay. Sounds like it's time for me to try to reproduce this. Can you please try one more thing for me? Can you create a self-signed certificate, and use ONLY that self-signed
certificate in your trust store, and have the client send that to the
server?
It will be easier for me if I just have to deal with a single cert on
either side of the connection rather than set up a whole signing
authority, etc. before I'm able to reproduce it.
-chris
---- On Wed, 21 May 2025 07:19:06 -0500 Christopher Schultz 
<mailto:ch...@christopherschultz.net> wrote ---



Alex,

On 5/19/25 5:37 PM, My Subs wrote:
   > I'm using Ubuntu 20.04 with OpenSSL 1.1.1f.

Okay.

In your earlier message, you had a different configuration. This time you haven't 
specified the class name in the "protocol" attribute. Which one are you 
actually using?



I did change the connector configuration because when updating to Tomcat 10.1.40, I could 
no longer use class Http11AprProtocol on the protocol attribute (I learned then that the 
APR connector had been deprecated).  So, I set it to "HTTP/1.1" to get 
automatic selection of the JSSE OpenSSL implementation.



I also set certificateVerification="required" because I found in the logs an error 
message saying that "optional" does not work with HTTP/2.



Besides, I'm now testing on Tomcat 11.0.6.

Okay.

So the above configuration works for all requests that do not try to send a 
client certificate during the handshake? It's only when you try to send a 
client certificate that things stop working?



Actually, the configuration works seamlessly with client certificate 
verification for as long as no CRL verification is set up.  Client certificates 
are accepted and made visible to servlets.



However, as soon as I set on the <SSLHostConfig>, attribute 
certificateRevocationListFile to the CRL file, or certificateRevocationListPath to 
the directory containing the CRL file (properly c_rehashed), all client certificates 
are rejected.

When you have configured a CRL, are *all* requests rejected, or only
those which include a client certificate during the handshake? I see you
have configured certificateVerification="required" so maybe there are no
modes of operation where client certificates are used.

I'm trying to understand whether this is a problem with the whole setup
when CRLs are added, or only a problem when a client certificate is
actively being checked against the CRL.

When they stop working, does that mean that no more requests are accepted and 
processed, or is it that handshakes fail with client certs but handshakes 
without client certs work okay?



Since certificateVerification is now set to "required", it means that 
handshakes fail with client certs, and therefore, there is no access at all.

Does the connection actually hang, or do you simply get a failed (but
complete) handshake?

If you connect to your server like this, what does the output look like:

$ openssl s_client -showcerts -connect https://host/whatever



I get the following:



       CONNECTED(00000003)

       Can't use SSL_get_servername

       depth=0 CN = localhost

       verify error:num=18:self signed certificate

       verify return:1

       depth=0 CN = localhost

       verify return:1

       ---

       Certificate chain

        0 s:CN = localhost

           i:CN = localhost

           -----BEGIN CERTIFICATE-----

           MIIBfzCCASWgAwIBAgIUBtGtuw6cAZvC560e0RVjnI/+tnwwCgYIKoZIzj0EAwIw

           FDESMBAGA1UEAwwJbG9jYWxob3N0MCAXDTI1MDQxNjIyNTg0OFoYDzIxMjUwMzIz

           MjI1ODQ4WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjO

           PQMBBwNCAASWvdHleExdyTqn+wXgNY3XueCLjkkpbrtVhw8lB4DsmkTJDUCdszZX

           9ElKT01bP10cX+mrinNNEtgKFPBwcTCXo1MwUTAdBgNVHQ4EFgQUJIQfq2nU9T2J

           uexYvw1bqosji6cwHwYDVR0jBBgwFoAUJIQfq2nU9T2JuexYvw1bqosji6cwDwYD

           VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiAUmPONFAU4ThvidgLnlXiu

           7XElAkAGfmlXKkN0DgJWwAIhAPkF8ngCXY4G7Y2obrGUS2u80p06O2ZYFtXyrM3+

           UuRN

           -----END CERTIFICATE-----

           ---

           Server certificate

           subject=CN = localhost



           issuer=CN = localhost



           ---

           No client certificate CA names sent

This looks like a problem. Do you have the trusted certificates
configured correctly? I would have expected Tomcat to send a list of
acceptable certificates back to the client. That's not strictly required
by the TLS spec, but it's handy for debugging like this.

If you do not configure the CRL, are any CA certs listed in this output?

I haven't used TLS with Tomcat much, so I'm not entirely sure what to
expect.

Just to be clear, this is my current <Connector>:



       <Connector

           protocol="HTTP/1.1"

           port="8443"

           SSLEnabled="true"

           maxParameterCount="1000"

           >

           <SSLHostConfig

               protocols="TLSv1.3"

               certificateVerification="required"

               caCertificatePath="tls/client/certs-ca"

               certificateRevocationListPath="tls/client/crls"

               >

               <Certificate

                   certificateKeyFile="tls/server/localhost-key.pem"

                   certificateFile="tls/server/localhost-cert.pem"

                   />

           </SSLHostConfig>

           <UpgradeProtocol

               className="org.apache.coyote.http2.Http2Protocol"

               />

       </Connector>


Thanks for posting the whole thing.

-chris

---- On Fri, 09 May 2025 13:46:35 -0500 Christopher Schultz 
<mailto:mailto:ch...@christopherschultz.net> wrote ---



Alex,

On 5/9/25 2:11 PM, My Subs wrote:
I have tested on Tomcat 10.1.40 with Native
Library 1.3.1 running on JDK 21.0.7+6.  The result is exactly the
same as described before.  The connector below works well with client
authentication, until I add the caCertificatePath attribute.  There
are no error messages in the logs.

Thanks for confirming that.

It probably does not matter, but what OS are you using, and what version
of OpenSSL are you using?

        <Connector
       protocol="HTTP/1.1"
       port="8443"
       SSLEnabled="true"
       maxParameterCount="1000"
       >

In your earlier message, you had a different configuration. This time
you haven't specified the class name in the "protocol" attribute. Which
one are you actually using?

            <SSLHostConfig
           protocols="TLSv1.3"
           certificateVerification="required"
           caCertificatePath="tls/client/certs-ca"
           >
                <Certificate
           certificateKeyFile="tls/server/localhost-key.pem"
           certificateFile="tls/server/localhost-cert.pem"
           />
            </SSLHostConfig>
       <UpgradeProtocol
           className="org.apache.coyote.http2.Http2Protocol"
           />
        </Connector>


This time around, Firefox only shows "0 B" on the
"Transferred" column of the "Network" tab in
developer tools.

Any ideas on what could be wrong?

So the above configuration works for all requests that do not try to
send a client certificate during the handshake?

It's only when you try to send a client certificate that things stop
working?

When they stop working, does that mean that no more requests are
accepted and processed, or is it that handshakes fail with client certs
but handshakes without client certs work okay?

If you connect to your server like this, what does the output look like:

$ openssl s_client -showcerts -connect https://host/whatever

This would usually give you a list of allowable client certificates like
this:
"
Acceptable client certificate CA names
(cert 1)
(cert 2)
...
(cert N)
"

I'm interested in what that returns, if anything.

-chris

---- On Wed, 07 May 2025 12:37:16 -0500 Chuck Caldarale 
<mailto:mailto:mailto:n82...@gmail.com> wrote ---




On 2025 May 7, at 11:43, My Subs 
<mailto:mailto:mailto:mailto:my.s...@zoho.com.invalid> wrote:

I'm setting up certificate client authentication on Tomcat 10.0.0
running on Java 16+36.


Before doing anything else, you need to upgrade. That version of Tomcat is over 
4 years old, and no 10.0.x version is currently supported. Move up to the 
10.1.x level (current version is 10.1.40) and see if your issue has already 
been addressed.

     - Chuck


I'm having trouble getting it to work with a
CRL.  My SSL connector is:

       <Connector
        protocol="org.apache.coyote.http11.Http11AprProtocol"
        port="8443"
        SSLEnabled="true"
        maxParameterCount="1000"
        >
           <SSLHostConfig
            protocols="TLSv1.3"
            certificateVerification="optional"
            caCertificatePath="conf/ca-certs"
            certificateRevocationListPath="conf/ca-crls"
            >
               <Certificate
            certificateKeyFile="conf/localhost-ec-key.pem"
            certificateFile="conf/localhost-ec-cert.pem"
            />
           </SSLHostConfig>
        <UpgradeProtocol
            className="org.apache.coyote.http2.Http2Protocol"
            />
       </Connector>

In my PKI setup (using OpenSSL), I have a root CA
(cert: root-ca.pem), and a subordinate CA (cert: sub-ca-01.pem),
which signs leaf certificates, and issues a CRL (crl:
sub-ca-01-crl.pem).

File root-ca.pem is in conf/ca-certs.  File
sub-ca-01-crl.pem is in conf/ca-crls, as follows:

0551d8aa.r0 -> sub-ca-01-crl.pem
c79c8ddb.r0 -> sub-ca-01-crl.pem
sub-ca-01-crl.pem -> /home/me/somedir/sub-ca-01-crl.pem

Before adding to <SSLHostConfig>, attribute
«certificateRevocationListPath="conf/ca-crls"», client
authentication works fine.  The servlet can see a valid client
certificate and extract its attributes from the X509Certificate
object returned by
request.getAttribute("jakarta.servlet.request.X509Certificate").

However, once I add attribute
certificateRevocationListPath, the connector stops responding to
requests that present a client certificate regardless of whether the
certificate is valid or revoked —it still responds though if the
request does not present a client certificate.

Firefox only shows error NS_ERROR_FAILURE on the
"Transferred" column of the "Network" tab in
developer tools.

The CRL is not expired (and it won't be for long),
as its printout shows:

Certificate Revocation List (CRL):
           Version 2 (0x1)
           Signature Algorithm: ecdsa-with-SHA256
           Issuer: CN = Sub CA 01
           Last Update: May  6 21:53:22 2025 GMT
           Next Update: Apr 12 21:53:22 2125 GMT
           CRL extensions:
               X509v3 CRL Number:
                   4097
Revoked Certificates:
       Serial Number: 82AB03509A91A8DCCBA0CE62A67417B6
           Revocation Date: May  6 21:51:40 2025 GMT
           CRL entry extensions:
               X509v3 CRL Reason Code:
                   Unspecified
       Signature Algorithm: ecdsa-with-SHA256
            30:45:02:21:00:f7:98:07:1f:2f:cf:d5:ad:b7:5e:20:61:de:
            1b:7b:1f:c7:74:f9:80:33:d8:a2:cc:3a:75:28:4c:64:65:93:
            c1:02:20:5b:3e:e9:dd:52:9e:11:9b:45:5a:53:fc:2f:bb:b3:
            f4:db:52:64:f6:ea:13:54:43:d6:54:2b:f3:28:03:ae:6f

The problem persists if I drop attribute
certificateRevocationListPath, and replace it with
«certificateRevocationListFile="conf/ca-crls/sub-ca-01-crl.pem"».
It persists as well if I add to  conf/ca-crls a CRL for the root CA.

I found nothing helpful in the logs.  The source
of the problem escapes me.  How can I get certificate client
authentication to work with CRLs in Tomcat?

Help is appreciated.  Thank you.


---------------------------------------------------------------------
To unsubscribe, e-mail: 
mailto:mailto:mailto:mailto:users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: 
mailto:mailto:mailto:mailto:users-h...@tomcat.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: mailto:mailto:mailto:users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: 
mailto:mailto:mailto:users-h...@tomcat.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: mailto:mailto:users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: mailto:mailto:users-h...@tomcat.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: mailto:users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: mailto:users-h...@tomcat.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to