Ftplet which forces TLS/SSL for control and data channels when using explicit
FTPS
----------------------------------------------------------------------------------
Key: FTPSERVER-277
URL: https://issues.apache.org/jira/browse/FTPSERVER-277
Project: FtpServer
Issue Type: New Feature
Reporter: Niklas Therning
Priority: Minor
I've developed a simple Ftplet which forces the client to use secure control
and data channels when the server has been configured for explicit FTPS. The
code has been pasted below. Let me know what you think about it. I've tried it
with curl and it seems to work as expected both for passive and active data
channels. Feel free to include it in Ftpserver if you find it useful.
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.apache.ftpserver.ftplet.DefaultFtpReply;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.FtpReply;
import org.apache.ftpserver.ftplet.FtpRequest;
import org.apache.ftpserver.ftplet.FtpSession;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.ftplet.FtpletContext;
import org.apache.ftpserver.ftplet.FtpletResult;
/**
* {...@link Ftplet} which forces the client to use secure control and data
* channels when connecting in explicit FTPS mode. In implicit FTPS the control
* channel is always secure, however, the data channel can be plain text. This
* {...@link Ftplet} will not allow clients to open insecure data channels in
* implicit FTPS mode.
*
* @version $Id$
*/
public class ExplicitSslForcingFtplet implements Ftplet {
private static final String SECURE =
ExplicitSslForcingFtplet.class.getName() + ".secure";
private static final Set<String> DATA_CHANNEL_COMMANDS;
static {
DATA_CHANNEL_COMMANDS = new HashSet<String>();
DATA_CHANNEL_COMMANDS.add("APPE");
DATA_CHANNEL_COMMANDS.add("LIST");
DATA_CHANNEL_COMMANDS.add("MLSD");
DATA_CHANNEL_COMMANDS.add("NLST");
DATA_CHANNEL_COMMANDS.add("RETR");
DATA_CHANNEL_COMMANDS.add("STOR");
DATA_CHANNEL_COMMANDS.add("STOU");
}
public FtpletResult afterCommand(FtpSession session, FtpRequest request,
FtpReply reply) throws FtpException, IOException {
String cmd = request.getCommand().toUpperCase();
int code = reply.getCode();
if ("AUTH".equals(cmd) && code >= 200 && code < 300) {
session.setAttribute(SECURE, true);
}
return FtpletResult.DEFAULT;
}
public FtpletResult beforeCommand(FtpSession session, FtpRequest request)
throws FtpException, IOException {
String cmd = request.getCommand().toUpperCase();
boolean secure = (Boolean) session.getAttribute(SECURE);
if ("USER".equals(cmd)) {
if (!secure) {
session.write(new DefaultFtpReply(500, "Control channel not
secure. Issue AUTH command first."));
return FtpletResult.SKIP;
}
} else if (DATA_CHANNEL_COMMANDS.contains(cmd)) {
if (!session.getDataConnection().isSecure()) {
session.write(new DefaultFtpReply(500, "Data channel not
secure. Issue PROT command first."));
return FtpletResult.SKIP;
}
}
return FtpletResult.DEFAULT;
}
public void destroy() {
}
public void init(FtpletContext ftpletContext) throws FtpException {
}
public FtpletResult onConnect(FtpSession session) throws FtpException,
IOException {
session.setAttribute(SECURE, session.isSecure());
return FtpletResult.DEFAULT;
}
public FtpletResult onDisconnect(FtpSession session) throws FtpException,
IOException {
return FtpletResult.DEFAULT;
}
}
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.