Hello.
I have a specific page in my site that uses ssl client certificates
for authentication and the application itself does the cert
validation. As the rest of the site does not use them I have
clientAuth="false" in my connector otherwise the browsers keep asking
for client certificates.
I installed a custom security provider to accept all certificates and
built a Valve that requests a SSL renegotiation to try and get a
certificate:
req.getCoyoteRequest().action(ActionCode.ACTION_REQ_SSL_CERTIFICATE,
null);
Using APR no certificate is requested from the client (probably
because of bug 46950). Without APR a SSL renegotiation occurs and a
certificate is requested. If a certificate is presented everything
works fine and my application sees it, if the client does not send a
certificate the connection is promptly closed and the request never
makes it to my application to display some kind of error message. This
exception is printed to the logs:
javax.net.ssl.SSLProtocolException: handshake alert: no_certificate
at
com
.sun
.net
.ssl
.internal.ssl.ServerHandshaker.handshakeAlert(ServerHandshaker.java:
1167)
at
com
.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:
1675)
at
com
.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:
932)
at
com
.sun
.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:
746)
at
com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
at java.io.InputStream.read(InputStream.java:85)
at
org.apache.tomcat.util.net.jsse.JSSESupport.handShake(JSSESupport.java:
162)
at
org
.apache
.tomcat
.util.net.jsse.JSSESupport.getPeerCertificateChain(JSSESupport.java:138)
at
org.apache.coyote.http11.Http11Processor.action(Http11Processor.java:
1099)
at org.apache.coyote.Request.action(Request.java:350)
at
pt.sapo.tomcat.valve.SSLClientRequestor.invoke(SSLClientRequestor.java:
31)
This happens because the code in JSSESupport::handshake() sets the
needClientAuth flag when clientAuth != "want":
if( ssl.getWantClientAuth() ) {
log.debug("No client cert sent for want");
} else {
ssl.setNeedClientAuth(true);
}
If I set clientAuth="want" in my connector this process works but then
the browser always asks for a certificate which is not what I want.
Wouldn't it be better to just set the "want" flag in the SSLSocket
instead of "need"?
Best regards,
André Cruz