2using System.ComponentModel;
4using System.Security.Authentication;
5using System.Security.Cryptography.X509Certificates;
7using System.Threading.Tasks;
23 private static readonly Random rnd =
new Random();
25 private readonly Guid
id = Guid.NewGuid();
26 private readonly UTF8Encoding encoding =
new UTF8Encoding(
false,
false);
31 private string authId =
null;
32 private bool disposed =
false;
34 private object tag =
null;
35 private bool upgradeToTls =
false;
50 this.persistence = Persistence;
52 this.client.OnDisconnected += this.Client_OnDisconnected;
53 this.client.OnError += this.Client_OnError;
54 this.client.OnReceived += this.Client_OnReceived;
55 this.client.OnPaused += this.Client_OnPaused;
66 public Guid
ID => this.id;
89 set => this.tag = value;
112 get => this.upgradeToTls;
113 protected set => this.upgradeToTls = value;
127 [Obsolete(
"Use the DisposeAsync() method.")]
141 if (!(Sniffers is
null) && !(this.server is
null))
147 this.disposed =
true;
155 private async Task<bool> Client_OnReceived(
object Sender,
bool ConstantBuffer,
byte[] Buffer,
int Offset,
int Count)
159 return await this.
ParseIncoming(ConstantBuffer, Buffer, Offset, Count);
178 private async Task Client_OnError(
object Sender, Exception Exception)
191 private Task Client_OnDisconnected(
object Sender, EventArgs e)
204 protected abstract Task<bool>
ParseIncoming(
bool ConstantBuffer,
byte[] Data,
int Offset,
int NrRead);
206 private async Task Client_OnPaused(
object Sender, EventArgs e)
208 if (this.upgradeToTls)
210 this.upgradeToTls =
false;
226 catch (AuthenticationException ex)
230 catch (Win32Exception ex)
237 await this.ToError(
null);
241 await this.ToError(
null);
257 private async Task LoginFailure(Exception ex,
string RemoteIpEndpoint)
262 await this.ToError(
null);
265 private async Task ToError(
string ClosingCommand)
267 if (
string.IsNullOrEmpty(ClosingCommand))
271 await this.
BeginWrite(ClosingCommand, async (Sender, e) =>
285 public Task<bool>
BeginWrite(
string Text, EventHandlerAsync<DeliveryEventArgs> Callback,
object State)
288 return Task.FromResult(
false);
290 return this.client.
SendAsync(
true, this.encoding.GetBytes(Text), async (Sender, e) =>
294 if (!(Callback is
null))
295 await Callback.Raise(
this, e);
325 return Task.CompletedTask;
376 bool BlockingBak = this.client.
Client.Client.Blocking;
379 byte[] Temp =
new byte[1];
381 this.client.Client.Client.Blocking =
false;
382 this.client.
Client.Client.Send(Temp, 0, 0);
386 catch (SocketException e)
388 if (e.NativeErrorCode.Equals(10035))
395 this.client.Client.Client.Blocking = BlockingBak;
420 internal static int Next(
int MaxValue)
424 return rnd.Next(MaxValue);
Static class managing the application event log. Applications and services log events on this static ...
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
Implements a binary TCP Client, by encapsulating a TcpClient. It also makes the use of TcpClient safe...
bool Connected
If the connection is open.
bool RemoteCertificateValid
If the remote certificate is valid.
TcpClient Client
Underlying TcpClient object.
Task< bool > SendAsync(byte[] Packet)
Sends a binary packet.
string RemoteEndPoint
Remote End-point of connection. This corresponds to the IP Endpoint of the remote party in normal cas...
void DisposeWhenDone()
Disposes the client when done sending all data.
void Continue()
Continues reading from the socket, if paused in an event handler.
X509Certificate RemoteCertificate
Certificate used by the remote endpoint.
Task UpgradeToTlsAsServer(X509Certificate ServerCertificate)
Upgrades a server connection to TLS.
bool IsEncrypted
If connection is encrypted or not.
Simple base class for classes implementing communication protocols.
void TransmitText(string Text)
Called when text has been transmitted.
void Exception(Exception Exception)
Called to inform the viewer of an exception state.
ISniffer[] Sniffers
Registered sniffers.
Task RemoveRange(IEnumerable< ISniffer > Sniffers)
Removes a set of sniffers, if registered.
Abstract base class for FTP client connections.
bool UpgradeToTls
If the connection is to be upgraded to TLS.
abstract Task AfterUpgradeToTls(object Item)
Called after upgrading to TLS.
abstract Task< bool > SaslErrorNotAuthorized()
Is called when a failed authentication attempt has been made.
bool IsEncrypted
If the connection is encrypted.
abstract Task< object > BeforeUpgradeToTls()
Called before upgrading to TLS.
virtual async Task DisposeAsync()
Closes the connection and disposes of all resources.
IAccount Account
Account of authenticated user.
virtual Task SetAccount(IAccount Account)
Sets the account for the connection.
abstract Task< bool > SaslErrorAccountDisabled()
Is called when a an authentication attempt has been made using a disabled account.
Task< bool > BeginWrite(string Text, EventHandlerAsync< DeliveryEventArgs > Callback, object State)
Starts sending a text command to the client.
string AuthId
ID client claims to have
virtual void ResetState(bool Authenticated)
Resets the state of the connection.
string Protocol
String representing protocol being used.
abstract Task< bool > SaslErrorMalformedRequest()
Is called when a an authentication attempt has been made using a malformed request.
void SetUserIdentity(CaseInsensitiveString UserName)
Sets the identity of the user after successful authentication.
void ResetState()
Resets the state of the connection.
virtual bool CheckLive()
Checks if the connection is live.
string RemoteEndPoint
Remote endpoint.
void Dispose()
IDisposable.Dispose
abstract Task< bool > SaslChallenge(string ChallengeBase64)
Is called when a an authentication challenge has been received.
FtpClientConnection(BinaryTcpClient Client, FtpServer Server, IFtpServerPersistenceLayer Persistence, params ISniffer[] Sniffers)
Class managing a connection.
virtual async Task ErrorAndClose()
Closes the connection due to an error.
object Tag
Tag object. Can be used to maintain states between calls, for instance during authentication.
BinaryTcpClient Client
Underlying TCP connection.
abstract Task< bool > SaslSuccess(string ProofBase64)
Is called when a a successful authentication response has been received.
FtpServer Server
FTP Server serving the client.
CaseInsensitiveString UserName
User name
bool Disposed
If object has been disposed.
abstract Task< bool > ParseIncoming(bool ConstantBuffer, byte[] Data, int Offset, int NrRead)
Parses incoming binary data.
Implements a simple FTP Server, as defined in:
X509Certificate ServerCertificate
Server domain certificate.
CaseInsensitiveString Domain
Domain name.
Represents a case-insensitive string.
static readonly CaseInsensitiveString Empty
Empty case-insensitive string
Helper methods for encrypting and decrypting streams of data.
const SslProtocols SecureTls
TLS 1.2 & 1.3
Class that monitors login events, and help applications determine malicious intent....
static bool CanStartTls(string RemoteEndPoint)
Checks if TLS negotiation can start, for a given endpoint. If the endpoint has tries a TLS hack attem...
static void ReportTlsHackAttempt(string RemoteEndPoint, string Message, string Protocol)
Reports a TLS hacking attempt from an endpoint. Can be used to deny TLS negotiation to proceed,...
Interface for asynchronously disposable objects.
Persistence layer for FTP servers.
Interface for SMTP user accounts.
CaseInsensitiveString UserName
User Name
void AccountLogin(CaseInsensitiveString UserName, string RemoteEndPoint)
Successful login to account registered.
Interface for server-side client connections.
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
ClientCertificates
Client Certificate Options