in core/src/main/java/org/apache/ftpserver/impl/IODataConnectionFactory.java [237:364]
private synchronized Socket createDataSocket() throws Exception {
// get socket depending on the selection
dataSoc = null;
DataConnectionConfiguration dataConfig = session.getListener().getDataConnectionConfiguration();
try {
if (!passive) {
if (secure) {
LOG.debug("Opening secure active data connection");
SslConfiguration ssl = getSslConfiguration();
if (ssl == null) {
throw new FtpException("Data connection SSL not configured");
}
// get socket factory
SSLSocketFactory socFactory = ssl.getSocketFactory();
// create socket
SSLSocket ssoc = (SSLSocket) socFactory.createSocket();
ssoc.setUseClientMode(false);
// initialize socket
if (ssl.getEnabledCipherSuites() != null) {
ssoc.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
}
if (ssl.getEnabledProtocols() != null) {
ssoc.setEnabledProtocols(ssl.getEnabledProtocols());
}
dataSoc = ssoc;
} else {
LOG.debug("Opening active data connection");
dataSoc = new Socket();
}
dataSoc.setReuseAddress(true);
InetAddress localAddr = resolveAddress(dataConfig.getActiveLocalAddress());
// if no local address has been configured, make sure we use the same as the client connects from
if (localAddr == null) {
localAddr = ((InetSocketAddress) session.getLocalAddress()).getAddress();
}
SocketAddress localSocketAddress = new InetSocketAddress(localAddr, dataConfig.getActiveLocalPort());
LOG.debug("Binding active data connection to {}", localSocketAddress);
dataSoc.bind(localSocketAddress);
dataSoc.connect(new InetSocketAddress(address, port));
} else {
if (secure) {
LOG.debug("Opening secure passive data connection");
// this is where we wrap the unsecured socket as a SSLSocket. This is
// due to the JVM bug described in FTPSERVER-241.
// get server socket factory
SslConfiguration ssl = getSslConfiguration();
// we've already checked this, but let's do it again
if (ssl == null) {
throw new FtpException("Data connection SSL not configured");
}
SSLSocketFactory ssocketFactory = ssl.getSocketFactory();
Socket serverSocket = servSoc.accept();
SSLSocket sslSocket = (SSLSocket) ssocketFactory.createSocket(serverSocket, serverSocket.getInetAddress().getHostAddress(), serverSocket.getPort(), true);
sslSocket.setUseClientMode(false);
// initialize server socket
if (ssl.getClientAuth() == ClientAuth.NEED) {
sslSocket.setNeedClientAuth(true);
} else if (ssl.getClientAuth() == ClientAuth.WANT) {
sslSocket.setWantClientAuth(true);
}
if (ssl.getEnabledCipherSuites() != null) {
sslSocket.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
}
if (ssl.getEnabledProtocols() != null) {
sslSocket.setEnabledProtocols(ssl.getEnabledProtocols());
}
dataSoc = sslSocket;
} else {
LOG.debug("Opening passive data connection");
dataSoc = servSoc.accept();
}
if (dataConfig.isPassiveIpCheck()) {
// Let's make sure we got the connection from the same
// client that we are expecting
InetAddress remoteAddress = ((InetSocketAddress) session.getRemoteAddress()).getAddress();
InetAddress dataSocketAddress = dataSoc.getInetAddress();
if (!dataSocketAddress.equals(remoteAddress)) {
LOG.warn("Passive IP Check failed. Closing data connection from " + dataSocketAddress + " as it does not match the expected address " + remoteAddress);
closeDataConnection();
return null;
}
}
DataConnectionConfiguration dataCfg = session.getListener().getDataConnectionConfiguration();
dataSoc.setSoTimeout(dataCfg.getIdleTime() * 1000);
LOG.debug("Passive data connection opened");
}
} catch (Exception ex) {
closeDataConnection();
LOG.warn("FtpDataConnection.getDataSocket()", ex);
throw ex;
}
dataSoc.setSoTimeout(dataConfig.getIdleTime() * 1000);
// Make sure we initiate the SSL handshake, or we'll
// get an error if we turn out not to send any data
// e.g. during the listing of an empty directory
if (dataSoc instanceof SSLSocket) {
((SSLSocket) dataSoc).startHandshake();
}
return dataSoc;
}