diff options
| author | Luke <luke.pulverenti@gmail.com> | 2016-09-09 15:42:40 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-09-09 15:42:40 -0400 |
| commit | 080a6511dc44edde960e6aefcab7e6cc068a3414 (patch) | |
| tree | 499c61fec48dcc080888d9cfc021baf734886fe7 /MediaBrowser.ServerApplication | |
| parent | 51051c27cd4a30010eee98f4f99ebb895e166a91 (diff) | |
| parent | 5ad606a2232c6911e2cd8cf5d03da635c7c0c75d (diff) | |
Merge pull request #2151 from MediaBrowser/beta
Beta
Diffstat (limited to 'MediaBrowser.ServerApplication')
6 files changed, 449 insertions, 2 deletions
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 8f153f33f..cdacdc81f 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -292,7 +292,6 @@ namespace MediaBrowser.ServerApplication ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX); } - var task = _appHost.Init(initProgress); Task.WaitAll(task); @@ -332,7 +331,7 @@ namespace MediaBrowser.ServerApplication Application.Run(); } - private static SplashForm _splash; + internal static SplashForm _splash; private static Thread _splashThread; private static void ShowSplashScreen(Version appVersion, Progress<double> progress, ILogger logger) { diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 9c5470358..a32312493 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -119,6 +119,7 @@ <Compile Include="MainStartup.cs" /> <Compile Include="Native\LnkShortcutHandler.cs" /> <Compile Include="Native\DbConnector.cs" /> + <Compile Include="Native\LoopbackUtil.cs" /> <Compile Include="Native\Standby.cs" /> <Compile Include="Native\ServerAuthorization.cs" /> <Compile Include="Native\WindowsApp.cs" /> 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..b08b82de5 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -7,6 +7,7 @@ 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; @@ -203,5 +204,76 @@ namespace MediaBrowser.ServerApplication.Native { ((Process)sender).Dispose(); } + + public void EnableLoopback(string appName) + { + LoopUtil.Run(appName); + } + + private bool Confirm() + { + if (MainStartup._splash == null) + { + return false; + } + + return MessageBox.Show(MainStartup._splash, "Emby has detected that a rule has been added to Windows Firewall that may prevent your other devices from accessing Emby Server. Click OK to remove this rule, or cancel to proceed anyway.", "Windows Firewall", MessageBoxButtons.OKCancel) == DialogResult.OK; + } + + 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); + return Confirm(); + } + + //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/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs index d04128a18..7805c0d68 100644 --- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs +++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs @@ -20,6 +20,7 @@ namespace MediaBrowser.ServerApplication private ToolStripMenuItem cmdRestart; private ToolStripSeparator toolStripSeparator1; private ToolStripMenuItem cmdCommunity; + private ToolStripMenuItem cmdPremiere; private Container components; private readonly ILogger _logger; @@ -50,6 +51,7 @@ namespace MediaBrowser.ServerApplication cmdExit = new ToolStripMenuItem(); cmdCommunity = new ToolStripMenuItem(); + cmdPremiere = new ToolStripMenuItem(); toolStripSeparator1 = new ToolStripSeparator(); cmdRestart = new ToolStripMenuItem(); toolStripSeparator2 = new ToolStripSeparator(); @@ -69,6 +71,7 @@ namespace MediaBrowser.ServerApplication contextMenuStrip1.Items.AddRange(new ToolStripItem[] { cmdBrowse, cmdConfigure, + cmdPremiere, toolStripSeparator2, cmdRestart, toolStripSeparator1, @@ -89,6 +92,11 @@ namespace MediaBrowser.ServerApplication cmdCommunity.Name = "cmdCommunity"; cmdCommunity.Size = new System.Drawing.Size(208, 22); // + // cmdPremiere + // + cmdPremiere.Name = "cmdPremiere"; + cmdPremiere.Size = new System.Drawing.Size(208, 22); + // // toolStripSeparator1 // toolStripSeparator1.Name = "toolStripSeparator1"; @@ -118,6 +126,7 @@ namespace MediaBrowser.ServerApplication cmdRestart.Click += cmdRestart_Click; cmdConfigure.Click += cmdConfigure_Click; cmdCommunity.Click += cmdCommunity_Click; + cmdPremiere.Click += cmdPremiere_Click; cmdBrowse.Click += cmdBrowse_Click; _configurationManager.ConfigurationUpdated += Instance_ConfigurationUpdated; @@ -138,6 +147,7 @@ namespace MediaBrowser.ServerApplication cmdExit.Text = _localization.GetLocalizedString("LabelExit"); cmdCommunity.Text = _localization.GetLocalizedString("LabelVisitCommunity"); + cmdPremiere.Text = _localization.GetLocalizedString("Emby Premiere"); cmdBrowse.Text = _localization.GetLocalizedString("LabelBrowseLibrary"); cmdConfigure.Text = _localization.GetLocalizedString("LabelConfigureServer"); cmdRestart.Text = _localization.GetLocalizedString("LabelRestartServer"); @@ -163,6 +173,11 @@ namespace MediaBrowser.ServerApplication BrowserLauncher.OpenWebClient(_appHost); } + void cmdPremiere_Click(object sender, EventArgs e) + { + BrowserLauncher.OpenEmbyPremiere(_appHost); + } + void cmdCommunity_Click(object sender, EventArgs e) { BrowserLauncher.OpenCommunity(_appHost); |
