Results 1 to 5 of 5
  1. #1
    gforce40589 is offline Member
    Join Date
    Apr 2017
    Posts
    1
    Rep Power
    0

    Default Help with defensive coding technique in java

    I have a the following four classes..

    FTPApplication- Models FTP commands in a modular, extendible way. This abstract class provides
    several methods used by both the client and server.
    ServerSession- Models an FTP session with a client. Implements methods declared by FTPApplication
    from the perspective of an FTP server.
    FTPServer- A pseudo FTP server. Accepts client connection and initiates a session.
    FTPClient- A pseudo-FTP client. Connects to server and enters a control loop which enables it to
    query the server.

    I want to make appropriate changes to harden the software system against attack and misuse. How can I do that and what changes do I need to make?
    This code is working correctly but I want to make it more secure and harden it for misuse.

    import java.io.*;
    import java.net.Socket;
    import java.text.MessageFormat;
    import java.util.StringTokenizer;

    /**
    * Models FTP commands in a modular, extendible way. This abstract class
    * provides several methods used by both the client and server.
    *

    abstract public class FTPApplication {
    /* constants common to the client and server */
    static final int SOCKET_TIMEOUT = 300000;
    static final int ERROR = -1;
    static final String DEFAULT_FILEBASE = "user.dir";

    /* FTP commands */
    static final String PUT = "put";
    static final String GET = "get";
    static final String LS = "ls";
    static final String EXIT = "exit";

    /* Path to the directory from which to serve or store files */
    protected String fileBase;

    /* Network I/O objects used for sending/receiving data */
    protected Socket socket;
    protected BufferedReader lineIn;
    protected PrintWriter lineOut;

    /* Flag used to break session loop */
    protected boolean exitRecieved = false;

    // ----------------------------------------------------------------------
    // CONSTRUCTOR
    // ----------------------------------------------------------------------

    /**
    * Default constructor. Establishes file base.
    *
    * @param filebase
    * The directory from which to read & write files.
    */
    public FTPApplication(String filebase) {
    try {
    File path = new File(filebase);
    this.fileBase = path.getCanonicalPath() + File.separator;
    } catch (IOException ioe) {
    this.fileBase = "";
    System.err.printf("Could not access %s: %s", filebase, ioe);
    }
    }

    // ----------------------------------------------------------------------
    // PROTECTED METHODS
    // ----------------------------------------------------------------------

    /**
    * Sets a timeout on the socket and instantiates I/O objects.
    *
    * @throws IOException
    */
    protected void setUpIO() throws IOException {
    if (socket != null) {
    socket.setSoTimeout(SOCKET_TIMEOUT);
    InputStreamReader input = new InputStreamReader(
    socket.getInputStream());
    lineIn = new BufferedReader(input);
    lineOut = new PrintWriter(socket.getOutputStream(), true);
    } else {
    System.err.println("Cannot set up IO, socket is null.\n");
    }
    }

    /**
    * Closes the socket and its associated I/O objects.
    */
    protected void terminate() {
    try {
    System.out.printf("Terminating session ... ");
    if (lineIn != null) {
    lineIn.close();
    }

    if (lineOut != null) {
    lineOut.flush();
    lineOut.close();
    }

    if (socket != null) {
    socket.close();
    }

    System.out.printf("done.\n");

    } catch (IOException ioe) {
    System.err.printf("I/O Error terminating session: %s\n", ioe);
    }
    }

    /**
    * Calls the proper method based on user input.
    *
    * @param args
    * User arguments
    */
    protected void processCommand(StringTokenizer args) {
    if (args.hasMoreTokens()) {
    String command = args.nextToken();
    if (command.equalsIgnoreCase(PUT)) {
    String file = args.hasMoreTokens() ? args.nextToken() : null;
    handlePut(file);
    } else if (command.equalsIgnoreCase(GET)) {
    String file = args.hasMoreTokens() ? args.nextToken() : null;
    handleGet(file);
    } else if (command.equalsIgnoreCase(LS)) {
    handleLs();
    } else if (command.equalsIgnoreCase(EXIT)) {
    handleExit();
    } else {
    handleOther(true);
    }
    } else {
    handleOther(false);
    }
    }

    /**
    * Returns the path to the given file by prepending the filebase.
    *
    * @param file
    * target filename
    * @return full local path to file
    */
    protected String getFilePath(String file) {
    return MessageFormat.format("{0}{1}", fileBase, file);
    }

    /**
    * Read the given file from disk into a byte array.
    *
    * @param file
    * the target file
    * @return byte array containing file contents
    */
    protected byte[] readFile(File file) {
    byte[] data = new byte[(int) file.length()];

    try {
    System.out.printf("Loading %s ... ", file);
    FileInputStream fis = new FileInputStream(file);
    int amt = fis.read(data, 0, data.length);
    fis.close();
    System.out.printf("done (%d bytes).\n", amt);
    } catch (IOException ioe) {
    System.err.printf("Error reading file: %s\n", ioe);
    }

    return data;
    }

    /**
    * Writes a file to the filebase.
    *
    * @param data
    * Raw bytes of a file
    * @param filename
    * the name to give the new file.
    * @throws IOException
    */
    protected void storeFile(byte[] data, String filename) throws IOException {
    String toWrite = getFilePath(filename);
    System.out.printf("Storing file at %s... ", toWrite);
    FileOutputStream fileOut = new FileOutputStream(toWrite);
    fileOut.write(data);
    fileOut.flush();
    fileOut.close();
    System.out.printf("done.\n");
    }

    /**
    * Receives a byte[] as individual ints.
    *
    * @return a byte[] value
    */
    protected byte[] receiveData() throws IOException {
    // get amount of bytes expected
    int byteAmt = new Integer(lineIn.readLine());
    byte[] toReturn = new byte[byteAmt];

    // receive the bytes
    for (int i = 0; i < byteAmt; i++) {
    toReturn[i] = new Integer(lineIn.readLine()).byteValue();
    }

    return toReturn;
    }

    /**
    * Transmits bytes one by one as ints.
    *
    * @param bytes
    * a byte[] value
    */
    protected void sendData(byte[] bytes) {
    // tell receiver # of bytes to expect
    lineOut.println(bytes.length);

    // send each byte as ints, one-by-one
    for (byte aB : bytes) {
    lineOut.println(new Byte(aB).intValue());
    }
    }

    /**
    * Sends the string to over the socket.
    *
    * @param message
    */
    protected void sendMessage(String message) {
    sendData(message.getBytes());
    }

    /**
    * Receives a string from the socket.
    *
    * @return string received
    */
    protected String receiveMessage() throws IOException {
    return new String(receiveData());
    }

    // ----------------------------------------------------------------------
    // ABSTRACT METHODS - inherited & implemented by client and server
    // ----------------------------------------------------------------------

    /**
    * Uploads a client-side file to the server.
    *
    * @param filename
    */
    abstract protected void handlePut(String filename);

    /**
    * Downloads a file from the server
    *
    * @param filename
    */
    abstract protected void handleGet(String filename);

    /**
    * Lists the files available on the server.
    */
    abstract protected void handleLs();

    /**
    * Ends an FTP session, tearing down the server-client connection.
    */
    abstract protected void handleExit();

    /**
    * Models receiving bad input.
    *
    * @param invalidCmd
    */
    abstract protected void handleOther(boolean invalidCmd);

    }


    import java.io.BufferedReader;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.text.MessageFormat;
    import java.util.StringTokenizer;

    /**
    * A pseudo-FTP client. Connects to server and enters a control loop which
    * enables it to query the server.


    public class FTPClient extends FTPApplication {
    protected int port;
    protected InetAddress ip;

    // ----------------------------------------------------------------------
    // CONSTRUCTOR
    // ----------------------------------------------------------------------

    /**
    * Default constructor.
    *
    * @param port
    * The port to connect to on the server.
    * @param ip
    * The server's IP address
    * @param fileBase
    * The directory from which the client will read and write.
    */
    public FTPClient(int port, InetAddress ip, String fileBase) {
    super(fileBase);
    this.port = port;
    this.ip = ip;
    System.out.printf("Working out of %s\n", this.fileBase);
    }

    // ----------------------------------------------------------------------
    // PRIVATE METHODS
    // ----------------------------------------------------------------------

    /**
    * Prints usage message to the console.
    */
    private static void printUsage() {
    System.out.printf("Usage: FTPClient -i <ip> -p <port> [options]\n\n");
    System.out.printf("\tWhere valid options include: \n");
    System.out.printf("\t\t -h \t Prints usage \n");
    System.out.printf("\t\t -d \t File directory \n");
    }

    // ----------------------------------------------------------------------
    // INHERITED, PROTECTED METHODS
    // ----------------------------------------------------------------------

    /**
    * Checks that the specified file is valid, then transmits the file's name,
    * size, and data. After transmission, the client waits for a response from
    * the server.
    *
    * @param filename
    * Name of the file to send.
    */
    protected void handlePut(String filename) {
    // confirm existence of file
    File file = new File(getFilePath(filename));
    if (!file.exists()) {
    System.err.printf("%s does not exist.\n", file);
    handleOther(false);
    } else {
    try {
    // send filename
    System.out.printf("Sending filename ... ");
    sendMessage(MessageFormat.format("{0} {1}", PUT, filename));
    System.out.printf("done.\n");

    // send data
    byte[] data = readFile(file);
    sendData(data);

    // await reply
    System.out.printf("Server reply: ");
    String reply = receiveMessage();
    System.out.printf("%s\n", reply);
    } catch (IOException ioe) {
    ioe.printStackTrace();
    }
    }
    }

    /**
    * Sends the request to the server, receives the length of the file (if it
    * exists), and receives the file's data.
    *
    * @param filename
    * Name of the file to receive.
    */
    protected void handleGet(String filename) {
    try {
    // request file
    sendMessage(MessageFormat.format("{0} {1}", GET, filename));

    // receive file length
    System.out.printf("Receiving length ... ");
    String input = receiveMessage();
    long length = (input != null) ? Long.valueOf(input) : ERROR;
    System.out.printf("done.\n");

    // in case the file doesn't exist on the server side
    if (length == ERROR) {
    System.out.printf("Server: %s does not exist.\n", filename);
    } else {
    // GET DATA
    byte[] data = receiveData();

    // SAVE DATA
    storeFile(data, filename);
    System.out.printf("Received %s OK.\n", filename);
    }

    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    /**
    * Sends the listing request to the server, receives the amount of files
    * there are, and receives each filename.
    */
    protected void handleLs() {
    try {
    // request listing
    sendMessage(LS);

    // receive number of files
    String input = receiveMessage();
    int fileAmt = input != null ? Integer.valueOf(input) : ERROR;

    // receive and print names of files
    if (fileAmt != ERROR) {
    for (int i = 0; i < fileAmt; i++) {
    System.out.printf("\t%s\n", receiveMessage());
    }
    }

    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    /**
    * Models receiving a null or invalid command
    *
    * @param invalidCmd
    * If true, prints message stating that an invalid cmd was
    * received.
    */
    protected void handleOther(boolean invalidCmd) {
    sendMessage("\n");
    if (invalidCmd) {
    System.err.printf("Invalid command.\n");
    }
    }

    /**
    * Sends an exit signal to the server and terminates the connection.
    */
    protected void handleExit() {
    sendMessage(EXIT);
    exitRecieved = true;
    terminate();
    }

    // ----------------------------------------------------------------------
    // PUBLIC METHODS
    // ----------------------------------------------------------------------

    /**
    * Establish connection with server and create I/O objects.
    *
    * @return true if connection was established successfully.
    */
    public boolean connect() {
    boolean success = false;

    try {
    System.out.printf("Connecting to %s:%d ... ", ip, port);
    socket = new Socket(ip, port);
    setUpIO();
    success = true;
    System.out.printf("Established.\n");

    } catch (Exception e) {
    e.printStackTrace();
    }

    return success;
    }

    /**
    * Begins loop that allows client to send commands to the server.
    */
    public void queryServer() {
    if (lineIn == null || lineOut == null) {
    System.err.printf("Cannot query server, IO has not been set up\n");
    } else {
    try {
    String serverReply;
    String userInput;
    StringTokenizer args;
    InputStreamReader input = new InputStreamReader(System.in);
    BufferedReader console = new BufferedReader(input);

    // client-side control loop
    while (!exitRecieved) {
    // Wait for PROMPT
    serverReply = receiveMessage();
    System.out.printf("%s", serverReply);

    // ACCEPT & PROCESS USER INPUT
    userInput = console.readLine();
    userInput = userInput == null ? "" : userInput;
    args = new StringTokenizer(userInput);
    processCommand(args);
    }

    // clean up
    console.close();
    input.close();

    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

    /**
    * Driver for FTPClient
    *
    * @param args
    * Command-line arguments
    */
    public static void main(String[] args) {
    int port = -1;
    String directory = System.getProperty(FTPApplication.DEFAULT_FILEBASE );
    InetAddress ip = null;

    // Process arguments
    boolean helpRequested = false;
    for (int index = 0; !helpRequested && index < args.length; index++) {
    if (args[index].length() == 2 & args[index].charAt(0) == '-') {
    switch (args[index].charAt(1)) {
    case 'p':
    if (index + 1 >= args.length) {
    System.err.println("Port number expected.");
    helpRequested = true;
    } else {
    port = Integer.valueOf(args[++index]);
    }
    break;
    case 'h':
    helpRequested = true;
    break;
    case 'd':
    if (index + 1 >= args.length) {
    System.err.println("Directory expected.");
    helpRequested = true;
    } else {
    File path = new File(args[++index]);
    if (path.exists()) {
    directory = args[index];
    } else {
    System.err.println("Invalid directory");
    helpRequested = true;
    }
    }
    break;
    case 'i':
    if (index + 1 >= args.length) {
    System.err.println("IP address expected.");
    helpRequested = true;
    } else {
    try {
    ip = InetAddress.getByName(args[++index]);
    } catch (UnknownHostException uhe) {
    System.err.printf("Bad address: %s\n", uhe);
    helpRequested = true;
    }
    }
    break;
    default:
    helpRequested = true;
    break;
    }
    } else {
    helpRequested = true;
    }
    }

    // Begin execution
    if (helpRequested || port == -1 || ip == null) {
    printUsage();
    } else {
    FTPClient client = new FTPClient(port, ip, directory);
    if (client.connect()) {
    client.queryServer();
    }
    }
    }

    }


    import java.io.File;
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;

    /**
    * A pseudo FTP server. Accepts client connection and initiates a session.


    public class FTPServer {
    protected int port;
    protected String fileBase;

    // ----------------------------------------------------------------------
    // CONSTRUCTOR
    // ----------------------------------------------------------------------

    /**
    * Default constructor.
    *
    * @param port
    * Port which the server will listen on.
    * @param fileBase
    * The path to the directory from which files will be served
    */
    public FTPServer(int port, String fileBase) {
    this.port = port;
    this.fileBase = fileBase;
    }

    // ----------------------------------------------------------------------
    // PRIVATE METHODS
    // ----------------------------------------------------------------------

    /**
    * Prints usage message to the console.
    */
    private static void printUsage() {
    System.out.printf("Usage: FTPServer -p <port> [options] \n\n");
    System.out.printf("\tWhere valid options include: \n");
    System.out.printf("\t\t -h \t Prints usage \n");
    System.out.printf("\t\t -d \t File directory \n");
    }

    // ----------------------------------------------------------------------
    // PUBLIC METHODS
    // ----------------------------------------------------------------------

    /**
    * Performs a passive open and accepts a client. ServerSession objects are
    * instantiated to serve client requests.
    */
    public void acceptClients() {
    try {
    // initiate server socket
    System.out.printf("Creating socket ... ");
    ServerSocket serverSocket = new ServerSocket(port);
    serverSocket.setSoTimeout(FTPApplication.SOCKET_TI MEOUT);
    System.out.printf("Bound to %s:%s \n", InetAddress.getLocalHost(),
    serverSocket.getLocalPort());

    // listen for clients
    System.out.printf("Listening for connections ... ");
    Socket clientSocket = serverSocket.accept();
    System.out.printf("Accepted client from %s\n", clientSocket);

    // SERVE THE CLIENT
    ServerSession session = new ServerSession(clientSocket, fileBase);
    session.serveClient();

    // clean up
    System.out.printf("Closing socket ... ");
    serverSocket.close();
    System.out.printf("done.");

    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    /**
    * Driver for the FTPServer.
    *
    * @param args
    * command line arguments
    */
    public static void main(String[] args) {
    int port = -1;
    String directory = System.getProperty(FTPApplication.DEFAULT_FILEBASE );

    // Process arguments
    boolean helpRequested = false;
    for (int index = 0; !helpRequested & index < args.length; index++) {
    if (args[index].length() == 2 & args[index].charAt(0) == '-') {
    switch (args[index].charAt(1)) {
    case 'p':
    if (index + 1 >= args.length) {
    System.err.println("Port number expected.");
    helpRequested = true;
    } else {
    port = Integer.valueOf(args[++index]);
    }
    break;
    case 'h':
    helpRequested = true;
    break;
    case 'd':
    if (index + 1 >= args.length) {
    System.err.println("Directory expected.");
    helpRequested = true;
    } else {
    File path = new File(args[++index]);
    if (path.exists()) {
    directory = args[index];
    } else {
    System.err.println("Invalid directory");
    helpRequested = true;
    }
    }
    break;
    default:
    helpRequested = true;
    break;
    }
    } else {
    helpRequested = true;
    }

    }

    // Begin execution
    if (helpRequested || port == -1) {
    printUsage();
    } else {
    FTPServer server = new FTPServer(port, directory);
    server.acceptClients();
    }
    }

    }


    import java.io.File;
    import java.io.IOException;
    import java.net.Socket;
    import java.util.StringTokenizer;


    public class ServerSession extends FTPApplication {
    private static final String PROMPT = "secFTP>";

    // ----------------------------------------------------------------------
    // CONSTRUCTOR
    // ----------------------------------------------------------------------

    /**
    * Default constructor. Sets up I/O objects associated with the socket.
    *
    * @param socket
    * Network endpoint connected to a client.
    * @param filePath
    * Path to the file base.
    */
    public ServerSession(Socket socket, String filePath) throws IOException {
    super(filePath);
    System.out.printf("Serving files out of %s. \n", fileBase);
    this.socket = socket;
    setUpIO();
    }

    // ----------------------------------------------------------------------
    // PROTECTED METHODS
    // ----------------------------------------------------------------------

    /**
    * Receives the name, length, and data of the file to upload. The data
    * received is written to a file and a status message is sent.
    *
    * @param filename
    * the name of the file to upload.
    */
    protected void handlePut(String filename) {
    boolean success = false;

    try {
    System.out.printf("Receiving %s\n", filename);

    // GET DATA
    byte[] data = receiveData();

    // SAVE DATA
    if (data != null) {
    storeFile(data, filename);
    success = true;
    }

    } catch (IOException ioe) {
    System.err.printf("I/O error receiving file: %s\n", ioe);
    } catch (NumberFormatException nfe) {
    System.err.printf("Invalid length specified: %s\n", nfe);
    }

    // SEND REPLY
    System.out.printf("Sending reply ... ");
    String message = success ? "PUT OK" : "PUT FAILED";
    sendMessage(message);
    System.out.printf("done.\n");
    }

    /**
    * Determines if the specified file exists, and sends the file's length and
    * data.
    *
    * @param filename
    * name of the file to transmit.
    */
    protected void handleGet(String filename) {
    System.out.printf("Preparing to send %s ... \n", filename);

    // CHECK EXISTANCE OF FILE, AND SEND LENGTH
    File file = new File(getFilePath(filename));
    if (!file.exists()) {
    System.err.printf("%s does not exist.\n", file);
    sendMessage(String.valueOf(ERROR));
    } else {
    // send length
    System.out.printf("Sending length ... ");
    sendMessage(String.valueOf(file.length()));
    System.out.printf("done.\n");

    // send data
    byte[] data = readFile(file);
    sendData(data);
    }
    }

    /**
    * Determines the available files, then sends the number, followed by names
    * of them.
    */
    protected void handleLs() {
    System.out.printf("Listing available files.\n");

    File[] availableFiles = new File(fileBase).listFiles();

    if (availableFiles == null) {
    System.err.printf("%s is not a directory.\n", fileBase);
    sendMessage(String.valueOf(ERROR));
    } else {
    sendMessage(String.valueOf(availableFiles.length)) ;

    /* send each file name */
    for (File file : availableFiles) {
    sendMessage(file.getName());
    }
    }
    }

    /**
    * Models receiving an invalid or null command: ignore it.
    *
    * @param invalidCmd
    */
    protected void handleOther(boolean invalidCmd) {
    // do nothing
    }

    /**
    * Terminates connection to client, toggles control loop variable.
    */
    protected void handleExit() {
    exitRecieved = true;
    terminate();
    }

    // ----------------------------------------------------------------------
    // PUBLIC METHODS
    // ----------------------------------------------------------------------

    /**
    * Initiates the service loop that serves client requests.
    */
    public void serveClient() {
    if (lineIn == null || lineOut == null) {
    System.err.printf("I/O has not been set up.\n");
    } else {
    try {
    String clientRequest;
    StringTokenizer args;

    // control loop, receiving client requests
    while (!exitRecieved) {
    // PRESENT PROMPT
    sendMessage(PROMPT);

    // ACCEPT & PROCESS INPUT
    clientRequest = receiveMessage();
    clientRequest = clientRequest == null ? "" : clientRequest;
    args = new StringTokenizer(clientRequest);
    processCommand(args);
    }

    } catch (IOException ioe) {
    System.err.printf("IO Error receiving client input: %s\n", ioe);
    }
    }
    }

    }

  2. #2
    Norm's Avatar
    Norm is online now Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    19,966
    Rep Power
    31

    Default Re: Help with defensive coding technique in java

    Please edit your post and wrap your code with code tags:

    [code]
    **YOUR CODE GOES HERE**
    [/code]

    to get highlighting and preserve formatting.
    If you don't understand my response, don't ignore it, ask a question.

  3. #3
    Norm's Avatar
    Norm is online now Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    19,966
    Rep Power
    31

    Default Re: Help with defensive coding technique in java

    If you don't understand my response, don't ignore it, ask a question.

  4. #4
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    13,541
    Rep Power
    26

    Default Re: Help with defensive coding technique in java

    That's an awful lot of code to expect people to go through.
    Please do not ask for code as refusal often offends.

    ** This space for rent **

  5. #5
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    6,226
    Rep Power
    13

    Default Re: Help with defensive coding technique in java

    Which is why I didn't.

    Regards,
    Jim
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

Similar Threads

  1. Replies: 6
    Last Post: 11-15-2012, 09:39 AM
  2. Replies: 1
    Last Post: 10-27-2012, 03:22 PM
  3. [Ask] Good Decomposition Technique
    By YLTO in forum New To Java
    Replies: 2
    Last Post: 07-07-2011, 10:04 AM
  4. need advice regarding coding technique
    By Basit56 in forum New To Java
    Replies: 4
    Last Post: 01-08-2010, 04:28 PM
  5. Programing Technique question - Try or If
    By TimHuey in forum New To Java
    Replies: 6
    Last Post: 09-15-2009, 10:03 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •