Added SecurityProvider to deal with administrative tasks (Url Registering and FW Port Opening).

pull/6/head
Mark McDowall 13 years ago
parent 5cea5282bd
commit 691a004d39

@ -142,6 +142,12 @@ namespace NzbDrone.Common
} }
} }
public virtual Version GetOsVersion()
{
OperatingSystem os = Environment.OSVersion;
Version version = os.Version;
return version;
}
} }
} }

@ -63,12 +63,24 @@
<Compile Include="ProcessProvider.cs" /> <Compile Include="ProcessProvider.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\SharedAssemblyInfo.cs" /> <Compile Include="Properties\SharedAssemblyInfo.cs" />
<Compile Include="SecurityProvider.cs" />
<Compile Include="ServiceProvider.cs" /> <Compile Include="ServiceProvider.cs" />
<Compile Include="WebClientProvider.cs" /> <Compile Include="WebClientProvider.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<COMReference Include="NetFwTypeLib">
<Guid>{58FBCF7C-E7A9-467C-80B3-FC65E8FCCA08}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

@ -0,0 +1,213 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Principal;
using System.Text;
using NLog;
using NetFwTypeLib;
using Ninject;
using NzbDrone.Common.Model;
namespace NzbDrone.Common
{
public class SecurityProvider
{
private static readonly Logger Logger = LogManager.GetLogger("Host.SecurityProvider");
private readonly ConfigFileProvider _configFileProvider;
private readonly EnviromentProvider _enviromentProvider;
private readonly ProcessProvider _processProvider;
[Inject]
public SecurityProvider(ConfigFileProvider configFileProvider, EnviromentProvider enviromentProvider,
ProcessProvider processProvider)
{
_configFileProvider = configFileProvider;
_enviromentProvider = enviromentProvider;
_processProvider = processProvider;
}
public SecurityProvider()
{
}
public virtual void MakeAccessible()
{
if (!IsCurrentUserAdmin())
{
Logger.Trace("User is not an admin, skipping.");
return;
}
if (IsNzbDronePortOpen())
{
Logger.Trace("NzbDrone port is already open, skippings");
return;
}
//Close any old ports
var port = CloseFirewallPort();
//Open the new port
OpenFirewallPort(_configFileProvider.Port);
//Skip Url Register if not Vista or 7
if (_enviromentProvider.GetOsVersion().Major < 6)
return;
//Unregister Url (if port != 0)
if (port != 0)
UnregisterUrl(port);
//Register Url
RegisterUrl(_configFileProvider.Port);
}
public virtual bool IsCurrentUserAdmin()
{
try
{
var currentIdentity = WindowsIdentity.GetCurrent();
if (currentIdentity == null)
{
Logger.Trace("Could not obtain the current user.");
return false;
}
var principal = new WindowsPrincipal(currentIdentity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch(Exception ex)
{
Logger.TraceException("Error checking is current user is an administrator.", ex);
return false;
}
}
public virtual bool IsNzbDronePortOpen()
{
var netFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
var mgr = (INetFwMgr)Activator.CreateInstance(netFwMgrType);
if (!mgr.LocalPolicy.CurrentProfile.FirewallEnabled)
return false;
var ports = mgr.LocalPolicy.CurrentProfile.GloballyOpenPorts;
foreach (INetFwOpenPort p in ports)
{
if (p.Port == _configFileProvider.Port)
return true;
}
return false;
}
private bool OpenFirewallPort(int portNumber)
{
try
{
var type = Type.GetTypeFromProgID("HNetCfg.FWOpenPort", false);
var port = Activator.CreateInstance(type) as INetFwOpenPort;
port.Port = portNumber;
port.Name = "NzbDrone";
port.Protocol = NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
port.Enabled = true;
var netFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
var mgr = (INetFwMgr)Activator.CreateInstance(netFwMgrType);
var ports = mgr.LocalPolicy.CurrentProfile.GloballyOpenPorts;
ports.Add(port);
return true;
}
catch(Exception ex)
{
Logger.Trace("Failed to open port in firewall for NzbDrone" + portNumber, ex);
return false;
}
}
private int CloseFirewallPort()
{
try
{
var netFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
var mgr = (INetFwMgr)Activator.CreateInstance(netFwMgrType);
var ports = mgr.LocalPolicy.CurrentProfile.GloballyOpenPorts;
var portNumber = 8989;
foreach (INetFwOpenPort p in ports)
{
if (p.Name == "NzbDrone")
{
portNumber = p.Port;
break;
}
}
if (portNumber != _configFileProvider.Port)
{
ports.Remove(portNumber, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP);
return portNumber;
}
}
catch(Exception ex)
{
Logger.Trace("Failed to close port in firewall for NzbDrone", ex);
}
return 0;
}
private bool RegisterUrl(int portNumber)
{
try
{
var startInfo = new ProcessStartInfo()
{
FileName = "netsh.exe",
Arguments = string.Format("http add urlacl http://*:{0}/ user=EVERYONE", portNumber)
};
var process = _processProvider.Start(startInfo);
process.WaitForExit(5000);
return true;
}
catch(Exception ex)
{
Logger.Trace("Error registering URL", ex);
}
return false;
}
private bool UnregisterUrl(int portNumber)
{
try
{
var startInfo = new ProcessStartInfo()
{
FileName = "netsh.exe",
Arguments = string.Format("http delete urlacl http://*:{0}/", portNumber)
};
var process = _processProvider.Start(startInfo);
process.WaitForExit(5000);
return true;
}
catch (Exception ex)
{
Logger.Trace("Error registering URL", ex);
}
return false;
}
}
}

@ -19,12 +19,13 @@ namespace NzbDrone
private readonly IISProvider _iisProvider; private readonly IISProvider _iisProvider;
private readonly ProcessProvider _processProvider; private readonly ProcessProvider _processProvider;
private readonly MonitoringProvider _monitoringProvider; private readonly MonitoringProvider _monitoringProvider;
private readonly SecurityProvider _securityProvider;
private readonly WebClient _webClient; private readonly WebClient _webClient;
[Inject] [Inject]
public ApplicationServer(ConfigFileProvider configFileProvider, WebClient webClient, IISProvider iisProvider, public ApplicationServer(ConfigFileProvider configFileProvider, WebClient webClient, IISProvider iisProvider,
DebuggerProvider debuggerProvider, EnviromentProvider enviromentProvider, DebuggerProvider debuggerProvider, EnviromentProvider enviromentProvider,
ProcessProvider processProvider, MonitoringProvider monitoringProvider) ProcessProvider processProvider, MonitoringProvider monitoringProvider, SecurityProvider securityProvider)
{ {
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
_webClient = webClient; _webClient = webClient;
@ -33,6 +34,7 @@ namespace NzbDrone
_enviromentProvider = enviromentProvider; _enviromentProvider = enviromentProvider;
_processProvider = processProvider; _processProvider = processProvider;
_monitoringProvider = monitoringProvider; _monitoringProvider = monitoringProvider;
_securityProvider = securityProvider;
} }
public ApplicationServer() public ApplicationServer()
@ -48,6 +50,7 @@ namespace NzbDrone
public virtual void Start() public virtual void Start()
{ {
_iisProvider.StopServer(); _iisProvider.StopServer();
_securityProvider.MakeAccessible();
_iisProvider.StartServer(); _iisProvider.StartServer();
_debuggerProvider.Attach(); _debuggerProvider.Attach();

Loading…
Cancel
Save