From 3617bef54bbfa533f291441c70ce19c19ecf87d0 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 4 Dec 2022 22:08:56 -0800 Subject: [PATCH] Fixed: Improve Bind Address validation and help text Closes #7849 (cherry picked from commit 6bdeafcf8c78e145595f52e885356be1210abe91) --- .../IsValidIPAddressFixture.cs | 25 +++++++++++++++++++ .../Extensions/StringExtensions.cs | 22 ++++++++++++++++ src/NzbDrone.Core/Localization/Core/en.json | 2 +- src/NzbDrone.Core/Validation/IpValidation.cs | 22 +++------------- .../Config/HostConfigController.cs | 4 +-- 5 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 src/NzbDrone.Common.Test/ExtensionTests/StringExtensionTests/IsValidIPAddressFixture.cs diff --git a/src/NzbDrone.Common.Test/ExtensionTests/StringExtensionTests/IsValidIPAddressFixture.cs b/src/NzbDrone.Common.Test/ExtensionTests/StringExtensionTests/IsValidIPAddressFixture.cs new file mode 100644 index 000000000..0e2ac3d63 --- /dev/null +++ b/src/NzbDrone.Common.Test/ExtensionTests/StringExtensionTests/IsValidIPAddressFixture.cs @@ -0,0 +1,25 @@ +using System.Globalization; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Common.Extensions; + +namespace NzbDrone.Common.Test.ExtensionTests.StringExtensionTests +{ + [TestFixture] + public class IsValidIPAddressFixture + { + [TestCase("192.168.0.1")] + [TestCase("::1")] + [TestCase("2001:db8:4006:812::200e")] + public void should_validate_ip_address(string input) + { + input.IsValidIpAddress().Should().BeTrue(); + } + + [TestCase("sonarr.tv")] + public void should_not_parse_non_ip_address(string input) + { + input.IsValidIpAddress().Should().BeFalse(); + } + } +} diff --git a/src/NzbDrone.Common/Extensions/StringExtensions.cs b/src/NzbDrone.Common/Extensions/StringExtensions.cs index 0f842a3fa..c57a23ebb 100644 --- a/src/NzbDrone.Common/Extensions/StringExtensions.cs +++ b/src/NzbDrone.Common/Extensions/StringExtensions.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Net; +using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; @@ -192,5 +194,25 @@ namespace NzbDrone.Common.Extensions .Replace("'", "%27") .Replace("%7E", "~"); } + + public static bool IsValidIpAddress(this string value) + { + if (!IPAddress.TryParse(value, out var parsedAddress)) + { + return false; + } + + if (parsedAddress.Equals(IPAddress.Parse("255.255.255.255"))) + { + return false; + } + + if (parsedAddress.IsIPv6Multicast) + { + return false; + } + + return parsedAddress.AddressFamily == AddressFamily.InterNetwork || parsedAddress.AddressFamily == AddressFamily.InterNetworkV6; + } } } diff --git a/src/NzbDrone.Core/Localization/Core/en.json b/src/NzbDrone.Core/Localization/Core/en.json index f3b85e496..b23b4af61 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -89,7 +89,7 @@ "Backups": "Backups", "BeforeUpdate": "Before update", "BindAddress": "Bind Address", - "BindAddressHelpText": "Valid IPv4 address or '*' for all interfaces", + "BindAddressHelpText": "Valid IP address, localhost or '*' for all interfaces", "Blocklist": "Blocklist", "Blocklisted": "Blocklisted", "BlocklistHelpText": "Prevents Radarr from automatically grabbing this release again", diff --git a/src/NzbDrone.Core/Validation/IpValidation.cs b/src/NzbDrone.Core/Validation/IpValidation.cs index 7037ae1ea..eb5863caa 100644 --- a/src/NzbDrone.Core/Validation/IpValidation.cs +++ b/src/NzbDrone.Core/Validation/IpValidation.cs @@ -1,30 +1,14 @@ -using System.Net; -using System.Net.Sockets; using FluentValidation; using FluentValidation.Validators; +using NzbDrone.Common.Extensions; namespace NzbDrone.Core.Validation { public static class IpValidation { - public static IRuleBuilderOptions ValidIp4Address(this IRuleBuilder ruleBuilder) + public static IRuleBuilderOptions ValidIpAddress(this IRuleBuilder ruleBuilder) { - return ruleBuilder.Must(x => - { - IPAddress parsedAddress; - - if (!IPAddress.TryParse(x, out parsedAddress)) - { - return false; - } - - if (parsedAddress.Equals(IPAddress.Parse("255.255.255.255"))) - { - return false; - } - - return parsedAddress.AddressFamily == AddressFamily.InterNetwork; - }).WithMessage("Must contain wildcard (*) or a valid IPv4 Address"); + return ruleBuilder.Must(x => x.IsValidIpAddress()).WithMessage("Must contain wildcard (*) or a valid IP Address"); } public static IRuleBuilderOptions NotListenAllIp4Address(this IRuleBuilder ruleBuilder) diff --git a/src/Radarr.Api.V3/Config/HostConfigController.cs b/src/Radarr.Api.V3/Config/HostConfigController.cs index 7d172d18a..5ac2b2c6f 100644 --- a/src/Radarr.Api.V3/Config/HostConfigController.cs +++ b/src/Radarr.Api.V3/Config/HostConfigController.cs @@ -33,9 +33,9 @@ namespace Radarr.Api.V3.Config _userService = userService; SharedValidator.RuleFor(c => c.BindAddress) - .ValidIp4Address() + .ValidIpAddress() .NotListenAllIp4Address() - .When(c => c.BindAddress != "*"); + .When(c => c.BindAddress != "*" && c.BindAddress != "localhost"); SharedValidator.RuleFor(c => c.Port).ValidPort();