package de.tudarmstadt.informatik.hostage.protocol; import java.util.ArrayList; import java.util.List; import de.tudarmstadt.informatik.hostage.wrapper.Packet; /** * FTP protocol. Implementation of RFC document 959. It can handle the following * requests: USER, PASS, QUIT. * * @author Wulf Pfeiffer */ public class FTP implements Protocol { /** * Represents the states of the protocol */ private static enum STATE { NONE, OPEN, CLOSED, USER, LOGGED_IN }; /** * Denotes in which state the protocol is right now */ private STATE state = STATE.NONE; // commands private static final String REPLY_CODE_220 = "220 Service ready for new user."; private static final String REPLY_CODE_221 = "221 Service closing control connection."; private static final String REPLY_CODE_230 = "230 User logged in."; private static final String REPLY_CODE_331 = "331 User name ok, need password."; private static final String REPLY_CODE_332 = "332 Need account for login."; private static final String REPLY_CODE_421 = "421 Service not available, closing control connection."; private static final String REPLY_CODE_500 = "500 Syntax error, command unrecognized."; private static final String REPLY_CODE_501 = "501 Syntax error in parameters or arguments"; @Override public int getPort() { return 21; } @Override public boolean isClosed() { return state == STATE.CLOSED; } @Override public boolean isSecure() { return false; } @Override public List processMessage(Packet requestPacket) { String request = null; if (requestPacket != null) { request = requestPacket.toString(); } List responsePackets = new ArrayList(); switch (state) { case NONE: if (request == null) { state = STATE.OPEN; responsePackets.add(new Packet(REPLY_CODE_220)); } else { state = STATE.CLOSED; responsePackets.add(new Packet(REPLY_CODE_421)); } break; case OPEN: if (request.contains("QUIT")) { state = STATE.CLOSED; return null; } else if (request.equals("USER \r\n")) { responsePackets.add(new Packet(REPLY_CODE_501)); } else if (request.contains("USER")) { state = STATE.USER; responsePackets.add(new Packet(REPLY_CODE_331)); } else { responsePackets.add(new Packet(REPLY_CODE_332)); } break; case USER: if (request.equals("PASS \r\n")) { state = STATE.OPEN; responsePackets.add(new Packet(REPLY_CODE_501)); } else if (request.contains("PASS")) { state = STATE.LOGGED_IN; responsePackets.add(new Packet(REPLY_CODE_230)); } else { state = STATE.CLOSED; responsePackets.add(new Packet(REPLY_CODE_221)); } break; case LOGGED_IN: if (request != null && !request.contains("QUIT")) { responsePackets.add(new Packet(REPLY_CODE_500)); } else { state = STATE.CLOSED; responsePackets.add(new Packet(REPLY_CODE_221)); } break; default: state = STATE.CLOSED; responsePackets.add(new Packet(REPLY_CODE_421)); } return responsePackets; } @Override public String toString() { return "FTP"; } @Override public TALK_FIRST whoTalksFirst() { return TALK_FIRST.SERVER; } }