diff --git a/src/NzbDrone.Api/Config/HostConfigModule.cs b/src/NzbDrone.Api/Config/HostConfigModule.cs index c5103222c..d8dce397f 100644 --- a/src/NzbDrone.Api/Config/HostConfigModule.cs +++ b/src/NzbDrone.Api/Config/HostConfigModule.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Reflection; using FluentValidation; using NzbDrone.Common.EnvironmentInfo; @@ -25,7 +26,9 @@ namespace NzbDrone.Api.Config SharedValidator.RuleFor(c => c.Branch).NotEmpty().WithMessage("Branch name is required, 'master' is the default"); SharedValidator.RuleFor(c => c.Port).ValidPort(); - + SharedValidator.RuleFor(c => c.BindAddress).ValidIp4Address().When(c => c.BindAddress != "*"); + SharedValidator.RuleFor(c => c.Port).InclusiveBetween(1, 65535); + SharedValidator.RuleFor(c => c.Username).NotEmpty().When(c => c.AuthenticationEnabled); SharedValidator.RuleFor(c => c.Password).NotEmpty().When(c => c.AuthenticationEnabled); diff --git a/src/NzbDrone.Api/Config/HostConfigResource.cs b/src/NzbDrone.Api/Config/HostConfigResource.cs index f8dde71a7..7cdf741ae 100644 --- a/src/NzbDrone.Api/Config/HostConfigResource.cs +++ b/src/NzbDrone.Api/Config/HostConfigResource.cs @@ -6,6 +6,7 @@ namespace NzbDrone.Api.Config { public class HostConfigResource : RestResource { + public String BindAddress { get; set; } public Int32 Port { get; set; } public Int32 SslPort { get; set; } public Boolean EnableSsl { get; set; } diff --git a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs index 6a9bcffbb..6120ef7a7 100644 --- a/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs +++ b/src/NzbDrone.Core/Configuration/ConfigFileProvider.cs @@ -23,6 +23,7 @@ namespace NzbDrone.Core.Configuration Dictionary GetConfigDictionary(); void SaveConfigDictionary(Dictionary configValues); + string BindAddress { get; } int Port { get; } int SslPort { get; } bool EnableSsl { get; } @@ -110,6 +111,22 @@ namespace NzbDrone.Core.Configuration _eventAggregator.PublishEvent(new ConfigFileSavedEvent()); } + public string BindAddress + { + get + { + const string defaultValue = "*"; + + string bindAddress = GetValue("BindAddress", defaultValue); + if (string.IsNullOrWhiteSpace(bindAddress)) + { + return defaultValue; + } + + return bindAddress; + } + } + public int Port { get { return GetValueInt("Port", 8989); } diff --git a/src/NzbDrone.Core/Validation/RuleBuilderExtensions.cs b/src/NzbDrone.Core/Validation/RuleBuilderExtensions.cs index b0fb71377..3751ee2b7 100644 --- a/src/NzbDrone.Core/Validation/RuleBuilderExtensions.cs +++ b/src/NzbDrone.Core/Validation/RuleBuilderExtensions.cs @@ -1,4 +1,6 @@ -using System.Text.RegularExpressions; +using System.Net; +using System.Net.Sockets; +using System.Text.RegularExpressions; using FluentValidation; using FluentValidation.Validators; using NzbDrone.Core.Parser; @@ -33,6 +35,21 @@ namespace NzbDrone.Core.Validation return ruleBuilder.SetValidator(new InclusiveBetweenValidator(1, 65535)); } + public static IRuleBuilderOptions ValidIp4Address(this IRuleBuilder ruleBuilder) + { + + return ruleBuilder.Must(x => + { + IPAddress parsedAddress; + if (!IPAddress.TryParse(x, out parsedAddress)) + { + return false; + } + + return parsedAddress.AddressFamily == AddressFamily.InterNetwork; + }); + } + public static IRuleBuilderOptions ValidLanguage(this IRuleBuilder ruleBuilder) { return ruleBuilder.SetValidator(new LangaugeValidator()); diff --git a/src/NzbDrone.Host/AccessControl/UrlAclAdapter.cs b/src/NzbDrone.Host/AccessControl/UrlAclAdapter.cs index fd2557e02..3b4bd5437 100644 --- a/src/NzbDrone.Host/AccessControl/UrlAclAdapter.cs +++ b/src/NzbDrone.Host/AccessControl/UrlAclAdapter.cs @@ -37,30 +37,30 @@ namespace NzbDrone.Host.AccessControl public void ConfigureUrl() { - var localHttpUrls = BuildUrls("http", "localhost", _configFileProvider.Port); - var wildcardHttpUrls = BuildUrls("http", "*", _configFileProvider.Port); + var localHostHttpUrls = BuildUrls("http", "localhost", _configFileProvider.Port); + var interfaceHttpUrls = BuildUrls("http", _configFileProvider.BindAddress, _configFileProvider.Port); - var localHttpsUrls = BuildUrls("https", "localhost", _configFileProvider.SslPort); - var wildcardHttpsUrls = BuildUrls("https", "*", _configFileProvider.SslPort); + var localHostHttpsUrls = BuildUrls("https", "localhost", _configFileProvider.SslPort); + var interfaceHttpsUrls = BuildUrls("https", _configFileProvider.BindAddress, _configFileProvider.SslPort); if (!_configFileProvider.EnableSsl) { - localHttpsUrls.Clear(); - wildcardHttpsUrls.Clear(); + Urls.Clear(); + interfaceHttpsUrls.Clear(); } if (OsInfo.IsWindows && !_runtimeInfo.IsAdmin) { - var httpUrls = wildcardHttpUrls.All(IsRegistered) ? wildcardHttpUrls : localHttpUrls; - var httpsUrls = wildcardHttpsUrls.All(IsRegistered) ? wildcardHttpsUrls : localHttpsUrls; + var httpUrls = interfaceHttpUrls.All(IsRegistered) ? interfaceHttpUrls : localHostHttpUrls; + var httpsUrls = interfaceHttpsUrls.All(IsRegistered) ? interfaceHttpsUrls : localHostHttpsUrls; Urls.AddRange(httpUrls); Urls.AddRange(httpsUrls); } else { - Urls.AddRange(wildcardHttpUrls); - Urls.AddRange(wildcardHttpsUrls); + Urls.AddRange(interfaceHttpUrls); + Urls.AddRange(interfaceHttpsUrls); if (OsInfo.IsWindows) { diff --git a/src/UI/Settings/General/GeneralViewTemplate.hbs b/src/UI/Settings/General/GeneralViewTemplate.hbs index 9c4e95a2b..c5ed1cadf 100644 --- a/src/UI/Settings/General/GeneralViewTemplate.hbs +++ b/src/UI/Settings/General/GeneralViewTemplate.hbs @@ -2,6 +2,18 @@
Start-Up +
+ + +
+ +
+ +
+ +
+
+