0

I try connect to a FTPS server and got this error. My server only open port 21. I try connect with FileZilla with same config and OK but not in java code. Here my code

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;
import org.apache.commons.net.util.TrustManagerUtils;

import java.io.ByteArrayInputStream;

public class FTPsX {
    private static final String ftpUrl = "192.168.0.100";
    private static final int ftpPort = 21;
    private static final String ftpUserName = "root";
    private static final String ftpUserPassword = "admin123";

    public static void main(String[] args) {
        try {
            System.setProperty("https.protocols", "TLSv1.2");
            FTPSClient ftpsClient = new FTPSClient("TLSv1.2", false);
            ftpsClient.addProtocolCommandListener(
                    new PrintCommandListener(
                            new PrintWriter(new OutputStreamWriter(System.out, "UTF-8")), true));
            ftpsClient.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
            ftpsClient.setUseClientMode(true);

            ftpsClient.connect(ftpUrl, ftpPort);
            int reply = ftpsClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpsClient.disconnect();
                throw new Exception("Failed to connect properly to FTP");
            }
            ftpsClient.login(ftpUserName, ftpUserPassword);
            ftpsClient.setFileType(FTP.BINARY_FILE_TYPE);

            ftpsClient.execPBSZ(0);
            ftpsClient.execPROT("P");
            ftpsClient.enterLocalPassiveMode();
            ftpsClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
            ftpsClient.storeFile("error_here", new ByteArrayInputStream("test".getBytes()));

            ftpsClient.logout();
            ftpsClient.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

And this is the error

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1009)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1388)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1416)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1400)
    at org.apache.commons.net.ftp.FTPSClient._openDataConnection_(FTPSClient.java:646)
    at org.apache.commons.net.ftp.FTPClient._storeFile(FTPClient.java:653)
    at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:639)
    at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:2030)
    at FTPsX.main(FTPsX.java:35)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.InputRecord.read(InputRecord.java:505)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:990)
    ... 8 more

I tried set some but not work. The command storeFile can create file with 0 byte and error come.

I already try add -Djdk.tls.useExtendedMasterSecret=false but no luck.

This is the log in FileZilla

09:58:12    Command:    AUTH TLS
09:58:12    Response:   234 Security mechanism set to TLS
09:58:12    Status: Initializing TLS...
09:58:12    Trace:  TLS Handshake successful
09:58:12    Trace:  Protocol: TLS1.2, Key exchange: ECDHE-RSA, Cipher: AES-256-GCM, MAC: AEAD
09:58:12    Status: Verifying certificate...
09:58:12    Status: TLS connection established.
09:58:12    Command:    USER root
09:58:12    Response:   331 Need password
09:58:12    Command:    PASS ***********
09:58:12    Response:   230 User logged in
09:58:12    Command:    OPTS UTF8 ON
09:58:12    Response:   202 The UTF8 option is already enabled
09:58:12    Command:    PBSZ 0
09:58:12    Response:   200 PBSZ=0
09:58:12    Command:    PROT P
09:58:12    Response:   200 Data protection level set to Private
09:58:12    Status: Logged in
09:58:12    Trace:  Measured latency of 141 ms
09:58:12    Status: Retrieving directory listing...
09:58:12    Command:    PWD
09:58:12    Response:   257 "/" is current directory
09:58:13    Status: Directory listing of "/" successful
------ File upload -------------
14:03:25    Command:    TYPE I
14:03:25    Response:   200 Representation type set to Image
14:03:25    Command:    PASV
14:03:25    Response:   227 Entering Passive Mode (192,168,0,100,31,153)
14:03:25    Trace:  Binding data connection source IP to control connection source IP 192.168.0.100
14:03:25    Command:    STOR test-270.log
14:03:25    Trace:  Trying to resume existing TLS session.
14:03:25    Response:   150 Opening data connection
14:03:25    Trace:  TLS Handshake successful
14:03:25    Trace:  TLS Session resumed
14:03:25    Trace:  Protocol: TLS1.2, Key exchange: ECDHE-RSA, Cipher: AES-256-GCM, MAC: AEAD
14:03:25    Response:   226 Data connection completed successfully
14:03:25    Status: File transfer successful, transferred 613,612 bytes in 1 second

I tried add custom FTPSClient as Martin Prikryl suggest:

import org.apache.commons.net.ftp.FTPSClient;

import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Locale;

public class SSLSessionReuseFTPSClient extends FTPSClient {
    public SSLSessionReuseFTPSClient(boolean isImplict) {
        super(isImplict);
    }

    @Override
    protected void _prepareDataSocket_(final Socket socket) throws IOException {
        System.out.println("_prepareDataSocket_");
        if (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 method = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
                    method.setAccessible(true);
                    String hostNameAddr = String
                            .format("%s:%s", socket.getInetAddress().getHostName(), socket.getPort())
                            .toLowerCase(Locale.ROOT);
                    System.out.println("hostNameAddr: " + hostNameAddr);
                    method.invoke(cache, hostNameAddr, session);

                    String hostAddressAddr = String
                            .format("%s:%s", socket.getInetAddress().getHostAddress(), socket.getPort())
                            .toLowerCase(Locale.ROOT);
                    System.out.println("hostAddressAddr: " + hostAddressAddr);
                    method.invoke(cache, hostAddressAddr, session);
                } catch (Exception e) {
                    throw new IOException(e);
                }
            } else {
                throw new IOException("Invalid SSL Session");
            }
        }
    }
}

but still get error

220 Bitvise SSH Server 8.44: free only for personal non-commercial use
FEAT
211-Features:
 LANG EN*
 UTF8
 MDTM
 SIZE
 REST STREAM
 TVFS
 AUTH TLS
 AUTH SSL
 PROT
 PBSZ
 EPSV
 HASH SHA-512;SHA-256;SHA-1*;MD5;CRC32
 XCRC "filename" SP EP
 XMD5 "filename" SP EP
 XSHA "filename" SP EP
 XSHA1 "filename" SP EP
 XSHA256 "filename" SP EP
 XSHA512 "filename" SP EP
211 End
AUTH TLS
234 Security mechanism set to TLS
USER *******
331 Need password
PASS *******
230 User logged in
TYPE I
200 Representation type set to Image
PBSZ 0
200 PBSZ=0
PROT P
200 Data protection level set to Private
TYPE A
200 Representation type set to ASCII Non-print
PASV
227 Entering Passive Mode (192,168,0,100,31,153)
STOR n8yd
150 Opening data connection
_prepareDataSocket_
hostNameAddr: 192.168.0.100:8089
hostAddressAddr: 192.168.0.100:8089
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1009)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1388)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1416)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1400)
    at org.apache.commons.net.ftp.FTPSClient._openDataConnection_(FTPSClient.java:646)
    at org.apache.commons.net.ftp.FTPClient._storeFile(FTPClient.java:653)
    at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:639)
    at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:2030)
    at FTPs.main(FTPs.java:118)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.InputRecord.read(InputRecord.java:505)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:990)
    ... 8 more

Anyone have any suggestion about this ? Or any workaroud for this like sendCommand("stor","filename","text_file_content") ? or some how i can send command at low level the same as the FileZilla did ?

BlackKat
  • 247
  • 3
  • 8

0 Answers0