SSLHandshakeException: No subject alternative names present

JavaTomcatSoapSslHttps

Java Problem Overview


I am invoking HTTPS SOAP web service through java code. I have already imported self-signed certificate in jre cacerts keystore. Now I am getting :

com.sun.xml.internal.ws.com.client.ClientTransportException: HTTP transport error: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present

The hostname of the service URL is not matching that of the CN provided in cert. I read about a workaround of defining a custom Hostname verifier here. But i cant able to make where I should implement the workaround in my code.

public SOAPMessage invokeWS(WSBean bean) throws Exception {

	SOAPMessage response=null;
	try{
	
	/** Create a service and add at least one port to it. **/
	String targetNameSpace = bean.getTargetNameSpace();
	String endpointUrl = bean.getEndpointUrl();
	QName serviceName = new QName(targetNameSpace, bean.getServiceName());
	QName portName = new QName(targetNameSpace, bean.getPortName());
	String SOAPAction = bean.getSOAPAction();
	HashMap<String, String> map = bean.getParameters();
	
	
	Service service = Service.create(serviceName);
	service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointUrl);
	
	/** Create a Dispatch instance from a service. **/
	Dispatch dispatch = service.createDispatch(portName, SOAPMessage.class,
			Service.Mode.MESSAGE);

	// The soapActionUri is set here. otherwise we get a error on .net based
	// services.
	dispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY,
			new Boolean(true));
	dispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY,
			SOAPAction);
	
	/** Create SOAPMessage request. **/
	// compose a request message
	MessageFactory messageFactory = MessageFactory.newInstance();
	SOAPMessage message = messageFactory.createMessage();

	// Create objects for the message parts
	SOAPPart soapPart = message.getSOAPPart();
	SOAPEnvelope envelope = soapPart.getEnvelope();
	SOAPBody body = envelope.getBody();

	SOAPElement bodyElement = body.addChildElement(bean.getInputMethod(),
			bean.getPrefix(), bean.getTargetNameSpace());
	
             ...more code to form soap body goes here

	// Print request
	message.writeTo(System.out);

	// Save the message
	message.saveChanges();

	response = (SOAPMessage)dispatch.invoke(message);
	}
	catch (Exception e) {
		log.error("Error in invokeSiebelWS :"+e);
	}
	return response;
}

Please ignore WSBean parameter as the namespaces and other wsdl attributes are coming from this bean. And if this exception can solved with some different workarounds, pls do suggest.

Java Solutions


Solution 1 - Java

Thanks,Bruno for giving me heads up on Common Name and Subject Alternative Name. As we figured out certificate was generated with CN with DNS name of network and asked for regeneration of new certificate with Subject Alternative Name entry i.e. san=ip:10.0.0.1. which is the actual solution.

But, we managed to find out a workaround with which we can able to run on development phase. Just add a static block in the class from which we are making ssl connection.

static {
    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
        {
            public boolean verify(String hostname, SSLSession session)
            {
                // ip address of the service URL(like.23.28.244.244)
                if (hostname.equals("23.28.244.244"))
                    return true;
                return false;
            }
        });
}

If you happen to be using Java 8, there is a much slicker way of achieving the same result:

static {
    HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> hostname.equals("127.0.0.1"));
}

Solution 2 - Java

Unlike some browsers, Java follows the HTTPS specification strictly when it comes to the server identity verification (RFC 2818, Section 3.1) and IP addresses.

When using a host name, it's possible to fall back to the Common Name in the Subject DN of the server certificate, instead of using the Subject Alternative Name.

When using an IP address, there must be a Subject Alternative Name entry (of type IP address, not DNS name) in the certificate.

You'll find more details about the specification and how to generate such a certificate in this answer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionshashankaholicView Question on Stackoverflow
Solution 1 - JavashashankaholicView Answer on Stackoverflow
Solution 2 - JavaBrunoView Answer on Stackoverflow