1 //------------------------------------------------------------------------------
2 // <copyright file="SocketPermission.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
9 using System.Collections;
10 using System.Security;
11 using System.Security.Permissions;
12 using System.Globalization;
13 using System.Threading;
15 //NOTE: While SocketPermissionAttribute resides in System.DLL,
16 // no classes from that DLL are able to make declarative usage of SocketPermission.
19 // THE syntax of this attribute is as followed
20 // [SocketPermsion(SecurityAction.Assert, Access=Connect, Host=hostname, Transport=Tcp/Udp/All, port=portN/All)]
21 // [SocketPermsion(SecurityAction.Assert, Access=Accept, Host=localname, Transport=Tcp/Udp/All, port=portN/All)]
25 // - hostname is either a DNS hostname OR an IP address 1.2.3.4 or an IP wildcard 1.2.*.*
26 // - protocol is either Tcp, Udp or All
27 // - port is a numeric value or -1 that means "All Ports"
29 // All the properites Host, Protocol and Port must be specified.
30 // "localIP" means that you put here a valid address or DNS name or the localhost
32 // NetworkAccess specifies the scope of permission, i.e. for connecting to remote peer,
33 // or for accepting data on the local resources.
36 [ AttributeUsage( AttributeTargets.Method | AttributeTargets.Constructor |
37 AttributeTargets.Class | AttributeTargets.Struct |
38 AttributeTargets.Assembly,
39 AllowMultiple = true, Inherited = false )]
42 public sealed class SocketPermissionAttribute: CodeAccessSecurityAttribute
44 private string m_access = null;
45 private string m_host = null;
46 private string m_port = null;
47 private string m_transport = null;
49 private const string strAccess = "Access";
50 private const string strConnect = "Connect";
51 private const string strAccept = "Accept";
52 private const string strHost = "Host";
53 private const string strTransport = "Transport";
54 private const string strPort = "Port";
56 public SocketPermissionAttribute( SecurityAction action ): base( action )
60 public string Access {
61 get { return m_access; }
63 if (m_access != null) {
64 throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strAccess, value), "value");
71 get { return m_host; }
74 throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strHost, value), "value");
80 public string Transport {
81 get { return m_transport;}
83 if (m_transport != null) {
84 throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strTransport, value), "value");
94 throw new ArgumentException(SR.GetString(SR.net_perm_attrib_multi, strPort, value), "value");
100 public override IPermission CreatePermission()
102 SocketPermission perm = null;
104 perm = new SocketPermission( PermissionState.Unrestricted);
107 perm = new SocketPermission(PermissionState.None);
108 if (m_access == null) {
109 throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strAccess));
111 if (m_host == null) {
112 throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strHost));
114 if (m_transport == null) {
115 throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strTransport));
117 if (m_port == null) {
118 throw new ArgumentException(SR.GetString(SR.net_perm_attrib_count, strPort));
120 ParseAddPermissions(perm);
126 private void ParseAddPermissions(SocketPermission perm) {
128 NetworkAccess access;
129 if (0 == string.Compare(m_access, strConnect, StringComparison.OrdinalIgnoreCase )) {
130 access = NetworkAccess.Connect;
133 if (0 == string.Compare(m_access, strAccept, StringComparison.OrdinalIgnoreCase )) {
134 access = NetworkAccess.Accept;
137 throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strAccess, m_access));
140 TransportType transport;
142 transport = (TransportType) Enum.Parse(typeof(TransportType), m_transport, true);
144 catch (Exception e) {
145 if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
148 throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strTransport, m_transport), e);
152 if (string.Compare(m_port, "All", StringComparison.OrdinalIgnoreCase ) == 0) {
156 port = Int32.Parse(m_port, NumberFormatInfo.InvariantInfo);
158 catch (Exception e) {
159 if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
162 throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, strPort, m_port), e);
165 if (!ValidationHelper.ValidateTcpPort(port) && port != SocketPermission.AllPorts) {
166 throw new ArgumentOutOfRangeException("port", port, SR.GetString(SR.net_perm_invalid_val, strPort, m_port));
168 perm.AddPermission(access, transport, m_host, port);
176 /// Controls rights to make or accept connections on a transport address.
180 public sealed class SocketPermission : CodeAccessPermission, IUnrestrictedPermission {
182 private ArrayList m_connectList;
183 private ArrayList m_acceptList;
184 private bool m_noRestriction;
189 /// Returns the enumeration of permissions to connect a remote peer.
192 public IEnumerator ConnectList {get {return m_connectList.GetEnumerator();}}
196 /// Returns the enumeration of permissions to accept incoming connections.
199 public IEnumerator AcceptList {get {return m_acceptList.GetEnumerator();}}
204 /// Defines a constant representing all ports.
207 public const int AllPorts = unchecked((int)0xFFFFFFFF);
210 internal const int AnyPort = unchecked((int)0);
214 /// Creates a new instance of the <see cref='System.Net.SocketPermission'/>
215 /// class that passes all demands
216 /// or that fails all demands.
219 public SocketPermission(PermissionState state) {
221 m_noRestriction = (state == PermissionState.Unrestricted);
224 internal SocketPermission(bool free) {
226 m_noRestriction = free;
232 /// Creates a new instance of the SocketPermissions class for the given transport address with the specified permission.
235 public SocketPermission(NetworkAccess access, TransportType transport, String hostName, int portNumber) {
237 m_noRestriction = false;
238 AddPermission(access, transport, hostName, portNumber);
243 /// Adds a permission to the set of permissions for a transport address.
246 public void AddPermission(NetworkAccess access, TransportType transport, string hostName, int portNumber) {
247 if (hostName == null) {
248 throw new ArgumentNullException("hostName");
251 EndpointPermission endPoint = new EndpointPermission(hostName, portNumber, transport);
253 AddPermission(access, endPoint);
256 internal void AddPermission(NetworkAccess access, EndpointPermission endPoint) {
257 if (m_noRestriction) { // Is the permission unrestricted?
258 return; // YES-- then additional endpoints have no effect
260 if ((access & NetworkAccess.Connect) != 0)
261 m_connectList.Add(endPoint);
262 if ((access & NetworkAccess.Accept) != 0)
263 m_acceptList.Add(endPoint);
266 // IUnrestrictedPermission interface methods
269 /// Checks the overall permission state of the object.
272 public bool IsUnrestricted() {
273 return m_noRestriction;
276 // IPermission interface methods
280 /// a copy of a <see cref='System.Net.SocketPermission'/> instance.
283 public override IPermission Copy() {
285 SocketPermission sp = new SocketPermission(m_noRestriction);
287 sp.m_connectList = (ArrayList)m_connectList.Clone();
288 sp.m_acceptList = (ArrayList)m_acceptList.Clone();
292 private bool FindSubset(ArrayList source, ArrayList target) {
293 foreach (EndpointPermission e in source) {
297 foreach (EndpointPermission ee in target) {
298 if (e.SubsetMatch(ee)) {
311 /// <para>Returns the logical union between two <see cref='System.Net.SocketPermission'/> instances.</para>
313 public override IPermission Union(IPermission target) {
314 // Pattern suggested by Security engine
318 SocketPermission other = target as SocketPermission;
320 throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
322 if (m_noRestriction || other.m_noRestriction) {
323 return new SocketPermission(true);
325 SocketPermission result = (SocketPermission)other.Copy();
327 for (int i = 0; i < m_connectList.Count; i++) {
328 result.AddPermission(NetworkAccess.Connect, (EndpointPermission)m_connectList[i]);
330 for (int i = 0; i < m_acceptList.Count; i++) {
331 result.AddPermission(NetworkAccess.Accept, (EndpointPermission)m_acceptList[i]);
338 /// Returns the logical intersection between two <see cref='System.Net.SocketPermission'/> instances.
341 public override IPermission Intersect(IPermission target) {
342 // Pattern suggested by Security engine
343 if (target == null) {
347 SocketPermission other = target as SocketPermission;
349 throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
352 SocketPermission result;
353 if (m_noRestriction) {
354 result = (SocketPermission)(other.Copy());
356 else if (other.m_noRestriction) {
357 result = (SocketPermission)(this.Copy());
360 result = new SocketPermission(false);
361 intersectLists(m_connectList, other.m_connectList, result.m_connectList);
362 intersectLists(m_acceptList, other.m_acceptList, result.m_acceptList);
365 // return null if resulting permission is restricted and empty
366 if (!result.m_noRestriction &&
367 result.m_connectList.Count == 0 && result.m_acceptList.Count == 0) {
374 /// <para>Compares two <see cref='System.Net.SocketPermission'/> instances.</para>
376 public override bool IsSubsetOf(IPermission target) {
377 // Pattern suggested by security engine
378 if (target == null) {
379 return (m_noRestriction == false && m_connectList.Count == 0 && m_acceptList.Count == 0);
382 SocketPermission other = target as SocketPermission;
384 throw new ArgumentException(SR.GetString(SR.net_perm_target), "target");
387 if (other.IsUnrestricted()) {
389 } else if (this.IsUnrestricted()) {
391 } else if (this.m_acceptList.Count + this.m_connectList.Count ==0) {
393 } else if (other.m_acceptList.Count + other.m_connectList.Count ==0) {
399 if (FindSubset(m_connectList, other.m_connectList) &&
400 FindSubset(m_acceptList, other.m_acceptList)) {
405 // This is around a back door into DNS
406 // Security engine will call isSubsetOf and probably have
407 // DNS permission asserted. We call DNS resolve.
408 // Before return do cleanup of DNS results.
410 // Only "this" needs cleanup, the policy object is not available for
411 // an application to look at.
419 //This is to cleanup DNS resolution results
421 private void CleanupDNS() {
422 foreach(EndpointPermission e in m_connectList) {
423 //DNS hostnames never produce 'cached=true'
430 foreach(EndpointPermission e in m_acceptList) {
431 //DNS hostnames never produce 'cached=true'
441 public override void FromXml(SecurityElement securityElement) {
442 if (securityElement == null) {
445 // null SecurityElement
448 throw new ArgumentNullException("securityElement");
450 if (!securityElement.Tag.Equals("IPermission")) {
453 // SecurityElement must be a permission element
456 throw new ArgumentException(SR.GetString(SR.net_not_ipermission), "securityElement");
459 string className = securityElement.Attribute("class");
461 if (className == null) {
464 // SecurityElement must be a permission element for this type
467 throw new ArgumentException(SR.GetString(SR.net_no_classname), "securityElement");
469 if (className.IndexOf(this.GetType().FullName) < 0) {
472 // SecurityElement must be a permission element for this type
475 throw new ArgumentException(SR.GetString(SR.net_no_typename), "securityElement");
479 // Start recovering the state from XML encoding
485 String str = securityElement.Attribute("Unrestricted");
488 m_noRestriction = (0 == string.Compare( str, "true", StringComparison.OrdinalIgnoreCase ));
493 m_noRestriction = false;
494 m_connectList = new ArrayList();
495 m_acceptList = new ArrayList();
497 SecurityElement et = securityElement.SearchForChildByTag("ConnectAccess");
499 ParseAddXmlElement(et, m_connectList, "ConnectAccess, ");
501 et = securityElement.SearchForChildByTag("AcceptAccess");
503 ParseAddXmlElement(et, m_acceptList, "AcceptAccess, ");
507 private static void ParseAddXmlElement(SecurityElement et, ArrayList listToAdd, string accessStr) {
509 foreach(SecurityElement uriElem in et.Children) {
510 if (uriElem.Tag.Equals("ENDPOINT")) {
511 Hashtable attributes = uriElem.Attributes;
515 tmpStr = attributes["host"] as string;
521 if (tmpStr == null) {
522 throw new ArgumentNullException(accessStr + "host");
524 string host = tmpStr;
527 tmpStr = attributes["transport"] as string;
532 if (tmpStr == null) {
533 throw new ArgumentNullException(accessStr + "transport");
535 TransportType transport;
537 transport = (TransportType) Enum.Parse(typeof(TransportType), tmpStr, true);
539 catch (Exception exception) {
540 if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
543 throw new ArgumentException(accessStr + "transport", exception);
547 tmpStr = attributes["port"] as string;
552 if (tmpStr == null) {
553 throw new ArgumentNullException(accessStr + "port");
555 if (string.Compare(tmpStr, "All", StringComparison.OrdinalIgnoreCase ) == 0) {
560 port = Int32.Parse(tmpStr, NumberFormatInfo.InvariantInfo);
562 catch (Exception exception) {
563 if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
566 throw new ArgumentException(SR.GetString(SR.net_perm_invalid_val, accessStr + "port", tmpStr), exception);
569 if (!ValidationHelper.ValidateTcpPort(port) && port != SocketPermission.AllPorts) {
570 throw new ArgumentOutOfRangeException("port", port, SR.GetString(SR.net_perm_invalid_val, accessStr + "port", tmpStr));
574 listToAdd.Add(new EndpointPermission(host, port , transport));
577 // improper tag found, just ignore
583 /// <para>[To be supplied.]</para>
585 public override SecurityElement ToXml() {
587 SecurityElement securityElement = new SecurityElement( "IPermission" );
589 securityElement.AddAttribute("class", this.GetType().FullName + ", " + this.GetType().Module.Assembly.FullName.Replace( '\"', '\'' ));
590 securityElement.AddAttribute("version", "1");
592 if (!IsUnrestricted()) {
593 if (m_connectList.Count > 0) {
595 SecurityElement permList = new SecurityElement("ConnectAccess");
596 foreach(EndpointPermission permission in m_connectList) {
597 SecurityElement endpoint = new SecurityElement("ENDPOINT");
598 endpoint.AddAttribute("host", permission.Hostname);
599 endpoint.AddAttribute("transport", permission.Transport.ToString());
600 endpoint.AddAttribute("port", permission.Port != AllPorts?
601 permission.Port.ToString(NumberFormatInfo.InvariantInfo): "All");
602 permList.AddChild(endpoint);
604 securityElement.AddChild(permList);
607 if (m_acceptList.Count > 0) {
609 SecurityElement permList = new SecurityElement("AcceptAccess");
610 foreach(EndpointPermission permission in m_acceptList) {
611 SecurityElement endpoint = new SecurityElement("ENDPOINT");
612 endpoint.AddAttribute("host", permission.Hostname);
613 endpoint.AddAttribute("transport", permission.Transport.ToString());
614 endpoint.AddAttribute("port", permission.Port != AllPorts?
615 permission.Port.ToString(NumberFormatInfo.InvariantInfo): "All");
616 permList.AddChild(endpoint);
618 securityElement.AddChild(permList);
622 securityElement.AddAttribute("Unrestricted", "true");
624 return securityElement;
627 private void initialize() {
628 m_noRestriction = false;
629 m_connectList = new ArrayList();
630 m_acceptList = new ArrayList();
633 private static void intersectLists(ArrayList A, ArrayList B, ArrayList result) {
634 // The optimization is done according to the following truth
635 // (A|B|C) intersect (B|C|E|D)) == B|C|(A inter E)|(A inter D)
637 // We also check on any duplicates in the result
640 bool[] aDone=new bool[A.Count]; //used to avoid duplicates in result
641 bool[] bDone=new bool[B.Count];
645 // Getting rid of same permissons in the input arrays (assuming X /\ X = X)
646 foreach (EndpointPermission a in A) {
648 foreach (EndpointPermission b in B) {
649 // check to see if b is in the result already
651 //if both elements are the same, copy it into result
654 aDone[ia]=bDone[ib]=true;
655 //since permissions are ORed we can break and go to the next A
666 // Grab only intersections of objects not found in both A and B
667 foreach (EndpointPermission a in A) {
671 foreach(EndpointPermission b in B) {
673 EndpointPermission intesection = a.Intersect(b);
674 if (intesection != null) {
676 // check to see if we already have the same result
677 foreach (EndpointPermission res in result) {
678 if (res.Equals(intesection)) {
684 result.Add(intesection);
695 }// class SocketPermission
699 /// Represents an element of SocketPermission object contents.
702 public class EndpointPermission {
711 internal String hostname;
713 internal TransportType transport;
714 internal bool wildcard;
715 internal IPAddress[] address;
716 internal bool cached = false;
718 private static char[] DotSeparator = new char[] {'.'};
719 private const String encSeperator = "#";
723 /// Returns the hostname part of EndpointPermission object
726 public String Hostname { get {return hostname;}}
730 /// Returns the transport of EndpointPermission object
733 public TransportType Transport { get {return transport;}}
737 /// Returns the Port part of EndpointPermission object
740 public int Port { get {return port;}}
748 internal EndpointPermission(String epname, int port, TransportType trtype) {
750 if (CheckEndPointName(epname) == EndPointType.Invalid) {
751 throw new ArgumentException(SR.GetString(SR.net_perm_epname, epname), "epname");
753 if (!ValidationHelper.ValidateTcpPort(port) && port != SocketPermission.AllPorts) {
754 throw new ArgumentOutOfRangeException("port", SR.GetString(SR.net_perm_invalid_val, "Port", port.ToString(NumberFormatInfo.InvariantInfo)));
764 // This is ONLY a syntatic check on equality, hostnames are compared as strings!
766 public override bool Equals(object obj) {
768 EndpointPermission ep = (EndpointPermission)obj;
770 if (String.Compare(hostname, ep.hostname, StringComparison.OrdinalIgnoreCase ) != 0) {
773 if (port != ep.port) {
776 if (transport != ep.transport) {
782 public override int GetHashCode() {
783 return ToString().GetHashCode();
790 internal bool IsDns {
792 if (IsValidWildcard) {
795 return CheckEndPointName(hostname) == EndPointType.DnsOrWildcard;
801 // In this version wildcards are only allowed over IP ranges
802 // not DNS names. For example "*.microsoft.com" is not allowed
803 // A valid wildcard will have exactly three periods
804 //IPv6 wildcards are NOT supported
806 private bool IsValidWildcard {
809 int len = hostname.Length;
812 // Check minimum length
820 // First and last characters cannot be periods
823 if ((hostname[0] == '.') || (hostname[len - 1] == '.')) {
830 for (int i = 0; i < hostname.Length; i++) {
831 if (hostname[i] == '.') {
834 else if (hostname[i] == '*') {
837 else if (!Char.IsDigit(hostname[i])) { // Not a digit?
838 return false; // Reject wildcard
841 return (dotCount == 3) && (anyCount > 0);
845 internal bool MatchAddress(EndpointPermission e) {
847 // For Asp.Net config we made it valid empty string in a hostname,
848 // but it will match to nothing.
849 if(this.Hostname.Length == 0 || e.Hostname.Length == 0) {
854 // This is a fix for INADDR_ANY in Bind()
855 // if this.Hostname == "0.0.0.0" then it matches only to e.Hostname="*.*.*.*"
857 // The reason is to not pass "0.0.0.0" into Resolve()
858 if(this.Hostname.Equals("0.0.0.0"))
860 if(e.Hostname.Equals("*.*.*.*") || e.Hostname.Equals("0.0.0.0"))
865 if (IsDns && e.IsDns) {
872 return (String.Compare(hostname, e.hostname, StringComparison.OrdinalIgnoreCase ) == 0);
878 // if Resolve() didn't work for some reason then we're out of luck
881 if (((address == null) && !wildcard) || ((e.address == null) && !e.wildcard)) {
886 // try matching IP addresses against other wildcard address(es) or
890 if (this.wildcard && !e.wildcard) {
891 return false; // as a wildcard I cannot be subset of a host.
894 else if (e.wildcard) {
896 // check against my _wildcard_
897 if (MatchWildcard(e.hostname)) {
902 // check against my _addresses_
903 for (int i = 0; i < address.Length; ++i) {
904 if (e.MatchWildcard(address[i].ToString())) {
910 //both are _not_ wildcards
911 for (int i = 0; i < address.Length; ++i) {
912 for (int j = 0; j < e.address.Length; ++j) {
913 if (address[i].Equals(e.address[j])) {
922 internal bool MatchWildcard(string str) {
924 string [] wcPieces = hostname.Split(DotSeparator);
925 string [] strPieces = str.Split(DotSeparator);
927 if ((strPieces.Length != 4) || (wcPieces.Length != 4)) {
930 for (int i = 0; i < 4; i++) {
931 if ((strPieces[i] != wcPieces[i]) && (wcPieces[i] != "*")) {
938 internal void Resolve() {
941 // if we already resolved this name then don't do it again
949 // IP wildcards are not resolved
957 // IP addresses with wildcards are allowed in permissions
960 if (IsValidWildcard) {
967 // Check if the permission was specified as numeric IP.
970 if (IPAddress.TryParse(hostname, out ipaddr))
972 address = new IPAddress[1];
979 // Not numeric: use GetHostByName to determine addresses
982 IPHostEntry ipHostEntry;
983 if (Dns.TryInternalResolve(hostname, out ipHostEntry)) {
984 address = ipHostEntry.AddressList;
987 // NB: It never caches DNS responses
991 catch (SecurityException) {
995 // ignore second exception
999 internal bool SubsetMatch(EndpointPermission e) {
1000 return ((transport == e.transport) || (e.transport == TransportType.All))
1001 && ((port == e.port) || (e.port == SocketPermission.AllPorts) || port == SocketPermission.AnyPort)
1005 public override String ToString() {
1006 return hostname + encSeperator + port + encSeperator + ((int)transport).ToString(NumberFormatInfo.InvariantInfo);
1009 internal EndpointPermission Intersect(EndpointPermission E) {
1011 String commonName=null;
1012 TransportType commonTransport;
1016 // Look at the transport
1019 if (transport == E.transport) { // same transport
1020 commonTransport = transport;
1022 // NO: check if one of the permissions authorize all transports
1023 else if (transport == TransportType.All) {
1024 commonTransport = E.transport;
1026 else if (E.transport == TransportType.All) {
1027 commonTransport = transport;
1029 else { // transport dont match-- intersection is empty
1034 // Determine common port
1037 if (port == E.port) {
1040 else if (port == SocketPermission.AllPorts) {
1041 commonPort = E.port;
1043 else if (E.port == SocketPermission.AllPorts) {
1050 //Work out common hostname part
1052 // This is a fix for INADDR_ANY in Bind()
1053 // if this.Hostname == "0.0.0.0" then it matches only to e.Hostname="*.*.*.*"
1055 // The reason is to not pass "0.0.0.0" into Resolve()
1056 if(this.Hostname.Equals("0.0.0.0"))
1058 if(E.Hostname.Equals("*.*.*.*") || E.Hostname.Equals("0.0.0.0"))
1059 commonName = this.Hostname;//i.e. 0.0.0.0
1063 else if(E.Hostname.Equals("0.0.0.0"))
1065 if(this.Hostname.Equals("*.*.*.*") || this.Hostname.Equals("0.0.0.0"))
1066 commonName = E.Hostname; //i.e. 0.0.0.0
1070 else if (IsDns && E.IsDns) {
1072 // If both are DNS names we compare names as strings
1074 if(String.Compare(hostname, E.hostname, StringComparison.OrdinalIgnoreCase ) != 0) {
1078 commonName = hostname;
1085 //after this step we got both clases updated with valid
1086 //wildcard and address members. It's safe now to access those members directly
1089 // if Resolve() didn't work for some reason then we're out of luck
1092 if (((address == null) && !wildcard) || ((E.address == null) && !E.wildcard)) {
1098 // Find intersection of address lists
1099 if(wildcard && E.wildcard) {
1100 string [] wcPieces = hostname.Split(DotSeparator);
1101 string [] strPieces = E.hostname.Split(DotSeparator);
1104 if ((strPieces.Length != 4) || (wcPieces.Length != 4)) {
1107 for (int i = 0; i < 4; i++) {
1111 if (strPieces[i] == wcPieces[i]) {
1112 result+=strPieces[i];
1115 if (strPieces[i] == "*") {
1116 result+=wcPieces[i];
1119 if (wcPieces[i] == "*") {
1120 result+=strPieces[i];
1125 commonName = result;
1127 if (wildcard) { //if ME is a wildcard
1130 // Check for wildcard IP matching
1132 for (int i = 0; i < E.address.Length; ++i) {
1133 if (MatchWildcard(E.address[i].ToString())) {
1134 commonName = E.hostname; //SHE fits into my wildcard
1139 else if (E.wildcard) { //if SHE is a wildcard
1140 for (int i = 0; i < address.Length; ++i) {
1141 if (E.MatchWildcard(address[i].ToString())) {
1142 commonName = hostname; //ME fit into her wildcard
1150 // Not wildcard: check aginst IP addresses list
1153 if (address == E.address) { // they both are NOT null (already checked)
1154 commonName = hostname;
1158 // Search the IP addresses for match
1160 for (int i = 0; commonName == null && i < address.Length; i++) {
1161 for (int k = 0; k < E.address.Length; k++) {
1162 if (address[i].Equals(E.address[k])) {
1163 commonName = hostname;
1169 if(commonName == null) {
1174 return new EndpointPermission(commonName, commonPort, commonTransport);
1180 1 A "name" (Net, Host, Gateway, or Domain name) is a text string up
1181 to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus sign (-), and period (.).
1182 Note that periods are only allowed when they serve to delimit components of "domain style names".
1183 (See RFC-921, "Domain Name System Implementation Schedule", for background).
1184 No blank or space characters are permitted as part of a name.
1185 No distinction is made between upper and lower case.
1186 The first character must be an alpha character.
1187 The last character must not be a minus sign or period.
1188 Single character names or nicknames are not allowed.
1190 Implementaion below is relaxed in terms of:
1191 - Hostname may start with a digit (as per RFC1123 )
1192 - Hostname may contain '_' character (historical Inet issue)
1193 - Hostname may be a single-character string (historical Inet issue)
1194 - Hostname may contain '*' as a wildcard for an EndPointPermission
1195 - Hostname may be empty (to support config templates)
1196 - Hostname may be an IPv6 string comprised of A-F, 0-9, '.', ':', and '%' chars
1198 private enum EndPointType {
1205 private static EndPointType CheckEndPointName(string name) {
1207 return EndPointType.Invalid;
1209 bool isIPv6 = false;
1210 bool isDnsOrWC = false;
1211 bool isHexLetter = false;
1212 for(int i=0; i < name.Length; ++i) {
1215 case '.': //note _all_ dots name is an error
1217 case '-': //if _all_ chars are those we call Dns (to confirm error)
1219 case '*': isDnsOrWC = true;
1222 case '%': isIPv6 = true;
1227 //Check on letters but NOT hex digits
1228 if ((ch > 'f' && ch <= 'z') || (ch > 'F' && ch <= 'Z')) {
1232 //Check on HEX letters
1233 if((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) {
1237 //Here only digits left (others are invalid)
1238 if (!(ch >= '0' && ch <= '9'))
1239 return EndPointType.Invalid;
1242 // The logic is (solely for the purpose of SocketPermssion class)
1243 // isIPv6 && isDnsOrWC = EndPointType.Invalid
1244 // isIPv6 && !isDnsOrWC = EndPointType.IPv6
1245 // !isIPv6 && isDnsOrWC = EndPointType.DnsOrWildcard
1246 // !isIPv6 && !isDnsOrWC && isHexLetter = EndPointType.DnsOrWildcard;
1247 // else = EndPointType.IPv4
1248 return isIPv6 ? (isDnsOrWC? EndPointType.Invalid: EndPointType.IPv6)
1249 : (isDnsOrWC? EndPointType.DnsOrWildcard :
1250 isHexLetter? EndPointType.DnsOrWildcard :EndPointType.IPv4);
1254 } // class EndpointPermission
1257 } // namespace System.Net