You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Bogdan Drozdowski (JIRA)" <ji...@apache.org> on 2011/03/10 16:17:59 UTC

[jira] Commented: (NET-326) A KeyManager is required when the protection level is set to 'P' with FTPSClient on active mode

    [ 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