Unable to connect to TLS 1.2 using HTTPclient 3.1 - java

I have a running code that i am already using to connect to a server using SSL. The API i am using is commons-httpclient-3.1.jar and i cant not upgrade the jar.
The servers have upgraded to only use TSL 1.2.
Now my existing code is not working.
My current code is
HttpClient httpClient = new HttpClient();
PostMethod post = new PostMethod("https://XYZserver");
post.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_1);
File f = new File("C://sampleXml.xml");
RequestEntity entity = new FileRequestEntity(f, "Application/xml");
post.setRequestEntity(entity);
int statusCode = httpClient.executeMethod(post);
If i modify my code as per link How to force Commons HTTPClient 3.1 to use TLS 1.2 only for HTTPS? then my code is working fine.
I have few questions (As i was unable to find their answers?)
Why do we require a separate class CustomHttpsSocketFactory. Is it possible to modify existing code to use TLS
Is there any other way to do?

Related

GSS_S_CONTINUE_NEEDED with apache http client

I'm trying to setup up an http client to authenticate with spnego (apache http client 4.5.2)
Here's the code that setups the client
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
final CredentialsProvider credsProvider = new SystemDefaultCredentialsProvider();
credsProvider.setCredentials(new AuthScope(null, -1, null), new KerberosCredentials(null));
final HttpClientBuilder builder = HttpClientBuilder.create();
builder.setDefaultCredentialsProvider(credsProvider);
final ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(builder.build());
final Client client = new ResteasyClientBuilder().httpEngine(engine).build();
On the server, I have a JAX-RS service which is sitting behind a waffle.servlet.NegotiateSecurityFilter to allow for ntlm or spnego authentication.
When I send my HTTP request from my chrome rest client, it works, authentication is successfully completed using negotiate.
When I try and use the apache http client however, it fails with the message in the log:
2018-03-05 16:47:16,048 DEBUG o.a.h.impl.auth.GGSSchemeBase main Authentication already attempted
2018-03-05 16:47:16,048 DEBUG o.a.h.i.auth.HttpAuthenticator main Authentication failed
After some further investigation I've discovered that the waffle filter is encoutingering GSS_S_CONTINUE_NEEDED and responding with an additional challenge which the apache client is simply ignoring and giving up on.
I've tested my apache client setup against another service which uses spnego (provided by a 3rd party) and it works properly, although doesn't employ the continue token.
I'm not sure if my system is setup incorrectly, and that the continue token shouldn't be happeneing or if the apache http client is improperly configured (or doesn't support continue tokens at all)
There's a very old ticket here https://issues.apache.org/jira/browse/HTTPCLIENT-1107 indicating that something was added to handle additional challenges, but from reading the code in org.apache.http.impl.auth.GGSSchemeBase.parseChallenge(CharArrayBuffer, int, int) it looks as though only the first challange is ever accepted.

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.

HTTP/2 Response Header in Java

Is there already a way to get the HTTP/2 response header in Java? I've tried to search in some libraries like URLConnection, Undertow or even Jetty, but without success.
P.S.: I'm using JDK 1.7 on my Java Project.
Other thing, the response header of the HTTP/2 is like this?
GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>
Is there any website who use this version already?
My main goal is to know if a website use the HTTP/2 version or not, is there a way to know this without need to read the response header in a Java Project?
Thanks.
HTTP/2 websites typically use TLS, because browsers only support HTTP/2 over TLS.
The method you are trying to use is the HTTP/1.1 upgrade to HTTP/2 which very few sites - if any at all - support.
Your snippet of code represent a request, not a response.
If the upgrade is successful, the HTTP/2 server sends back a 101 response in HTTP/1.1 format and the response to the GET request in HTTP/2 format. This is specified in RFC 7540, section 3.2.
In order to achieve what you want, i.e. to know if a website supports HTTP/2, you have to try to connect using HTTP/2 + TLS. If the connection succeeds, you know HTTP/2 is supported. If it fails, it's not supported.
For Jetty (disclaimer, I'm the HTTP/2 module maintainer), you have to use JDK 8, and the code will look like this:
// Setup.
HTTP2Client http2Client = new HTTP2Client();
SslContextFactory sslContextFactory = new SslContextFactory();
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client), sslContextFactory);
httpClient.start();
// Does webtide.com support HTTP/2 ?
ContentResponse response = httpClient.GET("https://webtide.com/");
// No errors, yes it supports HTTP/2 !
If you get a response without errors, you are on HTTP/2, otherwise the server does not support HTTP/2.
Remember that for that code to work, you have to use JDK 8 and the proper ALPN boot jar in the bootclasspath, as specified here.

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.

Proxy setting for HttpClient 4 not working

I am using Apache HttpClient library to connect to url. The network in which i am doing has a secure proxy to it. when i am using the java.net package to connect to the url i just have to add the
System.setProperty("http.proxyHost", proxy);
System.setProperty("http.proxyPort", proxyPort);
no proxy userid and password is needed to be passed but when i am trying to connect through httpclient i am getting 407 proxy authentication error.My code is:
HttpHost proxy = new HttpHost("xyz.abc.com",8080,"http");
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,proxy);
Proxy is using NTML authentication.I don't want to pass userid and password.
I have upgraded to httpclient 4.2 and this version has out of box NTML support. Just need to add following lines to the code
HttpClient httpclient = new DefaultHttpClient();
NTCredentials creds = new NTCredentials("user", "pwd", "myworkstation", "microsoft.com");
httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
For further reading Httpclent authentication scheme u can refer http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html#d5e947
But my question is still open, why HttpClent is not picking the system proxy as simple java program does.
In order for the system properties to be picked up, you could use SystemDefaultHttpClient instead of DefaultHttpClient.
As of HttpClient 4.3, this class has been deprecated in favor of HttpClientBuilder:
HttpClient hc = new HttpClientBuilder().useSystemProperties().build();

Categories

Resources