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)