Skip to content

Commit

Permalink
Unix file system implementation is complete
Browse files Browse the repository at this point in the history
  • Loading branch information
fubar-coder committed May 1, 2019
1 parent 2b1a9e2 commit ed472ed
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 43 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ The library is released under the [![MIT license](https://img.shields.io/github/

## Compilation

* Visual Studio 2017 / C# 7.3
* Visual Studio 2019 / C# 8.0

## Using

* Visual Studio 2017
* .NET Standard 2.0
* Visual Studio 2019
* .NET Standard 2.0 (everything **except** sample application, PAM authentication)
* .NET Core 3.0 (sample application, PAM authentication)

## NuGet packages

Expand Down
54 changes: 43 additions & 11 deletions samples/TestFtpServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using FubarDev.FtpServer.FileSystem.DotNet;
using FubarDev.FtpServer.FileSystem.GoogleDrive;
using FubarDev.FtpServer.FileSystem.InMemory;
using FubarDev.FtpServer.MembershipProvider.Pam;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
Expand Down Expand Up @@ -47,16 +48,21 @@ private static int Main(string[] args)
switch (v)
{
case "custom":
options.MembershipProviderType = MembershipProviderType.Custom;
options.MembershipProviderType |= MembershipProviderType.Custom;
break;
case "anonymous":
options.MembershipProviderType = MembershipProviderType.Anonymous;
options.MembershipProviderType |= MembershipProviderType.Anonymous;
break;
case "pam":
options.MembershipProviderType |= MembershipProviderType.PAM;
break;
default:
throw new ApplicationException("Invalid authentication module");
}
}
},
"Workarounds",
{ "no-pam-account-management", "Disable the PAM account management", v => options.NoPamAccountManagement = v != null },
"Server",
{ "a|address=", "Sets the IP address or host name", v => options.ServerAddress = v },
{ "p|port=", "Sets the listen port", v => options.Port = Convert.ToInt32(v) },
Expand Down Expand Up @@ -92,6 +98,14 @@ private static int Main(string[] args)
},
Run = a => RunWithFileSystemAsync(a.ToArray(), options).Wait(),
},
new Command("unix", "Use the Unix file system access")
{
Options = new OptionSet()
{
"usage: ftpserver unix",
},
Run = a => RunWithUnixFileSystemAsync(options).Wait(),
},
new Command("in-memory", "Use the in-memory file system access")
{
Options = new OptionSet()
Expand Down Expand Up @@ -148,6 +162,14 @@ private static Task RunWithFileSystemAsync(string[] args, TestFtpServerOptions o
return RunAsync(services);
}

private static Task RunWithUnixFileSystemAsync(TestFtpServerOptions options)
{
options.Validate();
var services = CreateServices(options)
.AddFtpServer(sb => Configure(sb, options).UseUnixFileSystem());
return RunAsync(services);
}

private static async Task RunWithGoogleDriveUserAsync(string[] args, TestFtpServerOptions options)
{
options.Validate();
Expand Down Expand Up @@ -255,7 +277,8 @@ private static IServiceCollection CreateServices(TestFtpServerOptions options)
opt.PasvMaxPort = options.PassivePortRange.Value.Item2;
}
})
.Configure<GoogleDriveOptions>(opt => opt.UseBackgroundUpload = options.UseBackgroundUpload);
.Configure<GoogleDriveOptions>(opt => opt.UseBackgroundUpload = options.UseBackgroundUpload)
.Configure<PamMembershipProviderOptions>(opt => opt.IgnoreAccountManagement = options.NoPamAccountManagement);

