okHttpClient proxy connection gives unexpected end of stream exception - java

I am trying to make a proxy connection using okHttpClient. Target connection requires basic authentication that I am doing using Authenticator. Proxy requires a header to connect to the target URL. I am passing this header in the authenticator header.
Below is the code that I am trying but it gives unexpected end of stream exception.
#Configuration
public class FeignClientConfig {
#Value("localhost")
private String proxyHost;
#Value("8443")
private int proxyPort;
#Value("root")
private String user;
#Value("abcd")
private String password;
#Bean
public Client feignClientConfig() throws NoSuchAlgorithmException, KeyManagementException {
OkHttpClient okHttpClient;
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
TrustManager[] trustAllCerts = getTrustManagers();
// SSLContext sslContext = SSLContext.getInstance("SSL");
// sslContext.init(null, trustAllCerts, new SecureRandom());
// SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = (hostname, session) -> true;
okHttpClient = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.sslSocketFactory(Objects.requireNonNull(getSSLSocketFactory()), (X509ExtendedTrustManager) trustAllCerts[0])
.hostnameVerifier(allHostsValid)
.proxy(proxy)
.proxyAuthenticator(authenticator())
.build();
return new feign.okhttp.OkHttpClient(okHttpClient);
}
private okhttp3.Authenticator authenticator() {
return (route, response) -> {
String credential = okhttp3.Credentials.basic(user, password);
return response.request().newBuilder()
.header("Authorization", credential)
.header("Content-Type", "application/json")
//this header is required by proxy not the target connection
.header("X-Connect-Client-Id", "xyz")
.build();
};
}
private SSLSocketFactory getSSLSocketFactory() {
try {
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
#Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
};
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
return sslContext.getSocketFactory();
}
catch (Exception exception) {
log.error("Error while getting SSLSocketFactory: "+exception.getMessage());
}
return null;
}
private TrustManager[] getTrustManagers() {
return new TrustManager[]{
new X509ExtendedTrustManager() {
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
#Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
#Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
#Override
public void checkServerTrusted(X509Certificate[] xcs, String string, Socket socket) throws CertificateException {
}
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException {
}
#Override
public void checkClientTrusted(X509Certificate[] xcs, String string, SSLEngine ssle) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] xcs, String string, SSLEngine ssle) throws CertificateException {
}
}
};
}
}

Related

How do I use an SSL client certificate with jersey client in java

I am trying to connect server using https url But still could not understand how should I add SSL certificate to jersey client
private static String post() throws Exception {
String url ="https://www.test.lk/services/erl/es/erl/view/index.action";
Client client =createClient();
try {
return client
.target(url)
.request()
.get()
.readEntity(String.class);
} finally {
client.close();
}
}
private static Client createClient() throws Exception {
SSLContext ctx = SSLContext.getInstance("SL");
ctx.init(null, getTrustManager(), new SecureRandom());
HostnameVerifier verifier = new HostnameVerifier() {
#Override
public boolean verify(String hostName, SSLSession sslSession) {
return true;
}
};
return ClientBuilder.newBuilder().sslContext(ctx).hostnameVerifier(verifier).build();
}
private static TrustManager[] getTrustManager() {
return new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// Trust all servers
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// Trust all clients
}
} };
}
I found the solution. I just need to add certificate to the java KeyStore This helped me

Apache HttpClient Error: javax.net.ssl.SSLPeerUnverifiedException: Peer Not Authenticated

I'm trying to configure org.apache.http.client.HttpClient to work with https. This is the client configuration:
TrustManager[] trustManagers = new TrustManager[] { new DummyTrustManager() };
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
SSLSocketFactory sf = new SSLSocketFactory(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme scheme = new Scheme("https", 443, sf);
SchemeRegistry registry = new SchemeRegistry();
registry.register(scheme);
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(registry);
DefaultHttpClient client = new DefaultHttpClient(cm, httpParameters);
This is the code of DummyTrustManager:
public static class DummyTrustManager implements X509TrustManager {
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
And when I send request, I get
`javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated`
What could be the problem?
You also need to adjust the TrustStrategy:
TrustStrategy acceptingTrustStrategy = new TrustStrategy() {
#Override
public boolean isTrusted(X509Certificate[] certificate, String authType) {
return true;
}
};
SSLSocketFactory sf = new SSLSocketFactory(acceptingTrustStrategy, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
...
see a full example at: http://www.baeldung.com/httpclient-ssl

an unsafe implementation of the interface X509TrustManager from google

I hava an app in Google Play, I received a mail from Google saying that:
Your app(s) listed at the end of this email use an unsafe implementation of the interface X509TrustManager. Specifically, the implementation ignores all SSL certificate validation errors when establishing an HTTPS connection to a remote host, thereby making your app vulnerable to man-in-the-middle attacks.
To properly handle SSL certificate validation, change your code in the checkServerTrusted method of your custom X509TrustManager interface to raise either CertificateException or IllegalArgumentException whenever the certificate presented by the server does not meet your expectations.
My app uses "https", my checkServerTrusted() is the following:
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
Then I modify this function:
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
if (chain == null) {
throw new IllegalArgumentException("checkServerTrusted: X509Certificate array is null");
}
if (!(chain.length > 0)) {
throw new IllegalArgumentException("checkServerTrusted: X509Certificate is empty");
}
if (!(null != authType && authType.equalsIgnoreCase("RSA"))) {
throw new CertificateException("checkServerTrusted: AuthType is not RSA");
}
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
the custom SSLSocketFactory:
public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");
public MySSLSocketFactory(KeyStore ctx) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(ctx);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[]{tm}, null);
}
#Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
#Override
public Socket createSocket() throws IOException {
return sslContext.getSocketFactory().createSocket();
}
}
the HttpClient function:
private static HttpClient getHttpClient(int timeout) {
if (null == mHttpClient) {
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
trustStore.load(null, null);
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params,
HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);
ConnManagerParams.setTimeout(params, timeout);
HttpConnectionParams.setConnectionTimeout(params, timeout);
HttpConnectionParams.setSoTimeout(params, timeout);
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
schReg.register(new Scheme("https", sf, 443));
ClientConnectionManager conManager = new ThreadSafeClientConnManager(
params, schReg);
mHttpClient = new DefaultHttpClient(conManager, params);
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient();
}
}
return mHttpClient;
}
But I do not know well about this,I just modify my code by what the email said,I think I have not sloved this problem.What is this warning all about? How to solve it?
I found this solution ,it works well!
X509TrustManager:
public class EasyX509TrustManager
implements X509TrustManager {
private X509TrustManager standardTrustManager = null;
/**
* Constructor for EasyX509TrustManager.
*/
public EasyX509TrustManager(KeyStore keystore)
throws NoSuchAlgorithmException, KeyStoreException {
super();
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init(keystore);
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0) {
throw new NoSuchAlgorithmException("no trust manager found");
}
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}
/**
* #see X509TrustManager#checkClientTrusted(X509Certificate[], String authType)
*/
public void checkClientTrusted(X509Certificate[] certificates, String authType)
throws CertificateException {
standardTrustManager.checkClientTrusted(certificates, authType);
}
/**
* #see X509TrustManager#checkServerTrusted(X509Certificate[], String authType)
*/
public void checkServerTrusted(X509Certificate[] certificates, String authType)
throws CertificateException {
if ((certificates != null) && (certificates.length == 1)) {
certificates[0].checkValidity();
} else {
standardTrustManager.checkServerTrusted(certificates, authType);
}
}
/**
* #see X509TrustManager#getAcceptedIssuers()
*/
public X509Certificate[] getAcceptedIssuers() {
return this.standardTrustManager.getAcceptedIssuers();
}
}
SSLSocketFactory:
public class EasySSLSocketFactory implements LayeredSocketFactory {
private SSLContext sslcontext = null;
private static SSLContext createEasySSLContext() throws IOException {
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[]{new EasyX509TrustManager(
null)}, null);
return context;
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
private SSLContext getSSLContext() throws IOException {
if (this.sslcontext == null) {
this.sslcontext = createEasySSLContext();
}
return this.sslcontext;
}
/**
* #see org.apache.http.conn.scheme.SocketFactory#connectSocket(Socket,
* String, int, InetAddress, int,
* HttpParams)
*/
public Socket connectSocket(Socket sock, String host, int port,
InetAddress localAddress, int localPort, HttpParams params)
throws IOException, UnknownHostException, ConnectTimeoutException {
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
int soTimeout = HttpConnectionParams.getSoTimeout(params);
InetSocketAddress remoteAddress = new InetSocketAddress(host, port);
SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket());
if ((localAddress != null) || (localPort > 0)) {
// we need to bind explicitly
if (localPort < 0) {
localPort = 0; // indicates "any"
}
InetSocketAddress isa = new InetSocketAddress(localAddress,
localPort);
sslsock.bind(isa);
}
sslsock.connect(remoteAddress, connTimeout);
sslsock.setSoTimeout(soTimeout);
return sslsock;
}
/**
* #see org.apache.http.conn.scheme.SocketFactory#createSocket()
*/
public Socket createSocket() throws IOException {
return getSSLContext().getSocketFactory().createSocket();
}
/**
* #see org.apache.http.conn.scheme.SocketFactory#isSecure(Socket)
*/
public boolean isSecure(Socket socket) throws IllegalArgumentException {
return true;
}
/**
* #see LayeredSocketFactory#createSocket(Socket,
* String, int, boolean)
*/
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}
// -------------------------------------------------------------------
// javadoc in org.apache.http.conn.scheme.SocketFactory says :
// Both Object.equals() and Object.hashCode() must be overridden
// for the correct operation of some connection managers
// -------------------------------------------------------------------
public boolean equals(Object obj) {
return ((obj != null) && obj.getClass().equals(
EasySSLSocketFactory.class));
}
public int hashCode() {
return EasySSLSocketFactory.class.hashCode();
}
}
Then:
SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
schReg.register(new Scheme("https", new EasySSLSocketFactory(), 443));
Your proposed modifications do not fix the security vulnerability. Your code will still accept any correctly formatted certificate, regardless of validity.
If you aren't sure how to properly verify certificates, you should just remove the custom trust manager. You don't need one unless you are doing something unusual.
The simplest way, is by not providing own custom TrustManager. Just use default TrustManager and it will do public key(X.509) validation and verification for you.
Make use of the default X509trustmanager's method only which are checkServerTrusted(chain, authType) and they will take care of all validation appropriately.

