Configuring Jetty HTTP/2 Client to use my HostnameVerifier implementation - java

I am using Jetty HTTP2 Client 9.4.12 to support HTTP/2 server connection. It's working fine but on top of verifying the certificate, I also want to verify the Hostname using my javax.net.ssl.HostnameVerifier implementation. According to the doc https://www.eclipse.org/jetty/javadoc/9.4.12.v20180830/org/eclipse/jetty/util/ssl/SslContextFactory.html I can use setEndpointIdentificationAlgorithm("HTTPS") to enable hostname verification but how do I configure Jetty to use my implementation?
Thanks.

Jetty's HttpClient does not support javax.net.ssl.HostnameVerifier.
An enhancement request exists for this ...
https://github.com/eclipse/jetty.project/issues/3154
Feel free to comment on the open enhancement requesting it, and providing an example of how you would use it.

The support has been added in Jetty v9.4.15.v20190215.
final SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setHostnameVerifier((hostname, sslSession) -> {
// logic to verify hostname
return false;
});

Related

Netty skips hostname validation when we use trust manager with trustCertCollectionFile

I am using io netty version 4.1.19.Final
I am trying to set up a client which will connect to a server using TLS.
I want the netty to perform hostname validation when it receives TLS certificates, but it looks like since I am using a custom trustManager using TLS Trust file path netty skips hostname validation completely.
Is there a way for me to specify a custom trustManager using TLS Trust file path AND have io netty perform hostname validation????
SslContextBuilder builder = SslContextBuilder.forClient();
File trustCertCollection = new File(conf.getTlsTrustCertsFilePath());
builder.trustManager(trustCertCollection);
Netty API:- https://netty.io/4.0/api/io/netty/handler/ssl/SslContextBuilder.html#trustManager-java.io.File-
Full code:-
https://github.com/apache/incubator-pulsar/blob/master/pulsar-client/src/main/java/org/apache/pulsar/client/impl/ConnectionPool.java#L97
Can you open a bug in the netty issue tracker and share some reproducer (best would a unit test)?

Which SSL version does Apache HttpClient 3 use and can it be changed?

If I try to connect to a https url with Apache Http client 3.1 like so..
HttpClient httpClient = new HttpClient()
HttpMethod method = new GetMethod("https://federation/galaxy-class/enterprise/getSheildFrequencies")
int responseCode = httpClient.executeMethod(method)
which SSL version does it use in the handshake?
If it is SSLv2, is there any way to tell it to use a later version or TLS?
At least Apache HTTP Client 4 uses the underlying JRE for SSL connections. So it's a matter of configuring the JRE (I would imagine the higher versions are enabled by default).
In an SSL handshake, the client presents it's highest supported version to the server by default. Then it's up to the server how high version it supports.
Try setting the "javax.net.debug" system property to value "ssl" so you can see the SSL handshake where the version is also displayed.

Consume Web service over ssl using XFire

My project use xfire as a web service client api. My project is in legacy Servlet/JSP. We used XFire eclipse plugin to generate client stub.
Web-service has Migrated to SLL (HTTPS). Is there any easy way to consume Webservice over SSL in XFire.
I found some code at http://docs.codehaus.org/display/XFIRE/HTTP+Transport.
I have some confusion there too. It motivates to use not-so-common-ssl which is in Alpha and I don't know if it is stable enough to be used in production.
// Technique similar to http://juliusdavies.ca/commons- ssl/TrustExample.java.html
HttpSecureProtocol protocolSocketFactory = new HttpSecureProtocol();
// "/thecertificate.cer" can be PEM or DER (raw ASN.1). Can even be several PEM certificates in one file.
TrustMaterial trustMaterial = new TrustMaterial(getClass().getResource("/thecertificate.cer"));
// We can use setTrustMaterial() instead of addTrustMaterial() if we want to remove
// HttpSecureProtocol's default trust of TrustMaterial.CACERTS.
protocolSocketFactory.addTrustMaterial(trustMaterial);
// Maybe we want to turn off CN validation (not recommended!):
protocolSocketFactory.setCheckHostname(false);
Protocol protocol = new Protocol("https", (ProtocolSocketFactory) protocolSocketFactory, 8443);
Protocol.registerProtocol("https", protocol);
Now above is a way to create a Protocol factory and getting it registered with Apache HTTPclient api. But id doesnot say what to do further with the generated stub.
Please feel free to ask more information if any.
We can't move to other web-service client api so that is not an option.
Managed to solve my own problem.
This is how I did it. XFire use Apache Http client internally so setting Security certifect detail on this Api will do the job. We will use no-yet-common-ssl.jar for this purpose.
First we will create org.apache.commons.ssl.TrustMaterial using commons and then set it in HttpSecureProtocol which is a child of javax.net.ssl.SSLSocketFactory.
Suppose XYZ.cer is the client certifect provided by service provider.
HttpSecureProtocol protocolSocketFactory = new HttpSecureProtocol();
protocolSocketFactory.addTrustMaterial(TrustMaterial.DEFAULT); //for trusting all the certifects in java trusted Store.
protocolSocketFactory.addTrustMaterial(new TrustMaterial(getClass().getResource("/XYZ.cer")));
Protocol protocol = new Protocol("https", (ProtocolSocketFactory)protocolSocketFactory, 443);
Protocol.registerProtocol("https", protocol);
If this is a web Application you can do this in ServletContextListener or in any part of code that executes when application boots.
Now you can use any ssl service using Xfire client stub. Any service which implement the above certifect.
Now why this work. Because XFire uses Apache Http Client as a connection api and we are telling Http client to use the above TrustManager when HTTPS is used.

