Skip to content

Commit

Permalink
Closes #2371
Browse files Browse the repository at this point in the history
  • Loading branch information
JustArchi committed Jul 10, 2021
1 parent fd4c1ef commit c60b038
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 16 deletions.
16 changes: 10 additions & 6 deletions ArchiSteamFarm/IPC/Integration/ApiAuthenticationMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,22 @@ private static async Task<HttpStatusCode> GetAuthenticationStatus(HttpContext co
throw new InvalidOperationException(nameof(ClearFailedAuthorizationsTimer));
}

string? ipcPassword = ASF.GlobalConfig != null ? ASF.GlobalConfig.IPCPassword : GlobalConfig.DefaultIPCPassword;

if (string.IsNullOrEmpty(ipcPassword)) {
return HttpStatusCode.OK;
}

IPAddress? clientIP = context.Connection.RemoteIpAddress;

if (clientIP == null) {
throw new InvalidOperationException(nameof(clientIP));
}

string? ipcPassword = ASF.GlobalConfig != null ? ASF.GlobalConfig.IPCPassword : GlobalConfig.DefaultIPCPassword;

if (string.IsNullOrEmpty(ipcPassword)) {
if (IPAddress.IsLoopback(clientIP) || Startup.KnownNetworks.Any(network => network.Contains(clientIP))) {
return HttpStatusCode.OK;
}

return HttpStatusCode.Forbidden;
}

if (FailedAuthorizations.TryGetValue(clientIP, out byte attempts)) {
if (attempts >= MaxFailedAuthorizationAttempts) {
return HttpStatusCode.Forbidden;
Expand Down
27 changes: 17 additions & 10 deletions ArchiSteamFarm/IPC/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#endif
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Net;
using System.Reflection;
Expand All @@ -53,6 +54,8 @@

namespace ArchiSteamFarm.IPC {
internal sealed class Startup {
internal static ImmutableHashSet<IPNetwork> KnownNetworks { get; private set; } = ImmutableHashSet<IPNetwork>.Empty;

private readonly IConfiguration Configuration;

public Startup(IConfiguration configuration) => Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
Expand Down Expand Up @@ -148,12 +151,12 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
app.UseRouting();
#endif

// We want to protect our API with IPCPassword and additional security, this should be called after routing, so the middleware won't have to deal with API endpoints that do not exist
app.UseWhen(context => context.Request.Path.StartsWithSegments("/Api", StringComparison.OrdinalIgnoreCase), appBuilder => appBuilder.UseMiddleware<ApiAuthenticationMiddleware>());

string? ipcPassword = ASF.GlobalConfig != null ? ASF.GlobalConfig.IPCPassword : GlobalConfig.DefaultIPCPassword;

if (!string.IsNullOrEmpty(ipcPassword)) {
// We want to protect our API with IPCPassword, this should be called after routing, so the middleware won't have to deal with API endpoints that do not exist
app.UseWhen(context => context.Request.Path.StartsWithSegments("/Api", StringComparison.OrdinalIgnoreCase), appBuilder => appBuilder.UseMiddleware<ApiAuthenticationMiddleware>());

// We want to apply CORS policy in order to allow userscripts and other third-party integrations to communicate with ASF API, this should be called before response compression, but can't be due to how our flow works
// We apply CORS policy only with IPCPassword set as an extra authentication measure
app.UseCors();
Expand Down Expand Up @@ -194,11 +197,10 @@ public void ConfigureServices(IServiceCollection services) {
// Prepare knownNetworks that we'll use in a second
HashSet<string>? knownNetworksTexts = Configuration.GetSection("Kestrel:KnownNetworks").Get<HashSet<string>>();

HashSet<IPNetwork>? knownNetworks = null;
HashSet<IPNetwork> knownNetworks = new();

if (knownNetworksTexts?.Count > 0) {
knownNetworks = new HashSet<IPNetwork>(knownNetworksTexts.Count);

// Use specified known networks
foreach (string knownNetworkText in knownNetworksTexts) {
string[] addressParts = knownNetworkText.Split('/', StringSplitOptions.RemoveEmptyEntries);

Expand All @@ -211,17 +213,22 @@ public void ConfigureServices(IServiceCollection services) {

knownNetworks.Add(new IPNetwork(ipAddress, prefixLength));
}
} else {
// Use private address space networks by default, https://datatracker.ietf.org/doc/html/rfc1918#section-3
knownNetworks.Add(new IPNetwork(IPAddress.Parse("10.0.0.0"), 8));
knownNetworks.Add(new IPNetwork(IPAddress.Parse("172.16.0.0"), 12));
knownNetworks.Add(new IPNetwork(IPAddress.Parse("192.168.0.0"), 16));
}

KnownNetworks = knownNetworks.ToImmutableHashSet();

// Add support for proxies
services.Configure<ForwardedHeadersOptions>(
options => {
options.ForwardedHeaders = ForwardedHeaders.All;

if (knownNetworks != null) {
foreach (IPNetwork knownNetwork in knownNetworks) {
options.KnownNetworks.Add(knownNetwork);
}
foreach (IPNetwork knownNetwork in KnownNetworks) {
options.KnownNetworks.Add(knownNetwork);
}
}
);
Expand Down

0 comments on commit c60b038

Please sign in to comment.