First off, I know there is a similar question here but it doesn't answer my doubts. I have a FTPS server (vsftpd) configured with SSL.
I've generated the appropriate keys with:
openssl req -x509 -nodes -days 1825 -newkey rsa:2048 \
-keyout private/vsftpd.key \
-out certs/vsftpd.crt
And configured the respective conf file in the server.
Now, in the Java client code with Apache commons net, I'm able to communicate with the server over SSL with something like this:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;
public class CommonsNetFTPSTest {
public static void main(String[] args) throws Exception {
System.setProperty("javax.net.debug", "ssl");
String server = "XXX.XXX.XXX.XXX";
String username = "USER_TEST";
String password = "ABCD1234";
String remoteFile = "/Data/Input/PH240819";
String localFile = "PH240819";
String protocol = "SSL"; // TLS / null (SSL)
int port = 990;
int timeoutInMillis = 10000;
boolean isImpicit = true;
FTPSClient client = new FTPSClient(protocol, isImpicit);
client.setDataTimeout(timeoutInMillis);
client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
System.out.println("################ Connecting to Server ################################");
try
{
int reply;
System.out.println("################ Connect Call ################################");
client.connect(server, port);
client.login(username, password);
System.out.println("################ Login Success ################################");
//client.setFileType(FTP.BINARY_FILE_TYPE);
client.setFileType(FTP.NON_PRINT_TEXT_FORMAT);
client.execPBSZ(0); // Set protection buffer size
client.execPROT("P"); // Set data channel protection to private
client.enterLocalPassiveMode();
System.out.println("Connected to " + server + ".");
reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply))
{
client.disconnect();
System.err.println("FTP server refused connection.");
System.exit(1);
}
client.listFiles();
boolean retrieved = client.retrieveFile(remoteFile, new FileOutputStream(localFile));
}
catch (Exception e)
{
if (client.isConnected())
{
try
{
client.disconnect();
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
System.err.println("Could not connect to server.");
e.printStackTrace();
return;
}
finally
{
//client.disconnect();
client.logout();
System.out.println("# client disconnected");
}
}
}
But in that way my client is accepting any certificate, and I guess it's possible a man-in-the-middle attack. So I'd like to tell my client what certificates to accept, and only connect when the certificate is valid.
Now, I have both files generated previously: vsftpd.key and vsftpd.crt, and I've imported the crt file in a local keystore like this:
keytool -import -alias alias -file vsftps.crt -keypass keypass -keystore mykeystore.jks -storepass Hello1
My question is, How do I tell my client that use the certificate from mykeystore? what else am I missing?. Thanks