[ 
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

Reply via email to