Пример #1
0
        public void CloseConnection()
        {
            try
            {
                if (_sslStream != null)
                {
                    _sslStream.Close();
                }
                if (_controlStream != null)
                {
                    _controlStream.Close();
                }
            }
            catch (Exception)
            {
                // ignored
            }
            _sslStream     = null;
            _controlStream = null;

            lock (_controlClientLocker)
            {
                if (_controlClient != null)
                {
                    _controlClient.Close();
                }
                _controlClient = null;
            }
        }
Пример #2
0
        public ClientConnection(TcpClient client, X509Certificate2 x509, bool useImplicit)
        {
            Client      = client;
            X509        = x509;
            UseImplicit = useImplicit;

            ControlStream = Client.GetStream();

            LogUser = new LogUser();
            Logger.RegisterUser(LogUser);
            LoggedIn = false;

            if (UseImplicit)
            {
                SslControlStream = new FixedSslStream(ControlStream);
                SslControlStream.AuthenticateAsServer(X509);

                ControlReader = new StreamReader(SslControlStream);
                ControlWriter = new StreamWriter(SslControlStream);
            }
            else
            {
                ControlReader = new StreamReader(ControlStream);
                ControlWriter = new StreamWriter(ControlStream);
            }

            ThreadPool.QueueUserWorkItem(HandleControl, null);
        }
Пример #3
0
        private void HandleNLST(IAsyncResult ar)
        {
            if (DataConnectionType == ConnectionType.Active)
            {
                DataActive.EndConnect(ar);
            }
            else
            {
                DataActive = DataPassive.EndAcceptTcpClient(ar);
            }

            string pathname = (string)ar.AsyncState;

            FixedSslStream ssl    = null;
            NetworkStream  stream = null;

            if (Protocol == Protocol.P)
            {
                ssl = new FixedSslStream(DataActive.GetStream());
                ssl.AuthenticateAsServer(X509, false, SslProtocols.Default, false);
                DataWriter = new StreamWriter(ssl, Encoding.ASCII);
            }
            else
            {
                stream     = DataActive.GetStream();
                DataWriter = new StreamWriter(stream, Encoding.ASCII);
            }

            IEnumerable <string> directories = Directory.EnumerateDirectories(pathname);

            foreach (string dir in directories)
            {
                DirectoryInfo d    = new DirectoryInfo(dir);
                string        line = d.Name;

                DataWriter.WriteLine(line);
                DataWriter.Flush();
            }

            IEnumerable <string> files = Directory.EnumerateFiles(pathname);

            foreach (string file in files)
            {
                FileInfo f    = new FileInfo(file);
                string   line = f.Name;

                DataWriter.WriteLine(line);
                DataWriter.Flush();
            }

            ssl.Dispose();

            DataActive.Close();
            DataActive = null;

            LogUser.LogMsg("226 NLST complete");
            ControlWriter.WriteLine("226 NLST complete");
            ControlWriter.Flush();
        }
Пример #4
0
        private void HandleStor(IAsyncResult ar)
        {
            if (DataConnectionType == ConnectionType.Active)
            {
                DataActive.EndConnect(ar);
            }
            else
            {
                DataActive = DataPassive.EndAcceptTcpClient(ar);
            }

            string pathname = (string)ar.AsyncState;

            FixedSslStream ssl    = null;
            NetworkStream  stream = null;

            if (Protocol == Protocol.P || UseImplicit)
            {
                ssl = new FixedSslStream(DataActive.GetStream());
                ssl.AuthenticateAsServer(X509, false, SslProtocols.Default, false);
                DataWriter = new StreamWriter(ssl, Encoding.ASCII);

                using (FileStream fs = new FileStream(pathname, FileMode.Open, FileAccess.Read))
                {
                    CopyStream(ssl, fs);
                }
            }
            else
            {
                stream     = DataActive.GetStream();
                DataWriter = new StreamWriter(stream, Encoding.ASCII);

                using (FileStream fs = new FileStream(pathname, FileMode.Open, FileAccess.Read))
                {
                    CopyStream(stream, fs);
                }
            }

            if (ssl != null)
            {
                ssl.Dispose();
            }

            if (stream != null)
            {
                stream.Dispose();
            }

            DataActive.Close();
            DataActive = null;

            LogUser.LogMsg("226 Closing data connection, file transfer successful");
            ControlWriter.WriteLine("226 Closing data connection, file transfer successful");
            ControlWriter.Flush();
        }
Пример #5
0
 public void SetUpSecureConnectionAsServer(X509Certificate certificate)
 {
     lock (_controlClientLocker)
     {
         lock (_activeStreamLocker)
         {
             _sslStream = new FixedSslStream(_controlStream, true);
             _sslStream.AuthenticateAsServer(certificate);
         }
     }
 }
Пример #6
0
        private static void Main()
        {
            // Load server certificate
            var cert = new X509Certificate2("test.pfx");

            AuthTlsCommandHandler.ServerCertificate = cert;

            // Only allow anonymous login
            var membershipProvider = new AnonymousMembershipProvider(new NoValidation());

            // Use the .NET file system
            var fsProvider = new DotNetFileSystemProvider(Path.Combine(Path.GetTempPath(), "TestFtpServer"));

            // Use all commands from the FtpServer assembly and the one(s) from the AuthTls assembly
            var commandFactory = new AssemblyFtpCommandHandlerFactory(typeof(FtpServer).Assembly, typeof(AuthTlsCommandHandler).Assembly);

            // Initialize the FTP server
            using (var ftpServer = new FtpServer(fsProvider, membershipProvider, "127.0.0.1", Port, commandFactory)
            {
                DefaultEncoding = Encoding.ASCII,
                LogManager = new FtpLogManager(),
            })
            {
#if USE_FTPS_IMPLICIT
                // Use an implicit SSL connection (without the AUTHTLS command)
                ftpServer.ConfigureConnection += (s, e) =>
                {
                    var sslStream = new FixedSslStream(e.Connection.OriginalStream);
                    sslStream.AuthenticateAsServer(cert);
                    e.Connection.SocketStream = sslStream;
                };
#endif

                // Create the default logger
                var log = ftpServer.LogManager?.CreateLog(typeof(Program));

                try
                {
                    // Start the FTP server
                    ftpServer.Start();
                    Console.WriteLine("Press ENTER/RETURN to close the test application.");
                    Console.ReadLine();

                    // Stop the FTP server
                    ftpServer.Stop();
                }
                catch (Exception ex)
                {
                    log?.Error(ex, "Error during main FTP server loop");
                }
            }
        }
Пример #7
0
 public void SetUpSecureConnectionAsClient()
 {
     _sslStream = new FixedSslStream(_controlStream, false, (sender, certificate, chain, errors) => true, null);
     _sslStream.AuthenticateAsClient(IpAddress.ToString());
 }
Пример #8
0
        private void HandleControl(object state)
        {
            try
            {
                LogUser.Address = Client.Client.RemoteEndPoint.ToString();
                LogUser.LogMsg($"220 Ready As I'll Ever Be");
                ControlWriter.WriteLine("220 Ready As I'll Ever Be");
                ControlWriter.Flush();

                string line = null;

                while (!string.IsNullOrEmpty(line = ControlReader.ReadLine()))
                {
                    LogUser.LogMsg($"Command: {line}");
                    string response = null;
                    bool   authTls  = false;

                    string[] command = line.Split(' ');
                    string   cmd     = command[0].ToUpperInvariant();
                    string   args    = command.Length > 1 ? line.Substring(command[0].Length + 1) : null;

                    if (response == null)
                    {
                        switch (cmd)
                        {
                        case "USER":
                            if (LoggedIn)
                            {
                                response = "230 User already logged in";
                                break;
                            }
                            response = Login(args);
                            break;

                        case "PASS":
                            response = Login(args);
                            break;

                        case "AUTH":
                            if (args == "TLS" || args == "SSL")
                            {
                                response = "234 Enable TLS/SSL Connection";
                                authTls  = true;
                                break;
                            }
                            response = $"502 Unknown Argument '{args}'";
                            break;

                        // File Commands
                        case "CDUP":
                            response = ChangeWD("..");
                            break;

                        case "CWD":
                            response = ChangeWD(args);
                            break;

                        case "PWD":
                            try
                            {
                                string cur = CurrentDir.Replace(Root, string.Empty).Replace('\\', '/');
                                response = cur.Length > 0 ? cur : "257 \"/\" is current directory";
                            }
                            catch
                            {
                                response = "550 PWD Failed Sucessfully";
                            }
                            break;

                        case "TYPE":
                            string[] splitArgs = args.Split(' ');
                            response = Type(splitArgs[0], splitArgs.Length > 1 ? splitArgs[1] : null);
                            break;

                        case "PASV":
                            response = Passive();
                            break;

                        case "PORT":
                            response = Port(args);
                            break;

                        case "LIST":
                            response = List(args ?? CurrentDir);
                            break;

                        case "RETR":
                            response = Retrieve(args);
                            break;

                        case "STOR":
                            response = Store(args);
                            break;

                        case "RNFR":
                            renameFrom = args;
                            response   = "350 Requested file action pending further information";
                            break;

                        case "RNTO":
                            response = Rename(renameFrom, args);
                            break;

                        case "PBSZ":
                            response = $"200 PBSZ={args}";
                            break;

                        case "PROT":
                            response = $"200 Protection level set to {args}";
                            Protocol = (args == "P") ? Protocol.P : Protocol.C;
                            break;

                        case "MLSD":
                            response = MLSD(args);
                            break;

                        case "NLSD":
                            response = NLST(args);
                            break;

                        case "SIZE":
                            args = Helpers.NormalizeFilename(args, Root, CurrentDir);
                            if (!Helpers.IsValidPath(args, Root))
                            {
                                response = "550 File Not Found";
                                break;
                            }
                            response = (File.Exists(args)) ? $"213 {new FileInfo(args).Length}" : "550 File Not Found";
                            break;

                        case "MDTM":
                            args = Helpers.NormalizeFilename(args, Root, CurrentDir);
                            if (!Helpers.IsValidPath(args, Root))
                            {
                                response = "550 File Not Found";
                                break;
                            }
                            response = (File.Exists(args)) ? $"213 {new FileInfo(args).LastWriteTime:yyyyMMddHHmmss.fff}" : "550 File Not Found";
                            break;

                        case "QUIT":
                            response = "221 Goodbye";
                            break;

                        case "DELE":
                            response = Delete(args);
                            break;

                        case "RMD":
                            response = RemoveDir(args);
                            break;

                        case "MKD":
                            response = CreateDir(args);
                            break;

                        case "SYST":
                            response = "215 UNIX Type: L8";
                            break;

                        default:
                            response = $"502 Command '{line}' Not Implemented";
                            break;
                        }

                        try
                        {
                            LogUser.LogMsg($"Response: {response}");
                            ControlWriter.WriteLine(response);
                            ControlWriter.Flush();
                        }
                        catch { }

                        if (response.StartsWith("221"))
                        {
                            if (SslControlStream != null)
                            {
                                SslControlStream.Dispose();
                            }
                            Client.Close();
                            break;
                        }

                        if (authTls)
                        {
                            SslControlStream = new FixedSslStream(ControlStream);
                            SslControlStream.AuthenticateAsServer(X509, false, SslProtocols.Default, false);
                            ControlWriter = new StreamWriter(SslControlStream);
                            ControlReader = new StreamReader(SslControlStream);
                        }
                    }
                }
                Logger.UnregisterUser(LogUser);
            }
            catch (Exception e)
            {
                Logger.Log($"Client {Client.Client.RemoteEndPoint} disconnected due to an error ({e.Message})");
                Client.Close();
                Logger.UnregisterUser(LogUser);
            }
        }
