When a part of a webapp requires an SSL connection with a client certificate there should be an SSL renegotiation to request a client certificate from the browser. This is the configuration I added to an webapp that already uses an SSL connector: <login-config id="LoginConfig_1"> <auth-method>CLIENT-CERT</auth-method> <realm-name>WPS</realm-name> </login-config> <security-constraint id="SecurityConstraint_1"> <web-resource-collection id="WebResourceCollection_1"> <web-resource-name/> <url-pattern>/LoginWithCert.do</url-pattern> <http-method>DELETE</http-method> <http-method>GET</http-method> <http-method>POST</http-method> <http-method>PUT</http-method> <http-method>HEAD</http-method> </web-resource-collection> <user-data-constraint id="UserDataConstraint_4"> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> Requests to /LoginWithCert.do require an SSL connection, if there isn't one, but no client certificate is requested.
There is no <auth-constraint> in the configuration, so of course Tomcat doesn't ask for a certificate.
Ok. So now I changed the security-constraint to: <security-constraint id="SecurityConstraint_1"> <web-resource-collection id="WebResourceCollection_1"> <web-resource-name/> <url-pattern>/LoginWithCert.do</url-pattern> <http-method>DELETE</http-method> <http-method>GET</http-method> <http-method>POST</http-method> <http-method>PUT</http-method> <http-method>HEAD</http-method> </web-resource-collection> <auth-constraint> <role-name>*</role-name> </auth-constraint> <user-data-constraint id="UserDataConstraint_4"> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> Now I get this error when I access the resource: HTTP Status 400 - No client certificate chain in this request BUT no certificate was asked in the SSL (re-)negotiation.
The following configuration works for me. At a guess, you haven't configured Tomcat to trust the issuer of your client certificate. The browser only prompts you to select a cert if it has one that the server will trust. Please use the users list if you need further help configuring your SSL certs. <security-constraint> <web-resource-collection> <web-resource-name>Bug46950</web-resource-name> <url-pattern>/bug46381.jsp</url-pattern> </web-resource-collection> <auth-constraint> <role-name>manager</role-name> </auth-constraint> </security-constraint> <security-constraint> <web-resource-collection> <web-resource-name>Everything</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint> <login-config> <auth-method>CLIENT-CERT</auth-method> </login-config>
What works for you? Did you even read what I said? How can the browser know if a server trusts a certain certificate or not without even asking for it? Let me explain the problem better. Most of my site runs without client cert checking, so I have SSLVerifyClient="none" on the connector. But I have one servlet that DOES want a client certificate and so I configured the security restriction accordingly in the deployment descriptor. Just that one resource, not the entire site. It's in these cases that a SSL renegotiation does not occur to ask for the client certificate. Tomcat only knows that I want a client certificate after the client sends the http request. Apache httpd has this feature and someone at the tomcat user's list asked me to file this as a bug. Maybe it's just a missing feature.
(In reply to comment #4) > What works for you? The security constraint and login configuration I posted which requires SSL for the entire context but only requires user authentication for a single JSP. If I browse to any resource except the one that requires auth using http I get switched to https as expected. If I then request the protected resource I get prompted for my certificate. > Did you even read what I said? Yes I did. Quite carefully. Taking that attitude is not going to induce people to help you. > How can the browser know if a server trusts a certain certificate or not > without even asking for it? This is the way the SSL handshake works. The server provides a client with a list of trusted certs. If the client doesn't have a user cert issued by one of the trysted certs the client doesn't waste time prompting the user to select one. > Let me explain the problem better. > > Most of my site runs without client cert checking, so I have > SSLVerifyClient="none" on the connector. That is new information. Your original bug report made no mention of using the APR/native connector. I'd expect the behaviour to remain the same but I'll re-test with the native and see.
OK, I can confirm this when I test with the APR/native connector. Looking for a fix now...
This is going to require a change to the APR/native connector.
Created attachment 23663 [details] Patch that makes the Apr connector behave like the non-Apr This patch will turn on the SSL Client requirement prior to the SSL renegotiation prompting the browser for one.
The proposed patch does not work exactly as intended. It does not trigger renegotiation, rather it sets SSLVerifyClient for the all future SSL sessions created by that request processor. The side effects of this are: - cert still not prompted for when transitioning from resource that doesn't require cert to one that does - subsequent SSL requests handled by that processor will prompt for a cert, even when not required. As per comment #7, a fix for this that aligns the APR/native connector behaviour with the Java connectors will require a change to the native component of the native connector (to enable the connection to be renegotiated for the current connection).
The native fixes have been applied to the 1.1.x branch and trunk (1.2.x) The Tomcat fixes have been applied to trunk (7.0.x) and proposed for 6.0.x and 5.5.x. Note that the 6.0.x/5.5.x patch depends on there being a new tc-native release
This has been fixed in 6.0.x and will be included in 6.0.21 onwards. It will also be proposed for backport to 5.5.x
Thanks!
This has been applied to 5.5.x and will be included in 5.5.29 onwards.