Sunday, July 16, 2017

Need help in identifying and fixing SSLPeerUnverifiedException

Leave a Comment

I am trying to do a post to TLS server for both default and custom keystores. After obtaining CloseableHttpClient instance when I do an execute

CloseableHttpResponse response1 = client.execute(postMethod); 

This is giving me javax.net.ssl.SSLPeerUnverifiedException: Certificate for <hostname.domain.com> doesn't match any of the subject alternative names: [] exception on above line.

Below is a class where I prepare client instance

public class ClientelUtil {      public static CloseableHttpClient getHttpClient(String scheme,SSLContext sslContext) {         HttpClientBuilder clientBuilder = HttpClients.custom();         CloseableHttpClient client = null;         if ("https".equalsIgnoreCase(scheme)) {             SSLConnectionSocketFactory sFactory = new SSLConnectionSocketFactory(sslContext);             final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()                     .register("http", new PlainConnectionSocketFactory()).register("https", sFactory).build();              final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);              clientBuilder = HttpClients.custom().setSSLSocketFactory(sFactory)                     .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)                     .setConnectionManager(cm);         }         client = clientBuilder.build();         return client;      }      public static CloseableHttpClient getHttpClient(String scheme) {         return getHttpClient(scheme, getSSLContext());      }      public static CloseableHttpClient getHttpClientWithoutTLSValidation(String scheme) {         return getHttpClient(scheme, getSSLContextWithoutValidation());      }      public static SSLContext getSSLContextWithoutValidation() {         SSLContext sslContext=null;         try {             sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {                 public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {                     return true;                 }             }).build();         } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {             e.printStackTrace();         }         return sslContext;     }      public static SSLContext getSSLContext() {         SSLContext sslContext=null;         try {             JKSInfo jksInfo = JKSUtil.getTrustStoreInfo();             sslContext = HttpSSLUtil.getSSLContext(jksInfo.getJksPath(), jksInfo.getJksPassword());         } catch (HttpSSLException e) {             e.printStackTrace();         }         return sslContext;     }  } 

Here is where I am using above class in my program

public String post(String host,int port,Map<String,String> data) {      CloseableHttpClient client = null;     String response = null;     String protocol = HTTP;     try{         if( isServerSSLEnabled() ){ //returns a boolean tru or false. In this case it is true             protocol = HTTPS;         }         client = ClientelUtil.getHttpClient(protocol);         //RequestConfig requestConfig = RequestConfig.custom().setCircularRedirectsAllowed(true).build();         URIBuilder builder = new URIBuilder()                     .setScheme(protocol)                     .setHost(host).setPort(port)                     .setPath(CONNECT_URI);          URI uri = builder.build();          HttpPost postMethod = new HttpPost(uri);         //postMethod.setConfig(requestConfig);         logger.debug("Sending request on host [" + host +"], port ["+ port+"], Protocol ["+ protocol + "] connectURI ["+CONNECT_URI+"]");           addRequestHeaders(postMethod);         ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();         try {             for(Map.Entry<String,String> entry : data.entrySet()) {                 postParameters.add(new BasicNameValuePair(entry.getKey(),entry.getValue()));             }             postMethod.setEntity(new UrlEncodedFormEntity(postParameters));             CloseableHttpResponse response1 = client.execute(postMethod);       // <-- SSLPeerUnverifiedException at this point             response = EntityUtils.toString(response1.getEntity());         } catch (IOException e) {             logger.error("Error while running the scenario on node host [" + host+"]",e);         } finally{             postMethod.releaseConnection();         }     } catch (URISyntaxException e1) {         e1.printStackTrace();     }finally {         if(client!=null)             try {                 client.close();             } catch (IOException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }     }     return response; } 

I am using apache http client 4.5 for this, please help on identifying what is wrong here.

Also is CN=FQDN required in keystore used in getSSLContext method as I am using NoopHostnameVerifier.INSTANCE to create HttpClientBuilder?

Thanks

Update

I created a new truststore file with Common Name (e.g. server FQDN or YOUR name) []: as my hostname, after which above code is working (Now I am using hostname to access my server code instead of hostname.domain.com as mentioned above in my question).

Now my question is, in case where CN | Common Name is not present in truststore file can it be verified using some modification in above code? Please suggest. Thanks again.

Update

Posting full stack trace. Also is it a good practice to return true in case of hostname verifier so that it ignores hostname verification and works incase of no CN or SAN is provided in production (Please let me know when this can be used and otherwise)?

javax.net.ssl.SSLPeerUnverifiedException: Certificate for <hostname.domain.com> doesn't match any of the subject alternative names: []     at org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:467)     at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:397)     at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)     at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)     at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)     at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)     at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)     at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)     at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)     at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)     at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)     at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)     at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)     at com.code.app.myapp.utils.HttpUtil.post(HttpUtil.java:102)     at com.code.app.myapp2.RequestDispatcher.dispatchRequest(RequestDispatcher.java:61)     at com.code.app.chain.commands.FetchDiagnosticsInfo.executeOperation(FetchDiagnosticsInfo.java:82)     at com.informatica.tools.ui.isomorphic.DSCommand.execute(DSCommand.java:45)     at com.code.app.chain.commands.BaseDSCommand.execute(BaseDSCommand.java:59)     at com.informatica.tools.ui.isomorphic.RPCCommand.execute(RPCCommand.java:43)     at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:166)     at com.informatica.tools.ui.isomorphic.RPCController.execute(RPCController.java:97)     at com.code.app.ui.IsomorphicController.execute(IsomorphicController.java:115)     at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:166)     at org.apache.struts.chain.commands.ExecuteCommand.execute(ExecuteCommand.java:70)     at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:51)     at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:166)     at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:175)     at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:166)     at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:283)     at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)     at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)     at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)     at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)     at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)     at com.code.app.ui.security.UserIdentifierFilter.doFilter(UserIdentifierFilter.java:352)     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)     at com.code.app.ui.i18n.InfEncodingFilter.doFilter(InfEncodingFilter.java:156)     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)     at com.code.app.config.InfSessionTimeoutManagerFilter.doFilter(InfSessionTimeoutManagerFilter.java:79)     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)     at com.code.app.ui.security.ResponseHeaderFilter.doFilter(ResponseHeaderFilter.java:26)     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)     at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:615)     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)     at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)     at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)     at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)     at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)     at java.lang.Thread.run(Thread.java:748) 

1 Answers

Answers 1

This is a problem with the server certificate, or the DNS mapping, not your code. The server name you connected to is not present in the SSL certificate it presented.

You should not look for insecure workarounds like null HTTPS hostname verifiers.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment