Andrea Cosentino created CAMEL-25674:
----------------------------------------

             Summary: camel-netty-http - hostnameVerification is applied to the 
server engine, where the JDK rejects it
                 Key: CAMEL-25674
                 URL: https://issues.apache.org/jira/browse/CAMEL-25674
             Project: Camel
          Issue Type: Bug
          Components: camel-netty-http
            Reporter: Andrea Cosentino


h3. Summary

{{HttpServerInitializerFactory}} sets {{endpointIdentificationAlgorithm=HTTPS}} 
on the *server* engine when {{hostnameVerification=true}}:

{code:java}
SSLEngine engine = sslContext.createSSLEngine();
engine.setUseClientMode(false);
if (consumer.getConfiguration().isNeedClientAuth()) {
    engine.setNeedClientAuth(true);
}
if (consumer.getConfiguration().isHostnameVerification()) {
    SSLParameters sslParams = engine.getSSLParameters();
    sslParams.setEndpointIdentificationAlgorithm("HTTPS");
    engine.setSSLParameters(sslParams);
}
{code}

The JDK does not support host name verification on that side of a handshake. 
When it checks a *client* certificate, {{X509TrustManagerImpl.checkIdentity}} 
skips the SNI name and uses {{SSLSession.getPeerHost()}}, which is {{null}} on 
a server engine; it then catches the resulting failure and replaces it with

{noformat}
java.security.cert.CertificateException: Endpoint Identification Algorithm 
HTTPS is not supported on the server side
{noformat}

So on a netty-http consumer with {{hostnameVerification=true}}, every handshake 
in which the client presents a certificate fails - and when the client presents 
none, nothing is checked. The line has never verified anything in server mode.

Verified on JDK 21.0.10, driving a client/server {{SSLEngine}} pair in memory:

|| server engine || result ||
| {{EIA=HTTPS}} + {{needClientAuth}} | {{Endpoint Identification Algorithm 
HTTPS is not supported on the server side}} |
| {{EIA=HTTPS}}, no client auth | handshake completes, nothing checked |
| no {{EIA}} + {{needClientAuth}} | handshake completes |

h3. The option also behaves differently depending on server sharing

{{HttpServerSharedInitializerFactory}}, used when consumers share a Netty 
server, creates its engine the same way but never looks at 
{{hostnameVerification}} at all. So the option is inert there and breaks mTLS 
in the non-shared factory - the same endpoint option, two different behaviours, 
neither of them verification.

h3. Proposed fix

Do what CAMEL-25649 did for {{camel-netty}}: do not set the algorithm in server 
mode, and document the option as applying to client connections. Removing it 
relaxes no check, because there was never a check - it only stops mTLS from 
failing when the option is set on a consumer.

Whether {{HttpServerSharedInitializerFactory}} should gain anything is a 
separate question; today its silence is the correct behaviour, it is just 
undocumented and inconsistent with its sibling.

h3. Context

CAMEL-25649 fixed the equivalent in {{camel-netty}} (PR #27820, merged for 
4.24.0): the client engine now carries the peer so verification works, and 
{{DefaultServerInitializerFactory}} only sets the algorithm when 
{{clientMode=true}}. That PR deliberately left the two netty-http server 
factories alone so it stayed a clean backport, and [~davsclaus] asked on review 
for them to be a separate issue - this is it.

Correction to what that PR's description said: it claimed both netty-http 
server factories carry the block. Only {{HttpServerInitializerFactory}} does; 
{{HttpServerSharedInitializerFactory}} does not set the algorithm at all.

Filed unassigned.



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

Reply via email to