[ 
https://issues.apache.org/jira/browse/CAMEL-25649?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18127232#comment-18127232
 ] 

Claus Ibsen commented on CAMEL-25649:
-------------------------------------

Merged to main in https://github.com/apache/camel/pull/27820

_Claude Code on behalf of davsclaus_

> camel-netty - hostnameVerification never verifies: the SSLEngine is created 
> without a peer, so enabling it fails every handshake
> --------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25649
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25649
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-netty
>            Reporter: Andrea Cosentino
>            Assignee: Andrea Cosentino
>            Priority: Major
>             Fix For: 4.24.0
>
>
> h3. Summary
> {{camel-netty}}'s {{hostnameVerification}} option cannot verify anything. 
> When it is enabled the TLS handshake fails for *every* certificate, matching 
> or not, with:
> {noformat}
> javax.net.ssl.SSLHandshakeException: ... 
>   caused by java.security.cert.CertificateException: Hostname or IP address 
> is undefined.
> {noformat}
> So the option has never worked since it was added in CAMEL-16315 (3.7.4 / 
> 3.9.0). An operator who turns it on to secure a TLS producer gets a hard 
> connection failure and has no working way to opt in.
> h3. Cause
> {{DefaultClientInitializerFactory.configureClientSSLOnDemand()}} creates the 
> engine with the *no-arg* factory method and then asks for host name 
> verification:
> {code:java}
> SSLEngine engine = sslContext.createSSLEngine();          // no peer host, no 
> peer port
> engine.setUseClientMode(true);
> if (producer.getConfiguration().isHostnameVerification()) {
>     SSLParameters sslParams = engine.getSSLParameters();
>     sslParams.setEndpointIdentificationAlgorithm("HTTPS");
>     engine.setSSLParameters(sslParams);
> }
> {code}
> The JDK's identity check reads the host from the session rather than from the 
> connection: {{X509TrustManagerImpl.checkIdentity}} calls 
> {{SSLSession.getPeerHost()}} and hands the result to 
> {{HostnameChecker.match}}, whose first statement is
> {code:java}
> if (expectedName == null) {
>     throw new CertificateException("Hostname or IP address is undefined.");
> }
> {code}
> {{getPeerHost()}} is only populated when the engine is created with 
> {{createSSLEngine(host, port)}}. With the no-arg form it is {{null}}, so the 
> check cannot run and the handshake is aborted instead.
> h3. Reproduction
> A client/server {{SSLEngine}} pair driven in memory against a certificate 
> whose only SAN is {{DNS:localhost}}, on JDK 21.0.10:
> || client engine || peerHost || result ||
> | {{createSSLEngine()}} - what camel-netty does | {{null}} | 
> {{CertificateException: Hostname or IP address is undefined.}} |
> | {{createSSLEngine("localhost", 443)}} - what camel-netty-http does | 
> {{localhost}} | handshake completes |
> | {{createSSLEngine("other.example", 443)}} | {{other.example}} | 
> {{CertificateException: No subject alternative DNS name matching 
> other.example found.}} |
> The third row is the control: it shows verification really is active in the 
> second row rather than passing vacuously.
> h3. Why camel-netty-http is not affected
> CAMEL-14070 gave {{camel-netty-http}} SNI support in 4.x by creating its 
> client engine as {{createSSLEngine(uri.getHost(), uri.getPort())}}. When 
> CAMEL-20812 later copied the host name verification block into 
> {{HttpClientInitializerFactory}}, it landed on an engine that already carried 
> the peer, so there it works. The original in {{camel-netty}} never did - 
> which is also why CAMEL-20812's reporter described the {{camel-netty}} 
> implementation as the working one.
> h3. Proposed fix
> Create the client engine with the configured peer when verification is 
> enabled, as {{camel-netty-http}} does. Keeping the no-arg form when the 
> option is off confines the change to operators who opted in - and for them 
> the current behaviour is a hard failure, so there is no regression to cause. 
> Attaching the peer also makes the JDK send SNI, which is why it is better not 
> to do it on the default path.
> h3. Consumer side - separate question
> {{DefaultServerInitializerFactory}} applies the same block to the consumer's 
> engine, also created with the no-arg form:
> * With {{clientMode=true}} the consumer *is* a TCP client, so the same fix 
> applies.
> * In server mode, {{endpointIdentificationAlgorithm=HTTPS}} asks the JDK to 
> match the *client's* certificate against a host name the server does not 
> have. Whenever a client certificate is actually presented this fails the 
> handshake the same way; and matching a client certificate against the 
> client's address is not a meaningful control. The honest options are to not 
> apply the algorithm in server mode, or to document the option as client-side 
> only.
> Same block is in {{camel-netty-http}}'s {{HttpServerInitializerFactory}} and 
> {{HttpServerSharedInitializerFactory}}.
> This is a functional defect rather than an exposure: the broken state fails 
> closed, and the insecure default ({{hostnameVerification=false}}) is 
> pre-existing, documented, and already carries {{security = "insecure:ssl"}}.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to