Paypal Sandbox API: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure - java

I am getting an exception while using PayPal MassPay API in sandbox mode.
The same code worked earlier, now it is giving me an SSLHandshakeException. I think this is because of PayPal's latest SSL certification updates. Could someone can help me fix this issue?
The following is my exception log:
http-bio-9090-exec-1, READ: TLSv1 Alert, length = 2
http-bio-9090-exec-1, RECV TLSv1 ALERT: fatal, handshake_failure
http-bio-9090-exec-1, called closeSocket()
http-bio-9090-exec-1, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
com.paypal.core.rest.PayPalRESTException: Received fatal alert: handshake_failure
at com.paypal.core.rest.PayPalResource.execute(PayPalResource.java:374)
at com.paypal.core.rest.PayPalResource.configureAndExecute(PayPalResource.java:225)
at com.paypal.sdk.openidconnect.Tokeninfo.createFromAuthorizationCode(Tokeninfo.java:245)
at com.oldwallet.controllers.CouponPaymentController.redeemed(CouponPaymentController.java:321)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:844)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1008)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077)
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.getInputStream(HttpURLConnection.java:1300)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at com.paypal.core.HttpConnection.execute(HttpConnection.java:93)
at com.paypal.core.rest.PayPalResource.execute(PayPalResource.java:367)
... 36 more

The issue is that PayPal recently (19th or 20th of Jan) switched the sandbox to TLS 1.2 and do not support TLS 1 anymore. I guess that you are running on Java SE 7 or older. If you search the net a bit you will find this:
Although SunJSSE in the Java SE 7 release supports TLS 1.1 and TLS
1.2, neither version is enabled by default for client connections. Some servers do not implement forward compatibility correctly and
refuse to talk to TLS 1.1 or TLS 1.2 clients. For interoperability,
SunJSSE does not enable TLS 1.1 or TLS 1.2 by default for client
connections.
Link
To enable TLS 1.2 you can use the following setting of the VM: -Dhttps.protocols=TLSv1.1,TLSv1.2 Then it will work.
If you want to see more details about the handshake you can use this VM option: -Djavax.net.debug=all
Then you may confirm that TLS 1.2 is disabled if you see something like this:
*** ClientHello, TLSv1
After the server response is read the exception will be thrown. Java 8 has no such problem because TLS 1.2 is enabled by default.
Currently only the sandbox is affected. You can read on PayPal's site:
PayPal is updating its services to require TLS v1.2 for all HTTPS
connections on June 17, 2016. After that date, all TLS v1.0 and TLS
v1.1 API connections will be refused.
Most likely this will be postponed even more.
You may reproduce the problem and experiment with this simple throw-away code:
URL sandbox = new URL("https://api.sandbox.paypal.com/v1/oauth2/token");
URLConnection yc = sandbox.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();

http-bio-9090-exec-1, RECV TLSv1 ALERT: fatal, handshake_failure
Looks like you're using an older version of TLS. PayPal recently (a few days ago) made a change to their sandbox to require all connections be done over HTTP 1.1 and TLS 1.2. Try setting your code to use the newer version of TLS (1.2) and see if that helps. Apparently it's worked for a lot of people on here.
Link to the change description on PayPal dev blog
https://devblog.paypal.com/upcoming-security-changes-notice/

I have been dealing with the same problem (Paypal TLS 1.2 Vs JRE 1.6) this week. After some crazy hours, I managed to solve the problem using BouncyCastle and a some code I am not proud of (just as a patch. lasting solution will be upgrading to JRE 1.8).
BouncyCastle dependency:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.54</version>
</dependency>
My working code:
package es.webtools.eencuesta.redsys.component.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.bouncycastle.crypto.tls.CertificateRequest;
import org.bouncycastle.crypto.tls.DefaultTlsClient;
import org.bouncycastle.crypto.tls.TlsAuthentication;
import org.bouncycastle.crypto.tls.TlsClientProtocol;
import org.bouncycastle.crypto.tls.TlsCredentials;
import es.webtools.eencuesta.common.util.HttpUtils;
public class PayPayAPIHandler {
public static Map<String, String> doAPIRequest(Map<String, String> paramMap) {
StringBuilder data = new StringBuilder();
Iterator<Entry<String, String>> paramIt = paramMap.entrySet().iterator();
while (paramIt.hasNext()) {
Entry<String, String> param = paramIt.next();
data.append(param.getKey()).append("=").append(HttpUtils.encodeUTF8(param.getValue()));
if (paramIt.hasNext()) {
data.append("&");
}
}
try {
URL url = new URL("https://api-3t.sandbox.paypal.com/nvp");
// TODO #39 Utilizar HttpConnection (Java 8 implementa TLS 1.2, necesaria para comunicación con PayPal)
java.security.SecureRandom secureRandom = new java.security.SecureRandom();
Socket socket = new Socket(java.net.InetAddress.getByName(url.getHost()), 443);
TlsClientProtocol protocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), secureRandom);
DefaultTlsClient client = new DefaultTlsClient() {
public TlsAuthentication getAuthentication() throws IOException {
TlsAuthentication auth = new TlsAuthentication() {
// Capture the server certificate information!
public void notifyServerCertificate(org.bouncycastle.crypto.tls.Certificate serverCertificate) throws IOException {
}
public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
return null;
}
};
return auth;
}
};
protocol.connect(client);
java.io.OutputStream output2 = protocol.getOutputStream();
output2.write(("POST " + url.getPath() + " HTTP/1.1\r\n").getBytes("UTF-8"));
output2.write(("Host: " + url.getHost() + "\r\n").getBytes("UTF-8"));
output2.write("Connection: close\r\n".getBytes("UTF-8")); // So the server will close socket immediately.
output2.write(("Content-Length: " + data.length() + "\r\n").getBytes("UTF-8")); // So the server will close socket immediately.
output2.write("Content-Type:text/plain; charset=UTF-8\r\n".getBytes("UTF-8")); // So the server will close socket immediately.
output2.write("\r\n".getBytes("UTF-8")); // HTTP1.1 requirement: last line must be empty line.
output2.write(data.toString().getBytes("UTF-8"));
output2.flush();
InputStream input2 = protocol.getInputStream();
StringBuilder stringBuffer = new StringBuilder();
try {
InputStreamReader reader = new InputStreamReader(input2, "UTF-8");
int ch;
while ((ch = reader.read()) > -1) {
stringBuffer.append((char) ch);
}
reader.close();
} catch (Exception e) {
// Log some messages...
}
Map<String, String> result = new HashMap<String, String>();
String[] lines = stringBuffer.toString().split("\r\n");
String paramsLine = "";
for (int i = 0; i < lines.length; i++) {
if (lines[i].equals("")) {
paramsLine = lines[i + 1];
i = lines.length;
}
}
// El contenido de la respuesta vendrá después del salto de linea
for (String param : paramsLine.split("&")) {
String[] keyValue = param.split("=");
result.put(keyValue[0], URLDecoder.decode(keyValue[1], "UTF-8"));
}
return result;
} catch (Exception e) {
// Log some messages....
return null;
}
}
}

If you are calling https request from a web service or in a standalone application in JAVA, use the following line to make it work :
System.setProperty(“https.protocols”, “TLSv1,TLSv1.1,TLSv1.2”);

My problem was that I had java 7 installed so I upgraded to java 8 and voila, the exception was not there anymore :)

Related

SSL Socket Connection Error

I am using JAVA 8. I am trying to connect a Socket Server using client certificates and certificate tree.
I have followings provided by client:
Client CERT (PEM)
Private Key (PEM)
CA Tree (PEM) - with 4 Certificates
I have created keystore.jks using following steps:
Combining client cert and CA tree in a single pem file using cat
Crested PKCS12 file from combined file encrypted using private key(OpenSSL Command)
Generated JKS keystore file using keytool
I have created trustore.jks using following steps:
Split CA Tree (4 certificates) into 4 different files
Generated trustore file using keytool by importing each file one by one
My Sample code is as following :
package com.tutorial.exception.customize;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
import java.util.Scanner;
/**
* Created by SomnathG on 12/1/2016.
*/
public class Client {
public Client() {
System.setProperty("javax.net.ssl.keyStore", {keystore Location});
System.setProperty("javax.net.ssl.keyStorePassword", {password});
System.setProperty("javax.net.ssl.trustStore", {trustore location});
System.setProperty("javax.net.ssl.trustStorePassword", {password});
System.setProperty("javax.net.debug", "all");
System.setProperty( "sun.security.ssl.allowUnsafeRenegotiation", "true" );
}
public void connectHost(){
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslSocket = null;
try {
sslSocket = (SSLSocket) sslSocketFactory.createSocket(host, port);
sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
sslSocket.startHandshake();
InputStream inputStream = sslSocket.getInputStream();
OutputStream outputStream = sslSocket.getOutputStream();
System.out.println("Sending request to Socket Server");
outputStream.write("Hello".getBytes());
outputStream.write("exit".getBytes());
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
int bytesRead = 0;
String messageString = "";
DataInputStream in = new DataInputStream(sslSocket.getInputStream());
while(!end)
{
bytesRead = in.read(messageByte);
messageString += new String(messageByte, 0, bytesRead);
if (messageString.length() == 100)
{
end = true;
}
}
System.out.println("MESSAGE: " + messageString);
// byte[] read = (byte[]) ois.readObject();
//String s2 = new String(read);
//System.out.println("" + s2);
//System.out.println("Message: " + message);
//close resources
//System.out.println(receive(inputStream));
}catch (IOException e) {
e.printStackTrace();
System.out.println("=====");
System.out.println(e.getMessage());
System.out.println("=====");
CertPathValidatorException ce = new CertPathValidatorException(e);
System.out.println("******");
System.out.println(ce.getIndex());
System.out.println(ce.getReason());
System.out.println("******");
//e.printStackTrace();
}
}
public static void main(String[] args){
new Client().connectHost();
}
}
I am getting following exception after executing the code:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: basic constraints check failed: this is not a CA certificate
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
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 com.tutorial.exception.customize.Client.connectHost(Client.java:33)
at com.tutorial.exception.customize.Client.main(Client.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
After analyzing the log I have found "clientHello" and "serverHello" messages but after that application is throwing above mentioned exception.
What am I doing wrong? Please advice.
Thanks,
Somnath Guha
I have figured out the issue after analyzing the debug lo.
"BasicConstraints" was missing from the server V3 certificates and thus java was failing to recognize the certificate as a valid certificate. Once that constraint has been added then the client was able to handshake with the server and able to communicate with server.
BasicConstraints:[
CA:true
PathLen:2147483647
]

Java, jsch and EC2...can't run an application in root

I'm connecting to an EC2 instance from a remote machine via Java and Jsch. Once connected, I want to start a jboss server that sits in a directory owned and created by root. (I can't change that).
Usually from my putty shell, I would start jboss by issuing the following commands:
myUser#myIP:~# sudo su -
root#myIP:~:# cd jbossDirectory
root#myIp:~/jbossDirectory# ./startJbossScript.sh
The problems start when I try to do the same via Java/Jscp. This is my code:
import java.io.InputStream;
import java.io.OutputStream;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
public class SSHExecutor {
static String SSHprivateKey = privateKeyFileLocation;
static String username = myUser;
static String hostnamePublicIP = EC2InstanceIP;
static String startJbossCommand = "sudo -i /root/jbossDirectory/startJbossScript.sh";
static String sudo_pass = "";
public static void main(String[] arg) {
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
try {
JSch jsch = new JSch();
jsch.addIdentity(SSHprivateKey);
Session session = jsch.getSession(username, hostnamePublicIP, 22);
// username and passphrase will be given via UserInfo interface.
UserInfo ui = new MyUserInfo();
session.setUserInfo(ui);
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(startJbossCommnand);
InputStream in = channel.getInputStream();
OutputStream out = channel.getOutputStream();
((ChannelExec) channel).setErrStream(System.err);
channel.connect();
out.write((sudo_pass + "\n").getBytes());
out.flush();
byte[] tmp = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0)
break;
System.out.print(new String(tmp, 0, i));
}
if (channel.isClosed()) {
System.out.println("exit-status: "
+ channel.getExitStatus());
break;
}
try {
Thread.sleep(1000);
} catch (Exception ee) {
}
}
channel.disconnect();
session.disconnect();
} catch (Exception e) {
System.out.println(e);
}
}
}
This program will correctly starts Jboss. However, when Jboss receives a request for a dynamic page, it throws the following error:
06:48:13,137 INFO [STDOUT] >>>>>>>>/root/.
06:8:13,138 INFO [STDOUT] Exception while initializing hibernate: java.io.FileNotFoundException: WEBAPP_CONF/hibernate.properties (No such file or directory)
06:48:13,141 INFO [[/rubis]] Marking servlet BrowseRegions as unavailable
06:48:13,141 ERROR [[BrowseRegions]] Allocate exception for servlet BrowseRegions
javax.servlet.UnavailableException: Couldn't find file mysql.properties: java.io.FileNotFoundException: WEBAPP_CONF/mysql.properties (No such file or directory)<br>
at edu.rice.rubis.servlets.RubisHttpServlet.init(Unknown Source)
at edu.rice.rubis.servlets.HibernateRubisHttpServlet.init(Unknown Source)
at javax.servlet.GenericServlet.init(GenericServlet.java:212)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1161)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:806)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:129)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
at java.lang.Thread.run(Thread.java:724)
So it appears that it can't find the mysql configuration file. The file is there and this issue does not happen when I launch jboss from the console (as showed above). My guess is that the process does start with the sudo -i command, but then, it can't access the files that are within the jbossDirectory folder, hence it throws the error file not found. The WEBAPP_CONF/ is a subdirectory of jbossDirectory.
Any idea on how to fix this?
Thank you.
You are running the shell script from a different directory, and there is something in your code that expects the start-up script to start specifically in /root/jbossDirectory.
A simple workaround would be to edit startJbossScript.sh and add
cd /root/jbossDirectory
as the first line.
Before the channel.connect() line in your code add the below line which will allow you to excecute sudo commands
((ChannelExec) channel).setPty(true);

SSL socket connection between PHP client and Java server

I'm attempting to setup an SSL connection between a PHP client and a Java server. I don't know a whole lot about SSL and I'm getting very confused with this.
The connection doesn't need to be trusted or verified, it just has to encrypt the data to make it safe for transfer.
The PHP client is able to connect (acknowledges a connection) to the Java server, but upon the handshake between the two, I reveive the following error in Java:
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: no cipher suites in common
at sun.security.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1458)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:92)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at com.test.ConnectionHandler.getRequest(ConnectionHandler.java:23)
at com.test.Interaction.run(Interaction.java:35)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.net.ssl.SSLHandshakeException: no cipher suites in common
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1868)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:266)
at sun.security.ssl.ServerHandshaker.chooseCipherSuite(ServerHandshaker.java:892)
at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:620)
at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:167)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:998)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1294)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:685)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:111)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at java.io.BufferedWriter.flush(BufferedWriter.java:254)
at java.io.PrintWriter.newLine(PrintWriter.java:482)
at java.io.PrintWriter.println(PrintWriter.java:629)
at java.io.PrintWriter.println(PrintWriter.java:740)
at com.test.ConnectionHandler.println(ConnectionHandler.java:28)
at com.test.Interaction.run(Interaction.java:29)
... 1 more
and these errors in PHP:
Warning: fsockopen(): SSL operation failed with code 1. OpenSSL Error messages:
error:14077410:SSL routines:func(119):reason(1040) in /var/www/html/inc/node.class.php on line 48
Warning: fsockopen(): Failed to enable crypto in /var/www/html/inc/node.class.php on line 48
Warning: fsockopen(): unable to connect to ssl://127.0.0.1:30627 (Unknown error) in /var/www/html/inc/node.class.php on line 48
This is my code in Java which handles the socket setup:
SSLServerSocketFactory socketfactory;
SSLServerSocket ssock;
SSLContext sslContext = SSLContext.getInstance( "SSL" );
KeyStore ks = KeyStore.getInstance("JKS");
InputStream ksIs = ClassLoader.class.getResourceAsStream("resources/keystore.jks");
try {
ks.load(ksIs, "password".toCharArray());
} catch (CertificateException e) {
e.printStackTrace();
} finally {
if (ksIs != null) {
ksIs.close();
}
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, "password".toCharArray());
sslContext.init( kmf.getKeyManagers(), null, null );
socketfactory = sslContext.getServerSocketFactory();
socketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
ssock = (SSLServerSocket) socketfactory.createServerSocket(myPort);
for(String item : ssock.getEnabledCipherSuites()) {
System.out.println(item);
}
while(true) {
SSLSocket sock = (SSLSocket) ssock.accept();
new Interaction(sock);
}
This is my PHP code which handles the connection to the Java server:
(Starting at line 48)
$this->stream = fsockopen("ssl://127.0.0.1", 30627, $errno, $errstr);
if(!$this->stream) {
return array(
'errornum' => $errno,
'errorstr' => $errstr,
);
} else {
return true;
}
Can someone help explain what I'm doing wrong or provide a solution?
--Edit
I've tried using a Java client to connect to see where the problem lies. But I still receive the same error and this is shown on the Java Client:
javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHands
hakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.jav
a:1293)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkWrite(SSLSocketImpl.j
ava:1305)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.ja
va:43)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:276)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:122)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:212)
at java.io.BufferedWriter.flush(BufferedWriter.java:236)
at Main.main(Main.java:55)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_
failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.ja
va:1720)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.j
ava:954)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SS
LSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketIm
pl.java:753)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:
75)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at Main$Output.run(Main.java:77)
at java.lang.Thread.run(Thread.java:662)
I figured out that the problem was with loading the keystore. The way I was retrieving it as a resource wasn't working.
I got the keystore to load correctly and everything then worked fine.

JAVA: How to create http url connection selecting the ip address to use

I have a pool of public ip addresses configured on my multiple NICs.
In my JAVA project, which runs on a LINUX machine, I need to select a specific ip address from the pool and create an HttpURLConnecion using that ip. Further, I will cycle on the pool, using each time a different ip.
At the current stage, I was not able to find a solution using the java.net library. I have rather looked at the HttpClient from Apache. At the following link, http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html, it is said that such library can support the functionality I was looking for. A discussion on this can be found at Define source ip address using Apache HttpClient. Actually, the posted thread seems not conclusive, as users' experiences are very contrasting on the described use of the library.
Therefore, I don't think that SO community really succeeded in solving this issue. It is a matter of fact that several replayed questions/answers on this topic can be found on SO, but none of them seems to give an exhaustive analysis of the problem.
Moreover, the problem is not faced with the use of java.net library (as in my project) at all.
At the moment, a possible option that I have is to invoke some LINUX system commands (from java) to switch the NIC to use for the current connection. However, I have not figure it out yet.
Therefore, I would appreciate if any users, who had POSITIVE experiences in solving this issue, can address me to a solution/idea/method.
Thanks in advance,
Marcello
UPDATE:
I've currently implemented this test code. It gives me correct status code (200). However, it needs to be tested with multiple ip addresses.
public class test {
public static void main(String[] args) {
final String authUser = "admin";
final String authPassword = "password";
Authenticator.setDefault(
new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
authUser, authPassword.toCharArray());
}
}
);
System.setProperty("http.proxyUser", authUser);
System.setProperty("http.proxyPassword", authPassword);
try {
Properties systemProperties = System.getProperties();
URL url = new URL("yourURL");
systemProperties.setProperty("http.proxyHost","localhost");
systemProperties.setProperty("http.proxyPort", "8080");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int status = connection.getResponseCode();
System.out.println(status);
} catch (IOException e) {
System.out.println("connection problems");
}
}
}
At this point, you should be able to configure the different TCP ports related to each NIC. Did anyone try something like this?
I am looking forward to reading new ideas/comments.
UPDATE 2:
To be precise, I've included authentication setup for those who needed it.
Why don't you just use org.apache.httpcomponents?
Here an example that works (using maven plugin org.apache.httpcomponents, version 4.3.1):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
public class HttpClientExample {
public void gogo() throws ClientProtocolException, IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
// Local interface1:
byte ip1[] = new byte[] { (byte)192, (byte)168, (byte)100, (byte)32 };
// Local interface2:
byte ip2[] = new byte[] { (byte)192, (byte)168, (byte)100, (byte)33 };
RequestConfig requestConfig = RequestConfig.custom().setLocalAddress(InetAddress.getByAddress(ip1)).build();
try {
HttpGet httpget = new HttpGet("http://server.com");
httpget.setConfig(requestConfig);
System.out.println("executing request" + httpget.getRequestLine());
StringBuilder response = httpclient.execute(httpget,handler);
System.out.println(response.toString());
requestConfig = RequestConfig.custom().setLocalAddress(InetAddress.getByAddress(ip2)).build();
httpget = new HttpGet("http://server.com");
httpget.setConfig(requestConfig);
System.out.println("executing request" + httpget.getRequestLine());
response = httpclient.execute(httpget,handler);
System.out.println(response.toString());
} finally {
httpclient.close();
}
}
private final ResponseHandler<StringBuilder> handler = new ResponseHandler<StringBuilder>() {
#Override
public StringBuilder handleResponse(final HttpResponse response)
throws ClientProtocolException, IOException {
return sortResponse(response);
}
};
private StringBuilder sortResponse(final HttpResponse httpResponse) throws IOException {
StringBuilder builder = null;
if (httpResponse != null) {
switch (httpResponse.getStatusLine().getStatusCode()) {
case HttpStatus.SC_OK:
final HttpEntity entity = httpResponse.getEntity();
if (entity != null) {
final InputStreamReader instream = new InputStreamReader(entity.getContent());
try {
final BufferedReader reader = new BufferedReader(instream);
builder = new StringBuilder();
String currentLine = null;
currentLine = reader.readLine();
while (currentLine != null) {
builder.append(currentLine).append("\n");
currentLine = reader.readLine();
}
} finally {
instream.close();
}
}
break;
default:
throw new IllegalArgumentException("Error.");
}
}
return builder;
}
}
java.net uses sun.net.www.protocol package to create HttpURLConnection.
sun.net.www.protocol.HttpURLConnection is implementation of java.net.HttpURLConnection interface.
Try extending sun.net.www.protocol.HttpURLConnection and other appropriate classes like NetworkClient and HttpClient and protocol handler classes from sun.www. packages.
Use linux command "ip addr" which gives ouput similar to:
[root#user ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:18:a5:97 brd ff:ff:ff:ff:ff:ff
inet 100.10.52.15/24 brd 10.0.2.255 scope global eth1
inet 100.10.52.16/24 brd 10.0.2.255 scope global secondary eth1
inet6 fe80::a00:27ff:fe18:a597/64 scope link
valid_lft forever preferred_lft forever
3: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:11:1f:0c brd ff:ff:ff:ff:ff:ff
inet 158.17.47.19/24 brd 172.17.37.255 scope global eth2
inet6 fe80::a00:27ff:fe11:1f0c/64 scope link
valid_lft forever preferred_lft forever
4: eth3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:cf:96:2d brd ff:ff:ff:ff:ff:ff
inet6 fe80::a00:27ff:fecf:962d/64 scope link
valid_lft forever preferred_lft forever
By default linux uses first ip address as source ip adress on perticular adapter.
For example, for above system configuration linux will use "100.10.52.15/24" as source ip adress.
You can write java program with "ProcessBuilder" to execute following commands change order of ip address.
(commands:
ip addr del 100.10.25.15/24 dev eth0
ip addr add 100.10.25.15/24 dev eth0)
Delete all ip addresses on perticular adapter, store it in memory. Add it in order you want (IP address which should use as source ip should add first)
For example ip adress "100.10.52.16/24" should use as source ip adress then
ip addr del 100.10.25.15/24 dev eth0
ip addr del 100.10.25.16/24 dev eth0
ip addr add 100.10.25.16/24 dev eth0
ip addr add 100.10.25.15/24 dev eth0
Well i dont have that particular answer for the same but ya u can try this may be i am not sure that will work or not but try once.
URL url = new URL(yourUrlHere);
Proxy proxy = new Proxy(Proxy.Type.DIRECT,
new InetSocketAddress(
InetAddress.getByAddress(
new byte[]{your, ip, interface, here}), yourTcpPortHere));
URLConnection conn = url.openConnection(proxy);

calling a http get request in java

I want the request of http get request using the following java code.
But, uncertainly i am getting the following exception.
import java.net.*;
import java.io.*;
public class API {
public static void main(String[] args) throws Exception {
URL oracle = new URL("http://www.oracle.com/");
URLConnection yc = oracle.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}
The Error or exception is as follows:
Exception in thread "main" java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:337)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:198)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:180)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at sun.net.NetworkClient.doConnect(NetworkClient.java:180)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:388)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:483)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:213)
at sun.net.www.http.HttpClient.New(HttpClient.java:300)
at sun.net.www.http.HttpClient.New(HttpClient.java:316)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:992)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:928)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:846)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1296)
at API.main(API.java:8)
I'm guessing you have a firewall and it's blocking this HTTP get request.
You code should work as you expect it. Something outside the Java runtime is preventing the connection.
Check whether you can ping to http://www.oracle.com/.
If you can ping check whether you are behind a proxy server.
If so provide -Dhttp.proxyHost and -Dhttp.proxyPort while starting the JVM
java -Dhttp.proxyHost=<Your Proxy Server Name/IP> -Dhttp.proxyPort=<Your Proxy Server Port>

Categories

Resources