How to configure client authentication using apache.commons.net.ftps?

I implemented an FTP client (FTP over SSL / TLS) in java using apache.commons.net-framework. It is configured for explicit protection on standard port 21.

ftpsClient = new FTPSClient(false); ftpsClient.setTrustManager(getConfiguration().getCertificatesManager()); ftpsClient.connect(getConfiguration().getHostName(), getConfiguration().getPort()); 

Until I apply client authentication to the server, everything works fine. But I need to enable client authentication, so I use it on the server and configure the properties of the client system:

 -Djavax.net.ssl.keyStore="D:/.../ftps-client-auth.keystore" -Djavax.net.ssl.keyStorePassword="*****" -Djavax.net.ssl.keyStoreType=JKS 

What I got was the same as if I did not set the system properties:

 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1806) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:986) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181) at org.apache.commons.net.ftp.FTPSClient.sslNegotiation(FTPSClient.java:265) at org.apache.commons.net.ftp.FTPSClient._connectAction_(FTPSClient.java:207) at org.apache.commons.net.SocketClient.connect(SocketClient.java:172) at org.apache.commons.net.SocketClient.connect(SocketClient.java:192) 

The server log says:

 DEBUG: Client "<my ip address>", "SSL_accept failed: error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate" 

It looks like I have included -Djavax.net.debug = all, which indicates that the server is sending the CN list that it is receiving, but the client is sending an empty certificate chain.

  • What have I done wrong?
  • Do I need to do some configuration programmatically?
  • Do certificates or a private key need to support something special for SSL / TLS?
+4
source share
1 answer

It KeyManager out: you need to programmatically install KeyManager . Setting the system properties ( -Djavax.net.ssl.keyStore , ...) is not enough because Suns SSLSocketFactory not used in the structure.

Example:

 ftpsClient = new FTPSClient(false); ftpsClient.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager()); KeyManager keyManager = org.apache.commons.net.util.KeyManagerUtils.createClientKeyManager(new File(keystorePath), keystorePass); ftpsClient.setKeyManager(keyManager); ftpsClient.connect(getConfiguration().getHostName(), getConfiguration().getPort()); 

You might want to choose another Trust-Manager, for example. which is based on Java-keystore. The utilities also provide a method for this: TrustManagerUtils.getDefaultTrustManager(keystore)

+5
source

Source: https://habr.com/ru/post/1447187/


All Articles