Apache SocketFactory compatible with java.net SocketFactory?

I'm making a request using Apache's DefaultHttpClient and I need to override the SSL call so that I can attach a custom SSLSocketFactory (essentially a client cert) to it. To do this, I create a new custom scheme and connection manager and pass them over at httpClient creation:
...
new Scheme("https", 443, thirdPartySocketFactory);
...
DefaultHttpClient httpClient = new DefaultHttpClient(ccm);
...
The thirdPartySocketFactory passed at Scheme creation is the important part here. As the name suggests, it comes from a third party library that automatically handles mutual cert authentication with a JBoss server. I.e., it attaches a client cert + password to each outbound request.
The call itself is also made from a JBoss server (I'm actually hosting SOLR on it which is why the Apache call is necessary in the first place).
Problem is, the thirdPartySocketFactory object is of the type javax.net.SocketFactory, not org.apache.http.conn.scheme.SocketFactory which the Apache Scheme requires (see here).
Question: Is there any way to solve this nicely via some sort of wrapper? I thought the Apache SocketFactory would inherit from the javax.net one in some way but it doesn't look like it.
Alternatively, I can create a truely custom Apache SSLSocketFactory (see here), complete with truststore etc, but I really don't want to go down route until the other option is exhausted. Main reason being, the thirdPartySocketFactory method is tried and tested.
Thanks!
There is SSLSocketFactory#SSLSocketFactory(javax.net.ssl.SSLSocketFactory socketfactory, X509HostnameVerifier hostnameVerifier) since version 4.2. This constructor serves as a adapter for any arbitrary JSSE SSLSocketFactory implementation.

How can I configure HTTPClient to authenticate against a SOCKS proxy?

I need to set up proxy authentication against a SOCKS proxy.
I found out this post giving instructions that appear to work with common HTTP proxies.
httpclient.getHostConfiguration().setProxy("proxyserver.example.com", 8080);
HttpState state = new HttpState();
state.setProxyCredentials(new AuthScope("proxyserver.example.com", 8080),
new UsernamePasswordCredentials("username", "password"));
httpclient.setState(state);
Would that work with SOCKS proxies as well or do I have to do something different?
Java supports Socks proxy configuration via preferences:
socksProxyHost for the host name of the SOCKS proxy server
socksProxyPort for the port number, the default value being 1080
e.g.
java -DsocksProxyHost=socks.mydomain.com
(edit) For your example, if the socks proxy was configured in the way outlined before:
httpclient.getHostConfiguration().setProxy("proxyserver.example.com", 8080);
Credentials cred = new UsernamePasswordCredentials("username","password");
httpclient.getState().setProxyCredentials(AuthScope.ANY, cred);
You can also use this variant (without httpclient):
SocketAddress addr = new
InetSocketAddress("webcache.mydomain.com", 8080);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, addr); // Type.HTTP for HTTP
So completing the previous example, we can now add:
URL url = new URL("http://java.sun.com/");
URConnection conn = url.openConnection(proxy);
HTH
The Features page of Apache HTTPClient says:
Transparent connections through SOCKS proxies (version 4 & 5) using native Java socket support.
With "transparent", I guess they mean that it works without you needing to do anything special. Do you have a SOCKS proxy available somewhere? Can't you just try it out to see if it works?
SOCKS is not supported by HttpClient 3 natively. You can try the SOCKS support in JDK as suggested by others. The side effect is that your whole JVM will go through the same SOCKS proxy.
Java 5 supports Username/Password authentication in SOCKS (type 2). All you have to do is to setup the authenticator like this,
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
});
Again, this may not work for you because it affects all authentication in your JVM (HTTP auth, Proxy Auth).
You can provide a custom socket factory which implements the SOCKS protocol, and register it as your default HTTP protocol handler. This solution has a limitation similar to tuergeist's answer above has - it applies globally, to any HTTP connection you'll establish through HttpClient.
If you find this a problem, take a look at this correspondence, where Oleg suggests using HttpClient 4.0, but also refers to a possible patch in HostConfiguration class for HttpClient 3.x.
Another possible solution, which is my personal favorite, is to write a wrapper HTTP proxy to the socks proxy.
I tried
System.setProperty("socksProxyHost", "socks.xyz.com");
System.setProperty("socksProxyPort", "1000");
and it's working fine.

Categories

Resources