nextgenhealthcare / connect

The swiss army knife of healthcare integration.
Other
926 stars 280 forks source link

[BUG] TLS Hostname verification with a variable in the URL #5506

Open elavy-harris opened 2 years ago

elavy-harris commented 2 years ago

Describe the bug Using the SSL Manager for a Destination, if

  1. the hostname for the URL is represented as a variable, e.g. ${Smile_CDR_Server_Address}, AND
  2. Hostname verification is enabled

then attempts to send a message fail.

ERROR MESSAGE: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <${Smile_CDR_Server_Address}> doesn't match any of the subject alternative names: [*.harris-chr.com, harris-chr.com]

To Reproduce

  1. Create an entry in the Configuration Map, e.g. hostname, populated with the hostname of a remote server that will accept TLS.
  2. Create a Destination with SSL Manager enabled and Hostname verification enabled.
  3. Specify the Remote Address (if using a TCP Sender) to ${hostname}
  4. Send any message.
  5. See error.

Expected behavior TLS handshake should succeed, assuming that the rest of TLS is configured properly.

Actual behavior Hostname verification fails.

Screenshots If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

Workaround(s) Turn off Hostname verification. This, however, reduces security.

elavy-harris commented 2 years ago

Example destination:

Mirth Issue 5506.zip

jonbartels commented 2 years ago

Lets rule out the simple things first - what is the literal URL for Smile_CDR_Server_Address?

ERROR MESSAGE: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <${Smile_CDR_Server_Address}> doesn't match any of the subject alternative names: [*.harris-chr.com, harris-chr.com] would happen if, for example, ${Smile_CDR_Server_Address} was https://elavy.harris-smile.com . In other words, it isn't a substitution issue, it's literally a hostname mismatch AFTER substituting the correct values.

It'll be a few hours but I'll try to reproduce the results with your example. If this is an issue, it will impact me also.

elavy-harris commented 1 year ago

The literal URL is smilecdrdev.harris-chr.com. If I put that in the destination explicitly, in place of the map reference, hostname verification works.

ChristopherSchultz commented 1 year ago

Do you have a full stack trace @elavy-harris ?

elavy-harris commented 1 year ago

Here's what shows up on the Error tab:

TCP Sender error
ERROR MESSAGE: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <${Smile_CDR_Server_Address}> doesn't match any of the subject alternative names: [*.harris-chr.com, harris-chr.com]
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <${Smile_CDR_Server_Address}> doesn't match any of the subject alternative names: [*.harris-chr.com, harris-chr.com]
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:353)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:296)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:291)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1357)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1232)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1175)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:183)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1506)
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1416)
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:456)
    at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:921)
    at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1291)
    at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
    at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
    at java.base/java.io.DataOutputStream.flush(DataOutputStream.java:123)
    at com.mirth.connect.model.transmission.framemode.FrameStreamHandler.write(FrameStreamHandler.java:265)
    at com.mirth.connect.model.transmission.framemode.FrameStreamHandler.writeFrame(FrameStreamHandler.java:246)
    at com.mirth.connect.model.transmission.framemode.FrameStreamHandler.write(FrameStreamHandler.java:242)
    at com.mirth.connect.connectors.tcp.TcpDispatcher.send(TcpDispatcher.java:523)
    at com.mirth.connect.connectors.tcp.TcpDispatcher.send(TcpDispatcher.java:457)
    at com.mirth.connect.donkey.server.channel.DestinationConnector.handleSend(DestinationConnector.java:904)
    at com.mirth.connect.donkey.server.channel.DestinationConnector.run(DestinationConnector.java:730)
    at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.security.cert.CertificateException: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <${Smile_CDR_Server_Address}> doesn't match any of the subject alternative names: [*.harris-chr.com, harris-chr.com]
    at com.mirth.connect.plugins.ssl.server.e.b(SourceFile:137)
    at com.mirth.connect.plugins.ssl.server.e.checkServerTrusted(SourceFile:92)
    at java.base/sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:1510)
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1341)
    ... 23 more
Caused by: javax.net.ssl.SSLPeerUnverifiedException: Certificate for <${Smile_CDR_Server_Address}> doesn't match any of the subject alternative names: [*.harris-chr.com, harris-chr.com]
    at org.apache.http.conn.ssl.DefaultHostnameVerifier.matchDNSName(DefaultHostnameVerifier.java:177)
    at org.apache.http.conn.ssl.DefaultHostnameVerifier.verify(DefaultHostnameVerifier.java:122)
    at com.mirth.connect.plugins.ssl.server.e.b(SourceFile:132)
    ... 26 more
elavy-harris commented 1 year ago

FYI, I upgraded to 4.2.0 before producing the stack trace above.

ChristopherSchultz commented 1 year ago

Thanks. I checked, and I don't see anywhere in Mirth where a hostname verifier is being created and handed an exact hostname, so it must be looking at the URL being contacted and/or the contents of the Host header being sent versus the CN/SAN of the server certificate.

Obviously, the effective hostname must be correct otherwise you'd be getting MalformedURLException or IOException/connection failure or whatever.

I'm (currently) at a loss as to why the connection would work but the hostname verifier would be convinced to use a non-token-replaced hostname for verification.

ChristopherSchultz commented 1 year ago

Are you sending a custom Host header in your HTTP request?

ChristopherSchultz commented 1 year ago

Oh. I'm also only viewing the source of the community edition. It's entirely possible that the SSL Manager Plug-in does things differently.

I would file a support case with NextGen as this is a paid-for plug-in.

mcswaip1 commented 1 year ago

I am also running into this issue. We are using the SSL Manager Extension. Running Mirth 4.4.0. Is there any update on this issue?

JackieK5 commented 11 months ago

@mcswaip1 This item is currently on the bubble for 4.5.0. At this point it looks about 50/50 if it will make it or not. 4.5 is tentatively scheduled for the end of January.