[
https://issues.apache.org/jira/browse/NET-326?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13005100#comment-13005100
]
Bogdan Drozdowski commented on NET-326:
---------------------------------------
Terence, you didn't show us:
* your code
* the way you're running your code
* the server's configuration.
Since you're saying that a KeyManager is required, I'm guessing that the FTP
server connecting to you in active mode as a "client" requires you to provide
your certificate/key. Since there's no default certificate, the connection
fails. If this is true, then to reproduce this (if anyone's interested):
* install vsftpd (the easiest, I guess) and set in the config file:
** require_ssl_reuse=no
** ssl_enable=yes
** ssl_sslv3=yes
** ssl_tlsv1=yes
** rsa_cert_file=/path/to/your_certificate_and_key_file
** ssl_request_cert=yes
** require_cert=yes
* run the following code:
{code}
FTPSClient c = new FTPSClient ();
c.connect ("127.0.0.1", 21);
c.enterLocalActiveMode();
System.out.println (c.getReplyString());
c.login ("login", "password");
System.out.println (c.getReplyString());
c.execPROT ("P");
System.out.println (c.getReplyString());
String[] names = c.listNames();
{code}
Now, to the point: for this to work automatically, the FTPSClient class would
have to have all the possible key/certificates. Because of the number of these,
this is impossible to have. The solution is the FTPSClient constructor with the
SSLContext parameter. A quick search on the Web (with the errors as the search
term) made me produce the following code:
{code}
private static X509TrustManager s_x509TrustManager;
static {
s_x509TrustManager = new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {}; }
public boolean isClientTrusted(java.security.cert.X509Certificate[]
chain) { return true; }
public boolean isServerTrusted(java.security.cert.X509Certificate[]
chain) { return true; }
public void checkServerTrusted(java.security.cert.X509Certificate[]
certificates, String authType)
{}
public void checkClientTrusted(java.security.cert.X509Certificate[]
certificates, String authType) {}
};
}
private static void testFTPS () throws Exception
{
SSLContext ctx;
KeyManagerFactory kmf;
KeyStore ks;
char[] passphrase = "aaaaaa".toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("keystore"), passphrase);
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), new X509TrustManager[]
{s_x509TrustManager}, null);
FTPSClient c = new FTPSClient (ctx);
c.connect ("127.0.0.1", 21);
c.enterLocalActiveMode();
System.out.println (c.getReplyString());
c.login ("login", "password");
System.out.println (c.getReplyString());
c.execPROT ("P");
System.out.println (c.getReplyString());
String[] names = c.listNames();
}
{code}
This code *works* when connecting to *the same* vsftpd server as before (when
the previous code caused an exception). To run this code, add the following
command-line options to "java" (don't know if still required actually, but
won't hurt):
* -Djavax.net.ssl.trustStore=truststore
* -Djavax.net.ssl.trustStorePassword=aaaaaa
Please read the [JSSE Reference
Guide|http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html],
especially the "Code Examples" section. That's where I got most of the
information I needed (especially about creating the keystores in files:
"keystore" used by the code, and "truststore" used on the command-line). I
think that only a certificate for "localhost" is required, but just in case,
I've also added a certificate for my hostname in the keystores.
Furthermore, if there's a KeyManager missing, you can always install your own
with the FTPSClient.setKeyManager method.
> A KeyManager is required when the protection level is set to 'P' with
> FTPSClient on active mode
> -----------------------------------------------------------------------------------------------
>
> Key: NET-326
> URL: https://issues.apache.org/jira/browse/NET-326
> Project: Commons Net
> Issue Type: Bug
> Components: FTP
> Affects Versions: 2.0
> Environment: Windows XP profesional service pack 2, Java Java
> 1.6.0_12-b04
> Reporter: Terence Dudouit
>
> Using a simple FTPS client that list a directory, when execPROT("P") is set
> and the active mode is on, the following exception is thrown :
> javax.net.ssl.SSLException: No available certificate or key corresponds to
> the SSL cipher suites which are enabled.
> at
> com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.checkEnabledSuites(SSLServerSocketImpl.java:303)
> at
> com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.accept(SSLServerSocketImpl.java:253)
> at
> org.apache.commons.net.ftp.FTPClient._openDataConnection_(FTPClient.java:489)
> at
> org.apache.commons.net.ftp.FTPSClient._openDataConnection_(FTPSClient.java:494)
> at org.apache.commons.net.ftp.FTPClient.listNames(FTPClient.java:1950)
> at org.apache.commons.net.ftp.FTPClient.listNames(FTPClient.java:1996)
> at
> fr.enovacom.eai.actions.dynamiques.protocole.ftp.FTPGet.testFTPS(FTPGet.java:379)
> at
> fr.enovacom.eai.actions.dynamiques.protocole.ftp.FTPGet.main(FTPGet.java:401)
> This doesn't occur on passive mode.
> The only way to make it work is to set a keyManager although there is no need
> for a client authentication.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira