SSL handshake exception while connecting over https - java

My java application was able to connect to the third party application using https SSL connection when the endpoint URL had IP address in it.
Now, when the IP address got changed to Hostname, I am getting “SSL handshake exception” .
Apart from this there were no code update or any other changes done.
Only change what was done is that the thiry party is using Hostname in the Endpoint URL , instead of IP address.
Earlier URL: https://10.0.0.1:5368/invoke/Upload.Accept/receiveReply
Present URL: https://service.serviceprovider.com:5368/invoke/Upload.Accept/receiveReply
Any ideas what is causing this and how to fix it?
Please let me know if any more details is required.
Below is the stacktrace of the error:
javax.net.ssl.SSLHandshakeException: Could not generate secret
at sun.security.ssl.DHCrypt.getAgreedSecret(DHCrypt.java:219)
at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1056)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:348)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
at com.etsalat.adapter.sadad.PaymentLoadAdapter.run(PaymentLoadAdapter.java:130)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.security.NoSuchAlgorithmException: TlsPremasterSecret SecretKeyFactory not available
at javax.crypto.SecretKeyFactory.<init>(SecretKeyFactory.java:122)
at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java:160)
at iaik.security.dh.DHKeyAgreement.engineGenerateSecret(Unknown Source)
at javax.crypto.KeyAgreement.generateSecret(KeyAgreement.java:648)
at sun.security.ssl.DHCrypt.getAgreedSecret(DHCrypt.java:217)

I had the same issue before.
The exception: "SecretKeyFactory not available" happens if the digital signature API you are using is not added to Java SDK your application use.
To add the API to Java SDK:
1. Navigate to the lib-signed folder and then copy API jar file (for example: iaik_jce.jar) to /jre/lib/ext.
2. Navigate to /jre/lib/security and then add the following to java.security
security.provider.10=iaik.security.provider.IAIK
Note: If the number '10' is being used by another entry, use the next available number.
for more information refer to: http://docs.oracle.com/cd/E61144_01/English/Install_and_Config/Automatic_Install_and_Config/helpmain.htm?toc.htm?89631.htm

Related

SSL peer shut down incorrectly in https POST with public key [duplicate]

I am getting javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake exception when I try to do HTTPS Post of a web service through internet. But same code works for other internet hosted web services. I tried many things, nothing is helping me. I posted my sample code here. Can anyone please help me to resolve this problem?
public static void main(String[] args) throws Exception {
String xmlServerURL = "https://example.com/soap/WsRouter";
URL urlXMLServer = new URL(xmlServerURL);
// URLConnection supports HTTPS protocol only with JDK 1.4+
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
"xxxx.example.com", 8083));
HttpURLConnection httpsURLConnection = (HttpURLConnection) urlXMLServer
.openConnection(proxy);
httpsURLConnection.setRequestProperty("Content-Type","text/xml; charset=utf-8");
//httpsURLConnection.setDoInput(true);
httpsURLConnection.setDoOutput(true);
httpsURLConnection.setConnectTimeout(300000);
//httpsURLConnection.setIgnoreProxy(false);
httpsURLConnection.setRequestMethod("POST");
//httpsURLConnection.setHostnameVerifier(DO_NOT_VERIFY);
// send request
PrintWriter out = new PrintWriter(
httpsURLConnection.getOutputStream());
StringBuffer requestXML = new StringBuffer();
requestXML.append(getProcessWorkOrderSOAPXML());
// get list of user
out.println(requestXML.toString());
out.close();
out.flush();
System.out.println("XML Request POSTed to " + xmlServerURL + "\n");
System.out.println(requestXML.toString() + "\n");
//Thread.sleep(60000);
// read response
BufferedReader in = new BufferedReader(new InputStreamReader(
httpsURLConnection.getInputStream()));
String line;
String respXML = "";
while ((line = in.readLine()) != null) {
respXML += line;
}
in.close();
// output response
respXML = URLDecoder.decode(respXML, "UTF-8");
System.out.println("\nXML Response\n");
System.out.println(respXML);
}
Full stacktrace:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1091)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
at com.labcorp.efone.vendor.TestATTConnectivity.main(TestATTConnectivity.java:43)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:482)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
... 8 more
Actually, there are two scenarios here. When I work as a standalone Java program I am getting the above exception. But when I try to execute in weblogic application server, I am getting the below exception: Any clue what could be the reason?
java.io.IOException: Connection closed, EOF detected
at weblogic.socket.JSSEFilterImpl.handleUnwrapResults(JSSEFilterImpl.java:637)
at weblogic.socket.JSSEFilterImpl.unwrapAndHandleResults(JSSEFilterImpl.java:515)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:96)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:75)
at weblogic.socket.JSSEFilterImpl.write(JSSEFilterImpl.java:448)
at weblogic.socket.JSSESocket$JSSEOutputStream.write(JSSESocket.java:93)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at java.io.FilterOutputStream.flush(FilterOutputStream.java:140)
at weblogic.net.http.HttpURLConnection.writeRequests(HttpURLConnection.java:192)
at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:433)
at weblogic.net.http.SOAPHttpsURLConnection.getInputStream(SOAPHttpsURLConnection.java:37)
at com.labcorp.efone.service.impl.WorkOrderServiceImpl.processATTWorkOrder(ATTWorkOrderServiceImpl.java:86)
at com.labcorp.efone.bds.WorkOrderBusinessDelegateImpl.processATTWorkOrder(WorkOrderBusinessDelegateImpl.java:59)
at com.labcorp.efone.actions.ATTWorkOrderAction.efonePerformForward(ATTWorkOrderAction.java:41)
at com.labcorp.efone.actions.EfoneAction.efonePerformActionForward(EfoneAction.java:149)
at com.labcorp.efone.actions.EfoneAction.execute(EfoneAction.java:225)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:751)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:844)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:280)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:254)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:136)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:341)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at com.labcorp.efone.security.EfoneAuthenticationFilter.doFilter(EfoneAuthenticationFilter.java:115)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:79)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3367)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3333)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2220)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2146)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2124)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1564)
at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:254)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:295)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:254)
Exception: java.io.IOException: Connection closed, EOF detected
Java 7 defaults to TLS 1.0, which can cause this error when that protocol is not accepted. I ran into this problem with a Tomcat application and a server that would not accept TLS 1.0 connections any longer. I added
-Dhttps.protocols=TLSv1.1,TLSv1.2
to the Java options and that fixed it. (Tomcat was running Java 7.)
I faced the same problem and solved it by adding:
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
before openConnection method.
Not an answer yet, but too much for a comment. This is clearly not a server cert problem; the symptoms of that are quite different. From your system's POV, the server appears to be closing during the handshake. There are two possibilities:
The server really is closing, which is a SSL/TLS protocol violation though a fairly minor one; there are quite a few reasons a server might fail to handshake with you but it should send a fatal alert first, which your JSSE or the weblogic equivalent should indicate. In this case there may well be some useful information in the server log, if you are able (and permitted) to communicate with knowledgeable server admin(s). Or you can try putting a network monitor on your client machine, or one close enough it sees all your traffic; personally I like www.wireshark.org. But this usually shows only that the close came immediately after the ClientHello, which doesn't narrow it down much. You don't say if you are supposed to and have configured a "client cert" (actually key&cert, in the form of a Java privateKeyEntry) for this server; if that is required by the server and not correct, some servers may perceive that as an attack and knowingly violate protocol by closing even though officially they should send an alert.
Or, some middlebox in the network, most often a firewall or purportedly-transparent proxy, is deciding it doesn't like your connection and forcing a close. The Proxy you use is an obvious suspect; when you say the "same code" works to other hosts, confirm if you mean through the same proxy (not just a proxy) and using HTTPS (not clear HTTP). If that isn't so, try testing to other hosts with HTTPS through the proxy (you needn't send a full SOAP request, just a GET / if enough). If you can, try connecting without the proxy, or possibly a different proxy, and connecting HTTP (not S) through the proxy to the host (if both support clear) and see if those work.
If you don't mind publishing the actual host (but definitely not any authentication credentials) others can try it. Or you can go to www.ssllabs.com and request they test the server (without publishing the results); this will try several common variations on SSL/TLS connection and report any errors it sees, as well as any security weaknesses.
A first step to diagnose the issue is by starting the client - and if you are running the server yourself, a private test instance of the server - by starting Java with the VM option:
-Djavax.net.debug=all
See also https://blogs.oracle.com/java-platform-group/entry/diagnosing_tls_ssl_and_https
I encountered a similar problem with glassfish application server and Oracle JDK/JRE but not in Open JDK/JRE.
When connecting to a SSL domain I always ran into:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
...
Caused by: java.io.EOFException: SSL peer shut down incorrectly
The solution for me was to install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files because the server only understood certificates that are not included in Oracle JDK by default, only OpenJDK includes them.
After installing everything worked like charme.
JCE 7: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JCE 8: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
I think you are missing your certificates.
You can try generating them by using InstallCerts app. Here you can see how to use it:
https://github.com/escline/InstallCert
Once you get your certificate, you need to put it under your security directory within your jdk home, for example:
C:\Program Files\Java\jdk1.6.0_45\jre\lib\security
Let me know if it works.
I ran into a similar issue and found I was hitting the wrong port. After fixing the port things worked great.
In my case, I got this problem because I had given the server a non-existent certificate, due to a typo in the config file. Instead of throwing an exception, the server proceeded like normal and sent an empty certificate to the client. So it might be worth checking to make sure that the server is providing the correct response.
I experienced this error while using the Jersey Client to connect to a server. The way I resolved it was by debugging the library and seeing that it actually did receive an EOF the moment it tried to read. I also tried connecting using a web browser and got the same results.
Just writing this here in case it ends up helping anyone.
You May Write this below code insdie your current java programme
System.setProperty("https.protocols", "TLSv1.1");
or
System.setProperty("http.proxyHost", "proxy.com");
System.setProperty("http.proxyPort", "911");
Thanks to all for sharing your answers and examples. The same standalone program worked for me by small changes and adding the lines of code below.
In this case, keystore file was given by webservice provider.
// Small changes during connection initiation..
// Please add this static block
static {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
{ #Override
public boolean verify(String hostname, SSLSession arg1) {
// TODO Auto-generated method stub
if (hostname.equals("X.X.X.X")) {
System.out.println("Return TRUE"+hostname);
return true;
}
System.out.println("Return FALSE");
return false;
}
});
}
String xmlServerURL = "https://X.X.X.X:8080/services/EndpointPort";
URL urlXMLServer = new URL(null,xmlServerURL,new sun.net.www.protocol.https.Handler());
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) urlXMLServer .openConnection();
// Below extra lines are added to the same program
//Keystore file
System.setProperty("javax.net.ssl.keyStore", "Drive:/FullPath/keystorefile.store");
System.setProperty("javax.net.ssl.keyStorePassword", "Password"); // Password given by vendor
//TrustStore file
System.setProperty("javax.net.ssl.trustStore"Drive:/FullPath/keystorefile.store");
System.setProperty("javax.net.ssl.trustStorePassword", "Password");
I encountered this problem with Java 1.6. Running under Java 1.7 fixed my particular rendition of the problem. I think the underlying cause was that the server I was connecting to must have required stronger encryption than was available under 1.6.
I had the same error, but in my case it was caused by the DEBUG mode in Intellij IDE. The debug slowed down the library and then server ended communication at handshake phase. The standard "RUN" worked perfectly.
I run my application with Java 8 and Java 8 brought security certificate onto its trust store. Then I switched to Java 7 and added the following into VM options:
-Djavax.net.ssl.trustStore=C:\<....>\java8\jre\lib\security\cacerts
Simply I pointed to the location where a certificate is.
I was using the p12 which I exported with Keychain in my MacBook, however, it didn't work on my java-apns server code. What I had to do was to create a new p12 key as stated here, using my already generated pem keys:
openssl pkcs12 -export -in your_app.pem -inkey your_key.pem -out your_app_key.p12
Then updated the path to that new p12 file and everything worked perfectly.
How you would solve it is by going to
Settings
Search"Network"
Choose "Use IDEA general proxy settings as default Subversion"
As per https://kb.informatica.com/solution/23/Pages/69/570664.aspx adding this property works
CryptoProtocolVersion=TLSv1.2
With base at TLSv1.2 ALERT: fatal, handshake_failure I obtained after debug with this thread previos answer
-Djavax.net.debug=all
I went to https://www.ssllabs.com/and observed that the web server required a SSLv3 connection deprecate at june 2015, and deprecated at JDKu31 Release notes
I edited the ${java_home}/jre/lib/security/java.security at the line
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,
EC keySize < 224, 3DES_EDE_CBC, anon, NULL
to
jdk.tls.disabledAlgorithms= RC4, DES, MD5withRSA, DH keySize < 1024,
EC keySize < 224, 3DES_EDE_CBC, anon, NULL
As a final step I got this error
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target [javax.net.ssl.SSLHandshakeException]
I fixed this intalling the cert with the java keytool, following this answer PKIX path building failed” and “unable to find valid certification path to requested target”
I get this error when specifying a https url and in the same url explicitly specifying an http port (instead of an https port). Removing the explicit port :8080 solved the issue for me.
Adding certificates to Java\jdk\jre\lib\security folder worked for me. If you are using Chrome click on the green bulb [https://support.google.com/chrome/answer/95617?p=ui_security_indicator&rd=1] and save the certificate in security folder.
I faced the same issue once. I think its because of the URL
String xmlServerURL = "https://example.com/soap/WsRouter";
Check whether its a proper one or not ??
javax.net.ssl.SSLHandshakeException is because the server not able to connect to the specified URL because of following reason-
Either the identity of the website is not verified.
Server's certificate does not match the URL.
Or, Server's certificate is not trusted.
This is what solve my problem.
If you are trying to use debugger make sure you breakpoint is not on URL or URLConnection just put your breakpoint on BufferReader or inside while loop.
If nothing works try using apache library http://hc.apache.org/index.html.
no SSL, no JDK update needed, no need to set properties even, just simple trick :)

javax.net.ssl.SSLKeyException: Invalid signature on ECDH server key exchange message( in java)

I am getting below exception while firing simple http GET request from java.(actually from jsoup java api).
javax.net.ssl.SSLKeyException: Invalid signature on ECDH server key exchange message
at sun.security.ssl.HandshakeMessage$ECDH_ServerKeyExchange.<init>(HandshakeMessage.java:1098)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:278)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:913)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:849)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1035)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1344)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:512)
at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:493)
at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:205)
at org.jsoup.helper.HttpConnection.get(HttpConnection.java:194)
at com.ampower.scraper.data.util.DocumentUtil.test(DocumentUtil.java:205)
at com.ampower.scraper.goolesearch.email.EmailScraper.doGoogleSearch(EmailScraper.java:87)
at com.ampower.scraper.goolesearch.email.EmailScraper.main(EmailScraper.java:50)
Here iam using java version is 1.7.0_101. please suggest.
It could be a expired certificate problem. I stumbled upon the same error; after debugging the SSL/TLS Connections I noticed said certicate was no longer valid anymore:
Validaty: [From: date-in-the-past,
To: date-in-the-past]
As soon as the certicate was renewed, the error was gone.
Try one of the following options:
Option 1: JDK upgrade
If possible, change your JDK version for a newer version and check if you run into the same issue again.
Option 2: Possible known issue
A similar issue has been reported. The solution comes from the using of the jdk.tls.client.protocols system property.
Option 3: Disable TLS certificates validation
Jsoup.connect(url).validateTLSCertificates(false).get();
Option 4: Debug the SSL exchange
Paste the url of your target site here: Comodoca's SSL analyzer
See the full detailed approach in this SO answer (Wht not Java7?).
See also:
Android Jsoup certificate issues
getting javax.net.ssl.SSLException: Received fatal alert: protocol_version while scraping data using Jsoup
HttpConnection#validateTLSCertificates

Exception while connecting to mail server

I got the following exception while connecting to Mail server from IBM WAS.
javax.mail.MessagingException: Could not convert socket to TLS; nested exception is: java.net.SocketException: java.security.PrivilegedActionException: java.io.FileNotFoundException: D:\Program Files (x86)\IBM\WebSphere\AppServer\jre\lib\security\cacerts (The system cannot find the path specified.)
My question is:
What is the certificate that I should import? Is it the mail server's certificate which needs to be imported into WAS? Should I ask the mail server admin to share the certificate?
Once I figure out which certificate, I plan to follow these instructions to import it:
How to connect to a secure website using SSL in Java with a pkcs12 file?
That link is not the correct way to use mail sessions in WAS. Check this Websphere 7 javax.mail.MessagingException: SSLSocketFactory is null.
Try to use default SSL WebSphere configuration and Mail session resource. You will need to add your mail server certificate to the Trust store (NodeDeaultTrustStore or CellDefaultTrustStore depending whether you use standalone or network deployment version).
It should be possible to get mail server cert using a browser, when you connect using https://mailserver:port/ it should give you certificate which you could save locally and add to truststore. If you will have problems contact mail server admin.
PrivilegedActionException also suggest that you may have Java 2 security enabled. Check if it is enabled and if you really need it.

Trouble with securing a Tomcat/Axis2 web service via SSL

I have successfully built a working web service, client, and .jsp-driven UI. I did this with Eclipse, Axis2, Tomcat 7, and Java 7.
The basic flow is that the user visits the .jsp and submits a form with input data. The JSP forwards the "request" object to the Java client. The Java client consumes the web service and submits the user input. The service connects to a SQL Server database via JDBC to retrieve information, which is displayed back to the user.
This all works perfectly over HTTP, but now I want to secure the process, and this is where I'm running into problems. I'm able to create a cert and get Tomcat to use it. I can connect to the web UI via HTTPS and submit the form and get data back just fine. The problem is that this is only securing the front-end. The web service client code is still connecting to the service via HTTP in the background.
According to this page, all I really need to do to enable my service for connections via SSL is to update the axis2.xml file and include a new "transportReceiver" node for HTTPS. I did that and regenerated my client code to use the secure endpoint. It doesn't work.
I have configured Tomcat to listen on ports 8081 for http and 8443 for https. But after changing axis2.xml to match, and starting up Tomcat, I get the following:
[INFO] Listening on port 8443 [ERROR] Terminating connection
listener
org.apache.axis2.transport.http.server.DefaultConnectionListener#16d60567
after 10retries in 0 seconds. java.net.BindException: Address already
in use: JVM_Bind at java.net.DualStackPlainSocketImpl.bind0(Native
Method) at java.net.DualStackPlainSocketImpl.socketBind(Unknown
Source) at java.net.AbstractPlainSocketImpl.bind(Unknown Source) at
java.net.PlainSocketImpl.bind(Unknown Source) at
java.net.ServerSocket.bind(Unknown Source) at
java.net.ServerSocket.(Unknown Source) at
java.net.ServerSocket.(Unknown Source) at
org.apache.axis2.transport.http.server.DefaultConnectionListener.run(DefaultConnectionListener.java:80)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
I have tried changing the port number in axis2.xml (for example, to 8445), and that sort of works. The server is able to start cleanly, but eventually, the same errors start showing up. For example, when I retrieve the WSDL, I see the error via the console (though the WSDL does show up). Also, if I try to actually use the service when on port 8445, I get the following error:
org.apache.axis2.AxisFault: Connection has been shutdown:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext
connection?
I can only assume this is because Tomcat is configured to handle HTTPS on 8443, not 8445, but I honestly don't know.
If I leave the port as 8443 and ignore the errors at startup, I get the following message when I connect to the service:
org.apache.axis2.AxisFault: Connection has been shutdown:
javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to
find valid certification path to requested target
I followed these steps to try to get it to recognize my certificate, but when importing it into my JRE7 keystore, I get the following:
keytool error: java.lang.Exception: Certificate reply and certificate
in keystore are identical
Basically, that cert is already there. Which makes sense, because it's the one that Tomcat is already using successfully.
So, I'm pretty clueless at this point. I'm really not sure what I'm supposed to be doing. Any general guidance, or a link to a step-by-step how-to would be really helpful.
But for a specific question... What, exactly, am I doing when I set the transportReceiver nodes in axis2.xml? Am I telling it what ports Tomcat is running on and that it should use, or does Axis2 have its own servers that will start on those ports? It seems to be the latter, but that doesn't make a whole lot of sense to me.
The correct way to configure the servlet transport is described in the Axis2 documentation. The symptoms you are describing suggest that you have a transportReceiver that refers to org.apache.axis2.transport.http.SimpleHTTPServer. Please also make sure that you use a recent version of Axis2 (1.5.6 or 1.6.1).
See Andreas's response for the port issue. As for the certificate issue, it was a misunderstanding on my part over the distinction between a keystore and truststore. The JVM defaults to using JAVA_HOME\lib\security\cacerts as its trust store, rather than the USER_HOME\.keystore file. Once I imported my certificate there, the errors went away.
I was also able to resolve the certificate problems by explicity setting the trust store to be the key store file, via code. I did this before importing the certificate into the cacerts store. It goes in the client code, right before invoking the service:
System.setProperty("javax.net.ssl.trustStore","C:\\path\\to\\.keystore");
System.setProperty("javax.net.ssl.trustStorePassword","password");
One of the way to connect to HTTPS is using jax-ws
E:\WSDL>wsimport -keep -p com.mypack.webservice https://domain:port/ws/MyService?wsdl
This will generate package structure under the wsdl folder. Use it.
Now all you have to do is put trust store in run.bat or use System class to set property.
It will work fine.

HANDSHAKE_FAILURE alert received

I am writing a Java client (on weblogic 10.3) to invoke a secure web service.
I have been provided with a client certificate which I have installed in cacerts, DemoIdentity.jks and DemoTrust,jks
In my weblogic I have set up keystore as DemoIdentity and DemoTrust.
In weblogic console I have set
"Two Way Client Cert Behavior:" as "Client Certs requested but not enforced".
and for "SSL Listen Port enabled:" I have checked the checkbox.
I get the below exception while trying to access the web service:
] FaultActor [null] Detail [<detail><bea_fault:stacktrace xmlns:bea_fault="http:
//www.bea.com/servers/wls70/webservice/fault/1.0.0">javax.net.ssl.SSLHandshakeEx
ception: [Security:090497]HANDSHAKE_FAILURE alert received from ************** Check both sides of the SSL configuration for mismatches in supported ciphers, supported protocol versions, trusted CAs, and hos
tname verification settings.
at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireException(Unknow
n Source)
at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireAlertReceived(Un
known Source)
at com.certicom.tls.record.alert.AlertHandler.handle(Unknown Source)
at com.certicom.tls.record.alert.AlertHandler.handleAlertMessages(Unknow
n Source)
at com.certicom.tls.record.MessageInterpreter.interpretContent(Unknown S
ource)
at com.certicom.tls.record.MessageInterpreter.decryptMessage(Unknown Sou
rce)
at com.certicom.tls.record.ReadHandler.processRecord(Unknown Source)
at com.certicom.tls.record.ReadHandler.readRecord(Unknown Source)
at com.certicom.tls.record.ReadHandler.readUntilHandshakeComplete(Unknow
n Source)
at com.certicom.tls.interfaceimpl.TLSConnectionImpl.completeHandshake(Un
known Source)
at com.certicom.tls.record.WriteHandler.write(Unknown Source)
at com.certicom.io.OutputSSLIOStreamWrapper.write(Unknown Source)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65
)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at java.io.FilterOutputStream.flush(FilterOutputStream.java:123)
at weblogic.net.http.HttpURLConnection.writeRequests(HttpURLConnection.j
ava:158)
at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.
java:363)
at weblogic.net.http.SOAPHttpsURLConnection.getInputStream(SOAPHttpsURLC
onnection.java:37)
at weblogic.wsee.connection.transport.TransportUtil.getInputStream(Trans
portUtil.java:85)
at weblogic.wsee.connection.transport.http.HTTPClientTransport.receive(H
TTPClientTransport.java:271)
at weblogic.wsee.connection.soap.SoapConnection.receive(SoapConnection.j
ava:485)
at weblogic.wsee.ws.dispatch.client.ConnectionHandler.handleResponse(Con
nectionHandler.java:179)
at weblogic.wsee.handler.HandlerIterator.handleResponse(HandlerIterator.
java:287)
at weblogic.wsee.handler.HandlerIterator.handleResponse(HandlerIterator.
java:271)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.handleResponse(Clie
ntDispatcher.java:213)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.dispatch(ClientDisp
atcher.java:150)
at weblogic.wsee.ws.WsStub.invoke(WsStub.java:87)
at weblogic.wsee.jaxrpc.StubImpl._invoke(StubImpl.java:339)
at sips_cn_contract.PaymentService_Stub.processPaymentWebInit(Unknown So
urce)
at uk.gov.gateway.payments.SipsStartupController.handleRequest(SipsStart
upController.java:73)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.ha
ndle(SimpleControllerHandlerAdapter.java:45)
at org.springframework.web.servlet.DispatcherServlet.doService(Dispatche
rServlet.java:485)
at org.springframework.web.servlet.FrameworkServlet.serviceWrapper(Frame
workServlet.java:342)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServl
et.java:318)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run
(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecuri
tyHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.jav
a:300)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.jav
a:183)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationActio
n.doIt(WebAppServletContext.java:3686)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationActio
n.run(WebAppServletContext.java:3650)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(Authenticate
dSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:
121)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppS
ervletContext.java:2268)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletC
ontext.java:2174)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.j
ava:1446)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
</bea_fault:stacktrace></detail>]; nested exception is:
However in firefox, i have added the certificate, and when i view the wsdl of the web service.It prompts me with the certificate and after i click ok, it renders the wsdl file for secure web service.
Anybody has idea what should I do to make the client working using Java?
I think that the real problem is that Weblogic is not using standard Sun HTTPS implementation provided by JDK, but rather uses its own, as apparent on this line:
at weblogic.net.http.SOAPHttpsURLConnection.getInputStream(SOAPHttpsURLConnection.java:37)
The standard Sun implementation class is called javax.net.ssl.HttpsURLConnection.
As a result, the certificate policy is different inside Weblogic than in a standalone Java program. I just discovered this debugging a similar problem.
This page advises to use a Sun implementation instead of Weblogic:
http://webtech-kapil.blogspot.com/2010/06/javalangclasscastexception.html
They advice to start WL with the following flag:
-DUseSunHttpHandler=true
which will use standard Sun's implementation of SSL. However, I personally have not tried this yet.
Thanks,
Igor
You have likely not imported your certificate and key correctly. You can test your keystore by adding the following to a JUnit or something similar:
static {
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12"); // or whatever
System.setProperty("javax.net.ssl.keyStore", "c:/folder/mycert.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "mypassword");
System.setProperty("javax.net.debug", "ssl");
}
The javax.net.debug property set to ssl will print your certificate chain and all other SSL logging, which can be helpful. You'll want to add the certificate, etc. to your application container like you already have in production.
Try debugging with SSL and see what comes of that. More than likely you just need to configure weblogic correctly. Check to see if there are custom SSL endpoint configurations (i.e. when URI is /test/test use keyStore XYZ).

Categories

Resources