Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
+ MemberValidationStatus : TooManyUsers
  • Loading branch information
ALEKSANDRS ZELIKOVICS committed Oct 6, 2022
1 parent edfe7a7 commit 1ce30c6
Show file tree
Hide file tree
Showing 27 changed files with 357 additions and 98 deletions.
1 change: 1 addition & 0 deletions FubarDev.FtpServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ Global
EndGlobalSection
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\FubarDev.FtpServer.Shared\FubarDev.FtpServer.Shared.projitems*{01ebbf94-7469-43a0-a618-07fb734b163f}*SharedItemsImports = 5
third-party\GnuSslStream\GnuSslStream.projitems*{01ebbf94-7469-43a0-a618-07fb734b163f}*SharedItemsImports = 5
src\FubarDev.FtpServer.Shared\FubarDev.FtpServer.Shared.projitems*{37ce4218-fac3-4201-82a0-54945698c6ad}*SharedItemsImports = 5
src\FubarDev.FtpServer.Shared\FubarDev.FtpServer.Shared.projitems*{474bd381-5b80-4580-bfb1-d41beb70c458}*SharedItemsImports = 5
third-party\ReadLine\ReadLine.projitems*{4bda38ca-a19d-4ba9-ac7e-e0b091b3770d}*SharedItemsImports = 5
Expand Down
6 changes: 6 additions & 0 deletions samples/TestFtpServer/TestFtpServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
<AssemblyName>ftpserver</AssemblyName>
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JKang.IpcServiceFramework.Server" Version="2.3.1" />
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />
Expand Down
15 changes: 8 additions & 7 deletions samples/TestFtpServer/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
{
"Serilog": {
"Using": ["Serilog.Sinks.Console"],
"MinimumLevel":{
"Using": [ "Serilog.Sinks.Console" ],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft": "Information",
"FubarDev.FtpServer.CommandHandlers.ListCommandHandler": "Verbose",
"FubarDev.FtpServer.CommandHandlers.MlstCommandHandler": "Verbose"
}
},
"WriteTo": [
"WriteTo": [
{
"Name": "Console",
"OutputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {ConnectionId} {Message:lj}{NewLine}{Exception}"
}
],
"Enrich": ["FromLogContext"]
"Enrich": [ "FromLogContext" ]
},

/* Supported authentication types are: "custom","anonymous", "pam", "default".
* "default" means "not set" and is equal to "anonymous". */
"authentication": "default",
// "authentication": "default",
"authentication": "custom",

/* Sets the user id and group id for file system operations when
* authentication is "pam" and "backend" is "unix". */
Expand Down Expand Up @@ -76,11 +77,11 @@
"ftps": {
/* Path to the X.509 certificate.
* It may either be a certificate or a PKCS#12-file with private key. */
"certificate": null,
"certificate": "C:\\Users\\alex\\Desktop\\cert\\alexander.abc.pfx",
/* Path to private key for the certificate. */
"privateKey": null,
/* Password used to decrypt the PFX file. */
"password": null,
"password": "123",
/* Use implicit AUTH TLS? */
"implicit": false
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,14 @@ public interface IMembershipProviderAsync : IMembershipProvider
/// <param name="password">The password.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
/// <returns>The result of the validation.</returns>
Task<MemberValidationResult> ValidateUserAsync(
string username,
string password,
CancellationToken cancellationToken = default);
Task<MemberValidationResult> ValidateUserAsync(string username, string password, CancellationToken cancellationToken = default);

/// <summary>
/// Logout of the given <paramref name="principal"/>.
/// </summary>
/// <param name="principal">The principal to be logged out.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
/// <returns>The task.</returns>
Task LogOutAsync(
ClaimsPrincipal principal,
CancellationToken cancellationToken = default);
Task LogOutAsync(ClaimsPrincipal principal, CancellationToken cancellationToken = default);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,10 @@ public enum MemberValidationStatus
/// User authenticated successfully.
/// </summary>
AuthenticatedUser,

/// <summary>
/// The too many users
/// </summary>
TooManyUsers,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,8 @@ private async Task SendResponseAsync(IFtpResponse? response, CancellationToken c
}

var serverCommandFeature = _connection.Features.Get<IServerCommandFeature>();
await serverCommandFeature.ServerCommandWriter
.WriteAsync(new SendResponseServerCommand(response), cancellationToken)
.ConfigureAwait(false);
await serverCommandFeature.ServerCommandWriter.WriteAsync(new SendResponseServerCommand(response), cancellationToken).ConfigureAwait(false);

if (response.Code == 421)
{
// Critical Error: We have to close the connection!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,21 @@ public interface ISecureConnectionFeature
/// </summary>
/// <remarks>This doesn't apply to encrypted data streams.</remarks>
CloseEncryptedStreamDelegate CloseEncryptedControlStream { get; set; }

/// <summary>
/// Checks the security.
/// </summary>
/// <param name="errorMess">The error mess.</param>
/// <param name="connection">The connection.</param>
/// <returns>IFtpResponse.</returns>
public IFtpResponse CheckSecurity(string errorMess, IFtpConnection connection);

/// <summary>
/// Gets or sets a value indicating whether this instance is secure.
/// </summary>
/// <value>
/// <c>true</c> if this instance is secure; otherwise, <c>false</c>.
/// </value>
public bool IsSecure { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1;net472</TargetFrameworks>
<Description>Interfaces for the portable FTP server</Description>
<RootNamespace>FubarDev.FtpServer</RootNamespace>
<PackageTags>portable;FTP;server</PackageTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ public AppeCommandHandler(
/// <inheritdoc/>
public override async Task<IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken)
{
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();

var isSecureResponse = secureConnectionFeature.CheckSecurity(T("Please use TLS connection"), Connection);

if (isSecureResponse != null)
{
return isSecureResponse;
}

var restartPosition = Connection.Features.Get<IRestCommandFeature?>()?.RestartPosition;
Connection.Features.Set<IRestCommandFeature?>(null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;

using FubarDev.FtpServer.Commands;
using FubarDev.FtpServer.Features;

using Microsoft.Extensions.DependencyInjection;

Expand All @@ -21,7 +22,13 @@ public class AuthCommandHandler : FtpCommandHandler
public override Task<IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken)
{
var loginStateMachine = Connection.ConnectionServices.GetRequiredService<IFtpLoginStateMachine>();
return loginStateMachine.ExecuteAsync(command, cancellationToken);

var res = loginStateMachine.ExecuteAsync(command, cancellationToken);

var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();
secureConnectionFeature.IsSecure = true;

return res;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ public DeleCommandHandler(ILogger<DeleCommandHandler>? logger = null)
/// <inheritdoc/>
public override async Task<IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken)
{
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();

var isSecureResponse = secureConnectionFeature.CheckSecurity(T("Please use TLS connection"), Connection);

if (isSecureResponse != null)
{
return isSecureResponse;
}

var path = command.Argument;
var fsFeature = Connection.Features.Get<IFileSystemFeature>();
var currentPath = fsFeature.Path.Clone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ public ListCommandHandler(
/// <inheritdoc/>
public override async Task<IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken)
{
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();

var isSecureResponse = secureConnectionFeature.CheckSecurity(T("Please use TLS connection"), Connection);

if (isSecureResponse != null)
{
return isSecureResponse;
}

await FtpContext.ServerCommandWriter
.WriteAsync(
new SendResponseServerCommand(new FtpResponse(150, T("Opening data connection."))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ public class MdtmCommandHandler : FtpCommandHandler
/// <inheritdoc/>
public override async Task<IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken)
{
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();

var isSecureResponse = secureConnectionFeature.CheckSecurity(T("Please use TLS connection"), Connection);

if (isSecureResponse != null)
{
return isSecureResponse;
}

var path = command.Argument;
var fsFeature = Connection.Features.Get<IFileSystemFeature>();
var currentPath = fsFeature.Path.Clone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ internal static IMlstFactsFeature CreateMlstFactsFeature()

private async Task<IFtpResponse?> ProcessMlstAsync(FtpCommand command, CancellationToken cancellationToken)
{
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();

var isSecureResponse = secureConnectionFeature.CheckSecurity(T("Please use TLS connection"), Connection);

if (isSecureResponse != null)
{
return isSecureResponse;
}

var argument = command.Argument;
var fsFeature = Connection.Features.Get<IFileSystemFeature>();
var path = fsFeature.Path.Clone();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading.Tasks;

using FubarDev.FtpServer.Commands;
using FubarDev.FtpServer.Features;

using Microsoft.Extensions.DependencyInjection;

Expand All @@ -23,6 +24,15 @@ public class PassCommandHandler : FtpCommandHandler
/// <inheritdoc/>
public override Task<IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken)
{
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();

var isSecureResponse = secureConnectionFeature.CheckSecurity(T("Please use TLS connection"), Connection);

if (isSecureResponse != null)
{
return Task.FromResult(isSecureResponse);
}

var loginStateMachine = Connection.ConnectionServices.GetRequiredService<IFtpLoginStateMachine>();
return loginStateMachine.ExecuteAsync(command, cancellationToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ public RetrCommandHandler(
/// <inheritdoc/>
public override async Task<IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken)
{
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();

var isSecureResponse = secureConnectionFeature.CheckSecurity(T("Please use TLS connection"), Connection);

if (isSecureResponse != null)
{
return isSecureResponse;
}

var restartPosition = Connection.Features.Get<IRestCommandFeature?>()?.RestartPosition;
Connection.Features.Set<IRestCommandFeature?>(null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ public StorCommandHandler(
/// <inheritdoc/>
public override async Task<IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken)
{
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();

var isSecureResponse = secureConnectionFeature.CheckSecurity(T("Please use TLS connection"), Connection);

if (isSecureResponse != null)
{
return isSecureResponse;
}

var restartPosition = Connection.Features.Get<IRestCommandFeature?>()?.RestartPosition;
Connection.Features.Set<IRestCommandFeature?>(null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading.Tasks;

using FubarDev.FtpServer.Commands;
using FubarDev.FtpServer.Features;

using Microsoft.Extensions.DependencyInjection;

Expand All @@ -23,6 +24,15 @@ public class UserCommandHandler : FtpCommandHandler
/// <inheritdoc/>
public override Task<IFtpResponse?> Process(FtpCommand command, CancellationToken cancellationToken)
{
var secureConnectionFeature = Connection.Features.Get<ISecureConnectionFeature>();

var isSecureResponse = secureConnectionFeature.CheckSecurity(T("Please use TLS connection"), Connection);

if (isSecureResponse != null)
{
return Task.FromResult(isSecureResponse);
}

var loginStateMachine = Connection.ConnectionServices.GetRequiredService<IFtpLoginStateMachine>();
return loginStateMachine.ExecuteAsync(command, cancellationToken);
}
Expand Down
8 changes: 8 additions & 0 deletions src/FubarDev.FtpServer/AuthTlsOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,13 @@ public class AuthTlsOptions
/// Gets or sets a value indicating whether implicit FTPS is used.
/// </summary>
public bool ImplicitFtps { get; set; }

/// <summary>
/// Gets or sets a value indicating whether [only secure connection].
/// </summary>
/// <value>
/// <c>true</c> if [only secure connection]; otherwise, <c>false</c>.
/// </value>
public bool OnlySecureConnection { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
Expand Down Expand Up @@ -39,6 +40,7 @@ public async Task<Stream> WrapStreamAsync(
{
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
_logger?.LogTrace("Create SSL stream");
var sslStream = CreateSslStream(unencryptedStream, keepOpen);
try
Expand Down
30 changes: 30 additions & 0 deletions src/FubarDev.FtpServer/Authentication/SslStreamExt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace FubarDev.FtpServer.Authentication
{
namespace System.Net.Security
{
public class NegotiateStream : AuthenticatedStream
{
public override Task FlushAsync(CancellationToken cancellationToken);
}
public class SslStream : AuthenticatedStream
{
public virtual void AuthenticateAsClient(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation);
public virtual Task AuthenticateAsClientAsync(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation);
public virtual void AuthenticateAsServer(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation);
public virtual Task AuthenticateAsServerAsync(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation);
public virtual IAsyncResult BeginAuthenticateAsClient(string targetHost, X509CertificateCollection clientCertificates, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
public virtual IAsyncResult BeginAuthenticateAsServer(X509Certificate serverCertificate, bool clientCertificateRequired, bool checkCertificateRevocation, AsyncCallback asyncCallback, object asyncState);
public override Task FlushAsync(CancellationToken cancellationToken);
public virtual Task ShutdownAsync();
}
}
}
Loading

0 comments on commit 1ce30c6

Please sign in to comment.