Added ssl support (config file only)
This commit is contained in:
parent
48dbc127a7
commit
2b85b7f466
|
@ -20,6 +20,8 @@ namespace NzbDrone.Core.Configuration
|
||||||
void SaveConfigDictionary(Dictionary<string, object> configValues);
|
void SaveConfigDictionary(Dictionary<string, object> configValues);
|
||||||
|
|
||||||
int Port { get; }
|
int Port { get; }
|
||||||
|
int SslPort { get; }
|
||||||
|
bool EnableSsl { get; }
|
||||||
bool LaunchBrowser { get; }
|
bool LaunchBrowser { get; }
|
||||||
bool AuthenticationEnabled { get; }
|
bool AuthenticationEnabled { get; }
|
||||||
string Username { get; }
|
string Username { get; }
|
||||||
|
@ -27,6 +29,7 @@ namespace NzbDrone.Core.Configuration
|
||||||
string LogLevel { get; }
|
string LogLevel { get; }
|
||||||
string Branch { get; }
|
string Branch { get; }
|
||||||
bool Torrent { get; }
|
bool Torrent { get; }
|
||||||
|
string SslCertHash { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ConfigFileProvider : IConfigFileProvider
|
public class ConfigFileProvider : IConfigFileProvider
|
||||||
|
@ -90,6 +93,16 @@ namespace NzbDrone.Core.Configuration
|
||||||
get { return GetValueInt("Port", 8989); }
|
get { return GetValueInt("Port", 8989); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int SslPort
|
||||||
|
{
|
||||||
|
get { return GetValueInt("SslPort", 9898); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool EnableSsl
|
||||||
|
{
|
||||||
|
get { return GetValueBoolean("EnableSsl", false); }
|
||||||
|
}
|
||||||
|
|
||||||
public bool LaunchBrowser
|
public bool LaunchBrowser
|
||||||
{
|
{
|
||||||
get { return GetValueBoolean("LaunchBrowser", true); }
|
get { return GetValueBoolean("LaunchBrowser", true); }
|
||||||
|
@ -125,6 +138,11 @@ namespace NzbDrone.Core.Configuration
|
||||||
get { return GetValue("LogLevel", "Info"); }
|
get { return GetValue("LogLevel", "Info"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string SslCertHash
|
||||||
|
{
|
||||||
|
get { return GetValue("SslCertHash", ""); }
|
||||||
|
}
|
||||||
|
|
||||||
public int GetValueInt(string key, int defaultValue)
|
public int GetValueInt(string key, int defaultValue)
|
||||||
{
|
{
|
||||||
return Convert.ToInt32(GetValue(key, defaultValue));
|
return Convert.ToInt32(GetValue(key, defaultValue));
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
using System;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Processes;
|
||||||
|
|
||||||
|
namespace NzbDrone.Host.AccessControl
|
||||||
|
{
|
||||||
|
public interface INetshProvider
|
||||||
|
{
|
||||||
|
ProcessOutput Run(string arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NetshProvider : INetshProvider
|
||||||
|
{
|
||||||
|
private readonly IProcessProvider _processProvider;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public NetshProvider(IProcessProvider processProvider, Logger logger)
|
||||||
|
{
|
||||||
|
_processProvider = processProvider;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessOutput Run(string arguments)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var output = _processProvider.StartAndCapture("netsh.exe", arguments);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.WarnException("Error executing netsh with arguments: " + arguments, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
|
namespace NzbDrone.Host.AccessControl
|
||||||
|
{
|
||||||
|
public interface ISslAdapter
|
||||||
|
{
|
||||||
|
void Register();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SslAdapter : ISslAdapter
|
||||||
|
{
|
||||||
|
private const string APP_ID = "C2172AF4-F9A6-4D91-BAEE-C2E4EE680613";
|
||||||
|
|
||||||
|
private readonly INetshProvider _netshProvider;
|
||||||
|
private readonly IConfigFileProvider _configFileProvider;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public SslAdapter(INetshProvider netshProvider, IConfigFileProvider configFileProvider, Logger logger)
|
||||||
|
{
|
||||||
|
_netshProvider = netshProvider;
|
||||||
|
_configFileProvider = configFileProvider;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Register()
|
||||||
|
{
|
||||||
|
if (!_configFileProvider.EnableSsl) return;
|
||||||
|
if (IsRegistered()) return;
|
||||||
|
|
||||||
|
if (String.IsNullOrWhiteSpace(_configFileProvider.SslCertHash))
|
||||||
|
{
|
||||||
|
_logger.Warn("Unable to enable SSL, SSL Cert Hash is required");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var arguments = String.Format("netsh http add sslcert ipport=0.0.0.0:{0} certhash={1} appid={{{2}}", _configFileProvider.SslPort, _configFileProvider.SslCertHash, APP_ID);
|
||||||
|
_netshProvider.Run(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsRegistered()
|
||||||
|
{
|
||||||
|
var ipPort = "0.0.0.0:" + _configFileProvider.SslPort;
|
||||||
|
var arguments = String.Format("http show sslcert ipport={0}", ipPort);
|
||||||
|
|
||||||
|
var output = _netshProvider.Run(arguments);
|
||||||
|
|
||||||
|
if (output == null || !output.Standard.Any()) return false;
|
||||||
|
|
||||||
|
return output.Standard.Any(line => line.Contains(ipPort));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common;
|
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Processes;
|
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
namespace NzbDrone.Host.AccessControl
|
namespace NzbDrone.Host.AccessControl
|
||||||
|
@ -11,43 +9,50 @@ namespace NzbDrone.Host.AccessControl
|
||||||
public interface IUrlAclAdapter
|
public interface IUrlAclAdapter
|
||||||
{
|
{
|
||||||
void ConfigureUrl();
|
void ConfigureUrl();
|
||||||
string UrlAcl { get; }
|
string Url { get; }
|
||||||
|
string HttpsUrl { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UrlAclAdapter : IUrlAclAdapter
|
public class UrlAclAdapter : IUrlAclAdapter
|
||||||
{
|
{
|
||||||
private const string URL_ACL = "http://{0}:{1}/";
|
private readonly INetshProvider _netshProvider;
|
||||||
|
|
||||||
private readonly IProcessProvider _processProvider;
|
|
||||||
private readonly IConfigFileProvider _configFileProvider;
|
private readonly IConfigFileProvider _configFileProvider;
|
||||||
private readonly IRuntimeInfo _runtimeInfo;
|
private readonly IRuntimeInfo _runtimeInfo;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public string UrlAcl { get; private set; }
|
public string Url { get; private set; }
|
||||||
|
public string HttpsUrl { get; private set; }
|
||||||
|
|
||||||
private string _localUrl;
|
private string _localUrl;
|
||||||
private string _wildcardUrl;
|
private string _wildcardUrl;
|
||||||
|
private string _localHttpsUrl;
|
||||||
|
private string _wildcardHttpsUrl;
|
||||||
|
|
||||||
public UrlAclAdapter(IProcessProvider processProvider,
|
public UrlAclAdapter(INetshProvider netshProvider,
|
||||||
IConfigFileProvider configFileProvider,
|
IConfigFileProvider configFileProvider,
|
||||||
IRuntimeInfo runtimeInfo,
|
IRuntimeInfo runtimeInfo,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_processProvider = processProvider;
|
_netshProvider = netshProvider;
|
||||||
_configFileProvider = configFileProvider;
|
_configFileProvider = configFileProvider;
|
||||||
_runtimeInfo = runtimeInfo;
|
_runtimeInfo = runtimeInfo;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
_localUrl = String.Format(URL_ACL, "localhost", _configFileProvider.Port);
|
_localUrl = String.Format("http://localhost:{0}/", _configFileProvider.Port);
|
||||||
_wildcardUrl = String.Format(URL_ACL, "*", _configFileProvider.Port);
|
_wildcardUrl = String.Format("http://*:{0}/", _configFileProvider.Port);
|
||||||
|
_localHttpsUrl = String.Format("https://localhost:{0}/", _configFileProvider.SslPort);
|
||||||
|
_wildcardHttpsUrl = String.Format("https://*:{0}/", _configFileProvider.SslPort);
|
||||||
|
|
||||||
UrlAcl = _wildcardUrl;
|
Url = _wildcardUrl;
|
||||||
|
HttpsUrl = _wildcardHttpsUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ConfigureUrl()
|
public void ConfigureUrl()
|
||||||
{
|
{
|
||||||
if (!_runtimeInfo.IsAdmin && !IsRegistered)
|
if (!_runtimeInfo.IsAdmin)
|
||||||
{
|
{
|
||||||
UrlAcl = _localUrl;
|
if (!IsRegistered(_wildcardUrl)) Url = _localUrl;
|
||||||
|
if (!IsRegistered(_wildcardHttpsUrl)) HttpsUrl = _localHttpsUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_runtimeInfo.IsAdmin)
|
if (_runtimeInfo.IsAdmin)
|
||||||
|
@ -61,42 +66,24 @@ namespace NzbDrone.Host.AccessControl
|
||||||
if (OsInfo.Version.Major < 6)
|
if (OsInfo.Version.Major < 6)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RegisterUrl();
|
RegisterUrl(Url);
|
||||||
|
RegisterUrl(HttpsUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsRegistered(string urlAcl)
|
||||||
|
{
|
||||||
|
var arguments = String.Format("http show urlacl {0}", urlAcl);
|
||||||
|
var output = _netshProvider.Run(arguments);
|
||||||
|
|
||||||
|
if (output == null || !output.Standard.Any()) return false;
|
||||||
|
|
||||||
|
return output.Standard.Any(line => line.Contains(urlAcl));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsRegistered
|
private void RegisterUrl(string urlAcl)
|
||||||
{
|
{
|
||||||
get
|
var arguments = String.Format("http add urlacl {0} sddl=D:(A;;GX;;;S-1-1-0)", urlAcl);
|
||||||
{
|
_netshProvider.Run(arguments);
|
||||||
var arguments = String.Format("http show urlacl {0}", _wildcardUrl);
|
|
||||||
var output = RunNetsh(arguments);
|
|
||||||
|
|
||||||
if (output == null || !output.Standard.Any()) return false;
|
|
||||||
|
|
||||||
return output.Standard.Any(line => line.Contains(_wildcardUrl));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RegisterUrl()
|
|
||||||
{
|
|
||||||
var arguments = String.Format("http add urlacl {0} sddl=D:(A;;GX;;;S-1-1-0)", UrlAcl);
|
|
||||||
RunNetsh(arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ProcessOutput RunNetsh(string arguments)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var output = _processProvider.StartAndCapture("netsh.exe", arguments);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.WarnException("Error executing netsh with arguments: " + arguments, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -117,6 +117,8 @@
|
||||||
<Compile Include="..\NzbDrone.Common\Properties\SharedAssemblyInfo.cs">
|
<Compile Include="..\NzbDrone.Common\Properties\SharedAssemblyInfo.cs">
|
||||||
<Link>Properties\SharedAssemblyInfo.cs</Link>
|
<Link>Properties\SharedAssemblyInfo.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="AccessControl\NetshProvider.cs" />
|
||||||
|
<Compile Include="AccessControl\SslAdapter.cs" />
|
||||||
<Compile Include="ApplicationServer.cs">
|
<Compile Include="ApplicationServer.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
@ -21,17 +21,24 @@ namespace NzbDrone.Host.Owin
|
||||||
private readonly IRuntimeInfo _runtimeInfo;
|
private readonly IRuntimeInfo _runtimeInfo;
|
||||||
private readonly IUrlAclAdapter _urlAclAdapter;
|
private readonly IUrlAclAdapter _urlAclAdapter;
|
||||||
private readonly IFirewallAdapter _firewallAdapter;
|
private readonly IFirewallAdapter _firewallAdapter;
|
||||||
|
private readonly ISslAdapter _sslAdapter;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
private IDisposable _host;
|
private IDisposable _host;
|
||||||
|
|
||||||
public OwinHostController(IConfigFileProvider configFileProvider, IEnumerable<IOwinMiddleWare> owinMiddleWares,
|
public OwinHostController(IConfigFileProvider configFileProvider,
|
||||||
IRuntimeInfo runtimeInfo, IUrlAclAdapter urlAclAdapter, IFirewallAdapter firewallAdapter, Logger logger)
|
IEnumerable<IOwinMiddleWare> owinMiddleWares,
|
||||||
|
IRuntimeInfo runtimeInfo,
|
||||||
|
IUrlAclAdapter urlAclAdapter,
|
||||||
|
IFirewallAdapter firewallAdapter,
|
||||||
|
ISslAdapter sslAdapter,
|
||||||
|
Logger logger)
|
||||||
{
|
{
|
||||||
_configFileProvider = configFileProvider;
|
_configFileProvider = configFileProvider;
|
||||||
_owinMiddleWares = owinMiddleWares;
|
_owinMiddleWares = owinMiddleWares;
|
||||||
_runtimeInfo = runtimeInfo;
|
_runtimeInfo = runtimeInfo;
|
||||||
_urlAclAdapter = urlAclAdapter;
|
_urlAclAdapter = urlAclAdapter;
|
||||||
_firewallAdapter = firewallAdapter;
|
_firewallAdapter = firewallAdapter;
|
||||||
|
_sslAdapter = sslAdapter;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,17 +51,24 @@ namespace NzbDrone.Host.Owin
|
||||||
if (_runtimeInfo.IsAdmin)
|
if (_runtimeInfo.IsAdmin)
|
||||||
{
|
{
|
||||||
_firewallAdapter.MakeAccessible();
|
_firewallAdapter.MakeAccessible();
|
||||||
|
_sslAdapter.Register();
|
||||||
}
|
}
|
||||||
|
|
||||||
_urlAclAdapter.ConfigureUrl();
|
_urlAclAdapter.ConfigureUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = new StartOptions(_urlAclAdapter.UrlAcl)
|
var options = new StartOptions(_urlAclAdapter.Url)
|
||||||
{
|
{
|
||||||
ServerFactory = "Microsoft.Owin.Host.HttpListener"
|
ServerFactory = "Microsoft.Owin.Host.HttpListener"
|
||||||
};
|
};
|
||||||
|
|
||||||
_logger.Info("starting server on {0}", _urlAclAdapter.UrlAcl);
|
if (_configFileProvider.EnableSsl)
|
||||||
|
{
|
||||||
|
_logger.Trace("SSL enabled, listening on: {0}", _urlAclAdapter.HttpsUrl);
|
||||||
|
options.Urls.Add(_urlAclAdapter.HttpsUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Info("starting server on {0}", _urlAclAdapter.Url);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue