Hello,

I'm working through upgrading an application from Tomcat 7 to Tomcat 9, and
am running into an issue with hostname verification. The application
initiates websocket connections using SSL to several other servers by IP
address, and those servers' certificates either do not have any subject
alternative names (SAN) set, or have SANs that do not include their IP
address. As a result, we're getting SSL connection errors like "No subject
alternative names present" and "No subject alternative names matching IP
address <ip address> found".

(I understand that the correct solution here would be to update all our
servers to have certificates with proper SANs and make our
application initiate websockets using hostnames that match the SANs, but
that will take some time to do and I'm trying to figure out if there's a
workaround that will let us complete the upgrade to Tomcat 9 without having
to do a complete rollout of those changes first.)

The how-to on websockets (
https://tomcat.apache.org/tomcat-9.0-doc/web-socket-howto.html) says that
you can bypass hostname verification with a custom TrustManager: "For
secure server endpoints, host name verification is enabled by default. To
bypass this verification (not recommended), it is necessary to provide a
custom SSLContext via the org.apache.tomcat.websocket.SSL_CONTEXT user
property. The custom SSLContext must be configured with a custom
TrustManager that extends javax.net.ssl.X509ExtendedTrustManager. The
desired verification (or lack of verification) can then be controlled by
appropriate implementations of the individual abstract methods."

I did a trial using an "accept everything" TrustManager, but was still
seeing the same errors. Poking around with a debugger, it seems like the
JSSE "AbstractTrustManagerWrapper" runs the configured TrustManager checks,
and then runs its own "additional" checks, which is where things are
failing (
https://github.com/JetBrains/jdk8u_jdk/blob/94318f9185757cc33d2b8d527d36be26ac6b7582/src/share/classes/sun/security/ssl/SSLContextImpl.java#L1097).
In particular, it seems like if the identity algorithm returned by
"getEndpointIdentificationAlgorithm" is non-null, it runs some identity
checks using X509TrustManagerImpl, regardless of what custom TrustManager
was set by the end user. I also found this Stackoverflow question:
https://stackoverflow.com/questions/51244136/tomcat-websocket-disable-hostname-verification,
which led me to this hardcoded parameter in WsWebSocketContainer:
https://github.com/apache/tomcat/blob/db0c10ea25cc8984f72d700ea48f32aadc2fe2f4/java/org/apache/tomcat/websocket/WsWebSocketContainer.java#L928
.

So, it seems to me that while you can disable *certificate* verification by
setting a custom TrustManager, you cannot disable *hostname* verification.
Is that correct, or am I missing some other option or parameter?

Thanks,
Zoe

Reply via email to