Пример #9
0
        // Handlers
        private void HandleList(IAsyncResult ar)
        {
            if (DataConnectionType == ConnectionType.Active)
            {
                DataActive.EndConnect(ar);
            }
            else
            {
                DataActive = DataPassive.EndAcceptTcpClient(ar);
            }

            string pathname = (string)ar.AsyncState;

            pathname = pathname.Replace("-l", "").Replace("-a", "");

            FixedSslStream ssl    = null;
            NetworkStream  stream = null;

            if (Protocol == Protocol.P || UseImplicit)
            {
                ssl = new FixedSslStream(DataActive.GetStream());
                ssl.AuthenticateAsServer(X509, false, SslProtocols.Default, false);
                DataWriter = new StreamWriter(ssl, Encoding.ASCII);
            }
            else
            {
                stream     = DataActive.GetStream();
                DataWriter = new StreamWriter(stream, Encoding.ASCII);
            }

            IEnumerable <string> directories = Directory.EnumerateDirectories(pathname);

            foreach (string dir in directories)
            {
                DirectoryInfo d    = new DirectoryInfo(dir);
                string        line = string.Format("drwxr-xr-x    2 2003     2003     {0,8} {1} {2}", "4096", d.LastWriteTime.ToString("MMM dd  yyyy"), d.Name);

                DataWriter.WriteLine(line);
                DataWriter.Flush();
            }
            IEnumerable <string> files = Directory.EnumerateFiles(pathname);

            foreach (string file in files)
            {
                FileInfo f = new FileInfo(file);

                string line = string.Format("-rw-r--r--    2 2003     2003     {0,8} {1} {2}", f.Length, f.LastWriteTime.ToString("MMM dd  yyyy"), f.Name);

                DataWriter.WriteLine(line);
                DataWriter.Flush();
            }

            // Virtual Directories
            if (pathname == Root)
            {
                foreach (VirtualDirectory vd in User.Directories)
                {
                    if (vd.IsRoot)
                    {
                        continue;
                    }
                    DirectoryInfo d    = new DirectoryInfo(vd.Path);
                    string        line = string.Format("drwxr-xr-x    2 2003     2003     {0,8} {1} {2}", "4096", d.LastWriteTime.ToString("MMM dd  yyyy"), vd.Alias);

                    DataWriter.WriteLine(line);
                    DataWriter.Flush();
                }
            }

            if (ssl != null)
            {
                ssl.Dispose();
            }

            if (stream != null)
            {
                stream.Dispose();
            }

            DataActive.Close();
            DataActive = null;

            LogUser.LogMsg("226 List complete");
            ControlWriter.WriteLine("226 List complete");
            ControlWriter.Flush();
        }