aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.ServerApplication/Native
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.ServerApplication/Native')
-rw-r--r--MediaBrowser.ServerApplication/Native/LoopbackUtil.cs358
-rw-r--r--MediaBrowser.ServerApplication/Native/RegisterServer.bat2
-rw-r--r--MediaBrowser.ServerApplication/Native/WindowsApp.cs67
-rw-r--r--MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs94
4 files changed, 421 insertions, 100 deletions
diff --git a/MediaBrowser.ServerApplication/Native/LoopbackUtil.cs b/MediaBrowser.ServerApplication/Native/LoopbackUtil.cs
new file mode 100644
index 000000000..5b260685b
--- /dev/null
+++ b/MediaBrowser.ServerApplication/Native/LoopbackUtil.cs
@@ -0,0 +1,358 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.ServerApplication.Native
+{
+ /// <summary>
+ /// http://blogs.msdn.com/b/fiddler/archive/2011/12/10/fiddler-windows-8-apps-enable-LoopUtil-network-isolation-exemption.aspx
+ /// </summary>
+ public class LoopUtil
+ {
+ //http://msdn.microsoft.com/en-us/library/windows/desktop/aa379595(v=vs.85).aspx
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SID_AND_ATTRIBUTES
+ {
+ public IntPtr Sid;
+ public uint Attributes;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct INET_FIREWALL_AC_CAPABILITIES
+ {
+ public uint count;
+ public IntPtr capabilities; //SID_AND_ATTRIBUTES
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct INET_FIREWALL_AC_BINARIES
+ {
+ public uint count;
+ public IntPtr binaries;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct INET_FIREWALL_APP_CONTAINER
+ {
+ internal IntPtr appContainerSid;
+ internal IntPtr userSid;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string appContainerName;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string displayName;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string description;
+ internal INET_FIREWALL_AC_CAPABILITIES capabilities;
+ internal INET_FIREWALL_AC_BINARIES binaries;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string workingDirectory;
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string packageFullName;
+ }
+
+
+ // Call this API to free the memory returned by the Enumeration API
+ [DllImport("FirewallAPI.dll")]
+ internal static extern void NetworkIsolationFreeAppContainers(IntPtr pACs);
+
+ // Call this API to load the current list of LoopUtil-enabled AppContainers
+ [DllImport("FirewallAPI.dll")]
+ internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids);
+
+ // Call this API to set the LoopUtil-exemption list
+ [DllImport("FirewallAPI.dll")]
+ private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SID_AND_ATTRIBUTES[] appContainerSids);
+
+
+ // Use this API to convert a string SID into an actual SID
+ [DllImport("advapi32.dll", SetLastError = true)]
+ internal static extern bool ConvertStringSidToSid(string strSid, out IntPtr pSid);
+
+ [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
+ static extern bool ConvertSidToStringSid(
+ [MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
+ out IntPtr ptrSid);
+
+ [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
+ static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid);
+
+ // Use this API to convert a string reference (e.g. "@{blah.pri?ms-resource://whatever}") into a plain string
+ [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
+ internal static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf);
+
+ // Call this API to enumerate all of the AppContainers on the system
+ [DllImport("FirewallAPI.dll")]
+ internal static extern uint NetworkIsolationEnumAppContainers(uint Flags, out uint pdwCntPublicACs, out IntPtr ppACs);
+ // DWORD NetworkIsolationEnumAppContainers(
+ // _In_ DWORD Flags,
+ // _Out_ DWORD *pdwNumPublicAppCs,
+ // _Out_ PINET_FIREWALL_APP_CONTAINER *ppPublicAppCs
+ //);
+
+ //http://msdn.microsoft.com/en-gb/library/windows/desktop/hh968116.aspx
+ enum NETISO_FLAG
+ {
+ NETISO_FLAG_FORCE_COMPUTE_BINARIES = 0x1,
+ NETISO_FLAG_MAX = 0x2
+ }
+
+
+ public class AppContainer
+ {
+ public String appContainerName { get; set; }
+ public String displayName { get; set; }
+ public String workingDirectory { get; set; }
+ public String StringSid { get; set; }
+ public List<uint> capabilities { get; set; }
+ public bool LoopUtil { get; set; }
+
+ public AppContainer(String _appContainerName, String _displayName, String _workingDirectory, IntPtr _sid)
+ {
+ this.appContainerName = _appContainerName;
+ this.displayName = _displayName;
+ this.workingDirectory = _workingDirectory;
+ String tempSid;
+ ConvertSidToStringSid(_sid, out tempSid);
+ this.StringSid = tempSid;
+ }
+ }
+
+ internal List<LoopUtil.INET_FIREWALL_APP_CONTAINER> _AppList;
+ internal List<LoopUtil.SID_AND_ATTRIBUTES> _AppListConfig;
+ public List<AppContainer> Apps = new List<AppContainer>();
+ internal IntPtr _pACs;
+
+ public LoopUtil()
+ {
+ LoadApps();
+ }
+
+ public void LoadApps()
+ {
+ Apps.Clear();
+ _pACs = IntPtr.Zero;
+ //Full List of Apps
+ _AppList = PI_NetworkIsolationEnumAppContainers();
+ //List of Apps that have LoopUtil enabled.
+ _AppListConfig = PI_NetworkIsolationGetAppContainerConfig();
+ foreach (var PI_app in _AppList)
+ {
+ AppContainer app = new AppContainer(PI_app.appContainerName, PI_app.displayName, PI_app.workingDirectory, PI_app.appContainerSid);
+
+ var app_capabilities = LoopUtil.getCapabilites(PI_app.capabilities);
+ if (app_capabilities.Count > 0)
+ {
+ //var sid = new SecurityIdentifier(app_capabilities[0], 0);
+
+ IntPtr arrayValue = IntPtr.Zero;
+ //var b = LoopUtil.ConvertStringSidToSid(app_capabilities[0].Sid, out arrayValue);
+ //string mysid;
+ //var b = LoopUtil.ConvertSidToStringSid(app_capabilities[0].Sid, out mysid);
+ }
+ app.LoopUtil = CheckLoopback(PI_app.appContainerSid);
+ Apps.Add(app);
+ }
+ }
+ private bool CheckLoopback(IntPtr intPtr)
+ {
+ foreach (SID_AND_ATTRIBUTES item in _AppListConfig)
+ {
+ string left, right;
+ ConvertSidToStringSid(item.Sid, out left);
+ ConvertSidToStringSid(intPtr, out right);
+
+ if (left == right)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private bool CreateExcemptions(string appName)
+ {
+ var hasChanges = false;
+
+ foreach (var app in Apps)
+ {
+ if ((app.appContainerName ?? string.Empty).IndexOf(appName, StringComparison.OrdinalIgnoreCase) != -1 ||
+ (app.displayName ?? string.Empty).IndexOf(appName, StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ if (!app.LoopUtil)
+ {
+ app.LoopUtil = true;
+ hasChanges = true;
+ }
+ }
+ }
+
+ return hasChanges;
+ }
+
+ public static void Run(string appName)
+ {
+ var util = new LoopUtil();
+ util.LoadApps();
+
+ var hasChanges = util.CreateExcemptions(appName);
+
+ if (hasChanges)
+ {
+ util.SaveLoopbackState();
+ }
+ util.SaveLoopbackState();
+ }
+
+ private static List<SID_AND_ATTRIBUTES> getCapabilites(INET_FIREWALL_AC_CAPABILITIES cap)
+ {
+ List<SID_AND_ATTRIBUTES> mycap = new List<SID_AND_ATTRIBUTES>();
+
+ IntPtr arrayValue = cap.capabilities;
+
+ var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
+ for (var i = 0; i < cap.count; i++)
+ {
+ var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES));
+ mycap.Add(cur);
+ arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
+ }
+
+ return mycap;
+
+ }
+
+ private static List<SID_AND_ATTRIBUTES> getContainerSID(INET_FIREWALL_AC_CAPABILITIES cap)
+ {
+ List<SID_AND_ATTRIBUTES> mycap = new List<SID_AND_ATTRIBUTES>();
+
+ IntPtr arrayValue = cap.capabilities;
+
+ var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
+ for (var i = 0; i < cap.count; i++)
+ {
+ var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES));
+ mycap.Add(cur);
+ arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
+ }
+
+ return mycap;
+
+ }
+
+ private static List<SID_AND_ATTRIBUTES> PI_NetworkIsolationGetAppContainerConfig()
+ {
+
+ IntPtr arrayValue = IntPtr.Zero;
+ uint size = 0;
+ var list = new List<SID_AND_ATTRIBUTES>();
+
+ // Pin down variables
+ GCHandle handle_pdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned);
+ GCHandle handle_ppACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned);
+
+ uint retval = NetworkIsolationGetAppContainerConfig(out size, out arrayValue);
+
+ var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
+ for (var i = 0; i < size; i++)
+ {
+ var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES));
+ list.Add(cur);
+ arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
+ }
+
+ //release pinned variables.
+ handle_pdwCntPublicACs.Free();
+ handle_ppACs.Free();
+
+ return list;
+
+
+ }
+
+ private List<INET_FIREWALL_APP_CONTAINER> PI_NetworkIsolationEnumAppContainers()
+ {
+
+ IntPtr arrayValue = IntPtr.Zero;
+ uint size = 0;
+ var list = new List<INET_FIREWALL_APP_CONTAINER>();
+
+ // Pin down variables
+ GCHandle handle_pdwCntPublicACs = GCHandle.Alloc(size, GCHandleType.Pinned);
+ GCHandle handle_ppACs = GCHandle.Alloc(arrayValue, GCHandleType.Pinned);
+
+ //uint retval2 = NetworkIsolationGetAppContainerConfig( out size, out arrayValue);
+
+ uint retval = NetworkIsolationEnumAppContainers((Int32)NETISO_FLAG.NETISO_FLAG_MAX, out size, out arrayValue);
+ _pACs = arrayValue; //store the pointer so it can be freed when we close the form
+
+ var structSize = Marshal.SizeOf(typeof(INET_FIREWALL_APP_CONTAINER));
+ for (var i = 0; i < size; i++)
+ {
+ var cur = (INET_FIREWALL_APP_CONTAINER)Marshal.PtrToStructure(arrayValue, typeof(INET_FIREWALL_APP_CONTAINER));
+ list.Add(cur);
+ arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
+ }
+
+ //release pinned variables.
+ handle_pdwCntPublicACs.Free();
+ handle_ppACs.Free();
+
+ return list;
+
+
+ }
+
+ public bool SaveLoopbackState()
+ {
+ var countEnabled = CountEnabledLoopUtil();
+ SID_AND_ATTRIBUTES[] arr = new SID_AND_ATTRIBUTES[countEnabled];
+ int count = 0;
+
+ for (int i = 0; i < Apps.Count; i++)
+ {
+ if (Apps[i].LoopUtil)
+ {
+ arr[count].Attributes = 0;
+ //TO DO:
+ IntPtr ptr;
+ ConvertStringSidToSid(Apps[i].StringSid, out ptr);
+ arr[count].Sid = ptr;
+ count++;
+ }
+
+ }
+
+
+ if (NetworkIsolationSetAppContainerConfig((uint)countEnabled, arr) == 0)
+ {
+ return true;
+ }
+ else
+ { return false; }
+
+ }
+
+ private int CountEnabledLoopUtil()
+ {
+ var count = 0;
+ for (int i = 0; i < Apps.Count; i++)
+ {
+ if (Apps[i].LoopUtil)
+ {
+ count++;
+ }
+
+ }
+ return count;
+ }
+
+ public void FreeResources()
+ {
+ NetworkIsolationFreeAppContainers(_pACs);
+ }
+
+ }
+}
diff --git a/MediaBrowser.ServerApplication/Native/RegisterServer.bat b/MediaBrowser.ServerApplication/Native/RegisterServer.bat
index 27f863d58..85baa0d03 100644
--- a/MediaBrowser.ServerApplication/Native/RegisterServer.bat
+++ b/MediaBrowser.ServerApplication/Native/RegisterServer.bat
@@ -20,7 +20,9 @@ netsh advfirewall firewall add rule name="Port %3" dir=in action=allow protocol=
if [%4]==[] GOTO DONE
+netsh advfirewall firewall delete rule name="mediabrowser.serverapplication.exe"
netsh advfirewall firewall delete rule name="Emby Server"
+
netsh advfirewall firewall add rule name="Emby Server" dir=in action=allow protocol=TCP program=%4 enable=yes
netsh advfirewall firewall add rule name="Emby Server" dir=in action=allow protocol=UDP program=%4 enable=yes
diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs
index 3c9c04acb..7ebede40c 100644
--- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs
+++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs
@@ -7,8 +7,8 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
+using System.Windows.Forms;
using CommonIO;
-using MediaBrowser.Controller.Power;
using MediaBrowser.Model.System;
using MediaBrowser.Server.Implementations.Persistence;
using MediaBrowser.Server.Startup.Common.FFMpeg;
@@ -147,11 +147,6 @@ namespace MediaBrowser.ServerApplication.Native
MainStartup.Invoke(Standby.AllowSleep);
}
- public IPowerManagement GetPowerManagement()
- {
- return new WindowsPowerManagement(_logger);
- }
-
public FFMpegInstallInfo GetFfmpegInstallInfo()
{
var info = new FFMpegInstallInfo();
@@ -203,5 +198,65 @@ namespace MediaBrowser.ServerApplication.Native
{
((Process)sender).Dispose();
}
+
+ public void EnableLoopback(string appName)
+ {
+ LoopUtil.Run(appName);
+ }
+
+ public bool PortsRequireAuthorization(string applicationPath)
+ {
+ var appNameSrch = Path.GetFileName(applicationPath);
+
+ var startInfo = new ProcessStartInfo
+ {
+ FileName = "netsh",
+
+ Arguments = "advfirewall firewall show rule \"" + appNameSrch + "\"",
+
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ WindowStyle = ProcessWindowStyle.Hidden,
+ ErrorDialog = false,
+ RedirectStandardOutput = true
+ };
+
+ using (var process = Process.Start(startInfo))
+ {
+ process.Start();
+
+ try
+ {
+ var data = process.StandardOutput.ReadToEnd() ?? string.Empty;
+
+ if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ _logger.Info("Found potential windows firewall rule blocking Emby Server: " + data);
+ }
+
+ //var parts = data.Split('\n');
+
+ //return parts.Length > 4;
+ //return Confirm();
+ return false;
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error querying windows firewall", ex);
+
+ // Hate having to do this
+ try
+ {
+ process.Kill();
+ }
+ catch (Exception ex1)
+ {
+ _logger.ErrorException("Error killing process", ex1);
+ }
+
+ throw;
+ }
+ }
+ }
}
} \ No newline at end of file
diff --git a/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs b/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs
deleted file mode 100644
index 866272639..000000000
--- a/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-using System;
-using System.ComponentModel;
-using System.Runtime.InteropServices;
-using System.Threading;
-using MediaBrowser.Controller.Power;
-using MediaBrowser.Model.Logging;
-using Microsoft.Win32.SafeHandles;
-
-namespace MediaBrowser.ServerApplication.Native
-{
- public class WindowsPowerManagement : IPowerManagement
- {
- [DllImport("kernel32.dll")]
- public static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes,
- bool bManualReset,
- string lpTimerName);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool SetWaitableTimer(SafeWaitHandle hTimer,
- [In] ref long pDueTime,
- int lPeriod,
- IntPtr pfnCompletionRoutine,
- IntPtr lpArgToCompletionRoutine,
- bool fResume);
-
- private BackgroundWorker _bgWorker;
- private readonly ILogger _logger;
- private readonly object _initLock = new object();
-
- public WindowsPowerManagement(ILogger logger)
- {
- _logger = logger;
- }
-
- public void ScheduleWake(DateTime utcTime)
- {
- //Initialize();
- //_bgWorker.RunWorkerAsync(utcTime.ToFileTime());
- throw new NotImplementedException();
- }
-
- private void Initialize()
- {
- lock (_initLock)
- {
- if (_bgWorker == null)
- {
- _bgWorker = new BackgroundWorker();
-
- _bgWorker.DoWork += bgWorker_DoWork;
- _bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;
- }
- }
- }
-
- void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
- {
- //if (Woken != null)
- //{
- // Woken(this, new EventArgs());
- //}
- }
-
- private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
- {
- try
- {
- long waketime = (long)e.Argument;
-
- using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, GetType().Assembly.GetName().Name + "Timer"))
- {
- if (SetWaitableTimer(handle, ref waketime, 0, IntPtr.Zero, IntPtr.Zero, true))
- {
- using (EventWaitHandle wh = new EventWaitHandle(false,
- EventResetMode.AutoReset))
- {
- wh.SafeWaitHandle = handle;
- wh.WaitOne();
- }
- }
- else
- {
- throw new Win32Exception(Marshal.GetLastWin32Error());
- }
- }
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error scheduling wake timer", ex);
- }
- }
- }
-}