Beispiel #1
0
        // Creates a data connection using the given command socket, mode, and message from the client giving the port
        public DataSocket(FTPSocket ftp, bool passive, string message)
        {
            if (passive)
            {
                // Establishes a server for the client to connect to in passive mode
                listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                listener.Bind(new IPEndPoint(ftp.LocalIP, 0));
                listener.Listen(1);

                var local = (IPEndPoint)listener.LocalEndPoint;
                var ip    = local.Address.ToString().Replace('.', ',');
                var port  = local.Port;

                ftp.Write("227 Entering Passive Mode ({0},{1},{2}).", ip, port / 256, port % 256);
            }
            else
            {
                // Connects to the clients data connection in active mode
                var match = Regex.Match(message, @"(\d+,\d+,\d+,\d+),(\d+),(\d+)");
                address = IPAddress.Parse(match.Groups[1].Value.Replace(',', '.'));
                port    = int.Parse(match.Groups[2].Value) * 256 + int.Parse(match.Groups[3].Value);

                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                ftp.Write("200 PORT command successful. Consider using PASV.");
            }
        }
Beispiel #2
0
        // Listens and responds to commands from the client
        public bool HandleCommand()
        {
            // Reads and extracts the command and arguments
            var input     = ftp.Read();
            var match     = Regex.Match(input, @"([^ ]+)(?: (.+))?");
            var command   = "";
            var arguments = "";

            if (match.Groups[1].Success)
            {
                command = match.Groups[1].Value.ToUpper();
            }
            if (match.Groups[2].Success)
            {
                arguments = match.Groups[2].Value;
            }

            // Stops if the client is not authenticated or authenticating
            if ((!user && command != "USER") || (!pass && command != "USER" && command != "PASS"))
            {
                ftp.Write("530 Please login with USER and PASS.");
                return(false);
            }

            switch (command)
            {
            // Moves the current path up 1 directory
            case "CDUP":
                path = Normalize(Path.Combine(".", path, ".."));
                ftp.Write("250 Directory successfully changed.");
                break;

            // Moves to the specified directory
            case "CWD":
                if (arguments.Length > 0)
                {
                    var temp = Path.Combine(".", path, arguments);
                    if (Directory.Exists(temp))
                    {
                        path = Normalize(temp);
                        ftp.Write("250 Directory successfully changed.");
                        break;
                    }
                }
                ftp.Write("550 Failed to change directory.");
                break;

            // Lists files in the current directory
            case "LIST":
                if (data == null)
                {
                    ftp.Write("425 Use PASV or PORT first.");
                    break;
                }

                ftp.Write("150 Here comes the directory listing.");
                data.SendDir(path);
                ftp.Write("226 Directory send OK.");
                data = null;
                break;

            // Accepts a password from the client
            case "PASS":
                ftp.Write("230 Login successful.");
                pass = true;
                break;

            // Sets up a passive mode data connection
            case "PASV":
                data = new DataSocket(ftp, true, null);
                break;

            // Sets up an active mode data connection
            case "PORT":
                data = new DataSocket(ftp, false, arguments);
                break;

            // Prints the working directory to the client
            case "PWD":
                ftp.Write("257 \"{0}\"", path);
                break;

            // Lets the client quit the connection
            case "QUIT":
                ftp.Write("221 Goodbye.");
                return(true);

            // Sends a file back to the client
            case "RETR":
                if (data == null)
                {
                    ftp.Write("425 Use PASV or PORT first.");
                    break;
                }

                var file = Path.GetRelativePath(".", Path.Combine(path, arguments));

                if (!File.Exists(file))
                {
                    ftp.Write("550 Failed to open file.");
                    break;
                }

                ftp.Write("150 Opening BINARY mode data connection for {0}", arguments);
                data.SendFile(file);
                ftp.Write("226 Transfer complete.");
                data = null;
                break;

            // Sets the file transfer encoding
            case "TYPE":
                if (arguments == "I")
                {
                    ftp.Write("200 Switching to Binary mode.");
                    break;
                }

                ftp.Write("200 Only Binary mode is supported.");
                break;

            // Accepts usernames for authentication
            case "USER":
                if (arguments == "ftp" || arguments == "anonymous")
                {
                    ftp.Write("331 Please specify the password.");
                    user = true;
                    break;
                }

                ftp.Write("530 This FTP server is anonymous only.");
                break;

            // Handles unknown commands
            default:
                ftp.Write("200 Command not supported.");
                break;
            }

            return(false);
        }