useRelaxedHTTPSValidation does not seem to work with Java 6 (JDK)

1,523 views
Skip to first unread message

Apoorva Sharma

unread,
May 25, 2015, 8:16:35 AM5/25/15
to rest-a...@googlegroups.com
I have a REST API test suite that uses Rest Assured 2.4.0. Login to the application is using a POST call. I am working around the cert validation by using RestAssured.useRelaxedHTTPSValidation() 
statically for all requests. The tests run just fine with JDK 1.7.0_79 but are failing with SocketException errors when running with JDK 1.6.0_43. (on Windows 7)

Here is how I login and get Authorization Header which are needed for all requests

    public static RequestSpecification userWithAuthHeader() throws IOException {
        testData = readTestDataFile();
        RestAssured.baseURI = testData.getString("environment.URI");
        RestAssured.basePath = testData.getString("environment.Path");
        RestAssured.config.getHttpClientConfig().reuseHttpClientInstance();
        RestAssured.useRelaxedHTTPSValidation();
        String user =  testData.getString("user.username");
        String password = testData.getString("user.password");
        String domain = testData.getString("user.domain");
        String acceptHeader = testData.getString("acceptHeader");
        String auth= post("/system/login?domain=" + domain + "&user=" + user + "&pw=" + password).getHeader("Authorization");
        RequestSpecification requestSpec = with().log().all().headers("Authorization", auth, "Accept", acceptHeader);
        return requestSpec;
}
	
The post method above fails when running it on Windows 7 with JDK 6  with the following errors:

    Running com.org.group.preCheckInSPTests.getAppliancesTest
    Configuring TestNG with: TestNG652Configurator
    May 24, 2015 7:54:26 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect
    INFO: I/O exception (java.net.SocketException) caught when connecting to {s}->https://<IP_ADDRESS>
    Connection reset
    May 24, 2015 7:54:26 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect
    INFO: Retrying connect to {s}->https://<IP_ADDRESS>
    May 24, 2015 7:54:26 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect
    INFO: I/O exception (java.net.SocketException) caught when connecting to {s}->https://<IP_ADDRESS>
    Connection reset
    May 24, 2015 7:54:26 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect
    INFO: Retrying connect to {s}->https://<IP_ADDRESS>
    May 24, 2015 7:54:26 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect
    INFO: I/O exception (java.net.SocketException) caught when connecting to {s}->https://<IP_ADDRESS>
    Connection reset
    May 24, 2015 7:54:26 AM org.apache.http.impl.client.DefaultRequestDirector tryConnect
    INFO: Retrying connect to {s}->https://<IP_ADDRESS>
    Tests run: 4, Failures: 1, Errors: 0, Skipped: 3, Time elapsed: 6.116 sec <<< FAILURE! - in com.org.group.preCheckInSPTests.getAppliancesTest
    loginAsUser(com.org.group.preCheckIn.getAppliancesTest)  Time elapsed: 5.846 sec  <<< FAILURE!
    java.net.SocketException: Connection reset
            at java.net.SocketInputStream.read(SocketInputStream.java:168)
            at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:422)
            at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:460)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:863)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1188)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1215)
            at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1199)
            at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:535)
            at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:403)
            at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
            at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:304)
            at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611)
            at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:446)
            at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
            at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
            at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
            at org.apache.http.client.HttpClient$execute$0.call(Unknown Source)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
            at com.jayway.restassured.internal.RequestSpecificationImpl$RestAssuredHttpBuilder.doRequest(RequestSpecificationImpl.groovy:1764)
            at com.jayway.restassured.internal.http.HTTPBuilder.post(HTTPBuilder.java:333)
            at com.jayway.restassured.internal.http.HTTPBuilder$post$2.call(Unknown Source)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
            at com.jayway.restassured.internal.RequestSpecificationImpl.sendRequest(RequestSpecificationImpl.groovy:1067)
            at com.jayway.restassured.internal.RequestSpecificationImpl.this$2$sendRequest(RequestSpecificationImpl.groovy)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:597)
            at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
            at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1207)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:807)
            at com.jayway.restassured.internal.RequestSpecificationImpl.invokeMethod(RequestSpecificationImpl.groovy)
            at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.call(PogoInterceptableSite.java:45)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:128)
            at com.jayway.restassured.internal.filter.SendRequestFilter.filter(SendRequestFilter.groovy:31)
            at com.jayway.restassured.filter.Filter$filter.call(Unknown Source)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
            at com.jayway.restassured.internal.filter.FilterContextImpl.next(FilterContextImpl.groovy:49)
            at com.jayway.restassured.filter.FilterContext$next.call(Unknown Source)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
            at com.jayway.restassured.internal.RequestSpecificationImpl.invokeFilterChain(RequestSpecificationImpl.groovy:956)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:597)
            at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
            at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1207)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:807)
            at com.jayway.restassured.internal.RequestSpecificationImpl.invokeMethod(RequestSpecificationImpl.groovy)
            at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.call(PogoInterceptableSite.java:45)
            at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.callCurrent(PogoInterceptableSite.java:55)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
            at com.jayway.restassured.internal.RequestSpecificationImpl.applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy:1414)
            at com.jayway.restassured.internal.RequestSpecificationImpl.this$2$applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
            at java.lang.reflect.Method.invoke(Method.java:597)
            at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
            at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1207)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
            at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:807)
            at com.jayway.restassured.internal.RequestSpecificationImpl.invokeMethod(RequestSpecificationImpl.groovy)
            at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.call(PogoInterceptableSite.java:45)
            at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.callCurrent(PogoInterceptableSite.java:55)
            at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
            at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149) 
    		at com.jayway.restassured.internal.RequestSpecificationImpl.post(RequestSpecificationImpl.groovy:154) 
    		at com.jayway.restassured.internal.RequestSpecificationImpl.post(RequestSpecificationImpl.groovy) 
    		at com.jayway.restassured.RestAssured.post(RestAssured.java:832)

Link to question on stackoverflow: http://stackoverflow.com/questions/30423660/rest-assured-userelaxedhttpsvalidation-and-java-6-issues

Johan Haleby

unread,
May 25, 2015, 8:20:27 AM5/25/15
to rest-a...@googlegroups.com
Hi, 

I didn't know this and I don't know what could be the cause of it off the top of my head. Unfortunately I don't have time to investigate it right now and it's a pretty marginal case so I probably won't prioritize it. However if you find out what's wrong and perhaps find a solution I would be very happy to accept a pull request.

/Johan

--
You received this message because you are subscribed to the Google Groups "REST assured" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rest-assured...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Apoorva Sharma

unread,
May 26, 2015, 5:59:13 PM5/26/15
to rest-a...@googlegroups.com
So.. while I was able to find out the root cause. I am not sure I have been able to think of a good way to work around this. 


Is there a way to specify to -Dhttps.protocols="TLSv1" to the http client that RestAssured uses ? I tried specifying it as a JVM parameter but that does not seem to be doing the trick. 

Apoorva Sharma

unread,
May 26, 2015, 6:19:15 PM5/26/15
to rest-a...@googlegroups.com
I think the parameter is enabledProtocols on SSLSocketFactory of the httpclient.

Johan Haleby

unread,
May 27, 2015, 2:13:43 AM5/27/15
to rest-a...@googlegroups.com
Thanks for investigating. You can pass in "TLSv1" as an argument to useRelaxedHTTPSValidation. For example RestAssured.useRelaxedHTTPSValidation("TLSv1"). Please try if that makes any difference.

Apoorva Sharma

unread,
May 27, 2015, 7:07:15 AM5/27/15
to rest-a...@googlegroups.com
Does not make a difference. 
Oddly enough the value does not get overridden even if I pass the value as a System Variable like this : -Dhttps.protocols=TLSv1. 

Any thoughts ?

Apoorva Sharma

unread,
May 27, 2015, 7:32:16 AM5/27/15
to rest-a...@googlegroups.com
I don't think that setting the value as an argument to useRelaxedHTTPSValidation will make a difference. 

This is because Java 6 uses SSLv2Hello to make an initial connection (or handshake). The value enabledProtocols = [SSLv2Hello, SSLv3, TLSv1] are set (by default) when the SocketFactory creates a socket. SSLv2Hello needs to be disabled explicitly on the clients.
final SSLSocket sock = (SSLSocket) this.socketfactory.createSocket(); (Line 505, SSLSocketFactory.java)

Johan Haleby

unread,
May 27, 2015, 2:15:01 PM5/27/15
to rest-a...@googlegroups.com
Perhaps you could supply a custom SSLSocketFactory? You do that by creating a SSLConfig:

given().config(RestAssured.config().sslConfig(sslConfig().sslSocketFactory(myCustomSSLSocketFactory)). ..

/Johan

Apoorva Sharma

unread,
May 28, 2015, 12:57:34 PM5/28/15
to rest-a...@googlegroups.com
I could give that a try. Let me know your thoughts on doing something like this within REST Assured library. It could save some other people the trouble of uncovering the real issue and then implementing a solution for the problem

import java.io.IOException;
import java.net.Socket;
 
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.params.HttpParams;
 
/**
* An {@link SSLSocketFactory} supporting only SSLv3 and TLSv1 sockets.
*
* @author jdolan
*
*/
public class Sslv3SocketFactory extends SSLSocketFactory {
 
private final Log log = LogFactory.getLog(getClass());
/**
* Instantaites a new {@link Sslv3SocketFactory}.
*
* @param sslContext
* The SSLContext.
*
* @param hostnameVerifier
* The X509HostnameVerifier.
*/
public Sslv3SocketFactory(SSLContext sslContext, X509HostnameVerifier hostnameVerifier) {
super(sslContext, hostnameVerifier);
}
 
@Override
public Socket createSocket(HttpParams params) throws IOException {
 
if (log.isDebugEnabled()) {
log.debug("createSocket: " + params);
}
 
SSLSocket socket = (SSLSocket) super.createSocket(params);
 
socket.setEnabledProtocols(new String[] { "SSLv3", "TLSv1" });
 
return socket;
}

AND a new method in SSLConfig.java
    public SSLConfig relaxedHTTPSValidationWithSSLv3(String protocol) {
        notNull(protocol, "Protocol");
        SSLContext sslContext;
        try {
            sslContext = SSLContext.getInstance(protocol);
        } catch (NoSuchAlgorithmException e) {
            return SafeExceptionRethrower.safeRethrow(e);
        }

        // Set up a TrustManager that trusts everything
        try {
            sslContext.init(null, new TrustManager[]{new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }}, new SecureRandom());
        } catch (KeyManagementException e) {
            return SafeExceptionRethrower.safeRethrow(e);
        }

        Sslv3SocketFactory sf = new Sslv3SocketFactory(sslContext, ALLOW_ALL_HOSTNAME_VERIFIER);
        return sslSocketFactory(sf);
    }

Johan Haleby

unread,
May 28, 2015, 1:17:31 PM5/28/15
to rest-a...@googlegroups.com
Thanks for sharing the code. I'm a bit reluctant to add it to the API though since it seems to me to be quite a marginal issue and (I hope) there's a workaround (to supply your own SSLSocketFactory). I need to sleep on it.

Apoorva Sharma

unread,
May 28, 2015, 2:19:54 PM5/28/15
to rest-a...@googlegroups.com
I understand your dilemma ..but the workaround is not just passing a mycustomSSLSocketFactory. One needs to re-implement the relaxedHTTPSValidation(String protocol) method in SSLConfig because of this declaration inside it : 
SSLSocketFactory sf = new SSLSocketFactory(sslContext, ALLOW_ALL_HOSTNAME_VERIFIER)

- with the new SSLv3SocketFactory. 

My two cents - It might be worth while adding because 1) It takes an enormous amount of time to debug the issue if one encounters it ..and 2) While I agree that Java 6 is unheard of in the web application world actively used and supported on the infrastructure side (virtualization, servers, data centers, etc.)...

And, I realize that you reserve right to make the final call .. :)

Johan Haleby

unread,
May 28, 2015, 2:43:52 PM5/28/15
to rest-a...@googlegroups.com
I just wonder if we could generalize it a bit more. Perhaps SSLSocketFactory sf = new SSLSocketFactory(sslContext, ALLOW_ALL_HOSTNAME_VERIFIER); in relaxedHTTPSValidation is wrong? If you've set a SSLSocketFactory explicitly perhaps that should be used instead?

Apoorva Sharma

unread,
May 29, 2015, 7:29:47 AM5/29/15
to rest-a...@googlegroups.com
I agree.. that seems like a reasonable approach. 

Johan Haleby

unread,
May 29, 2015, 8:05:48 AM5/29/15
to rest-a...@googlegroups.com
Hmm but should you be able to do this today already? I mean all that relaxedHTTPSValidation is doing today is setting a SSLSocketFactory. You should be able to roll your own and NOT call relaxedHTTPSValidation afterwards (since then it'll be overwritten).

Apoorva Sharma

unread,
May 29, 2015, 8:29:22 AM5/29/15
to rest-a...@googlegroups.com
Partly true. So I started using relaxedHTTPSValidation because in my development and test environments we do not setup real certs. Now, the tests run just fine on Java 7 but do not run at all on Java 6. 
In order to make the tests run on Java 6, I am setting up a new SSLv3SocketFactory, creating a fake trust manager, passing it a new sslcontext and then pass it to the RestAssured.config - that is pretty much re-doing everything inside relaxedHTTPSValidation.

In essence - relaxedHTTPSValidation will not work with Java 6 ..and then one has to re-implement the same thing. Was I able to give you a better picture ? 

Johan Haleby

unread,
Jun 1, 2015, 5:58:18 AM6/1/15
to rest-a...@googlegroups.com
What about adding something like a "functional interface" that takes an SSLContext and returns a SSLSocketFactory? I.e. relaxedHTTPSValidation(sslContext -> new MyCustomSSLSocketFactory(sslContext)). This is of course Java 8 syntax and using Java 6 will be more verbose.
Reply all
Reply to author
Forward
0 new messages