Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
FtpServer.cs
1using System;
3using System.ComponentModel;
4using System.IO;
5using System.Net;
6using System.Net.NetworkInformation;
8using System.Security.Authentication;
9using System.Security.Cryptography.X509Certificates;
10using System.Text;
11using System.Threading.Tasks;
12using Waher.Events;
19using Waher.Security;
20
22{
37 public class FtpServer : IDisposable, ITlsCertificateEndpoint
38 {
42 public const int DefaultFtpControlPort = 21;
43
47 public const int DefaultFtpsControlPort = 990;
48
52 public const int DefaultFtpDataPort = 20;
53
57 public const int DefaultConnectionBacklog = 10;
58
62 public const int DefaultBufferSize = 16384;
63
67 public const string FtpReadPrivilegePrefix = "FTP.Read.";
68
72 public const string FtpWritePrivilegePrefix = "FTP.Write.";
73
74 private LinkedList<TcpListener> listeners = new LinkedList<TcpListener>();
75 private Cache<Guid, FtpClientConnection> clientConnections;
76 private X509Certificate serverCertificate;
77 private Dictionary<int, KeyValuePair<ClientCertificates, bool>> portSpecificMTlsSettings;
78 private ClientCertificates clientCertificates = ClientCertificates.NotUsed;
79 private bool trustClientCertificates = false;
80 private bool clientCertificateSettingsLocked = false;
81 private readonly AsyncQueue<DataPortReference> dataPorts = null;
82 private readonly CommunicationLayer externalSniffers = new CommunicationLayer(false);
83 private readonly IFtpServerPersistenceLayer persistenceLayer;
84 private readonly CaseInsensitiveString domain;
85 private readonly bool hasDataPorts = false;
86 private bool encryptionRequired;
87 private bool disposed = false;
88
89 #region Constructors
90
99 IFtpServerPersistenceLayer PersistenceLayer)
100 : this(Domain, DefaultFtpControlPort, new int[] { DefaultFtpDataPort },
101 ServerCertificate, EncryptionRequired, PersistenceLayer)
102 {
103 }
104
113 public FtpServer(CaseInsensitiveString Domain, int ControlPort,
114 X509Certificate ServerCertificate, bool EncryptionRequired,
115 IFtpServerPersistenceLayer PersistenceLayer)
116 : this(Domain, ControlPort, new int[] { DefaultFtpDataPort }, ServerCertificate,
117 EncryptionRequired, PersistenceLayer)
118 {
119 }
120
132 X509Certificate ServerCertificate, bool EncryptionRequired,
133 IFtpServerPersistenceLayer PersistenceLayer)
134 : this(Domain, GetControlPort(Ports), GetEncryptedControlPort(Ports),
135 GetDataPorts(Ports), ServerCertificate, EncryptionRequired,
136 PersistenceLayer)
137 {
138 }
139
140 private static int GetControlPort(int[] Ports)
141 {
142 if ((Ports?.Length ?? 0) == 0)
143 throw new ArgumentException("No FTP ports defined.", nameof(Ports));
144
145 foreach (int Port in Ports)
146 {
147 if (Port == DefaultFtpControlPort)
148 return Port;
149 }
150
151 return Ports[0];
152 }
153
154 private static int? GetEncryptedControlPort(int[] Ports)
155 {
156 if ((Ports?.Length ?? 0) == 0)
157 return null;
158
159 foreach (int Port in Ports)
160 {
161 if (Port == DefaultFtpsControlPort)
162 return Port;
163 }
164
165 return null;
166 }
167
168 private static int[] GetDataPorts(int[] Ports)
169 {
170 List<int> Result = new List<int>();
171 int ControlPort = GetControlPort(Ports);
172
173 foreach (int Port in Ports)
174 {
175 if (Port != ControlPort)
176 Result.Add(Port);
177 }
178
179 return Result.ToArray();
180 }
181
182 private class DataPortReference
183 {
184 public int Port;
185
186 public DataPortReference(int Port)
187 {
188 this.Port = Port;
189 }
190 }
191
201 public FtpServer(CaseInsensitiveString Domain, int ControlPort, int[] DataPorts,
202 X509Certificate ServerCertificate, bool EncryptionRequired,
203 IFtpServerPersistenceLayer PersistenceLayer)
204 : this(Domain, ControlPort, null, DataPorts, ServerCertificate,
205 EncryptionRequired, PersistenceLayer)
206 {
207 }
208
219 public FtpServer(CaseInsensitiveString Domain, int ControlPort, int? EncryptedControlPort,
220 int[] DataPorts, X509Certificate ServerCertificate, bool EncryptionRequired,
221 IFtpServerPersistenceLayer PersistenceLayer)
222 : this(Domain, new int[] { ControlPort }, EncryptedControlPort.HasValue ? new int[] { EncryptedControlPort.Value } : Array.Empty<int>(),
223 DataPorts, ServerCertificate, EncryptionRequired, PersistenceLayer)
224 {
225 }
226
237 public FtpServer(CaseInsensitiveString Domain, int[] ControlPorts, int[] EncryptedControlPorts,
238 int[] DataPorts, X509Certificate ServerCertificate, bool EncryptionRequired,
239 IFtpServerPersistenceLayer PersistenceLayer)
240 : this(Domain, ControlPorts, EncryptedControlPorts, DataPorts, ServerCertificate,
241 EncryptionRequired, ClientCertificates.NotUsed, false, null, false, PersistenceLayer)
242 {
243 }
244
259 public FtpServer(CaseInsensitiveString Domain, int[] ControlPorts, int[] EncryptedControlPorts,
260 int[] DataPorts, X509Certificate ServerCertificate, bool EncryptionRequired,
262 Dictionary<int, KeyValuePair<ClientCertificates, bool>> PortSpecificSettings, bool LockSettings,
263 IFtpServerPersistenceLayer PersistenceLayer)
264 {
265 this.persistenceLayer = PersistenceLayer;
266 this.serverCertificate = ServerCertificate;
267 this.clientCertificates = ClientCertificates;
268 this.trustClientCertificates = TrustClientCertificates;
269 this.portSpecificMTlsSettings = PortSpecificSettings;
270 this.clientCertificateSettingsLocked = LockSettings;
271 this.encryptionRequired = EncryptionRequired;
272 this.domain = Domain;
273
274 if (EncryptionRequired && this.serverCertificate is null)
275 throw new ArgumentException("Server Certificate must be provided, if encryption is required.", nameof(ServerCertificate));
276
277 this.clientConnections = new Cache<Guid, FtpClientConnection>(int.MaxValue, TimeSpan.MaxValue, TimeSpan.FromMinutes(2), true);
278 this.clientConnections.Removed += this.ClientConnections_Removed;
279
280 if ((DataPorts?.Length ?? 0) > 0)
281 {
282 this.hasDataPorts = true;
283 this.dataPorts = new AsyncQueue<DataPortReference>();
284
285 foreach (int Port in DataPorts)
286 this.dataPorts.Queue(new DataPortReference(Port));
287 }
288
289 try
290 {
291 foreach (NetworkInterface Interface in NetworkInterface.GetAllNetworkInterfaces())
292 {
293 if (Interface.OperationalStatus != OperationalStatus.Up)
294 continue;
295
296 IPInterfaceProperties Properties = Interface.GetIPProperties();
297
298 foreach (UnicastIPAddressInformation UnicastAddress in Properties.UnicastAddresses)
299 {
300 if ((UnicastAddress.Address.AddressFamily == AddressFamily.InterNetwork && Socket.OSSupportsIPv4) ||
301 (UnicastAddress.Address.AddressFamily == AddressFamily.InterNetworkV6 && Socket.OSSupportsIPv6))
302 {
303 foreach (int Port in ControlPorts)
304 {
305 this.OpenDataListener(this.AcceptTcpClientFtpControlCallback,
306 UnicastAddress.Address, Port, false);
307 }
308
309 if (!(EncryptedControlPorts is null))
310 {
311 foreach (int Port in EncryptedControlPorts)
312 {
313 this.GetMTlsSettings(Port, out ClientCertificates ClientCertificates2, out bool TrustCertificates);
314
315 this.OpenDataListener(this.AcceptTcpClientFtpsControlCallback,
316 UnicastAddress.Address, Port, false);
317 }
318 }
319 }
320 }
321 }
322 }
323 catch (Exception ex)
324 {
325 Log.Exception(ex);
326 }
327 }
328
332 public bool HasDataPorts => this.hasDataPorts;
333
340 public async Task<int?> GetDataPort(int Timeout)
341 {
342 if (this.dataPorts is null)
343 return 0;
344
345 DataPortReference Ref = await this.dataPorts.Wait(Timeout);
346
347 return Ref?.Port;
348 }
349
354 public void ReleaseDataPort(int Port)
355 {
356 this.dataPorts?.Queue(new DataPortReference(Port));
357 }
358
359 internal DataPort OpenDataListener(AsyncCallback Callback, IPAddress Address,
360 int Port, bool ReleaseAfterUse)
361 {
362 try
363 {
364 if (Port == 0)
365 this.externalSniffers.Information("Opening listening port on " + Address.ToString() + ".");
366 else
367 this.externalSniffers.Information("Opening listening port " + Port.ToString() + " on " + Address.ToString() + ".");
368
369 DataPort Result = new DataPort()
370 {
371 Listener = new TcpListener(Address, Port),
372 ReleaseAfterUse = ReleaseAfterUse,
373 Server = this
374 };
375
376 Result.Listener.Start(DefaultConnectionBacklog);
377 Result.Listener.BeginAcceptTcpClient(Callback, Result);
378
379 lock (this.listeners)
380 {
381 this.listeners.AddLast(Result.Listener);
382 }
383
384 if (Result.Listener.LocalEndpoint is IPEndPoint LocalEndpoint)
385 {
386 this.externalSniffers.Information("Port " + LocalEndpoint.Port.ToString() + " on " + LocalEndpoint.Address.ToString() + " opened.");
387 Result.Port = LocalEndpoint.Port;
388 Result.LocalEndpoint = LocalEndpoint;
389 }
390 else
391 {
392 this.externalSniffers.Information("Port on " + Address.ToString() + " opened.");
393 Result.Port = Port;
394 }
395
396 return Result;
397 }
398 catch (Exception ex)
399 {
400 Log.Exception(ex, Address.ToString() + ":" + Port);
401 return null;
402 }
403 }
404
405 internal void Remove(DataPort DataPort)
406 {
407 lock (this.listeners)
408 {
409 this.listeners.Remove(DataPort.Listener);
410 }
411
412 if (DataPort.ReleaseAfterUse)
413 this.ReleaseDataPort(DataPort.Port);
414 }
415
419 public CommunicationLayer ExternalSniffers => this.externalSniffers;
420
424 public bool Disposed => this.disposed;
425
429 public bool AllowClearDataChannel { get; set; } = true;
430
434 public bool AllowSafeDataChannel { get; set; } = true;
435
439 public bool AllowConfidentialDataChannel { get; set; } = true;
440
444 public bool AllowPrivateDataChannel { get; set; } = true;
445
446 private async Task ClientConnections_Removed(object Sender, CacheItemEventArgs<Guid, FtpClientConnection> e)
447 {
448 try
449 {
450 await this.ClientConnectionRemoved.Raise(this, new ClientConnectionEventArgs(e.Value));
451 await e.Value.DisposeAsync();
452 }
453 catch (Exception ex)
454 {
455 Log.Exception(ex);
456 }
457 }
458
463 {
464 get => this.clientConnections.Count;
465 }
466
472 {
473 List<FtpClientConnection> Connections = new List<FtpClientConnection>();
474
475 foreach (Guid Id in this.clientConnections.GetKeys())
476 {
477 if (this.clientConnections.TryGetValue(Id, out FtpClientConnection Connection))
478 Connections.Add(Connection);
479 }
480
481 Connections.Sort((c1, c2) =>
482 {
483 return c1.UserName.CompareTo(c2.UserName);
484 });
485
486 return Connections.ToArray();
487 }
488
495 public bool TryGetClientConnection(Guid ID, out FtpClientConnection Connection)
496 {
497 return this.clientConnections.TryGetValue(ID, out Connection);
498 }
499
503 public CaseInsensitiveString Domain => this.domain;
504
508 public X509Certificate ServerCertificate => this.serverCertificate;
509
514 public void UpdateCertificate(X509Certificate ServerCertificate)
515 {
516 this.serverCertificate = ServerCertificate;
517 }
518
523 {
524 get => this.encryptionRequired;
525 set => this.encryptionRequired = value;
526 }
527
535 {
536 this.ConfigureMutualTls(ClientCertificates, TrustClientCertificates, null, LockSettings);
537 }
538
547 Dictionary<int, KeyValuePair<ClientCertificates, bool>> PortSpecificSettings, bool LockSettings)
548 {
549 if (this.clientCertificateSettingsLocked)
550 throw new InvalidOperationException("Mutual TLS settings locked.");
551
552 this.clientCertificates = ClientCertificates;
553 this.trustClientCertificates = TrustClientCertificates;
554 this.portSpecificMTlsSettings = PortSpecificSettings;
555 this.clientCertificateSettingsLocked = LockSettings;
556 }
557
561 public ClientCertificates ClientCertificates => this.clientCertificates;
562
566 public bool TrustClientCertificates => this.trustClientCertificates;
567
575 {
576 if (!(this.portSpecificMTlsSettings is null) &&
577 this.portSpecificMTlsSettings.TryGetValue(Port, out KeyValuePair<ClientCertificates, bool> P))
578 {
579 ClientCertificates = P.Key;
580 TrustClientCertificates = P.Value;
581 }
582 else
583 {
584 ClientCertificates = this.clientCertificates;
585 TrustClientCertificates = this.trustClientCertificates;
586 }
587 }
588
589 internal IFtpServerPersistenceLayer PersistenceLayer => this.persistenceLayer;
590
594 public void Dispose()
595 {
596 this.disposed = true;
597
598 if (!(this.clientConnections is null))
599 {
600 this.clientConnections.Clear();
601 this.clientConnections.Dispose();
602 this.clientConnections = null;
603 }
604
605 if (!(this.listeners is null))
606 {
607 LinkedList<TcpListener> Listeners = this.listeners;
608 this.listeners = null;
609
610 foreach (TcpListener Listener in Listeners)
611 Listener.Stop();
612 }
613
614 if (!(this.externalSniffers is null))
615 {
616 foreach (ISniffer Sniffer in this.externalSniffers)
617 (Sniffer as IDisposable)?.Dispose();
618 }
619 }
620
624 public int[] OpenPorts
625 {
626 get
627 {
628 lock (this.listeners)
629 {
630 return this.GetOpenPorts(this.listeners);
631 }
632 }
633 }
634
635 private int[] GetOpenPorts(LinkedList<TcpListener> Listeners)
636 {
637 SortedDictionary<int, bool> Open = new SortedDictionary<int, bool>();
638
639 if (!(Listeners is null))
640 {
641 IPEndPoint IPEndPoint;
642
643 foreach (TcpListener Listener in Listeners)
644 {
645 IPEndPoint = Listener.LocalEndpoint as IPEndPoint;
646 if (!(IPEndPoint is null))
647 Open[IPEndPoint.Port] = true;
648 }
649 }
650
651 int[] Result = new int[Open.Count];
652 Open.Keys.CopyTo(Result, 0);
653
654 return Result;
655 }
656
657 #endregion
658
659 #region Connections
660
661 private void AcceptTcpClientFtpControlCallback(IAsyncResult ar)
662 {
663 this.AcceptTcpClientControlCallback(ar, false);
664 }
665
666 private void AcceptTcpClientFtpsControlCallback(IAsyncResult ar)
667 {
668 this.AcceptTcpClientControlCallback(ar, true);
669 }
670
671 private async void AcceptTcpClientControlCallback(IAsyncResult ar, bool Tls)
672 {
673 try
674 {
675 if (this.disposed || NetworkingModule.Stopping)
676 return;
677
678 DataPort Port = (DataPort)ar.AsyncState;
679 TcpListener Listener = Port.Listener;
680
681 try
682 {
683 TcpClient Client = Listener.EndAcceptTcpClient(ar);
684 FtpClientControlConnection ClientConnection;
685 ISniffer[] Sniffers;
686
687 if (this.externalSniffers.HasSniffers)
688 Sniffers = this.externalSniffers.Sniffers;
689 else
690 Sniffers = Array.Empty<ISniffer>();
691
692 BinaryTcpClient BinaryTcpClient = new BinaryTcpClient(Client, false, false, Sniffers);
693 BinaryTcpClient.Bind(true);
694
695 if (Tls)
696 {
697 this.GetMTlsSettings(Port.Port, out ClientCertificates ClientCertificates, out bool TrustCertificates);
698
699 Task _ = this.SwitchToTls(BinaryTcpClient, ClientCertificates, TrustCertificates, true, Sniffers);
700 }
701 else
702 {
703 ClientConnection = new FtpClientControlConnection(BinaryTcpClient, this, this.persistenceLayer,
704 ClientCertificates.NotUsed, this.trustClientCertificates, Sniffers);
705
706 ClientConnection.Information("Control Connection accepted from " + BinaryTcpClient.RemoteEndPoint + ".");
707
708 ClientConnection.OnStateChanged += this.Nop;
709
710 this.clientConnections[ClientConnection.ID] = ClientConnection;
711
712 await this.ClientConnectionAdded.Raise(this, new ClientConnectionEventArgs(ClientConnection));
713
715 await ClientConnection.BeginWrite("220 Service ready.\r\n", null, null);
716 }
717 }
718 finally
719 {
720 if (!this.disposed)
721 {
722 if (Tls)
723 Listener.BeginAcceptTcpClient(this.AcceptTcpClientFtpsControlCallback, Port);
724 else
725 Listener.BeginAcceptTcpClient(this.AcceptTcpClientFtpControlCallback, Port);
726 }
727 }
728 }
729 catch (SocketException)
730 {
731 // Ignore
732 }
733 catch (ObjectDisposedException)
734 {
735 // Ignore
736 }
737 catch (NullReferenceException)
738 {
739 // Ignore
740 }
741 catch (Exception ex)
742 {
743 if (this.listeners is null)
744 return;
745
746 Log.Exception(ex);
747 }
748 }
749
750 internal async Task SwitchToTls(BinaryTcpClient Client, ClientCertificates ClientCertificates,
751 bool TrustCertificates, bool Control, ISniffer[] Sniffers)
752 {
753 string RemoteEndpoint = Client.RemoteEndPoint.RemovePortNumber();
754
755 if (Security.LoginMonitor.LoginAuditor.CanStartTls(RemoteEndpoint))
756 {
757 try
758 {
759 if (this.externalSniffers.HasSniffers)
760 {
761 this.externalSniffers.Information("Switching to TLS. (Client Certificates: " + ClientCertificates.ToString() +
762 ", Trust Certificates: " + TrustCertificates.ToString() + ")");
763 }
764
765 await Client.UpgradeToTlsAsServer(this.serverCertificate, Crypto.SecureTls,
766 ClientCertificates, null, TrustCertificates, "ftp");
767
768 if (this.externalSniffers.HasSniffers)
769 {
770 StringBuilder sb = new StringBuilder();
771
772 sb.Append("TLS established");
773 sb.Append(". Cipher Strength: ");
774 sb.Append(Client.CipherStrength.ToString());
775 sb.Append(", Hash Strength: ");
776 sb.Append(Client.HashStrength.ToString());
777 sb.Append(", Key Exchange Strength: ");
778 sb.Append(Client.KeyExchangeStrength.ToString());
779
780 this.externalSniffers.Information(sb.ToString());
781
782 if (!(Client.RemoteCertificate is null))
783 {
784 if (this.externalSniffers.HasSniffers)
785 {
786 sb.Clear();
787
788 sb.Append("Remote Certificate received. Valid: ");
789 sb.Append(Client.RemoteCertificateValid.ToString());
790 sb.Append(", Subject: ");
791 sb.Append(Client.RemoteCertificate.Subject);
792 sb.Append(", Issuer: ");
793 sb.Append(Client.RemoteCertificate.Issuer);
794 sb.Append(", S/N: ");
795 sb.Append(Convert.ToBase64String(Client.RemoteCertificate.GetSerialNumber()));
796 sb.Append(", Hash: ");
797 sb.Append(Convert.ToBase64String(Client.RemoteCertificate.GetCertHash()));
798
799 this.externalSniffers.Information(sb.ToString());
800 }
801 }
802 }
803
804 if (Control)
805 {
806 FtpClientControlConnection ClientConnection = new FtpClientControlConnection(Client,
807 this, this.persistenceLayer, ClientCertificates, TrustCertificates, Sniffers);
808
809 ClientConnection.Information("Encrypted Control Connection accepted from " + Client.RemoteEndPoint + ".");
810 ClientConnection.OnStateChanged += this.Nop;
811
812 this.clientConnections[ClientConnection.ID] = ClientConnection;
813
814 await this.ClientConnectionAdded.Raise(this, new ClientConnectionEventArgs(ClientConnection));
815
816 Client.Continue();
817
818 await ClientConnection.BeginWrite("220 Service ready.\r\n", null, null);
819 }
820 else
821 Client.Continue();
822 }
823 catch (AuthenticationException ex)
824 {
825 if (this.externalSniffers.HasSniffers)
826 this.externalSniffers.Exception(ex);
827
828 await this.LoginFailure(ex, Client, RemoteEndpoint);
829 }
830 catch (SocketException ex)
831 {
832 if (this.externalSniffers.HasSniffers)
833 this.externalSniffers.Exception(ex);
834
835 await Client.DisposeAsync();
836 }
837 catch (Win32Exception ex)
838 {
839 if (this.externalSniffers.HasSniffers)
840 this.externalSniffers.Exception(ex);
841
842 await this.LoginFailure(ex, Client, RemoteEndpoint);
843 }
844 catch (IOException ex)
845 {
846 if (this.externalSniffers.HasSniffers)
847 this.externalSniffers.Exception(ex);
848
849 await Client.DisposeAsync();
850 }
851 catch (Exception ex)
852 {
853 if (this.externalSniffers.HasSniffers)
854 this.externalSniffers.Exception(ex);
855
856 await Client.DisposeAsync();
857 Log.Exception(ex);
858 }
859 }
860 else
861 await Client.DisposeAsync();
862 }
863
864 internal async Task LoginFailure(Exception ex, BinaryTcpClient Client, string RemoteIpEndpoint)
865 {
866 Exception ex2 = Log.UnnestException(ex);
867 Security.LoginMonitor.LoginAuditor.ReportTlsHackAttempt(RemoteIpEndpoint, "TLS handshake failed: " + ex2.Message, "HTTPS");
868
869 await Client.DisposeAsync();
870 }
871
872 private Task Nop(object Sender, FtpControlConnectionState NewState)
873 {
874 return Task.CompletedTask;
875 }
876
877 internal string GetTransformPath()
878 {
879 foreach (ISniffer Sniffer in this.externalSniffers.Sniffers)
880 {
881 if (Sniffer is XmlFileSniffer XmlFileSniffer)
883 }
884
885 return null;
886 }
887
888 internal void Closed(FtpClientConnection Connection)
889 {
890 this.clientConnections?.Remove(Connection.ID);
891 }
892
893 internal void Ping(FtpClientConnection Connection)
894 {
895 this.clientConnections?.ContainsKey(Connection.ID);
896 }
897
898 #endregion
899
900 #region Accounts
901
907 internal Task<IAccount> GetAccount(CaseInsensitiveString UserName)
908 {
909 return this.persistenceLayer.GetAccount(UserName);
910 }
911
915 public event EventHandlerAsync<ClientConnectionEventArgs> ClientConnectionAdded = null;
916
920 public event EventHandlerAsync<ClientConnectionEventArgs> ClientConnectionRemoved = null;
921
922 #endregion
923
924 }
925}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1657
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
Definition: Log.cs:828
Implements a binary TCP Client, by encapsulating a TcpClient. It also makes the use of TcpClient safe...
void Bind()
Binds to a TcpClient that was already connected when provided to the constructor.
bool RemoteCertificateValid
If the remote certificate is valid.
int HashStrength
Hash algorithm strength. (Nr bits of brute force complexity required to break algorithm).
string RemoteEndPoint
Remote End-point of connection. This corresponds to the IP Endpoint of the remote party in normal cas...
void Continue()
Continues reading from the socket, if paused in an event handler.
virtual Task DisposeAsync()
Disposes of the object asynchronously. The underlying TcpClient is either disposed directly,...
X509Certificate RemoteCertificate
Certificate used by the remote endpoint.
int KeyExchangeStrength
Key Exchange strength. (Nr bits of brute force complexity required to break algorithm).
int CipherStrength
Cipher strength. (Nr bits of brute force complexity required to break algorithm).
Task UpgradeToTlsAsServer(X509Certificate ServerCertificate)
Upgrades a server connection to TLS.
Simple base class for classes implementing communication protocols.
Abstract base class for FTP client connections.
Implements a simple FTP Server, as defined in:
Definition: FtpServer.cs:38
int NrClientConnections
Number of client connections.
Definition: FtpServer.cs:463
FtpServer(CaseInsensitiveString Domain, int ControlPort, X509Certificate ServerCertificate, bool EncryptionRequired, IFtpServerPersistenceLayer PersistenceLayer)
Implements an FTP server.
Definition: FtpServer.cs:113
FtpServer(CaseInsensitiveString Domain, int ControlPort, int[] DataPorts, X509Certificate ServerCertificate, bool EncryptionRequired, IFtpServerPersistenceLayer PersistenceLayer)
Implements an FTP server.
Definition: FtpServer.cs:201
const string FtpWritePrivilegePrefix
Prefix of FTP Write Privileges
Definition: FtpServer.cs:72
bool AllowSafeDataChannel
If data can be transferred in the clear, with integrity protection
Definition: FtpServer.cs:434
X509Certificate ServerCertificate
Server domain certificate.
Definition: FtpServer.cs:508
CommunicationLayer ExternalSniffers
External Sniffers for FTP communication.
Definition: FtpServer.cs:419
const int DefaultBufferSize
Default buffer size (16384).
Definition: FtpServer.cs:62
void Dispose()
IDisposable.Dispose
Definition: FtpServer.cs:594
ClientCertificates ClientCertificates
If client certificates are not used by default, optional or required.
Definition: FtpServer.cs:561
EventHandlerAsync< ClientConnectionEventArgs > ClientConnectionAdded
Event raised when a client connection has been added.
Definition: FtpServer.cs:915
FtpServer(CaseInsensitiveString Domain, int[] ControlPorts, int[] EncryptedControlPorts, int[] DataPorts, X509Certificate ServerCertificate, bool EncryptionRequired, IFtpServerPersistenceLayer PersistenceLayer)
Implements an FTP server.
Definition: FtpServer.cs:237
FtpServer(CaseInsensitiveString Domain, int[] ControlPorts, int[] EncryptedControlPorts, int[] DataPorts, X509Certificate ServerCertificate, bool EncryptionRequired, ClientCertificates ClientCertificates, bool TrustClientCertificates, Dictionary< int, KeyValuePair< ClientCertificates, bool > > PortSpecificSettings, bool LockSettings, IFtpServerPersistenceLayer PersistenceLayer)
Implements an FTP server.
Definition: FtpServer.cs:259
bool AllowConfidentialDataChannel
If data can be transferred encrypted.
Definition: FtpServer.cs:439
FtpServer(CaseInsensitiveString Domain, X509Certificate ServerCertificate, bool EncryptionRequired, IFtpServerPersistenceLayer PersistenceLayer)
Implements an FTP server.
Definition: FtpServer.cs:98
bool AllowPrivateDataChannel
If data can be transferred encrypted, with integrity protection.
Definition: FtpServer.cs:444
bool TrustClientCertificates
If client certificates should be trusted by default, even if they do not validate.
Definition: FtpServer.cs:566
FtpServer(CaseInsensitiveString Domain, int[] Ports, X509Certificate ServerCertificate, bool EncryptionRequired, IFtpServerPersistenceLayer PersistenceLayer)
Implements an FTP server.
Definition: FtpServer.cs:131
const int DefaultFtpDataPort
Default FTP Data Port (20).
Definition: FtpServer.cs:52
const int DefaultFtpsControlPort
Default FTPS Control Port (990).
Definition: FtpServer.cs:47
bool TryGetClientConnection(Guid ID, out FtpClientConnection Connection)
Tries to get a client connection, given its ID
Definition: FtpServer.cs:495
bool HasDataPorts
If FTP Server has data ports defined.
Definition: FtpServer.cs:332
const int DefaultConnectionBacklog
Default Connection backlog (10).
Definition: FtpServer.cs:57
bool Disposed
If the class is disposed.
Definition: FtpServer.cs:424
void ConfigureMutualTls(ClientCertificates ClientCertificates, bool TrustClientCertificates, Dictionary< int, KeyValuePair< ClientCertificates, bool > > PortSpecificSettings, bool LockSettings)
Configures Mutual-TLS capabilities of the server. Affects all connections, all resources.
Definition: FtpServer.cs:546
void ConfigureMutualTls(ClientCertificates ClientCertificates, bool TrustClientCertificates, bool LockSettings)
Configures Mutual-TLS capabilities of the server. Affects all connections, all resources.
Definition: FtpServer.cs:534
bool AllowClearDataChannel
If data can be transferred in the clear
Definition: FtpServer.cs:429
void UpdateCertificate(X509Certificate ServerCertificate)
Updates the server certificate
Definition: FtpServer.cs:514
EventHandlerAsync< ClientConnectionEventArgs > ClientConnectionRemoved
Event raised when a client connection has been removed.
Definition: FtpServer.cs:920
void ReleaseDataPort(int Port)
Releases a port back to the pool of available data ports.
Definition: FtpServer.cs:354
CaseInsensitiveString Domain
Domain name.
Definition: FtpServer.cs:503
const int DefaultFtpControlPort
Default FTP Control Port (21).
Definition: FtpServer.cs:42
void GetMTlsSettings(int Port, out ClientCertificates ClientCertificates, out bool TrustClientCertificates)
Gets mTLS settings for a given port number.
Definition: FtpServer.cs:574
int[] OpenPorts
Ports successfully opened.
Definition: FtpServer.cs:625
const string FtpReadPrivilegePrefix
Prefix of FTP Read Privileges
Definition: FtpServer.cs:67
FtpClientConnection[] GetClientConnections()
Gets an array of client connections.
Definition: FtpServer.cs:471
async Task< int?> GetDataPort(int Timeout)
Gets a free data port for use in a passive-mode data connection.
Definition: FtpServer.cs:340
FtpServer(CaseInsensitiveString Domain, int ControlPort, int? EncryptedControlPort, int[] DataPorts, X509Certificate ServerCertificate, bool EncryptionRequired, IFtpServerPersistenceLayer PersistenceLayer)
Implements an FTP server.
Definition: FtpServer.cs:219
bool EncryptionRequired
If C2S encryption is requried.
Definition: FtpServer.cs:523
Module that controls the life cycle of communication.
static bool Stopping
If the system is stopping.
Outputs sniffed data to an XML file.
Represents a case-insensitive string.
static readonly CaseInsensitiveString Empty
Empty case-insensitive string
Implements an in-memory cache.
Definition: Cache.cs:17
bool ContainsKey(KeyType Key)
Checks if a key is available in the cache.
Definition: Cache.cs:404
void Dispose()
IDisposable.Dispose
Definition: Cache.cs:99
int Count
Number of items in cache
Definition: Cache.cs:337
bool Remove(KeyType Key)
Removes an item from the cache.
Definition: Cache.cs:616
bool TryGetValue(KeyType Key, out ValueType Value)
Tries to get a value from the cache.
Definition: Cache.cs:311
KeyType[] GetKeys()
Gets all available keys in the cache.
Definition: Cache.cs:366
void Clear()
Clears the cache.
Definition: Cache.cs:679
Event arguments for cache item removal events.
ValueType Value
Value of item that was removed.
Asynchronous First-in-First-out (FIFO) Queue, for use when transporting items of type T between task...
Definition: AsyncQueue.cs:16
Helper methods for encrypting and decrypting streams of data.
Definition: Crypto.cs:14
const SslProtocols SecureTls
TLS 1.2 & 1.3
Definition: Crypto.cs:18
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
Definition: ISniffer.cs:10
Interface for Mutual TLS (mTLS) Clients or TLS servers.
Definition: ImplTypes.g.cs:58
FtpControlConnectionState
State of FTP connection.
ClientCertificates
Client Certificate Options