How to property call SSL(https) url in Java?

It is spring based web app, using below method to accept all SSL certificates. This method works and I get results back,but it does not seems great. Please suggest. The endpoint( url) SSL has a verisign certificate)
private void prepareHttpsConnnection() throws NoSuchAlgorithmException,
KeyManagementException {
System.setProperty("https.proxyHost", proxyHost);
System.setProperty("https.proxyPort", proxyPort);
System.setProperty("jsse.enableSNIExtension", enableSNIExte`enter code here`nsion);
SSLContext sslContext;
sslContext = SSLContext.getInstance("SSL");
// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
// System.out.println("getAcceptedIssuers =============");
return null;
}
public void checkClientTrusted(X509Certificate[] certs,
String authType) {
// System.out.println("checkClientTrusted =============");
}
public void checkServerTrusted(X509Certificate[] certs,
String authType) {
// System.out.println("checkServerTrusted =============");
}
} }, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext
.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
}

Get server certificate from failed connection attempt with HttpClient 4.2

I'm currently adding a https download functionality to my application using the Apache HttpClient, specifically version 4.2.3.
I want to get my hands on the server certificate chain if the certificate validation fails. The exception that gets thrown SSLPeerUnverifiedException has no fields that provide any information.
try {
HttpResponse response = client.execute(get);
} catch (SSLPeerUnverifiedException e) {
// retrieve server certificate here
}
There is a way by injecting a TrustManager (to capture the certificates) into the SSLContext and recreating the SSLContext, SSLSocketFactory and HttpClient for each request. But, I would like to be able to reuse those instances for multiple, possible parallel, requests.
I used HC 4.3 for this example but should work exactly the same way with HC 4.2 though I would recommend upgrading
public static void main(final String[] args) throws Exception {
TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmfactory.init((KeyStore) null);
TrustManager[] tms = tmfactory.getTrustManagers();
if (tms != null) {
for (int i = 0; i < tms.length; i++) {
final TrustManager tm = tms[i];
if (tm instanceof X509TrustManager) {
tms[i] = new TrustManagerDelegate((X509TrustManager) tm);
}
}
}
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tms, null);
CloseableHttpClient httpClient = HttpClients.custom()
.setSslcontext(sslContext)
.build();
try {
CloseableHttpResponse response = httpClient.execute(new HttpGet("https://google.com/"));
try {
// do something usefull
} finally {
response.close();
}
} catch (SSLException ex) {
Throwable cause = ex.getCause();
if (cause instanceof MyCertificateException) {
X509Certificate[] chain = ((MyCertificateException) cause).getChain();
for (X509Certificate cert: chain) {
System.out.println(cert);
}
}
}
}
static class TrustManagerDelegate implements X509TrustManager {
private final X509TrustManager trustManager;
TrustManagerDelegate(final X509TrustManager trustManager) {
super();
this.trustManager = trustManager;
}
#Override
public void checkClientTrusted(
final X509Certificate[] chain, final String authType) throws CertificateException {
this.trustManager.checkClientTrusted(chain, authType);
}
#Override
public void checkServerTrusted(
final X509Certificate[] chain, final String authType) throws CertificateException {
try {
this.trustManager.checkServerTrusted(chain, authType);
} catch (CertificateException ex) {
throw new MyCertificateException(chain, ex);
}
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return this.trustManager.getAcceptedIssuers();
}
}
static class MyCertificateException extends CertificateException {
private final X509Certificate[] chain;
MyCertificateException(final X509Certificate[] chain, final CertificateException ex) {
super(ex);
this.chain = chain;
}
public X509Certificate[] getChain() {
return chain;
}
}

Categories

Resources