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