2 // System.Net.EndpointPermission.cs
\r
5 // Lawrence Pit (loz@cable.a2000.nl)
\r
9 // Permission is hereby granted, free of charge, to any person obtaining
\r
10 // a copy of this software and associated documentation files (the
\r
11 // "Software"), to deal in the Software without restriction, including
\r
12 // without limitation the rights to use, copy, modify, merge, publish,
\r
13 // distribute, sublicense, and/or sell copies of the Software, and to
\r
14 // permit persons to whom the Software is furnished to do so, subject to
\r
15 // the following conditions:
\r
17 // The above copyright notice and this permission notice shall be
\r
18 // included in all copies or substantial portions of the Software.
\r
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
30 using System.Collections;
\r
31 using System.Security;
\r
32 using System.Security.Permissions;
\r
34 namespace System.Net
\r
37 public class EndpointPermission // too bad about the lowercase p, not consistent with IPEndPoint ;)
\r
39 private static char [] dot_char = new char [] { '.' };
\r
42 private string hostname;
\r
44 private TransportType transport;
\r
46 private bool resolved;
\r
47 private bool hasWildcard;
\r
48 private IPAddress [] addresses;
\r
51 internal EndpointPermission (string hostname,
\r
53 TransportType transport) : base ()
\r
55 if (hostname == null)
\r
56 throw new ArgumentNullException ("hostname");
\r
57 this.hostname = hostname;
\r
59 this.transport = transport;
\r
60 this.resolved = false;
\r
61 this.hasWildcard = false;
\r
62 this.addresses = null;
\r
67 public string Hostname {
\r
68 get { return hostname; }
\r
72 get { return port; }
\r
75 public TransportType Transport {
\r
76 get { return transport; }
\r
81 public override bool Equals (object obj)
\r
83 EndpointPermission epp = obj as EndpointPermission;
\r
84 return ((epp != null) &&
\r
85 (this.port == epp.port) &&
\r
86 (this.transport == epp.transport) &&
\r
87 (String.Compare (this.hostname, epp.hostname, true) == 0));
\r
90 public override int GetHashCode ()
\r
92 return ToString ().GetHashCode ();
\r
95 public override string ToString ()
\r
97 return hostname + "#" + port + "#" + (int) transport;
\r
100 // Internal & Private Methods
\r
102 internal bool IsSubsetOf (EndpointPermission perm)
\r
107 if (perm.port != SocketPermission.AllPorts &&
\r
108 this.port != perm.port)
\r
111 if (perm.transport != TransportType.All &&
\r
112 this.transport != perm.transport)
\r
118 if (this.hasWildcard) {
\r
119 if (perm.hasWildcard)
\r
120 return IsSubsetOf (this.hostname, perm.hostname);
\r
125 if (this.addresses == null)
\r
128 if (perm.hasWildcard)
\r
129 // a bit dubious... should they all be a subset or is one
\r
130 // enough in this case?
\r
131 foreach (IPAddress addr in this.addresses)
\r
132 if (IsSubsetOf (addr.ToString (), perm.hostname))
\r
135 if (perm.addresses == null)
\r
138 // a bit dubious... should they all be a subset or is one
\r
139 // enough in this case?
\r
140 foreach (IPAddress addr in perm.addresses)
\r
141 if (IsSubsetOf (this.hostname, addr.ToString ()))
\r
147 private bool IsSubsetOf (string addr1, string addr2)
\r
149 string [] h1 = addr1.Split (dot_char);
\r
150 string [] h2 = addr2.Split (dot_char);
\r
152 for (int i = 0; i < 4; i++) {
\r
153 int part1 = ToNumber (h1 [i]);
\r
157 int part2 = ToNumber (h2 [i]);
\r
162 if (part1 != part2 && part2 != 256)
\r
168 internal EndpointPermission Intersect (EndpointPermission perm)
\r
174 if (this.port == perm.port)
\r
176 else if (this.port == SocketPermission.AllPorts)
\r
178 else if (perm.port == SocketPermission.AllPorts)
\r
183 TransportType _transport;
\r
184 if (this.transport == perm.transport)
\r
185 _transport = this.transport;
\r
186 else if (this.transport == TransportType.All)
\r
187 _transport = perm.transport;
\r
188 else if (perm.transport == TransportType.All)
\r
189 _transport = this.transport;
\r
193 string _hostname = IntersectHostname (perm);
\r
195 if (_hostname == null)
\r
198 if (!this.hasWildcard)
\r
201 if (!perm.hasWildcard)
\r
204 EndpointPermission newperm = new EndpointPermission (_hostname, _port, _transport);
\r
205 newperm.hasWildcard = true;
\r
206 newperm.resolved = true;
\r
210 private string IntersectHostname (EndpointPermission perm)
\r
212 if (this.hostname == perm.hostname)
\r
213 return this.hostname;
\r
218 string _hostname = null;
\r
220 if (this.hasWildcard) {
\r
221 if (perm.hasWildcard) {
\r
222 _hostname = Intersect (this.hostname, perm.hostname);
\r
223 } else if (perm.addresses != null) {
\r
224 for (int j = 0; j < perm.addresses.Length; j++) {
\r
225 _hostname = Intersect (this.hostname, perm.addresses [j].ToString ());
\r
226 if (_hostname != null)
\r
230 } else if (this.addresses != null) {
\r
231 for (int i = 0; i < this.addresses.Length; i++) {
\r
232 string thisaddr = this.addresses [i].ToString ();
\r
233 if (perm.hasWildcard) {
\r
234 _hostname = Intersect (thisaddr, perm.hostname);
\r
235 } else if (perm.addresses != null) {
\r
236 for (int j = 0; j < perm.addresses.Length; j++) {
\r
237 _hostname = Intersect (thisaddr, perm.addresses [j].ToString ());
\r
238 if (_hostname != null)
\r
248 // alas, currently we'll only support IPv4 as that's MS.Net behaviour
\r
249 // returns null when both host strings do not intersect
\r
250 private string Intersect (string addr1, string addr2)
\r
252 string [] h1 = addr1.Split (dot_char);
\r
253 string [] h2 = addr2.Split (dot_char);
\r
255 string [] s = new string [7];
\r
256 for (int i = 0; i < 4; i++) {
\r
257 int part1 = ToNumber (h1 [i]);
\r
261 int part2 = ToNumber (h2 [i]);
\r
266 s [i << 1] = (part2 == 256) ? "*" : String.Empty + part2;
\r
267 else if (part2 == 256)
\r
268 s [i << 1] = (part1 == 256) ? "*" : String.Empty + part1;
\r
269 else if (part1 == part2)
\r
270 s [i << 1] = String.Empty + part1;
\r
275 s [1] = s [3] = s [5] = ".";
\r
276 return String.Concat (s);
\r
279 // returns 256 if value is a '*' character
\r
280 // returns -1 if value isn't a number between 0 and 255
\r
281 private int ToNumber (string value)
\r
286 int len = value.Length;
\r
287 if (len < 1 || len > 3)
\r
291 for (int i = 0; i < len; i++) {
\r
292 char c = value [i];
\r
293 if ('0' <= c && c <= '9')
\r
294 val = checked (val * 10 + (c - '0'));
\r
299 return val <= 255 ? val : -1;
\r
302 internal void Resolve ()
\r
307 bool isHostname = false;
\r
308 bool hasWildcard = false;
\r
309 this.addresses = null;
\r
311 string [] s = hostname.Split (dot_char);
\r
313 if (s.Length != 4) {
\r
316 for (int i = 0; i < 4; i++) {
\r
317 int quad = ToNumber (s [i]);
\r
323 hasWildcard = true;
\r
328 this.hasWildcard = false;
\r
330 this.addresses = Dns.GetHostAddresses (hostname);
\r
331 } catch (System.Net.Sockets.SocketException) {
\r
334 this.hasWildcard = hasWildcard;
\r
335 if (!hasWildcard) {
\r
336 addresses = new IPAddress [1];
\r
337 addresses [0] = IPAddress.Parse (hostname);
\r
341 this.resolved = true;
\r
344 internal void UndoResolve ()
\r