android ftp file tranfer over explicit TLS

android, apache-commons-net, ftp, ftp-client, ftps

Solution

I have finally found a solution, the solution was to set the trust manager to accept all certificates. here is the code for those who are experiencing similar problems, maby it can be improved and/or optimized, but it works:

FTPSClient ftpClient = new FTPSClient("TLS", false);
try {
    TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(X509Certificate[] certs, String authType) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] certs, String authType) {
        }
    } };

    ftpClient.setTrustManager(trustManager[0]);
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(null, null);
    KeyManager km = kmf.getKeyManagers()[0];
    ftpClient.setKeyManager(km);
    ftpClient.setBufferSize(1024 * 1024);
    ftpClient.setConnectTimeout(100000);
    ftpClient.connect(InetAddress.getByName("ipaddress"), 990);
    ftpClient.setSoTimeout(100000);

    if (ftpClient.login("user", "password")) {
        ftpClient.execPBSZ(0);
        ftpClient.execPROT("P");
        ftpClient.changeWorkingDirectory("/");
        // 250 = directory succesfully changed
        if (ftpClient.getReplyString().contains("250")) {
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            BufferedInputStream buffIn = null;

            for (File picture : pictures) {
                buffIn = new BufferedInputStream(new FileInputStream(picture.getAbsolutePath()));
                boolean result = ftpClient.storeFile(picture.getName(), buffIn);
                try {
                    buffIn.close();
                } catch (Exception e) {
                }
                if (result)
                    picture.delete();
            }
        }
    }

} catch (SocketException e) {
    Log.e("APPTAG", e.getStackTrace().toString());
} catch (UnknownHostException e) {
    Log.e("APPTAG", e.getStackTrace().toString());
} catch (IOException e) {
    Log.e("APPTAG", e.getStackTrace().toString());
} catch (Exception e) {
    Log.e("APPTAG", e.getStackTrace().toString());
} finally {
    try {
        ftpClient.logout();
    } catch (Exception e2) {
    }
    try {
        ftpClient.disconnect();
    } catch (Exception e2) {
    }
}

Problem

I'm posting this question after have tried over and over again to get it working, with no success. I trying to implement a FTP file transfer in android, using apache commons library. The communication must be done through explicit TLS authentication. I can successfully login, connect to the server and list files, but whenever i try to get or store a file, I always get a timeout exception, also with very large timeout value, even for a 2Kb txt file. This is my code: ``` FTPSClient ftpClient = new FTPSClient("TLS", false); ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); KeyManagerFactory kmf = getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(null, null); KeyManager km = kmf.getKeyManagers()[0]; ftpClient.setKeyManager(km); ftpClient.setBufferSize(1024 * 1024); ftpClient.setConnectTimeout(900000); ftpClient.connect(InetAddress.getByName("server ip address"), 990); // Set protection buffer size ftpClient.execPBSZ(0); // // Set data channel protection to private ftpClient.execPROT("P"); ftpClient.login("user", "password"); ftpClient.changeWorkingDirectory("/"); ftpClient.setSoTimeout(900000); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); ftpClient.enterLocalPassiveMode(); buffIn = new BufferedInputStream(new FileInputStream(file.getAbsolutePath())); //this works FTPFile[] files = ftpClient.listFiles(); final OutputStream os = new FileOutputStream(finalStoragePath + "/OK.txt"); //this returns immediatly with false result boolean getResult=ftpClient.retrieveFile("OK.txt", os); //this always fail for timeout boolean result = ftpClient.storeFile( picture.getName(), buffIn ); ``` I can't find any example of this specific situation, all examples out there, are about normal FTP connection, which I can achieve with no problems. Did any of you had a similar problem? I really need a solution, I have to deliver the project ASAP. thanks.

Original source

Related problems