Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Validating server certificates in Jetty HTTP Client 9.3.5.v20151012

On 15/04/16 09:57, Simone Bordet wrote:
> Hi,
> 
> On Thu, Apr 14, 2016 at 7:02 PM, Alaric Snell-Pym
> <alaric@xxxxxxxxxxxxxxxx> wrote:
>> Hi there!
>>
>> I'm writing some software that needs to connect to HTTPS servers. I'm
>> using Jetty HTTP client, and it works fine, except that I can't seem to
>> get it to validate the server's certificate.
> 
> Use:
> 
> SslContextFactory.setEndpointIdentificationAlgorithm("HTTPS");
> 
> Test case that shows this is:
> 
> https://github.com/eclipse/jetty.project/blob/jetty-9.3.8.v20160314/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java
> 

Ah-hah! Fantastic, thanks!

Hmmm... But that leads me to another problem.

For my application, I need to disallow connections to certain IP ranges.
I need to do this check with the actual IP that Jetty is about to
connect to; I can't just resolve the hostname and check all its IPs are
valid, then pass the URL on to Jetty, because the hostname->IP mappings
could be changed at that point by a sufficiently clever attacker.

My first attempt was to pass in my own HttpClientTransport to the
HttpClient constructor. I subclassed the default
HttpClientTransportOverHttp, overriding the
connect(InetSocketAddress,Map<String,Object>) method with one that
performed my IP address validation on the provided address, threw a
SecurityException if it was bad, and otherwise delegated to
super.connect(...).

However, connect() never seemed to actually be called, so my IP address
validation never happened.

What I ended up doing was, before passing the URL to the HTTP client,
parsing it, extracting the hostname, resolving it, validating the IP,
and then sticking that back into the URL as a string; and then
explicitly setting a Host: header with the original name, so the
resulting HTTP request came out just the same as if I'd had the hostname
in the URL.

However, of course, it turns out that the HTTPS
EndpointIdentificationAlgorithm looks at the URL rather than the Host:
header, so it complains about every HTTPS request I make, on the grounds
(quite rightly) that the certificate has no CN matching the IP address!

I think I have two options:

1) Find a place where I can intercept Jetty's InetSocketAddress before
it connects to it, that actually works.

2) Try and write my own EndpointIdentificationAlgorithm that is
identical to the HTTPS one, except that it looks at the hostname in the
Host: header (or provided by me explicitly to it, as I'll only use it
for that one request), rather than from the URL.

Could anybody please tell me if there's a better option, or give me some
pointers towards the above?

Thank you :-)

ABS

-- 
Alaric Snell-Pym
http://www.snell-pym.org.uk/alaric/

Attachment: signature.asc
Description: OpenPGP digital signature


Back to the top