| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 | 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);        }    }}
 |