From acf3ef7fb2c6bdaaea04ec75c7994d121f8a02a0 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 #3167 (cherry picked from commit 6bdeafcf8c78e145595f52e885356be1210abe91) --- .../Config/HostConfigController.cs | 4 +-- .../IsValidIPAddressFixture.cs | 25 +++++++++++++++++++ .../Extensions/StringExtensions.cs | 22 ++++++++++++++++ src/NzbDrone.Core/Localization/Core/en.json | 2 +- src/NzbDrone.Core/Validation/IpValidation.cs | 22 +++------------- 5 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 src/NzbDrone.Common.Test/ExtensionTests/StringExtensionTests/IsValidIPAddressFixture.cs diff --git a/src/Lidarr.Api.V1/Config/HostConfigController.cs b/src/Lidarr.Api.V1/Config/HostConfigController.cs index 1eae320b6..c34fc3132 100644 --- a/src/Lidarr.Api.V1/Config/HostConfigController.cs +++ b/src/Lidarr.Api.V1/Config/HostConfigController.cs @@ -33,9 +33,9 @@ namespace Lidarr.Api.V1.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(); 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 686167d64..a3fa20bbf 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; @@ -231,5 +233,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 1a11a83a1..37cbbc441 100644 --- a/src/NzbDrone.Core/Localization/Core/en.json +++ b/src/NzbDrone.Core/Localization/Core/en.json @@ -100,7 +100,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", "BindAddressHelpTextWarning": "Requires restart to take effect", "Blocklist": "Blocklist", "BlocklistHelpText": "Prevents Lidarr from automatically grabbing these files 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)