if (options.ImplicitFtps)
{
Expand Down Expand Up @@ -286,15 +309,24 @@ private static IServiceCollection CreateServices(TestFtpServerOptions options)

private static IFtpServerBuilder Configure(IFtpServerBuilder builder, TestFtpServerOptions options)
{
switch (options.MembershipProviderType)
if (options.MembershipProviderType == MembershipProviderType.Default)
{
return builder.EnableAnonymousAuthentication();
}

if ((options.MembershipProviderType & MembershipProviderType.Anonymous) != 0)
{
builder = builder.EnableAnonymousAuthentication();
}

if ((options.MembershipProviderType & MembershipProviderType.Custom) != 0)
{
builder.Services.AddSingleton<IMembershipProvider, CustomMembershipProvider>();
}

if ((options.MembershipProviderType & MembershipProviderType.PAM) != 0)
{
case MembershipProviderType.Anonymous:
return builder.EnableAnonymousAuthentication();
case MembershipProviderType.Custom:
builder.Services.AddSingleton<IMembershipProvider, CustomMembershipProvider>();
break;
default:
throw new InvalidOperationException($"Unknown membership provider {options.MembershipProviderType}");
builder = builder.EnablePamAuthentication();
}

return builder;
Expand Down
24 changes: 20 additions & 4 deletions samples/TestFtpServer/TestFtpServerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class TestFtpServerOptions
/// <summary>
/// Gets or sets a value indicating whether the help message should be shown.
/// </summary>
public bool ShowHelp { get;set; }
public bool ShowHelp { get; set; }

/// <summary>
/// Gets or sets the requested server address.
Expand Down Expand Up @@ -59,13 +59,18 @@ public class TestFtpServerOptions
/// <summary>
/// Gets or sets the membership provider to be used.
/// </summary>
public MembershipProviderType MembershipProviderType { get; set; } = MembershipProviderType.Anonymous;
public MembershipProviderType MembershipProviderType { get; set; } = MembershipProviderType.Default;

/// <summary>
/// Gets or sets the passive port range.
/// </summary>
public (int, int)? PassivePortRange { get; set; }

/// <summary>
/// Gets or sets a value indicating whether PAM account management is disabled.
/// </summary>
public bool NoPamAccountManagement { get; set; }

/// <summary>
/// Gets the requested or the default port.
/// </summary>
Expand All @@ -90,16 +95,27 @@ public void Validate()
/// <summary>
/// The selected membership provider.
/// </summary>
[Flags]
public enum MembershipProviderType
{
/// <summary>
/// Use the default membership provider (<see cref="Anonymous"/>).
/// </summary>
Default = 0,

/// <summary>
/// Use the custom (example) membership provider.
/// </summary>
Custom,
Custom = 1,

/// <summary>
/// Use the membership provider for anonymous users.
/// </summary>
Anonymous,
Anonymous = 2,

/// <summary>
/// Use the PAM membership provider.
/// </summary>
PAM = 4,
}
}
8 changes: 7 additions & 1 deletion src/FubarDev.FtpServer.FileSystem.Unix/UnixDirectoryEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public UnixDirectoryEntry(
: base(info)
{
IsRoot = parent == null;
Info = info;

if (parent == null)
{
Expand All @@ -35,10 +36,15 @@ public UnixDirectoryEntry(
}
else
{
IsDeletable = parent.GetEffectivePermissions(user, userInfo).Write;
IsDeletable = parent.GetEffectivePermissions(user, userInfo.UserId, userInfo.GroupId).Write;
}
}

/// <summary>
/// Gets the unix directory info.
/// </summary>
public UnixDirectoryInfo Info { get; }

/// <inheritdoc />
public bool IsRoot { get; }

Expand Down
6 changes: 6 additions & 0 deletions src/FubarDev.FtpServer.FileSystem.Unix/UnixFileEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ internal class UnixFileEntry : UnixFileSystemEntry, IUnixFileEntry
public UnixFileEntry([NotNull] UnixFileInfo info)
: base(info)
{
Info = info;
Size = info.Length;
}

/// <summary>
/// Gets the unix file info.
/// </summary>
public UnixFileInfo Info { get; }

/// <inheritdoc />
public long Size { get; }
}
Expand Down
Loading

0 comments on commit ed472ed

Please sign in to comment.