1
0
Fork 0
mirror of https://github.com/Radarr/Radarr synced 2024-12-21 23:42:23 +00:00

New: Add config file setting for CGNAT authentication bypass

(cherry picked from commit 4c41a4f368046f73f82306bbd73bec992392938b)
This commit is contained in:
soup 2024-12-02 01:20:08 +01:00 committed by Bogdan
parent 9a107cc8d7
commit 0caa793df4
7 changed files with 42 additions and 3 deletions

View file

@ -21,9 +21,28 @@ public void should_return_true_for_local_ip_address(string ipAddress)
[TestCase("1.2.3.4")]
[TestCase("172.55.0.1")]
[TestCase("192.55.0.1")]
[TestCase("100.64.0.1")]
[TestCase("100.127.255.254")]
public void should_return_false_for_public_ip_address(string ipAddress)
{
IPAddress.Parse(ipAddress).IsLocalAddress().Should().BeFalse();
}
[TestCase("100.64.0.1")]
[TestCase("100.127.255.254")]
[TestCase("100.100.100.100")]
public void should_return_true_for_cgnat_ip_address(string ipAddress)
{
IPAddress.Parse(ipAddress).IsCgnatIpAddress().Should().BeTrue();
}
[TestCase("1.2.3.4")]
[TestCase("192.168.5.1")]
[TestCase("100.63.255.255")]
[TestCase("100.128.0.0")]
public void should_return_false_for_non_cgnat_ip_address(string ipAddress)
{
IPAddress.Parse(ipAddress).IsCgnatIpAddress().Should().BeFalse();
}
}
}

View file

@ -52,5 +52,11 @@ private static bool IsLocalIPv4(byte[] ipv4Bytes)
return isLinkLocal || isClassA || isClassC || isClassB;
}
public static bool IsCgnatIpAddress(this IPAddress ipAddress)
{
var bytes = ipAddress.GetAddressBytes();
return bytes.Length == 4 && bytes[0] == 100 && bytes[1] >= 64 && bytes[1] <= 127;
}
}
}

View file

@ -6,4 +6,5 @@ public class AuthOptions
public bool? Enabled { get; set; }
public string Method { get; set; }
public string Required { get; set; }
public bool? TrustCgnatIpAddresses { get; set; }
}

View file

@ -66,6 +66,7 @@ public interface IConfigFileProvider : IHandleAsync<ApplicationStartedEvent>,
string PostgresMainDb { get; }
string PostgresLogDb { get; }
string Theme { get; }
bool TrustCgnatIpAddresses { get; }
}
public class ConfigFileProvider : IConfigFileProvider
@ -461,5 +462,7 @@ public void Execute(ResetApiKeyCommand message)
{
SetValue("ApiKey", GenerateApiKey());
}
public bool TrustCgnatIpAddresses => _authOptions.TrustCgnatIpAddresses ?? GetValueBoolean("TrustCgnatIpAddresses", false, persist: false);
}
}

View file

@ -444,6 +444,12 @@ public bool CleanupMetadataImages
public string ApplicationUrl => GetValue("ApplicationUrl", string.Empty);
public bool TrustCgnatIpAddresses
{
get { return GetValueBoolean("TrustCgnatIpAddresses", false); }
set { SetValue("TrustCgnatIpAddresses", value); }
}
private string GetValue(string key)
{
return GetValue(key, string.Empty);

View file

@ -45,6 +45,7 @@ public class HostConfigResource : RestResource
public string BackupFolder { get; set; }
public int BackupInterval { get; set; }
public int BackupRetention { get; set; }
public bool TrustCgnatIpAddresses { get; set; }
}
public static class HostConfigResourceMapper

View file

@ -27,10 +27,13 @@ protected override Task HandleRequirementAsync(AuthorizationHandlerContext conte
if (_authenticationRequired == AuthenticationRequiredType.DisabledForLocalAddresses)
{
if (context.Resource is HttpContext httpContext &&
IPAddress.TryParse(httpContext.GetRemoteIP(), out var ipAddress) &&
ipAddress.IsLocalAddress())
IPAddress.TryParse(httpContext.GetRemoteIP(), out var ipAddress))
{
context.Succeed(requirement);
if (ipAddress.IsLocalAddress() ||
(_configService.TrustCgnatIpAddresses && ipAddress.IsCgnatIpAddress()))
{
context.Succeed(requirement);
}
}
}