If a client does not have a client certificate or doesn't select a client certificate to be used for authentication, Tomcat does not display an error page. It just does nothing (that the client would see). Steps to reproduce: 1. configure an ssl connector and set clientAuth="false" 2. create a security-constaint in the web.xml of the webapp 3. set the login-config in the web.xml to this: <login-config> <auth-method>CLIENT-CERT</auth-method> </login-config> 4. try to access the page without a client certificate
org.apache.catalina.authenticator.SSLAuthenticator.authenticate() it tests if the client has a certificate and displays an error page if not. But the client doesn't get that error page. if ((certs == null) || (certs.length < 1)) { if (containerLog.isDebugEnabled()) containerLog.debug(" No certificates included with this request"); response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString("authenticator.certificates")); return (false); }
The bug seems ot be in the JSSE package I could solve it by changing the method JSSE14Support.handshake() from: protected void handShake() throws IOException { if( ssl.getWantClientAuth() ) { logger.debug("No client cert sent for want"); } else { ssl.setNeedClientAuth(true); } synchronousHandshake(ssl); } to: protected void handShake() throws IOException { if( ssl.getNeedClientAuth() ) { logger.debug("No client cert sent for want"); } else { ssl.setWantClientAuth(true); } synchronousHandshake(ssl); } This way in the above scenario wantClientAuth is set to true. So the SSLSocket would also accept connection without client certificates, but the SSLAuthenticator will then display an error page.
Created attachment 19483 [details] added a patch with the proposed change in http://issues.apache.org/bugzilla/show_bug.cgi?id=41337#c2
Does this patch introduce a logical change for applications and therefore need an RFE?
Hi, The only way to present a useful error page is to establish a socket. JSSE won't let the socket happen if there's a problem with a client cert. In my mind the only way to provide a useful error page would be to for Tomcat to only ever use "setWantClientAuth" (which isn't even available pre Java 1.4 !), and to draw an HTML error page for all requests if "need=true" is set in Tomcat's own config. It's nicer to just leave all this stuff up to JSSE and not worry about it. By circumventing JSSE's "no socket for you" security, Tomcat risks making itself insecure, even though a helpful error page would be *really* handy! Workaround: set your own SSL config in Tomcat to "WANT" instead of "NEED" (in server.xml) and setup your own ServletFilter on "/*" that draws a nice error page if no client cert is provided. <Connector port="8443" minProcessors="5" maxProcessors="75" enableLookups="true" disableUploadTimeout="true" acceptCount="100" debug="0" scheme="https" secure="true"; sslProtocol="TLS" clientAuth="want" />
As Julius notes the desired behaviour is possible with the current configuration options and a little coding. The lack of useful error message when the SSL handshake fails is more a browser failing than a Tomcat one. I am have changed this issue to an enhancement and am resolving as WONTFIX as I do not believe the benefit of a nice error message outweighs the risk of allowing users with invalid certificates to make a successful connection.
The behaviour that I like is a bit different. I have a connector that is configured with clientAuth="none". And in the web.xml I specify certain pages that require a certificate. This way the user is not bothered with a certificate selection dialog, unless he accesses a page where a client cert authensication level is needed. So unexpirienced users are not overstrained with selecting a certificate, before theiy can even access the part of the page that does not need such an authentucation.
I second Armin's observation. If we ever want to make client certificate authentication mass-ready, we cannot only rely on browser manufacturers making client-cert-auth dialogs mass proof. It must be possible to first navigate on a https site/connector and read some "in-page" text and possibly submit some form info securely and only thereafter be confronted with the certificate selection popping up. Do you have any "third" approaches?
(In reply to comment #7) > The behaviour that I like is a bit different. I have a connector that is > configured with clientAuth="none". And in the web.xml I specify certain pages > that require a certificate. This is supported out of the box with CLIENT-CERT. My concerns in comment #6 remain and I am therefore re-closing this.