SocketPermission.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Net / System / Net / SocketPermission.cs / 1 / SocketPermission.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Net { 
 
    using System.Collections;
    using System.Security; 
    using System.Security.Permissions;
    using System.Globalization;
    using System.Threading;
 
    //NOTE: While SocketPermissionAttribute resides in System.DLL,
    //      no classes from that DLL are able to make declarative usage of SocketPermission. 
 

    // THE syntax of this attribute is as followed 
    // [SocketPermsion(SecurityAction.Assert, Access=Connect, Host=hostname, Transport=Tcp/Udp/All, port=portN/All)]
    // [SocketPermsion(SecurityAction.Assert, Access=Accept, Host=localname, Transport=Tcp/Udp/All, port=portN/All)]
    //
    // WHERE: 
    //=======
    // - hostname is either a DNS hostname OR an IP address 1.2.3.4 or an IP wildcard 1.2.*.* 
    // - protocol is either Tcp, Udp or All 
    // - port is a numeric value or -1 that means "All Ports"
    // 
    //  All the properites Host, Protocol and Port must be specified.
    // "localIP" means that you put here a valid address or DNS name or the localhost
    //
    //  NetworkAccess specifies the scope of permission, i.e. for connecting to remote peer, 
    //  or for accepting data on the local resources.
    // 
 
    [   AttributeUsage( AttributeTargets.Method | AttributeTargets.Constructor |
                        AttributeTargets.Class  | AttributeTargets.Struct      | 
                        AttributeTargets.Assembly,
                        AllowMultiple = true, Inherited = false )]

    [Serializable] 
    public sealed class SocketPermissionAttribute: CodeAccessSecurityAttribute
    { 
        private string  m_access = null; 
        private string  m_host   = null;
        private string  m_port   = null; 
        private string  m_transport  = null;

        private const string strAccess     = "Access";
        private const string strConnect    = "Connect"; 
        private const string strAccept     = "Accept";
        private const string strHost       = "Host"; 
        private const string strTransport  = "Transport"; 
        private const string strPort       = "Port";
 
        public SocketPermissionAttribute( SecurityAction action ): base( action )
        {
        }
 
        public string Access {
            get { return m_access; } 
            set { 
                if (m_access != null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strAccess, value), "value"); 
                }
                m_access = value;
            }
        } 

        public string Host { 
            get { return m_host; } 
            set {
                if (m_host != null) { 
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strHost, value), "value");
                }
                m_host = value;
            } 
        }
 
        public string Transport { 
            get { return m_transport;}
            set { 
                if (m_transport != null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strTransport, value), "value");
                }
                m_transport = value; 
            }
        } 
 
        public string Port {
            get { return m_port;} 
            set {
                if (m_port != null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strPort, value), "value");
                } 
                m_port = value;
            } 
        } 

        public override IPermission CreatePermission() 
        {
            SocketPermission perm = null;
            if (Unrestricted) {
                perm = new SocketPermission( PermissionState.Unrestricted); 
            }
            else { 
                perm = new SocketPermission(PermissionState.None); 
                if (m_access == null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strAccess)); 
                }
                if (m_host == null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strHost));
                } 
                if (m_transport == null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strTransport)); 
                } 
                if (m_port == null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strPort)); 
                }
                ParseAddPermissions(perm);
            }
            return perm; 
        }
 
 
        private void ParseAddPermissions(SocketPermission perm) {
 
            NetworkAccess access;
            if (0 == string.Compare(m_access, strConnect, StringComparison.OrdinalIgnoreCase )) {
                access = NetworkAccess.Connect;
            } 
            else
            if (0 == string.Compare(m_access, strAccept, StringComparison.OrdinalIgnoreCase )) { 
                access = NetworkAccess.Accept; 
            }
            else { 
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strAccess, m_access));
            }

            TransportType transport; 
            try {
                transport = (TransportType) Enum.Parse(typeof(TransportType), m_transport, true); 
            } 
            catch (Exception e) {
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { 
 		            throw;
	            }
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strTransport, m_transport), e);
            } 
            catch {
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strTransport, m_transport), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
            } 

            int port; 
            if (string.Compare(m_port, "All", StringComparison.OrdinalIgnoreCase ) == 0) {
                m_port = "-1";
            }
            try { 
                port = Int32.Parse(m_port, NumberFormatInfo.InvariantInfo);
            } 
            catch (Exception e) { 
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
		            throw; 
	            }
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strPort, m_port), e);
            }
            catch { 
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strPort, m_port), new Exception(SR.GetString(SR.net_nonClsCompliantException)));
            } 
 
            if (!ValidationHelper.ValidateTcpPort(port) && port != SocketPermission.AllPorts) {
                throw new ArgumentOutOfRangeException(SR.GetString(SR.net_perm_invalid_val, strPort, m_port)); 
            }
            perm.AddPermission(access, transport, m_host, port);
        }
 
    }
 
 
    /// 
    ///     
    ///       Controls rights to make or accept connections on a transport address.
    ///    
    /// 
    [Serializable] 
    public sealed class SocketPermission : CodeAccessPermission, IUnrestrictedPermission {
 
        private ArrayList m_connectList; 
        private ArrayList m_acceptList;
        private bool m_noRestriction; 


        /// 
        ///     
        ///       Returns the enumeration of permissions to connect a remote peer.
        ///     
        ///  
        public IEnumerator ConnectList    {get {return m_connectList.GetEnumerator();}}
 
        /// 
        ///    
        ///       Returns the enumeration of permissions to accept incoming connections.
        ///     
        /// 
        public IEnumerator AcceptList     {get {return m_acceptList.GetEnumerator();}} 
 

        ///  
        ///    
        ///       Defines a constant representing all ports.
        ///    
        ///  
        public const int AllPorts = unchecked((int)0xFFFFFFFF);
 
        //< 
        internal const int AnyPort = unchecked((int)0);
 
        /// 
        ///    
        ///       Creates a new instance of the 
        ///       class that passes all demands 
        ///       or that fails all demands.
        ///     
        ///  
        public SocketPermission(PermissionState state) {
            initialize(); 
            m_noRestriction = (state == PermissionState.Unrestricted);
        }

        internal SocketPermission(bool free) { 
            initialize();
            m_noRestriction = free; 
        } 

 
        /// 
        ///    
        ///       Creates a new instance of the SocketPermissions class for the given transport address with the specified permission.
        ///     
        /// 
        public SocketPermission(NetworkAccess access, TransportType transport, String hostName, int portNumber) { 
            initialize(); 
            m_noRestriction = false;
            AddPermission(access, transport, hostName, portNumber); 
        }

        /// 
        ///     
        ///       Adds a permission to the set of permissions for a transport address.
        ///     
        ///  
        public void AddPermission(NetworkAccess access, TransportType transport, string hostName, int portNumber) {
            if (hostName == null) { 
                throw new ArgumentNullException("hostName");
            }

            EndpointPermission endPoint = new EndpointPermission(hostName, portNumber, transport); 

            AddPermission(access, endPoint); 
        } 

        internal void AddPermission(NetworkAccess access, EndpointPermission endPoint) { 
            if (m_noRestriction) {    // Is the permission unrestricted?
                return;             // YES-- then additional endpoints have no effect
            }
            if ((access & NetworkAccess.Connect) != 0) 
                    m_connectList.Add(endPoint);
            if ((access & NetworkAccess.Accept) != 0) 
                    m_acceptList.Add(endPoint); 
        }
 
        // IUnrestrictedPermission interface methods
        /// 
        ///    
        ///       Checks the overall permission state of the object. 
        ///    
        ///  
        public bool IsUnrestricted() { 
            return m_noRestriction;
        } 

        // IPermission interface methods
        /// 
        ///     
        ///       Creates
        ///       a copy of a  instance. 
        ///     
        /// 
        public override IPermission Copy() { 

            SocketPermission sp = new SocketPermission(m_noRestriction);

            sp.m_connectList = (ArrayList)m_connectList.Clone(); 
            sp.m_acceptList = (ArrayList)m_acceptList.Clone();
                        return sp; 
        } 

        private bool FindSubset(ArrayList source, ArrayList target) { 
            foreach (EndpointPermission e in source) {

                bool found = false;
 
                foreach (EndpointPermission ee in target) {
                    if (e.SubsetMatch(ee)) { 
                        found = true; 
                        break;
                    } 
                }
                if (!found) {
                    return false;
                } 
            }
            return true; 
        } 

        ///  
        /// Returns the logical union between two  instances.
        /// 
        public override IPermission Union(IPermission target) {
            // Pattern suggested by Security engine 
            if (target==null) {
                return this.Copy(); 
            } 
            SocketPermission other = target as SocketPermission;
            if(other == null) { 
                throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
            }
            if (m_noRestriction || other.m_noRestriction) {
                return new SocketPermission(true); 
            }
            SocketPermission result = (SocketPermission)other.Copy(); 
 
            for (int i = 0; i < m_connectList.Count; i++) {
                result.AddPermission(NetworkAccess.Connect, (EndpointPermission)m_connectList[i]); 
            }
            for (int i = 0; i < m_acceptList.Count; i++) {
                result.AddPermission(NetworkAccess.Accept, (EndpointPermission)m_acceptList[i]);
            } 
            return result;
        } 
 
        /// 
        ///     
        ///       Returns the logical intersection between two  instances.
        ///    
        /// 
        public override IPermission Intersect(IPermission target) { 
            // Pattern suggested by Security engine
            if (target == null) { 
                return null; 
            }
 
            SocketPermission other = target as SocketPermission;
            if(other == null) {
                throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
            } 

            SocketPermission result; 
            if (m_noRestriction) { 
                result = (SocketPermission)(other.Copy());
            } 
            else if (other.m_noRestriction) {
                result = (SocketPermission)(this.Copy());
            }
            else { 
                result = new SocketPermission(false);
                intersectLists(m_connectList, other.m_connectList, result.m_connectList); 
                intersectLists(m_acceptList, other.m_acceptList, result.m_acceptList); 
            }
 
            // return null if resulting permission is restricted and empty
            if (!result.m_noRestriction &&
                result.m_connectList.Count == 0 && result.m_acceptList.Count == 0) {
                return null; 
            }
            return result; 
        } 

        ///  
        /// Compares two  instances.
        /// 
        public override bool IsSubsetOf(IPermission target) {
            // Pattern suggested by security engine 
            if (target == null) {
                return (m_noRestriction == false && m_connectList.Count == 0 && m_acceptList.Count == 0); 
            } 

            SocketPermission other = target as SocketPermission; 
            if (other == null) {
                throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
            }
 
            if (other.IsUnrestricted()) {
                return true; 
            } else if (this.IsUnrestricted()) { 
                return false;
            } else if (this.m_acceptList.Count + this.m_connectList.Count ==0) { 
                return true;
            } else if (other.m_acceptList.Count + other.m_connectList.Count ==0) {
                return false;
            } 

            bool result = false; 
            try { 
                if (FindSubset(m_connectList, other.m_connectList) &&
                    FindSubset(m_acceptList, other.m_acceptList)) { 
                    result = true;
                }
            }
            finally { 
                //  This is around a back door into DNS
                //  Security engine will call isSubsetOf and probably have 
                //  DNS permission asserted. We call DNS resolve. 
                //  Before return do cleanup of DNS results.
 
                //  Only "this" needs cleanup, the policy object is not available for
                //  an application to look at.
                this.CleanupDNS();
            } 

            return result; 
        } 

        // 
        //This is to cleanup DNS resolution results
        //
        private void CleanupDNS() {
            foreach(EndpointPermission e in m_connectList) { 
                //DNS hostnames never produce 'cached=true'
                if (e.cached) { 
                    continue; 
                }
                e.address = null; 
            }

            foreach(EndpointPermission e in m_acceptList) {
                //DNS hostnames never produce 'cached=true' 
                if (e.cached) {
                    continue; 
                } 
                e.address = null;
            } 
        }

        /// 
        ///  
        public override void FromXml(SecurityElement securityElement) {
            if (securityElement == null) { 
 
                //
                // null SecurityElement 
                //

                throw new ArgumentNullException("securityElement");
            } 
            if (!securityElement.Tag.Equals("IPermission")) {
 
                // 
                // SecurityElement must be a permission element
                // 

                throw new ArgumentException(SR.GetString(SR.net_not_ipermission), "securityElement");
            }
 
            string className = securityElement.Attribute("class");
 
            if (className == null) { 

                // 
                // SecurityElement must be a permission element for this type
                //

                throw new ArgumentException(SR.GetString(SR.net_no_classname), "securityElement"); 
            }
            if (className.IndexOf(this.GetType().FullName) < 0) { 
 
                //
                // SecurityElement must be a permission element for this type 
                //

                throw new ArgumentException(SR.GetString(SR.net_no_typename), "securityElement");
            } 

            // 
            // Start recovering the state from XML encoding 
            //
 
            initialize();


            String str = securityElement.Attribute("Unrestricted"); 

            if (str != null) { 
                m_noRestriction = (0 == string.Compare( str, "true", StringComparison.OrdinalIgnoreCase )); 
                if(m_noRestriction)
                    return; 
            }

            m_noRestriction = false;
            m_connectList = new ArrayList(); 
            m_acceptList = new ArrayList();
 
            SecurityElement et = securityElement.SearchForChildByTag("ConnectAccess"); 
            if (et != null) {
                ParseAddXmlElement(et, m_connectList, "ConnectAccess, "); 
            }
            et = securityElement.SearchForChildByTag("AcceptAccess");
            if (et != null) {
                ParseAddXmlElement(et, m_acceptList, "AcceptAccess, "); 
            }
        } 
 
        private static void ParseAddXmlElement(SecurityElement et, ArrayList listToAdd, string accessStr) {
 
            foreach(SecurityElement uriElem in et.Children) {
                if (uriElem.Tag.Equals("ENDPOINT")) {
                    Hashtable attributes = uriElem.Attributes;
                    string tmpStr; 

                    try { 
                        tmpStr = attributes["host"] as string; 
                    }
                    catch{ 
                        tmpStr = null;
                    }

                    if (tmpStr == null) { 
                        throw new ArgumentNullException(accessStr + "host");
                    } 
                    string host = tmpStr; 

                    try { 
                        tmpStr = attributes["transport"] as string;
                    }
                    catch{
                        tmpStr = null; 
                    }
                    if (tmpStr == null) { 
                        throw new ArgumentNullException(accessStr + "transport"); 
                    }
                    TransportType transport; 
                    try {
                        transport = (TransportType) Enum.Parse(typeof(TransportType), tmpStr, true);
                    }
                    catch (Exception exception) { 
                        if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
 		                    throw; 
	                    } 
                        throw new ArgumentException(accessStr + "transport", exception);
                    } 
                    catch {
                        throw new ArgumentException(accessStr + "transport", new Exception(SR.GetString(SR.net_nonClsCompliantException)));
                    }
 
                    try {
                        tmpStr = attributes["port"] as string; 
                    } 
                    catch{
                        tmpStr = null; 
                    }
                    if (tmpStr == null) {
                        throw new  ArgumentNullException(accessStr + "port");
                    } 
                    if (string.Compare(tmpStr, "All", StringComparison.OrdinalIgnoreCase ) == 0) {
                        tmpStr = "-1"; 
                    } 
                    int port;
                    try { 
                        port = Int32.Parse(tmpStr, NumberFormatInfo.InvariantInfo);
                    }
                    catch (Exception exception) {
                        if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) { 
 		                    throw;
 	                    } 
                        throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, accessStr + "port", tmpStr), exception); 
                    }
                    catch { 
                        throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, accessStr + "port", tmpStr), new Exception(SR.GetString(SR.net_nonClsCompliantException)));
                    }

                    if (!ValidationHelper.ValidateTcpPort(port) && port != SocketPermission.AllPorts) { 
                        throw new ArgumentOutOfRangeException(SR.GetString(SR.net_perm_invalid_val, accessStr + "port", tmpStr));
                    } 
 

                    listToAdd.Add(new EndpointPermission(host, port , transport)); 
                }
                else {
                    // improper tag found, just ignore
                } 
            }
        } 
 
        /// 
        ///    [To be supplied.] 
        /// 
        public override SecurityElement ToXml() {

            SecurityElement securityElement = new SecurityElement( "IPermission" ); 

            securityElement.AddAttribute("class", this.GetType().FullName + ", " + this.GetType().Module.Assembly.FullName.Replace( '\"', '\'' )); 
            securityElement.AddAttribute("version", "1"); 

            if (!IsUnrestricted()) { 
                if (m_connectList.Count > 0) {

                    SecurityElement permList = new SecurityElement("ConnectAccess");
                    foreach(EndpointPermission permission in m_connectList) { 
                        SecurityElement endpoint = new SecurityElement("ENDPOINT");
                        endpoint.AddAttribute("host", permission.Hostname); 
                        endpoint.AddAttribute("transport", permission.Transport.ToString()); 
                        endpoint.AddAttribute("port",   permission.Port != AllPorts?
                                                        permission.Port.ToString(NumberFormatInfo.InvariantInfo): "All"); 
                        permList.AddChild(endpoint);
                    }
                    securityElement.AddChild(permList);
                } 

                if (m_acceptList.Count > 0) { 
 
                    SecurityElement permList = new SecurityElement("AcceptAccess");
                    foreach(EndpointPermission permission in m_acceptList) { 
                        SecurityElement endpoint = new SecurityElement("ENDPOINT");
                        endpoint.AddAttribute("host", permission.Hostname);
                        endpoint.AddAttribute("transport", permission.Transport.ToString());
                        endpoint.AddAttribute("port",   permission.Port != AllPorts? 
                                                        permission.Port.ToString(NumberFormatInfo.InvariantInfo): "All");
                        permList.AddChild(endpoint); 
                    } 
                    securityElement.AddChild(permList);
                } 
            }
            else {
                securityElement.AddAttribute("Unrestricted", "true");
            } 
            return securityElement;
        } 
 
        private void initialize() {
            m_noRestriction = false; 
            m_connectList = new ArrayList();
            m_acceptList = new ArrayList();
        }
 
        private static void intersectLists(ArrayList A, ArrayList B, ArrayList result) {
            // The optimization is done according to the following truth 
            // (A|B|C) intersect (B|C|E|D)) == B|C|(A inter E)|(A inter D) 
            //
            // We also check on any duplicates in the result 


            bool[] aDone=new bool[A.Count];            //used to avoid duplicates in result
            bool[] bDone=new bool[B.Count]; 
            int ia=0;
            int ib=0; 
            // Round 1st 
            // Getting rid of same permissons in the input arrays (assuming X /\ X = X)
            foreach (EndpointPermission a in  A) { 
                ib = 0;
                foreach (EndpointPermission b in  B) {
                    // check to see if b is in the result already
                    if (!bDone[ib]) { 
                        //if both elements are the same, copy it into result
                        if (a.Equals(b)) { 
                            result.Add(a); 
                            aDone[ia]=bDone[ib]=true;
                            //since permissions are ORed we can break and go to the next A 
                            break;
                        }
                    }
                    ++ib; 
                } //foreach b in B
                ++ia; 
            } //foreach a in A 

            ia = 0; 
            // Round second
            // Grab only intersections of objects not found in both A and B
            foreach (EndpointPermission a in  A) {
 
                if (!aDone[ia]) {
                    ib = 0; 
                    foreach(EndpointPermission b in B) { 
                        if (!bDone[ib]) {
                            EndpointPermission intesection = a.Intersect(b); 
                            if (intesection != null) {
                                bool found = false;
                                // check to see if we already have the same result
                                foreach (EndpointPermission  res in result) { 
                                    if (res.Equals(intesection)) {
                                        found = true; 
                                        break; 
                                    }
                                } 
                                if (!found) {
                                    result.Add(intesection);
                                }
                            } 
                        } //!Done[ib]
                        ++ib; 
                    } //foreach b in B 
                } //!Done[ia]
                ++ia; 
            } //foreach a in A
        }

    }// class SocketPermission 

 
    ///  
    ///       Represents an element of SocketPermission object contents.
    ///  
    [Serializable]
    public class EndpointPermission {

        // 
        // <
 
 

 

        internal String hostname;
        internal int port;
        internal TransportType transport; 
        internal bool wildcard;
        internal IPAddress[] address; 
        internal bool cached = false; 

        private static char[] DotSeparator = new char[] {'.'}; 
        private const String encSeperator = "#";

        /// 
        ///     
        ///       Returns the hostname part of EndpointPermission object
        ///     
        ///  
        public String           Hostname        { get {return hostname;}}
 
        /// 
        ///    
        ///       Returns the transport of EndpointPermission object
        ///     
        /// 
        public TransportType    Transport       { get {return transport;}} 
 
        /// 
        ///     
        ///       Returns the Port part of EndpointPermission object
        ///    
        /// 
        public int              Port            { get {return port;}} 
        //
        // < 
 

 


        internal EndpointPermission(String epname, int port, TransportType trtype) {
 
            if (CheckEndPointName(epname) == EndPointType.Invalid) {
                throw new ArgumentException(SR.GetString(SR.net_perm_epname, epname), "epname"); 
            } 
            if (!ValidationHelper.ValidateTcpPort(port) && port != SocketPermission.AllPorts) {
                throw new ArgumentOutOfRangeException(SR.GetString(SR.net_perm_invalid_val, "Port", port.ToString(NumberFormatInfo.InvariantInfo))); 
            }

            hostname = epname;
            this.port = port; 
            transport = trtype;
            wildcard = false; 
        } 

        // 
        // This is ONLY a syntatic check on equality, hostnames are compared as strings!
        //
        public override bool Equals(object obj) {
 
            EndpointPermission ep = (EndpointPermission)obj;
 
            if (String.Compare(hostname, ep.hostname, StringComparison.OrdinalIgnoreCase ) != 0) { 
                return false;
            } 
            if (port != ep.port) {
                return false;
            }
            if (transport != ep.transport) { 
                return false;
            } 
            return true; 
        }
 
        public override int GetHashCode() {
            return ToString().GetHashCode();
        }
 
        //
        // < 
 

        internal bool IsDns { 
            get {
                if (IsValidWildcard) {
                    return false;
                } 
                return CheckEndPointName(hostname) == EndPointType.DnsOrWildcard;
            } 
        } 

 
        //
        // In this version wildcards are only allowed over IP ranges
        // not DNS names. For example "*.microsoft.com" is not allowed
        // A valid wildcard will have exactly three periods 
        //IPv6 wildcards are NOT supported
        // 
        private bool IsValidWildcard { 
            get {
 
                int len = hostname.Length;

                //
                // Check minimum length 
                //
 
                if (len < 3) { 
                    return false;
                } 

                //
                // First and last characters cannot be periods
                // 

                if ((hostname[0] == '.') || (hostname[len - 1] == '.')) { 
                    return false; 
                }
 
                int dotCount = 0;
                int anyCount = 0;

                for (int i = 0; i < hostname.Length; i++) { 
                    if (hostname[i] == '.') {
                        dotCount++; 
                    } 
                    else if (hostname[i] == '*') {
                        ++anyCount; 
                    }
                    else if (!Char.IsDigit(hostname[i])) {  // Not a digit?
                        return false;                       // Reject wildcard
                    } 
                }
                return (dotCount == 3) && (anyCount > 0); 
            } 
        }
 
        internal bool MatchAddress(EndpointPermission e) {

            // For Asp.Net config we made it valid empty string in a hostname,
            // but it will match to nothing. 
            if(this.Hostname.Length == 0 || e.Hostname.Length == 0) {
                return false; 
            } 

            // 
            // This is a fix for INADDR_ANY in Bind()
            // if this.Hostname == "0.0.0.0" then it matches only to e.Hostname="*.*.*.*"
            //
            // The reason is to not pass "0.0.0.0" into Resolve() 
            if(this.Hostname.Equals("0.0.0.0"))
            { 
                if(e.Hostname.Equals("*.*.*.*") || e.Hostname.Equals("0.0.0.0")) 
                    return true;
                return false; 
            }

            if (IsDns && e.IsDns) {
 
                //
                // < 
 

 
                return (String.Compare(hostname, e.hostname, StringComparison.OrdinalIgnoreCase ) == 0);
            }
            Resolve();
            e.Resolve(); 

            // 
            // if Resolve() didn't work for some reason then we're out of luck 
            //
 
            if (((address == null) && !wildcard) || ((e.address == null) && !e.wildcard)) {
                return false;
            }
 
            //
            // try matching IP addresses against other wildcard address(es) or 
            // wildcard 
            //
 
            if (this.wildcard && !e.wildcard) {
                return false;                           // as a wildcard I cannot be subset of a host.

            } 
            else if (e.wildcard) {
                if (this.wildcard) { 
                    // check against my _wildcard_ 
                    if (MatchWildcard(e.hostname)) {
                        return true; 
                    }
                }
                else {
                    // check against my _addresses_ 
                    for (int i = 0; i < address.Length; ++i) {
                        if (e.MatchWildcard(address[i].ToString())) { 
                            return true; 
                        }
                    } 
                }
            } else {
                //both are _not_ wildcards
                for (int i = 0; i < address.Length; ++i) { 
                    for (int j = 0; j < e.address.Length; ++j) {
                        if (address[i].Equals(e.address[j])) { 
                            return true; 
                        }
                    } 
                }
            }
            return false;
        } 

        internal bool MatchWildcard(string str) { 
 
            string [] wcPieces = hostname.Split(DotSeparator);
            string [] strPieces = str.Split(DotSeparator); 

            if ((strPieces.Length != 4) || (wcPieces.Length != 4)) {
                return false;
            } 
            for (int i = 0; i < 4; i++) {
                if ((strPieces[i] != wcPieces[i]) && (wcPieces[i] != "*")) { 
                    return false; 
                }
            } 
            return true;
        }

        internal void Resolve() { 

            // 
            // if we already resolved this name then don't do it again 
            //
 
            if (cached) {
                return;
            }
 
            //
            // IP wildcards are not resolved 
            // 

            if (wildcard) { 
                return;
            }

            // 
            // IP addresses with wildcards are allowed in permissions
            // 
 
            if (IsValidWildcard) {
                wildcard = true; 
                cached = true;
                return;
            }
 
            //
            // Check if the permission was specified as numeric IP. 
            // 
            IPAddress ipaddr;
            if (IPAddress.TryParse(hostname, out ipaddr)) 
            {
                address = new IPAddress[1];
                address[0] = ipaddr;
                cached = true; 
                return;
            } 
 
            //
            // Not numeric: use GetHostByName to determine addresses 
            //
            try {
                bool timedOut;
                IPHostEntry ipHostEntry = Dns.InternalResolveFast(hostname,Timeout.Infinite,out timedOut); 
                if(ipHostEntry != null){
                    address = ipHostEntry.AddressList; 
                } 

                // NB: It never caches DNS responses 
                //

            }
            catch (SecurityException) { 
                throw;
            } 
            catch { 
                // ignore second exception
            } 
        }

        internal bool SubsetMatch(EndpointPermission e) {
            return ((transport == e.transport) || (e.transport == TransportType.All)) 
                    && ((port == e.port) || (e.port == SocketPermission.AllPorts) || port == SocketPermission.AnyPort)
                    && MatchAddress(e); 
        } 

        public override String ToString() { 
            return hostname + encSeperator + port + encSeperator + ((int)transport).ToString(NumberFormatInfo.InvariantInfo);
        }

        internal EndpointPermission Intersect(EndpointPermission E) { 

            String commonName=null; 
            TransportType commonTransport; 
            int commonPort;
 
            //
            // Look at the transport
            //
 
            if (transport == E.transport) {           // same transport
                commonTransport = transport; 
            } 
            // NO: check if one of the permissions authorize all transports
            else if (transport == TransportType.All) { 
                commonTransport = E.transport;
            }
            else if (E.transport == TransportType.All) {
                commonTransport = transport; 
            }
            else {   // transport dont match-- intersection is empty 
                return null; 
            }
 
            //
            // Determine common port
            //
 
            if (port == E.port) {
                commonPort = port; 
            } 
            else if (port == SocketPermission.AllPorts) {
                commonPort = E.port; 
            }
            else if (E.port == SocketPermission.AllPorts) {
                commonPort = port;
            } 
            else {
                return null; 
            } 

            //Work out common hostname part 
            //
            // This is a fix for INADDR_ANY in Bind()
            // if this.Hostname == "0.0.0.0" then it matches only to e.Hostname="*.*.*.*"
            // 
            // The reason is to not pass "0.0.0.0" into Resolve()
            if(this.Hostname.Equals("0.0.0.0")) 
            { 
                if(E.Hostname.Equals("*.*.*.*") || E.Hostname.Equals("0.0.0.0"))
                    commonName = this.Hostname;//i.e. 0.0.0.0 
                else
                    return null;
            }
            else if(E.Hostname.Equals("0.0.0.0")) 
            {
                if(this.Hostname.Equals("*.*.*.*") || this.Hostname.Equals("0.0.0.0")) 
                    commonName = E.Hostname; //i.e. 0.0.0.0 
                else
                    return null; 
            }
            else if (IsDns && E.IsDns) {
                //
                // If both are DNS names we compare names as strings 
                //
                if(String.Compare(hostname, E.hostname, StringComparison.OrdinalIgnoreCase ) != 0) { 
                    return null; 
                }
                else { 
                    commonName = hostname;
                }
            }
            else 
            {
                Resolve(); 
                E.Resolve(); 
                //after this step we got both clases updated with valid
                //wildcard and address members. It's safe now to access those members directly 

                //
                // if Resolve() didn't work for some reason then we're out of luck
                // 

                if (((address == null) && !wildcard) || ((E.address == null) && !E.wildcard)) { 
                    return null; 
                }
 

                //
                // Find intersection of address lists
                if(wildcard && E.wildcard) { 
                    string [] wcPieces = hostname.Split(DotSeparator);
                    string [] strPieces = E.hostname.Split(DotSeparator); 
                    string  result=""; 

                    if ((strPieces.Length != 4) || (wcPieces.Length != 4)) { 
                        return null;
                    }
                    for (int i = 0; i < 4; i++) {
                        if(i != 0) { 
                            result+=".";
                        } 
                        if (strPieces[i] == wcPieces[i]) { 
                            result+=strPieces[i];
                        } 
                        else
                        if (strPieces[i] == "*") {
                            result+=wcPieces[i];
                        } 
                        else
                        if (wcPieces[i] == "*") { 
                            result+=strPieces[i]; 
                        }
                        else 
                            return null;
                    }
                    commonName = result;
                }else 
                if (wildcard) {                                                 //if ME is a wildcard
                    // 
                    // 
                    // Check for wildcard IP matching
                    // 
                    for (int i = 0; i < E.address.Length; ++i) {
                        if (MatchWildcard(E.address[i].ToString())) {
                            commonName = E.hostname;    //SHE fits into my wildcard
                            break; 
                        }
                    } 
                } 
                else if (E.wildcard) {                                   //if SHE is a wildcard
                    for (int i = 0; i < address.Length; ++i) { 
                        if (E.MatchWildcard(address[i].ToString())) {
                            commonName = hostname;      //ME fit  into her wildcard
                            break;
                        } 
                    }
                } 
                else 
                {
                    // 
                    // Not wildcard: check aginst  IP addresses list
                    //

                    if (address == E.address) {                 // they both are NOT null (already checked) 
                        commonName = hostname;
                    } 
 
                    //
                    // Search the IP addresses for match 
                    //
                    for (int i = 0; commonName == null && i < address.Length; i++) {
                        for (int k = 0; k < E.address.Length; k++) {
                            if (address[i].Equals(E.address[k])) { 
                                commonName = hostname;
                                break; 
                            } 
                        }
                    } 
                }
                if(commonName == null) {
                    return null;
                } 
            }
 
            return new EndpointPermission(commonName, commonPort, commonTransport); 
        }
/* 
FROM RFC 952
------------
ASSUMPTIONS
1   A "name" (Net, Host, Gateway, or Domain name) is a text string up 
    to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus sign (-), and period (.).
    Note that periods are only allowed when they serve to delimit components of "domain style names". 
    (See RFC-921, "Domain Name System Implementation Schedule", for background). 
    No blank or space characters are permitted as part of a name.
    No distinction is made between upper and lower case. 
    The first character must be an alpha character.
    The last character must not be a minus sign or period.
    Single character names or nicknames are not allowed.
 
    Implementaion below is relaxed in terms of:
    - Hostname may start with a digit (as per RFC1123 ) 
    - Hostname may contain '_' character (historical Inet issue) 
    - Hostname may be a single-character string (historical Inet issue)
    - Hostname may contain '*' as a wildcard for an EndPointPermission 
    - Hostname may be empty (to support config templates)
    - Hostname may be an IPv6 string comprised of A-F, 0-9, '.', ':', and '%' chars
*/
    private enum EndPointType { 
            Invalid,
            IPv6, 
            DnsOrWildcard, 
            IPv4
    }; 

    private static EndPointType CheckEndPointName(string name) {
        if (name == null) {
            return EndPointType.Invalid; 
        }
        bool isIPv6       = false; 
        bool isDnsOrWC    = false; 
        bool isHexLetter  = false;
        for(int i=0; i < name.Length; ++i) { 
            char ch = name[i];
            switch(ch) {
            case '.':   //note _all_ dots name is an error
                        continue; 
            case '-':   //if _all_ chars are those we call Dns (to confirm error)
            case '_': 
            case '*':   isDnsOrWC = true; 
                        continue;
            case ':': 
            case '%':   isIPv6 = true;
                        continue;
            default:    break;
            } 

            //Check on letters but NOT hex digits 
            if ((ch > 'f' && ch <= 'z') || (ch > 'F' && ch <= 'Z')) { 
                isDnsOrWC = true;
                continue; 
            }
            //Check on HEX letters
            if((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
                isHexLetter = true; 
                continue;
            } 
            //Here only digits left (others are invalid) 
            if (!(ch >= '0' && ch <= '9'))
                return EndPointType.Invalid; 
        }

        // The logic is (solely for the purpose of SocketPermssion class)
        //  isIPv6 && isDnsOrWC   = EndPointType.Invalid 
        //  isIPv6 && !isDnsOrWC  = EndPointType.IPv6
        //  !isIPv6 && isDnsOrWC  = EndPointType.DnsOrWildcard 
        //  !isIPv6 && !isDnsOrWC && isHexLetter = EndPointType.DnsOrWildcard; 
        //  else = EndPointType.IPv4
        return isIPv6 ? (isDnsOrWC? EndPointType.Invalid: EndPointType.IPv6) 
                      : (isDnsOrWC? EndPointType.DnsOrWildcard :
                                    isHexLetter? EndPointType.DnsOrWildcard :EndPointType.IPv4);
    }
 

    } // class EndpointPermission 
 

} // namespace System.Net 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Net { 
 
    using System.Collections;
    using System.Security; 
    using System.Security.Permissions;
    using System.Globalization;
    using System.Threading;
 
    //NOTE: While SocketPermissionAttribute resides in System.DLL,
    //      no classes from that DLL are able to make declarative usage of SocketPermission. 
 

    // THE syntax of this attribute is as followed 
    // [SocketPermsion(SecurityAction.Assert, Access=Connect, Host=hostname, Transport=Tcp/Udp/All, port=portN/All)]
    // [SocketPermsion(SecurityAction.Assert, Access=Accept, Host=localname, Transport=Tcp/Udp/All, port=portN/All)]
    //
    // WHERE: 
    //=======
    // - hostname is either a DNS hostname OR an IP address 1.2.3.4 or an IP wildcard 1.2.*.* 
    // - protocol is either Tcp, Udp or All 
    // - port is a numeric value or -1 that means "All Ports"
    // 
    //  All the properites Host, Protocol and Port must be specified.
    // "localIP" means that you put here a valid address or DNS name or the localhost
    //
    //  NetworkAccess specifies the scope of permission, i.e. for connecting to remote peer, 
    //  or for accepting data on the local resources.
    // 
 
    [   AttributeUsage( AttributeTargets.Method | AttributeTargets.Constructor |
                        AttributeTargets.Class  | AttributeTargets.Struct      | 
                        AttributeTargets.Assembly,
                        AllowMultiple = true, Inherited = false )]

    [Serializable] 
    public sealed class SocketPermissionAttribute: CodeAccessSecurityAttribute
    { 
        private string  m_access = null; 
        private string  m_host   = null;
        private string  m_port   = null; 
        private string  m_transport  = null;

        private const string strAccess     = "Access";
        private const string strConnect    = "Connect"; 
        private const string strAccept     = "Accept";
        private const string strHost       = "Host"; 
        private const string strTransport  = "Transport"; 
        private const string strPort       = "Port";
 
        public SocketPermissionAttribute( SecurityAction action ): base( action )
        {
        }
 
        public string Access {
            get { return m_access; } 
            set { 
                if (m_access != null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strAccess, value), "value"); 
                }
                m_access = value;
            }
        } 

        public string Host { 
            get { return m_host; } 
            set {
                if (m_host != null) { 
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strHost, value), "value");
                }
                m_host = value;
            } 
        }
 
        public string Transport { 
            get { return m_transport;}
            set { 
                if (m_transport != null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strTransport, value), "value");
                }
                m_transport = value; 
            }
        } 
 
        public string Port {
            get { return m_port;} 
            set {
                if (m_port != null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strPort, value), "value");
                } 
                m_port = value;
            } 
        } 

        public override IPermission CreatePermission() 
        {
            SocketPermission perm = null;
            if (Unrestricted) {
                perm = new SocketPermission( PermissionState.Unrestricted); 
            }
            else { 
                perm = new SocketPermission(PermissionState.None); 
                if (m_access == null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strAccess)); 
                }
                if (m_host == null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strHost));
                } 
                if (m_transport == null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strTransport)); 
                } 
                if (m_port == null) {
                    throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strPort)); 
                }
                ParseAddPermissions(perm);
            }
            return perm; 
        }
 
 
        private void ParseAddPermissions(SocketPermission perm) {
 
            NetworkAccess access;
            if (0 == string.Compare(m_access, strConnect, StringComparison.OrdinalIgnoreCase )) {
                access = NetworkAccess.Connect;
            } 
            else
            if (0 == string.Compare(m_access, strAccept, StringComparison.OrdinalIgnoreCase )) { 
                access = NetworkAccess.Accept; 
            }
            else { 
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strAccess, m_access));
            }

            TransportType transport; 
            try {
                transport = (TransportType) Enum.Parse(typeof(TransportType), m_transport, true); 
            } 
            catch (Exception e) {
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { 
 		            throw;
	            }
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strTransport, m_transport), e);
            } 
            catch {
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strTransport, m_transport), new Exception(SR.GetString(SR.net_nonClsCompliantException))); 
            } 

            int port; 
            if (string.Compare(m_port, "All", StringComparison.OrdinalIgnoreCase ) == 0) {
                m_port = "-1";
            }
            try { 
                port = Int32.Parse(m_port, NumberFormatInfo.InvariantInfo);
            } 
            catch (Exception e) { 
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
		            throw; 
	            }
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strPort, m_port), e);
            }
            catch { 
                throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strPort, m_port), new Exception(SR.GetString(SR.net_nonClsCompliantException)));
            } 
 
            if (!ValidationHelper.ValidateTcpPort(port) && port != SocketPermission.AllPorts) {
                throw new ArgumentOutOfRangeException(SR.GetString(SR.net_perm_invalid_val, strPort, m_port)); 
            }
            perm.AddPermission(access, transport, m_host, port);
        }
 
    }
 
 
    /// 
    ///     
    ///       Controls rights to make or accept connections on a transport address.
    ///    
    /// 
    [Serializable] 
    public sealed class SocketPermission : CodeAccessPermission, IUnrestrictedPermission {
 
        private ArrayList m_connectList; 
        private ArrayList m_acceptList;
        private bool m_noRestriction; 


        /// 
        ///     
        ///       Returns the enumeration of permissions to connect a remote peer.
        ///     
        ///  
        public IEnumerator ConnectList    {get {return m_connectList.GetEnumerator();}}
 
        /// 
        ///    
        ///       Returns the enumeration of permissions to accept incoming connections.
        ///     
        /// 
        public IEnumerator AcceptList     {get {return m_acceptList.GetEnumerator();}} 
 

        ///  
        ///    
        ///       Defines a constant representing all ports.
        ///    
        ///  
        public const int AllPorts = unchecked((int)0xFFFFFFFF);
 
        //< 
        internal const int AnyPort = unchecked((int)0);
 
        /// 
        ///    
        ///       Creates a new instance of the 
        ///       class that passes all demands 
        ///       or that fails all demands.
        ///     
        ///  
        public SocketPermission(PermissionState state) {
            initialize(); 
            m_noRestriction = (state == PermissionState.Unrestricted);
        }

        internal SocketPermission(bool free) { 
            initialize();
            m_noRestriction = free; 
        } 

 
        /// 
        ///    
        ///       Creates a new instance of the SocketPermissions class for the given transport address with the specified permission.
        ///     
        /// 
        public SocketPermission(NetworkAccess access, TransportType transport, String hostName, int portNumber) { 
            initialize(); 
            m_noRestriction = false;
            AddPermission(access, transport, hostName, portNumber); 
        }

        /// 
        ///     
        ///       Adds a permission to the set of permissions for a transport address.
        ///     
        ///  
        public void AddPermission(NetworkAccess access, TransportType transport, string hostName, int portNumber) {
            if (hostName == null) { 
                throw new ArgumentNullException("hostName");
            }

            EndpointPermission endPoint = new EndpointPermission(hostName, portNumber, transport); 

            AddPermission(access, endPoint); 
        } 

        internal void AddPermission(NetworkAccess access, EndpointPermission endPoint) { 
            if (m_noRestriction) {    // Is the permission unrestricted?
                return;             // YES-- then additional endpoints have no effect
            }
            if ((access & NetworkAccess.Connect) != 0) 
                    m_connectList.Add(endPoint);
            if ((access & NetworkAccess.Accept) != 0) 
                    m_acceptList.Add(endPoint); 
        }
 
        // IUnrestrictedPermission interface methods
        /// 
        ///    
        ///       Checks the overall permission state of the object. 
        ///    
        ///  
        public bool IsUnrestricted() { 
            return m_noRestriction;
        } 

        // IPermission interface methods
        /// 
        ///     
        ///       Creates
        ///       a copy of a  instance. 
        ///     
        /// 
        public override IPermission Copy() { 

            SocketPermission sp = new SocketPermission(m_noRestriction);

            sp.m_connectList = (ArrayList)m_connectList.Clone(); 
            sp.m_acceptList = (ArrayList)m_acceptList.Clone();
                        return sp; 
        } 

        private bool FindSubset(ArrayList source, ArrayList target) { 
            foreach (EndpointPermission e in source) {

                bool found = false;
 
                foreach (EndpointPermission ee in target) {
                    if (e.SubsetMatch(ee)) { 
                        found = true; 
                        break;
                    } 
                }
                if (!found) {
                    return false;
                } 
            }
            return true; 
        } 

        ///  
        /// Returns the logical union between two  instances.
        /// 
        public override IPermission Union(IPermission target) {
            // Pattern suggested by Security engine 
            if (target==null) {
                return this.Copy(); 
            } 
            SocketPermission other = target as SocketPermission;
            if(other == null) { 
                throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
            }
            if (m_noRestriction || other.m_noRestriction) {
                return new SocketPermission(true); 
            }
            SocketPermission result = (SocketPermission)other.Copy(); 
 
            for (int i = 0; i < m_connectList.Count; i++) {
                result.AddPermission(NetworkAccess.Connect, (EndpointPermission)m_connectList[i]); 
            }
            for (int i = 0; i < m_acceptList.Count; i++) {
                result.AddPermission(NetworkAccess.Accept, (EndpointPermission)m_acceptList[i]);
            } 
            return result;
        } 
 
        /// 
        ///     
        ///       Returns the logical intersection between two  instances.
        ///    
        /// 
        public override IPermission Intersect(IPermission target) { 
            // Pattern suggested by Security engine
            if (target == null) { 
                return null; 
            }
 
            SocketPermission other = target as SocketPermission;
            if(other == null) {
                throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
            } 

            SocketPermission result; 
            if (m_noRestriction) { 
                result = (SocketPermission)(other.Copy());
            } 
            else if (other.m_noRestriction) {
                result = (SocketPermission)(this.Copy());
            }
            else { 
                result = new SocketPermission(false);
                intersectLists(m_connectList, other.m_connectList, result.m_connectList); 
                intersectLists(m_acceptList, other.m_acceptList, result.m_acceptList); 
            }
 
            // return null if resulting permission is restricted and empty
            if (!result.m_noRestriction &&
                result.m_connectList.Count == 0 && result.m_acceptList.Count == 0) {
                return null; 
            }
            return result; 
        } 

        ///  
        /// Compares two  instances.
        /// 
        public override bool IsSubsetOf(IPermission target) {
            // Pattern suggested by security engine 
            if (target == null) {
                return (m_noRestriction == false && m_connectList.Count == 0 && m_acceptList.Count == 0); 
            } 

            SocketPermission other = target as SocketPermission; 
            if (other == null) {
                throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
            }
 
            if (other.IsUnrestricted()) {
                return true; 
            } else if (this.IsUnrestricted()) { 
                return false;
            } else if (this.m_acceptList.Count + this.m_connectList.Count ==0) { 
                return true;
            } else if (other.m_acceptList.Count + other.m_connectList.Count ==0) {
                return false;
            } 

            bool result = false; 
            try { 
                if (FindSubset(m_connectList, other.m_connectList) &&
                    FindSubset(m_acceptList, other.m_acceptList)) { 
                    result = true;
                }
            }
            finally { 
                //  This is around a back door into DNS
                //  Security engine will call isSubsetOf and probably have 
                //  DNS permission asserted. We call DNS resolve. 
                //  Before return do cleanup of DNS results.
 
                //  Only "this" needs cleanup, the policy object is not available for
                //  an application to look at.
                this.CleanupDNS();
            } 

            return result; 
        } 

        // 
        //This is to cleanup DNS resolution results
        //
        private void CleanupDNS() {
            foreach(EndpointPermission e in m_connectList) { 
                //DNS hostnames never produce 'cached=true'
                if (e.cached) { 
                    continue; 
                }
                e.address = null; 
            }

            foreach(EndpointPermission e in m_acceptList) {
                //DNS hostnames never produce 'cached=true' 
                if (e.cached) {
                    continue; 
                } 
                e.address = null;
            } 
        }

        /// 
        ///  
        public override void FromXml(SecurityElement securityElement) {
            if (securityElement == null) { 
 
                //
                // null SecurityElement 
                //

                throw new ArgumentNullException("securityElement");
            } 
            if (!securityElement.Tag.Equals("IPermission")) {
 
                // 
                // SecurityElement must be a permission element
                // 

                throw new ArgumentException(SR.GetString(SR.net_not_ipermission), "securityElement");
            }
 
            string className = securityElement.Attribute("class");
 
            if (className == null) { 

                // 
                // SecurityElement must be a permission element for this type
                //

                throw new ArgumentException(SR.GetString(SR.net_no_classname), "securityElement"); 
            }
            if (className.IndexOf(this.GetType().FullName) < 0) { 
 
                //
                // SecurityElement must be a permission element for this type 
                //

                throw new ArgumentException(SR.GetString(SR.net_no_typename), "securityElement");
            } 

            // 
            // Start recovering the state from XML encoding 
            //
 
            initialize();


            String str = securityElement.Attribute("Unrestricted"); 

            if (str != null) { 
                m_noRestriction = (0 == string.Compare( str, "true", StringComparison.OrdinalIgnoreCase )); 
                if(m_noRestriction)
                    return; 
            }

            m_noRestriction = false;
            m_connectList = new ArrayList(); 
            m_acceptList = new ArrayList();
 
            SecurityElement et = securityElement.SearchForChildByTag("ConnectAccess"); 
            if (et != null) {
                ParseAddXmlElement(et, m_connectList, "ConnectAccess, "); 
            }
            et = securityElement.SearchForChildByTag("AcceptAccess");
            if (et != null) {
                ParseAddXmlElement(et, m_acceptList, "AcceptAccess, "); 
            }
        } 
 
        private static void ParseAddXmlElement(SecurityElement et, ArrayList listToAdd, string accessStr) {
 
            foreach(SecurityElement uriElem in et.Children) {
                if (uriElem.Tag.Equals("ENDPOINT")) {
                    Hashtable attributes = uriElem.Attributes;
                    string tmpStr; 

                    try { 
                        tmpStr = attributes["host"] as string; 
                    }
                    catch{ 
                        tmpStr = null;
                    }

                    if (tmpStr == null) { 
                        throw new ArgumentNullException(accessStr + "host");
                    } 
                    string host = tmpStr; 

                    try { 
                        tmpStr = attributes["transport"] as string;
                    }
                    catch{
                        tmpStr = null; 
                    }
                    if (tmpStr == null) { 
                        throw new ArgumentNullException(accessStr + "transport"); 
                    }
                    TransportType transport; 
                    try {
                        transport = (TransportType) Enum.Parse(typeof(TransportType), tmpStr, true);
                    }
                    catch (Exception exception) { 
                        if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
 		                    throw; 
	                    } 
                        throw new ArgumentException(accessStr + "transport", exception);
                    } 
                    catch {
                        throw new ArgumentException(accessStr + "transport", new Exception(SR.GetString(SR.net_nonClsCompliantException)));
                    }
 
                    try {
                        tmpStr = attributes["port"] as string; 
                    } 
                    catch{
                        tmpStr = null; 
                    }
                    if (tmpStr == null) {
                        throw new  ArgumentNullException(accessStr + "port");
                    } 
                    if (string.Compare(tmpStr, "All", StringComparison.OrdinalIgnoreCase ) == 0) {
                        tmpStr = "-1"; 
                    } 
                    int port;
                    try { 
                        port = Int32.Parse(tmpStr, NumberFormatInfo.InvariantInfo);
                    }
                    catch (Exception exception) {
                        if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) { 
 		                    throw;
 	                    } 
                        throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, accessStr + "port", tmpStr), exception); 
                    }
                    catch { 
                        throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, accessStr + "port", tmpStr), new Exception(SR.GetString(SR.net_nonClsCompliantException)));
                    }

                    if (!ValidationHelper.ValidateTcpPort(port) && port != SocketPermission.AllPorts) { 
                        throw new ArgumentOutOfRangeException(SR.GetString(SR.net_perm_invalid_val, accessStr + "port", tmpStr));
                    } 
 

                    listToAdd.Add(new EndpointPermission(host, port , transport)); 
                }
                else {
                    // improper tag found, just ignore
                } 
            }
        } 
 
        /// 
        ///    [To be supplied.] 
        /// 
        public override SecurityElement ToXml() {

            SecurityElement securityElement = new SecurityElement( "IPermission" ); 

            securityElement.AddAttribute("class", this.GetType().FullName + ", " + this.GetType().Module.Assembly.FullName.Replace( '\"', '\'' )); 
            securityElement.AddAttribute("version", "1"); 

            if (!IsUnrestricted()) { 
                if (m_connectList.Count > 0) {

                    SecurityElement permList = new SecurityElement("ConnectAccess");
                    foreach(EndpointPermission permission in m_connectList) { 
                        SecurityElement endpoint = new SecurityElement("ENDPOINT");
                        endpoint.AddAttribute("host", permission.Hostname); 
                        endpoint.AddAttribute("transport", permission.Transport.ToString()); 
                        endpoint.AddAttribute("port",   permission.Port != AllPorts?
                                                        permission.Port.ToString(NumberFormatInfo.InvariantInfo): "All"); 
                        permList.AddChild(endpoint);
                    }
                    securityElement.AddChild(permList);
                } 

                if (m_acceptList.Count > 0) { 
 
                    SecurityElement permList = new SecurityElement("AcceptAccess");
                    foreach(EndpointPermission permission in m_acceptList) { 
                        SecurityElement endpoint = new SecurityElement("ENDPOINT");
                        endpoint.AddAttribute("host", permission.Hostname);
                        endpoint.AddAttribute("transport", permission.Transport.ToString());
                        endpoint.AddAttribute("port",   permission.Port != AllPorts? 
                                                        permission.Port.ToString(NumberFormatInfo.InvariantInfo): "All");
                        permList.AddChild(endpoint); 
                    } 
                    securityElement.AddChild(permList);
                } 
            }
            else {
                securityElement.AddAttribute("Unrestricted", "true");
            } 
            return securityElement;
        } 
 
        private void initialize() {
            m_noRestriction = false; 
            m_connectList = new ArrayList();
            m_acceptList = new ArrayList();
        }
 
        private static void intersectLists(ArrayList A, ArrayList B, ArrayList result) {
            // The optimization is done according to the following truth 
            // (A|B|C) intersect (B|C|E|D)) == B|C|(A inter E)|(A inter D) 
            //
            // We also check on any duplicates in the result 


            bool[] aDone=new bool[A.Count];            //used to avoid duplicates in result
            bool[] bDone=new bool[B.Count]; 
            int ia=0;
            int ib=0; 
            // Round 1st 
            // Getting rid of same permissons in the input arrays (assuming X /\ X = X)
            foreach (EndpointPermission a in  A) { 
                ib = 0;
                foreach (EndpointPermission b in  B) {
                    // check to see if b is in the result already
                    if (!bDone[ib]) { 
                        //if both elements are the same, copy it into result
                        if (a.Equals(b)) { 
                            result.Add(a); 
                            aDone[ia]=bDone[ib]=true;
                            //since permissions are ORed we can break and go to the next A 
                            break;
                        }
                    }
                    ++ib; 
                } //foreach b in B
                ++ia; 
            } //foreach a in A 

            ia = 0; 
            // Round second
            // Grab only intersections of objects not found in both A and B
            foreach (EndpointPermission a in  A) {
 
                if (!aDone[ia]) {
                    ib = 0; 
                    foreach(EndpointPermission b in B) { 
                        if (!bDone[ib]) {
                            EndpointPermission intesection = a.Intersect(b); 
                            if (intesection != null) {
                                bool found = false;
                                // check to see if we already have the same result
                                foreach (EndpointPermission  res in result) { 
                                    if (res.Equals(intesection)) {
                                        found = true; 
                                        break; 
                                    }
                                } 
                                if (!found) {
                                    result.Add(intesection);
                                }
                            } 
                        } //!Done[ib]
                        ++ib; 
                    } //foreach b in B 
                } //!Done[ia]
                ++ia; 
            } //foreach a in A
        }

    }// class SocketPermission 

 
    ///  
    ///       Represents an element of SocketPermission object contents.
    ///  
    [Serializable]
    public class EndpointPermission {

        // 
        // <
 
 

 

        internal String hostname;
        internal int port;
        internal TransportType transport; 
        internal bool wildcard;
        internal IPAddress[] address; 
        internal bool cached = false; 

        private static char[] DotSeparator = new char[] {'.'}; 
        private const String encSeperator = "#";

        /// 
        ///     
        ///       Returns the hostname part of EndpointPermission object
        ///     
        ///  
        public String           Hostname        { get {return hostname;}}
 
        /// 
        ///    
        ///       Returns the transport of EndpointPermission object
        ///     
        /// 
        public TransportType    Transport       { get {return transport;}} 
 
        /// 
        ///     
        ///       Returns the Port part of EndpointPermission object
        ///    
        /// 
        public int              Port            { get {return port;}} 
        //
        // < 
 

 


        internal EndpointPermission(String epname, int port, TransportType trtype) {
 
            if (CheckEndPointName(epname) == EndPointType.Invalid) {
                throw new ArgumentException(SR.GetString(SR.net_perm_epname, epname), "epname"); 
            } 
            if (!ValidationHelper.ValidateTcpPort(port) && port != SocketPermission.AllPorts) {
                throw new ArgumentOutOfRangeException(SR.GetString(SR.net_perm_invalid_val, "Port", port.ToString(NumberFormatInfo.InvariantInfo))); 
            }

            hostname = epname;
            this.port = port; 
            transport = trtype;
            wildcard = false; 
        } 

        // 
        // This is ONLY a syntatic check on equality, hostnames are compared as strings!
        //
        public override bool Equals(object obj) {
 
            EndpointPermission ep = (EndpointPermission)obj;
 
            if (String.Compare(hostname, ep.hostname, StringComparison.OrdinalIgnoreCase ) != 0) { 
                return false;
            } 
            if (port != ep.port) {
                return false;
            }
            if (transport != ep.transport) { 
                return false;
            } 
            return true; 
        }
 
        public override int GetHashCode() {
            return ToString().GetHashCode();
        }
 
        //
        // < 
 

        internal bool IsDns { 
            get {
                if (IsValidWildcard) {
                    return false;
                } 
                return CheckEndPointName(hostname) == EndPointType.DnsOrWildcard;
            } 
        } 

 
        //
        // In this version wildcards are only allowed over IP ranges
        // not DNS names. For example "*.microsoft.com" is not allowed
        // A valid wildcard will have exactly three periods 
        //IPv6 wildcards are NOT supported
        // 
        private bool IsValidWildcard { 
            get {
 
                int len = hostname.Length;

                //
                // Check minimum length 
                //
 
                if (len < 3) { 
                    return false;
                } 

                //
                // First and last characters cannot be periods
                // 

                if ((hostname[0] == '.') || (hostname[len - 1] == '.')) { 
                    return false; 
                }
 
                int dotCount = 0;
                int anyCount = 0;

                for (int i = 0; i < hostname.Length; i++) { 
                    if (hostname[i] == '.') {
                        dotCount++; 
                    } 
                    else if (hostname[i] == '*') {
                        ++anyCount; 
                    }
                    else if (!Char.IsDigit(hostname[i])) {  // Not a digit?
                        return false;                       // Reject wildcard
                    } 
                }
                return (dotCount == 3) && (anyCount > 0); 
            } 
        }
 
        internal bool MatchAddress(EndpointPermission e) {

            // For Asp.Net config we made it valid empty string in a hostname,
            // but it will match to nothing. 
            if(this.Hostname.Length == 0 || e.Hostname.Length == 0) {
                return false; 
            } 

            // 
            // This is a fix for INADDR_ANY in Bind()
            // if this.Hostname == "0.0.0.0" then it matches only to e.Hostname="*.*.*.*"
            //
            // The reason is to not pass "0.0.0.0" into Resolve() 
            if(this.Hostname.Equals("0.0.0.0"))
            { 
                if(e.Hostname.Equals("*.*.*.*") || e.Hostname.Equals("0.0.0.0")) 
                    return true;
                return false; 
            }

            if (IsDns && e.IsDns) {
 
                //
                // < 
 

 
                return (String.Compare(hostname, e.hostname, StringComparison.OrdinalIgnoreCase ) == 0);
            }
            Resolve();
            e.Resolve(); 

            // 
            // if Resolve() didn't work for some reason then we're out of luck 
            //
 
            if (((address == null) && !wildcard) || ((e.address == null) && !e.wildcard)) {
                return false;
            }
 
            //
            // try matching IP addresses against other wildcard address(es) or 
            // wildcard 
            //
 
            if (this.wildcard && !e.wildcard) {
                return false;                           // as a wildcard I cannot be subset of a host.

            } 
            else if (e.wildcard) {
                if (this.wildcard) { 
                    // check against my _wildcard_ 
                    if (MatchWildcard(e.hostname)) {
                        return true; 
                    }
                }
                else {
                    // check against my _addresses_ 
                    for (int i = 0; i < address.Length; ++i) {
                        if (e.MatchWildcard(address[i].ToString())) { 
                            return true; 
                        }
                    } 
                }
            } else {
                //both are _not_ wildcards
                for (int i = 0; i < address.Length; ++i) { 
                    for (int j = 0; j < e.address.Length; ++j) {
                        if (address[i].Equals(e.address[j])) { 
                            return true; 
                        }
                    } 
                }
            }
            return false;
        } 

        internal bool MatchWildcard(string str) { 
 
            string [] wcPieces = hostname.Split(DotSeparator);
            string [] strPieces = str.Split(DotSeparator); 

            if ((strPieces.Length != 4) || (wcPieces.Length != 4)) {
                return false;
            } 
            for (int i = 0; i < 4; i++) {
                if ((strPieces[i] != wcPieces[i]) && (wcPieces[i] != "*")) { 
                    return false; 
                }
            } 
            return true;
        }

        internal void Resolve() { 

            // 
            // if we already resolved this name then don't do it again 
            //
 
            if (cached) {
                return;
            }
 
            //
            // IP wildcards are not resolved 
            // 

            if (wildcard) { 
                return;
            }

            // 
            // IP addresses with wildcards are allowed in permissions
            // 
 
            if (IsValidWildcard) {
                wildcard = true; 
                cached = true;
                return;
            }
 
            //
            // Check if the permission was specified as numeric IP. 
            // 
            IPAddress ipaddr;
            if (IPAddress.TryParse(hostname, out ipaddr)) 
            {
                address = new IPAddress[1];
                address[0] = ipaddr;
                cached = true; 
                return;
            } 
 
            //
            // Not numeric: use GetHostByName to determine addresses 
            //
            try {
                bool timedOut;
                IPHostEntry ipHostEntry = Dns.InternalResolveFast(hostname,Timeout.Infinite,out timedOut); 
                if(ipHostEntry != null){
                    address = ipHostEntry.AddressList; 
                } 

                // NB: It never caches DNS responses 
                //

            }
            catch (SecurityException) { 
                throw;
            } 
            catch { 
                // ignore second exception
            } 
        }

        internal bool SubsetMatch(EndpointPermission e) {
            return ((transport == e.transport) || (e.transport == TransportType.All)) 
                    && ((port == e.port) || (e.port == SocketPermission.AllPorts) || port == SocketPermission.AnyPort)
                    && MatchAddress(e); 
        } 

        public override String ToString() { 
            return hostname + encSeperator + port + encSeperator + ((int)transport).ToString(NumberFormatInfo.InvariantInfo);
        }

        internal EndpointPermission Intersect(EndpointPermission E) { 

            String commonName=null; 
            TransportType commonTransport; 
            int commonPort;
 
            //
            // Look at the transport
            //
 
            if (transport == E.transport) {           // same transport
                commonTransport = transport; 
            } 
            // NO: check if one of the permissions authorize all transports
            else if (transport == TransportType.All) { 
                commonTransport = E.transport;
            }
            else if (E.transport == TransportType.All) {
                commonTransport = transport; 
            }
            else {   // transport dont match-- intersection is empty 
                return null; 
            }
 
            //
            // Determine common port
            //
 
            if (port == E.port) {
                commonPort = port; 
            } 
            else if (port == SocketPermission.AllPorts) {
                commonPort = E.port; 
            }
            else if (E.port == SocketPermission.AllPorts) {
                commonPort = port;
            } 
            else {
                return null; 
            } 

            //Work out common hostname part 
            //
            // This is a fix for INADDR_ANY in Bind()
            // if this.Hostname == "0.0.0.0" then it matches only to e.Hostname="*.*.*.*"
            // 
            // The reason is to not pass "0.0.0.0" into Resolve()
            if(this.Hostname.Equals("0.0.0.0")) 
            { 
                if(E.Hostname.Equals("*.*.*.*") || E.Hostname.Equals("0.0.0.0"))
                    commonName = this.Hostname;//i.e. 0.0.0.0 
                else
                    return null;
            }
            else if(E.Hostname.Equals("0.0.0.0")) 
            {
                if(this.Hostname.Equals("*.*.*.*") || this.Hostname.Equals("0.0.0.0")) 
                    commonName = E.Hostname; //i.e. 0.0.0.0 
                else
                    return null; 
            }
            else if (IsDns && E.IsDns) {
                //
                // If both are DNS names we compare names as strings 
                //
                if(String.Compare(hostname, E.hostname, StringComparison.OrdinalIgnoreCase ) != 0) { 
                    return null; 
                }
                else { 
                    commonName = hostname;
                }
            }
            else 
            {
                Resolve(); 
                E.Resolve(); 
                //after this step we got both clases updated with valid
                //wildcard and address members. It's safe now to access those members directly 

                //
                // if Resolve() didn't work for some reason then we're out of luck
                // 

                if (((address == null) && !wildcard) || ((E.address == null) && !E.wildcard)) { 
                    return null; 
                }
 

                //
                // Find intersection of address lists
                if(wildcard && E.wildcard) { 
                    string [] wcPieces = hostname.Split(DotSeparator);
                    string [] strPieces = E.hostname.Split(DotSeparator); 
                    string  result=""; 

                    if ((strPieces.Length != 4) || (wcPieces.Length != 4)) { 
                        return null;
                    }
                    for (int i = 0; i < 4; i++) {
                        if(i != 0) { 
                            result+=".";
                        } 
                        if (strPieces[i] == wcPieces[i]) { 
                            result+=strPieces[i];
                        } 
                        else
                        if (strPieces[i] == "*") {
                            result+=wcPieces[i];
                        } 
                        else
                        if (wcPieces[i] == "*") { 
                            result+=strPieces[i]; 
                        }
                        else 
                            return null;
                    }
                    commonName = result;
                }else 
                if (wildcard) {                                                 //if ME is a wildcard
                    // 
                    // 
                    // Check for wildcard IP matching
                    // 
                    for (int i = 0; i < E.address.Length; ++i) {
                        if (MatchWildcard(E.address[i].ToString())) {
                            commonName = E.hostname;    //SHE fits into my wildcard
                            break; 
                        }
                    } 
                } 
                else if (E.wildcard) {                                   //if SHE is a wildcard
                    for (int i = 0; i < address.Length; ++i) { 
                        if (E.MatchWildcard(address[i].ToString())) {
                            commonName = hostname;      //ME fit  into her wildcard
                            break;
                        } 
                    }
                } 
                else 
                {
                    // 
                    // Not wildcard: check aginst  IP addresses list
                    //

                    if (address == E.address) {                 // they both are NOT null (already checked) 
                        commonName = hostname;
                    } 
 
                    //
                    // Search the IP addresses for match 
                    //
                    for (int i = 0; commonName == null && i < address.Length; i++) {
                        for (int k = 0; k < E.address.Length; k++) {
                            if (address[i].Equals(E.address[k])) { 
                                commonName = hostname;
                                break; 
                            } 
                        }
                    } 
                }
                if(commonName == null) {
                    return null;
                } 
            }
 
            return new EndpointPermission(commonName, commonPort, commonTransport); 
        }
/* 
FROM RFC 952
------------
ASSUMPTIONS
1   A "name" (Net, Host, Gateway, or Domain name) is a text string up 
    to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus sign (-), and period (.).
    Note that periods are only allowed when they serve to delimit components of "domain style names". 
    (See RFC-921, "Domain Name System Implementation Schedule", for background). 
    No blank or space characters are permitted as part of a name.
    No distinction is made between upper and lower case. 
    The first character must be an alpha character.
    The last character must not be a minus sign or period.
    Single character names or nicknames are not allowed.
 
    Implementaion below is relaxed in terms of:
    - Hostname may start with a digit (as per RFC1123 ) 
    - Hostname may contain '_' character (historical Inet issue) 
    - Hostname may be a single-character string (historical Inet issue)
    - Hostname may contain '*' as a wildcard for an EndPointPermission 
    - Hostname may be empty (to support config templates)
    - Hostname may be an IPv6 string comprised of A-F, 0-9, '.', ':', and '%' chars
*/
    private enum EndPointType { 
            Invalid,
            IPv6, 
            DnsOrWildcard, 
            IPv4
    }; 

    private static EndPointType CheckEndPointName(string name) {
        if (name == null) {
            return EndPointType.Invalid; 
        }
        bool isIPv6       = false; 
        bool isDnsOrWC    = false; 
        bool isHexLetter  = false;
        for(int i=0; i < name.Length; ++i) { 
            char ch = name[i];
            switch(ch) {
            case '.':   //note _all_ dots name is an error
                        continue; 
            case '-':   //if _all_ chars are those we call Dns (to confirm error)
            case '_': 
            case '*':   isDnsOrWC = true; 
                        continue;
            case ':': 
            case '%':   isIPv6 = true;
                        continue;
            default:    break;
            } 

            //Check on letters but NOT hex digits 
            if ((ch > 'f' && ch <= 'z') || (ch > 'F' && ch <= 'Z')) { 
                isDnsOrWC = true;
                continue; 
            }
            //Check on HEX letters
            if((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
                isHexLetter = true; 
                continue;
            } 
            //Here only digits left (others are invalid) 
            if (!(ch >= '0' && ch <= '9'))
                return EndPointType.Invalid; 
        }

        // The logic is (solely for the purpose of SocketPermssion class)
        //  isIPv6 && isDnsOrWC   = EndPointType.Invalid 
        //  isIPv6 && !isDnsOrWC  = EndPointType.IPv6
        //  !isIPv6 && isDnsOrWC  = EndPointType.DnsOrWildcard 
        //  !isIPv6 && !isDnsOrWC && isHexLetter = EndPointType.DnsOrWildcard; 
        //  else = EndPointType.IPv4
        return isIPv6 ? (isDnsOrWC? EndPointType.Invalid: EndPointType.IPv6) 
                      : (isDnsOrWC? EndPointType.DnsOrWildcard :
                                    isHexLetter? EndPointType.DnsOrWildcard :EndPointType.IPv4);
    }
 

    } // class EndpointPermission 
 

} // namespace System.Net 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK