SSLSocket duplex close failed - java

I am getting following exception:
javax.net.ssl|DEBUG|79|Keep-Alive-Timer|2021-03-29 23:34:12.355 PDT|SSLSocketImpl.java:479|duplex close of SSLSocket<br>
javax.net.ssl|DEBUG|79|Keep-Alive-Timer|2021-03-29 23:34:12.356 PDT|SSLSocketImpl.java:1569|close the underlying socket<br>
javax.net.ssl|DEBUG|79|Keep-Alive-Timer|2021-03-29 23:34:12.356 PDT|SSLSocketImpl.java:1588|close the SSL connection (initiative)<br>
javax.net.ssl|DEBUG|79|Keep-Alive-Timer|2021-03-29 23:34:12.356 PDT|SSLSocketImpl.java:727|close inbound of SSLSocket<br>
javax.net.ssl|WARNING|79|Keep-Alive-Timer|2021-03-29 23:34:12.356 PDT|SSLSocketImpl.java:500|SSLSocket duplex close failed (
"throwable" : {
java.net.SocketException: Socket is closed
at java.base/java.net.Socket.shutdownInput(Socket.java:1538)
at java.base/sun.security.ssl.BaseSSLSocketImpl.shutdownInput(BaseSSLSocketImpl.java:216)
at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:742)
at java.base/sun.security.ssl.SSLSocketImpl.bruteForceCloseInput(SSLSocketImpl.java:692)
at java.base/sun.security.ssl.SSLSocketImpl.duplexCloseOutput(SSLSocketImpl.java:553)
at java.base/sun.security.ssl.SSLSocketImpl.close(SSLSocketImpl.java:485)
at java.base/sun.net.www.http.HttpClient.closeServer(HttpClient.java:1058)
at java.base/sun.net.www.http.KeepAliveCache.run(KeepAliveCache.java:183)
at java.base/java.lang.Thread.run(Thread.java:834)
at java.base/jdk.internal.misc.InnocuousThread.run(InnocuousThread.java:134)
}
I am really puzzled about where is this error came out.

I experienced this behavior with openJDK11 and above, it seems due to the new implementation of SSL/TLS channel in Java 11 in order to support TLSv1.3. The error it is noticed when it is called a server that supports also TLSv1.3, the JVM tries to open a channel using this protocol with no luck, evidently it is not fully supported yet.
I found a workaround (useful in OpenJDK11) by forcing TLSv1.2, just add the following options to JVM at application startup: -Djdk.tls.client.protocols=TLSv1.2 -Dhttps.protocols=TLSv1.2
Notice that this solution does not always work, it depends also by your java code and used libs.
A second way is to downgrade to Jdk1.8, that in default builds does not support TLSv1.3, but it is not always possible.
If you want to investigate more in detail the TLS handshake add also the following JVM parameter at startup: -Djavax.net.debug=ssl (for more details set it to all)
Edit
I initially experienced this error in Jenkins on openJDK11 during updates in "add-on manager" from 02/2021, when the repository added the support to TLSv1.3 (https://updates.jenkins.io). During the investigation of the issue I found and tried with jdk11 the following code from jenkins issue report:
public class DownloadWebpageExample {
public static void main(String[] args) {
try {
URL url = new URL("https://updates.jenkins.io/download/plugins/plugin-util-api/1.2.5/plugin-util-api.hpi");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
readStream(con.getInputStream());
// Give output for the command line
} catch (Exception e) {
e.printStackTrace();
}
}
private static void readStream(InputStream in)
{
char[] buf = new char[1024];
try (BufferedReader reader = new BufferedReader(new InputStreamReader(in));) {
while (reader.read(buf, 0, 1024) != -1) { }
} catch (IOException e) {
e.printStackTrace();
}
}
}
by running it with java -Djavax.net.debug=ssl DownloadWebpageExample it gives the error as above:
javax.net.ssl|DEBUG|01|main|2021-06-11 12:40:59.499 CEST|SSLSocketImpl.java:636|close inbound of SSLSocket
javax.net.ssl|WARNING|01|main|2021-06-11 12:40:59.501 CEST|SSLSocketImpl.java:494|SSLSocket duplex close failed (
"throwable" : {
java.net.SocketException: Socket is closed
at java.base/java.net.Socket.shutdownInput(Socket.java:1521)
By executing it with java -Djdk.tls.client.protocols=TLSv1.2 -Dhttps.protocols=TLSv1.2 -Djavax.net.debug=ssl DownloadWebpageExample does not solve the problem.I tried this code with many jdk versions and I found that jdk8 and openJDK9 are not affected by this behaviour, but it is in openJDK11-16.
In Jenkins I noticed a different behaviour, by adding the parameters in /etc/sysconfig/jenkins file like the following solved the problem with openJDK11. For me it is the confirmation that the error it is also dependent by source code implementation:
JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Djdk.tls.client.protocols=TLSv1.2 -Dhttps.protocols=TLSv1.2"

Was looking for the same thing, found https://bugs.openjdk.java.net/browse/JDK-8255148 which indicates that this logging is misleading.

Related

How to establish a FTPS data connection to a FileZilla Server 1.2.0

It is a known problem to use the Java FTPSClient of Apache commons-net with session resumption. Session resumption is a security feature which a FTPS server can require for data connections. The Apache FTPSClient does not support session resumption, and the JDK APIs make it hard to build a custom implementation. There are a couple of workarounds using reflection, see e.g. this answer and this commons-net bug entry.
I use such a workaround (see snipped below) in JDK 11 and tested it against a local FileZilla Server. It works with FileZilla Server 0.9.6, but it doesn't with FileZilla Server 1.2.0, which is the latest version at the time of writing. With that version, when trying to establish a data connection, the server responds with:
425 Unable to build data connection: TLS session of data connection not resumed.
As I said, FileZilla Server 0.9.6 is fine with how I do session resumption, and I made sure that the setting for requiring session resumption is activated.
In FileZilla Server 1.2.0, such settings are now set implicitly and cannot be changed via the GUI, maybe not at all. Are there some server settings that I can tweak for this to work? Or is it an issue with how I implemented the workaround? Does anyone experience similar issues?
This is the workaround I am using:
public class FTPSClientWithSessionResumption extends FTPSClient {
static {
System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
System.setProperty("jdk.tls.client.enableSessionTicketExtension", "false");
}
#Override
protected void _connectAction_() throws IOException {
super._connectAction_();
execPBSZ(0);
execPROT("P");
}
#Override
protected void _prepareDataSocket_(Socket socket) throws IOException {
if (useSessionResumption && socket instanceof SSLSocket) {
// Control socket is SSL
final SSLSession session = ((SSLSocket)_socket_).getSession();
if (session.isValid()) {
final SSLSessionContext context = session.getSessionContext();
try {
final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
sessionHostPortCache.setAccessible(true);
final Object cache = sessionHostPortCache.get(context);
final Method putMethod = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
putMethod.setAccessible(true);
Method getHostMethod;
try {
getHostMethod = socket.getClass().getMethod("getPeerHost");
}
catch (NoSuchMethodException e) {
// Running in IKVM
getHostMethod = socket.getClass().getDeclaredMethod("getHost");
}
getHostMethod.setAccessible(true);
Object peerHost = getHostMethod.invoke(socket);
InetAddress iAddr = socket.getInetAddress();
int port = socket.getPort();
putMethod.invoke(cache, String.format("%s:%s", peerHost, port).toLowerCase(Locale.ROOT), session);
putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostName(), port).toLowerCase(Locale.ROOT), session);
putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostAddress(), port).toLowerCase(Locale.ROOT), session);
}
catch (Exception e) {
throw new IOException(e);
}
}
else {
throw new IOException("Invalid SSL Session");
}
}
}
}
The address under which the socket is cached is determined using getPeerHost, getInetAddress().getHostName(), and getInetAddress().getHostAddress(). I tried several combinations of doing or not doing these three, but I always get the same result.
Edit:
Here is a screenshot of the server logs of the full session:
As stated in this StackOverflow post it is possible to tell the JVM that only TLS 1.2 should be used.
Here is the link to the original answer which worked for me: command for java to use TLS1.2 only
You have to add a command line parameter at the start of the JVM in this case this is: java -Djdk.tls.client.protocols=TLSv1.2 -jar ... <rest of command line here>
This simple parameter worked for me, now I can connect and transfer data from a FTP-Server wich runs FileZilla FTP-Server 1.3.0

Use of Java Smack 4.3.4 in a JUnit Testcase in Maven

I am working on a Java library with some services based on xmpp. For XMPP communication, I use Smack version 4.3.4. The development has so far been without problems and I have also created some test routines that can all be run without errors. After I migrated to a Maven project to generate a FatJar, I wanted to convert the executable test cases into JUnit tests. Unexpectedly, an error occurs, the reason of which I cannot explain. As I said, the code can be run outside of JUnit without any problems.
Below is the simplified test code (establishing a connection to the xmpp server):
#Test
public void connect()
{
Builder builder = XMPPTCPConnectionConfiguration.builder();
builder.setSecurityMode(SecurityMode.disabled);
builder.setUsernameAndPassword("iec61850client", "iec61850client");
builder.setPort(5222);
builder.setSendPresence(true);
try
{
builder.setXmppDomain("127.0.0.1");
builder.setHostAddress(InetAddress.getByName("127.0.0.1"));
}
catch (Exception e)
{
e.printStackTrace();
}
XMPPTCPConnectionConfiguration config = builder.build();
XMPPTCPConnection c = new XMPPTCPConnection(config);
c.setReplyTimeout(5000);
try
{
c.connect().login();
}
catch (Exception e)
{
e.printStackTrace();
}
}
And here is the error message I get:
Exception in thread "Smack Reader (0)" java.lang.AssertionError
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1154)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$1000(XMPPTCPConnection.java:1092)
at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:1112)
In Smack it boils down to this 'assert' instruction:
assert (config.getXMPPServiceDomain().equals(reportedServerDomain));
Any idea what the problem might be or similar problems? I'm grateful for any help!
Thanks a lot,
Markus
If you look at the source code you will find that reportedServerDomain is extracted from the server's stream open tag. In this case the xmpp domain reported by the server does not match the one that is configured. This should usually not happen, but I assume it is related to the way you run the unit tests. Or more precisely, related to the remote server or mocked server that is used in the tests. If you enable smack's debug output, you will see the stream open tag and the 'from' attribute and its value. Compare this with the configured XMPP service domain in the ConnectionConfiguration.

Regd httpclient.executeMethod(request); throws an IOException on server , whereas runs on local eclipse

Tried searching our blog but was not able to find some pointers so posting,
I was just working on a httpsClient Post method code as below and facing IOException. little Pointers may help , dont require detailed answers.
HttpClient httpclient = new HttpClient();
request = new PostMethod("https://ref.net/auth/token?grant_type=password");
request.setRequestHeader("Authorization", "Basic KolokYrZTo=");
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
NameValuePair[] data = {
new NameValuePair("username", "abc"),
new NameValuePair("password", "123"),
new NameValuePair("grant_type", "password"),
};
request.setRequestBody(data);
httpclient.executeMethod(request);
} catch (IOException e) {
e.printStackTrace();
logger.error( "IOException in post()...."+e.getMessage());
}
I am running this code on eclipse with commons-httpClient 3.1.jar it runs perfectly fine, But when i move my code to server and try to run the same code, the httpclient.executeMethod(request); throws IOException. To my surprise the e.printStackTrace(); does not prints as e object itself is null
How do i catch this exception and debug this, I am doing something wrong here.
On my local i have Java1.8 but running at compiler compliance level
1.6- On server. I tried running both 1.8 and 1.6 same error.
With the error message you added as comment it is clear what's happening here. The server you're connecting to is using a server certificate that the JVM you're using on the command shell doesn't know about.
If you search for this error message in combination with commons httpclient you can find a couple of pages discussion this, e.g. one at StackOverflow.

Java URLConnection Error

This error is from a PC connected to a comcast modem. Is port blocking an issue when a person is trying to make an outbound TCP channel with a Java URL . . . the relevant code is :
URL u = new URL("mailto:someguy#gmail.com"); // make a mailto: url
URLConnection c = u.openConnection(); // make its urlconnection
c.connect(); // connect to mail host
catch (Exception e) { // handle any exceptions, print error message
System.err.println(e);
}
The console returns the message :
connect. Timeout = -1
java.net.UnknownHostException: mailhost
MailToURLConnection is NOT in Java 6 or 7 or any earlier version. It is part of the OpenJDK implementation of J2SE specifications. Download and install OpenJDK and use that as your Java JDK and the problem will probably go away. I have checked, OpenJDK 6 has the MailToURLConnection class.
This exception java.net.UnknownHostException: mailhost is thrown to indicate that the IP address of a host could not be determined.
I reckon you might be trying to send a mail.
I cannot find any documentation but it seems URL.openConnection() above creates a sun.net.www.protocol.mailto.MailToURLConnection. Looking at the code here it creates an SmtpClient.
This creates a connection to System.getProperty("mail.host") or to "localhost" or to "mailhost". I guess the "mail.host" is not defined for you and localhost is not accepting the connection so the dns error for mailhost.
Where did find information to use "mailto:" anyway? That same place should also have the rest of usage documentation. If you were just trying something or ran into it accidentally then I would advice not to use it.

Check url existence without opening browser, in java

I want to check the existence of a url and i tried with the following code in java,
public boolean exists(String URLName) {
try {
if (!URLName.toUpperCase().contains("HTTP"))
URLName="http://"+URLName;
URL url = new URL(URLName);
System.setProperty("java.net.useSystemProxies", "true");
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
urlConn.setConnectTimeout(9000);
urlConn.setReadTimeout(9000);
urlConn.connect();
if(HttpURLConnection.HTTP_OK == urlConn.getResponseCode())
return true;
else
return false;
}
catch (SocketTimeoutException e){
return false;
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
The above code is working fine in windows but when the code is run through server (linux) i am getting the following error message,
GConf Error: Failed to contact configuration server; some possible
causes are that you need to enable TCP/IP networking for ORBit, or
you have stale NFS locks due to a system crash. See
http://projects.gnome.org/gconf/ for information. (Details - 1:
Not running within active session)
GConf Error: Failed to contact configuration server; some possible
causes are that you need to enable TCP/IP networking for ORBit, or
you have stale NFS locks due to a system crash. See
http://projects.gnome.org/gconf/ for information. (Details - 1:
Not running within active session)
java.net.UnknownHostException: www.ep.gov
at
java.net.PlainSocketImpl.connect(PlainSocketImpl.j ava:177)
at
java.net.SocksSocketImpl.connect(SocksSocketImpl.j ava:366)
at java.net.Socket.connect(Socket.java:525)
at sun.net.NetworkClient.doConnect(NetworkClient.java :158)
at
sun.net.http://www.http.HttpClient.openServe...lient.java:394)
at
sun.net.http://www.http.HttpClient.openServe...lient.java:529)
at sun.net.www.http.HttpClient.<init>(HttpClient.java :233)
at sun.net.www.http.HttpClient.New(HttpClient.java:306)
at sun.net.www.http.HttpClient.New(HttpClient.java:323)
at
sun.net.http://www.protocol.http.HttpURLConn...ction.java:860)
at
sun.net.http://www.protocol.http.HttpURLConn...ction.java:801)
at
sun.net.http://www.protocol.http.HttpURLConn...ction.java:726)
I got the below message from server admin
It is working, while it was run in X session (GUI Mode).
But it is not working in non-GUI mode. Please try to change the coding to make use of non-GUI mode." It seems the above code is making use of GUI mode.
I need an alternate code to check url existence without using GUI.
Regards
Linda
UnknownHostException means that the request is not reaching to its destination. There could be many reason that the linux server is unreachable to the desired URL www.ep.gov.
Please make sure that the server can reach the URL www.ep.gov.
I think your problem is with this line:
System.setProperty("java.net.useSystemProxies", "true");
It seems this causes the system to try and find the HTTP proxy configuration for the web browser, and ends up running into some problems with the Gnome configuration.
Do you actually need to use a HTTP proxy? If not, simply remove that line. If you do, read this page to learn how to configure proxies.

Categories

Resources