a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
350 lines
8.8 KiB
C#
350 lines
8.8 KiB
C#
//
|
|
// System.Net.EndpointPermission.cs
|
|
//
|
|
// Author:
|
|
// Lawrence Pit (loz@cable.a2000.nl)
|
|
//
|
|
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Security;
|
|
using System.Security.Permissions;
|
|
|
|
namespace System.Net
|
|
{
|
|
[Serializable]
|
|
public class EndpointPermission // too bad about the lowercase p, not consistent with IPEndPoint ;)
|
|
{
|
|
private static char [] dot_char = new char [] { '.' };
|
|
|
|
// Fields
|
|
private string hostname;
|
|
private int port;
|
|
private TransportType transport;
|
|
|
|
private bool resolved;
|
|
private bool hasWildcard;
|
|
private IPAddress [] addresses;
|
|
|
|
// Constructors
|
|
internal EndpointPermission (string hostname,
|
|
int port,
|
|
TransportType transport) : base ()
|
|
{
|
|
if (hostname == null)
|
|
throw new ArgumentNullException ("hostname");
|
|
this.hostname = hostname;
|
|
this.port = port;
|
|
this.transport = transport;
|
|
this.resolved = false;
|
|
this.hasWildcard = false;
|
|
this.addresses = null;
|
|
}
|
|
|
|
// Properties
|
|
|
|
public string Hostname {
|
|
get { return hostname; }
|
|
}
|
|
|
|
public int Port {
|
|
get { return port; }
|
|
}
|
|
|
|
public TransportType Transport {
|
|
get { return transport; }
|
|
}
|
|
|
|
// Methods
|
|
|
|
public override bool Equals (object obj)
|
|
{
|
|
EndpointPermission epp = obj as EndpointPermission;
|
|
return ((epp != null) &&
|
|
(this.port == epp.port) &&
|
|
(this.transport == epp.transport) &&
|
|
(String.Compare (this.hostname, epp.hostname, true) == 0));
|
|
}
|
|
|
|
public override int GetHashCode ()
|
|
{
|
|
return ToString ().GetHashCode ();
|
|
}
|
|
|
|
public override string ToString ()
|
|
{
|
|
return hostname + "#" + port + "#" + (int) transport;
|
|
}
|
|
|
|
// Internal & Private Methods
|
|
|
|
internal bool IsSubsetOf (EndpointPermission perm)
|
|
{
|
|
if (perm == null)
|
|
return false;
|
|
|
|
if (perm.port != SocketPermission.AllPorts &&
|
|
this.port != perm.port)
|
|
return false;
|
|
|
|
if (perm.transport != TransportType.All &&
|
|
this.transport != perm.transport)
|
|
return false;
|
|
|
|
this.Resolve ();
|
|
perm.Resolve ();
|
|
|
|
if (this.hasWildcard) {
|
|
if (perm.hasWildcard)
|
|
return IsSubsetOf (this.hostname, perm.hostname);
|
|
else
|
|
return false;
|
|
}
|
|
|
|
if (this.addresses == null)
|
|
return false;
|
|
|
|
if (perm.hasWildcard)
|
|
// a bit dubious... should they all be a subset or is one
|
|
// enough in this case?
|
|
foreach (IPAddress addr in this.addresses)
|
|
if (IsSubsetOf (addr.ToString (), perm.hostname))
|
|
return true;
|
|
|
|
if (perm.addresses == null)
|
|
return false;
|
|
|
|
// a bit dubious... should they all be a subset or is one
|
|
// enough in this case?
|
|
foreach (IPAddress addr in perm.addresses)
|
|
if (IsSubsetOf (this.hostname, addr.ToString ()))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
private bool IsSubsetOf (string addr1, string addr2)
|
|
{
|
|
string [] h1 = addr1.Split (dot_char);
|
|
string [] h2 = addr2.Split (dot_char);
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
int part1 = ToNumber (h1 [i]);
|
|
if (part1 == -1)
|
|
return false;
|
|
|
|
int part2 = ToNumber (h2 [i]);
|
|
if (part2 == -1)
|
|
return false;
|
|
if (part1 == 256)
|
|
continue;
|
|
if (part1 != part2 && part2 != 256)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
internal EndpointPermission Intersect (EndpointPermission perm)
|
|
{
|
|
if (perm == null)
|
|
return null;
|
|
|
|
int _port;
|
|
if (this.port == perm.port)
|
|
_port = this.port;
|
|
else if (this.port == SocketPermission.AllPorts)
|
|
_port = perm.port;
|
|
else if (perm.port == SocketPermission.AllPorts)
|
|
_port = this.port;
|
|
else
|
|
return null;
|
|
|
|
TransportType _transport;
|
|
if (this.transport == perm.transport)
|
|
_transport = this.transport;
|
|
else if (this.transport == TransportType.All)
|
|
_transport = perm.transport;
|
|
else if (perm.transport == TransportType.All)
|
|
_transport = this.transport;
|
|
else
|
|
return null;
|
|
|
|
string _hostname = IntersectHostname (perm);
|
|
|
|
if (_hostname == null)
|
|
return null;
|
|
|
|
if (!this.hasWildcard)
|
|
return this;
|
|
|
|
if (!perm.hasWildcard)
|
|
return perm;
|
|
|
|
EndpointPermission newperm = new EndpointPermission (_hostname, _port, _transport);
|
|
newperm.hasWildcard = true;
|
|
newperm.resolved = true;
|
|
return newperm;
|
|
}
|
|
|
|
private string IntersectHostname (EndpointPermission perm)
|
|
{
|
|
if (this.hostname == perm.hostname)
|
|
return this.hostname;
|
|
|
|
this.Resolve ();
|
|
perm.Resolve ();
|
|
|
|
string _hostname = null;
|
|
|
|
if (this.hasWildcard) {
|
|
if (perm.hasWildcard) {
|
|
_hostname = Intersect (this.hostname, perm.hostname);
|
|
} else if (perm.addresses != null) {
|
|
for (int j = 0; j < perm.addresses.Length; j++) {
|
|
_hostname = Intersect (this.hostname, perm.addresses [j].ToString ());
|
|
if (_hostname != null)
|
|
break;
|
|
}
|
|
}
|
|
} else if (this.addresses != null) {
|
|
for (int i = 0; i < this.addresses.Length; i++) {
|
|
string thisaddr = this.addresses [i].ToString ();
|
|
if (perm.hasWildcard) {
|
|
_hostname = Intersect (thisaddr, perm.hostname);
|
|
} else if (perm.addresses != null) {
|
|
for (int j = 0; j < perm.addresses.Length; j++) {
|
|
_hostname = Intersect (thisaddr, perm.addresses [j].ToString ());
|
|
if (_hostname != null)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return _hostname;
|
|
}
|
|
|
|
// alas, currently we'll only support IPv4 as that's MS.Net behaviour
|
|
// returns null when both host strings do not intersect
|
|
private string Intersect (string addr1, string addr2)
|
|
{
|
|
string [] h1 = addr1.Split (dot_char);
|
|
string [] h2 = addr2.Split (dot_char);
|
|
|
|
string [] s = new string [7];
|
|
for (int i = 0; i < 4; i++) {
|
|
int part1 = ToNumber (h1 [i]);
|
|
if (part1 == -1)
|
|
return null;
|
|
|
|
int part2 = ToNumber (h2 [i]);
|
|
if (part2 == -1)
|
|
return null;
|
|
|
|
if (part1 == 256)
|
|
s [i << 1] = (part2 == 256) ? "*" : String.Empty + part2;
|
|
else if (part2 == 256)
|
|
s [i << 1] = (part1 == 256) ? "*" : String.Empty + part1;
|
|
else if (part1 == part2)
|
|
s [i << 1] = String.Empty + part1;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
s [1] = s [3] = s [5] = ".";
|
|
return String.Concat (s);
|
|
}
|
|
|
|
// returns 256 if value is a '*' character
|
|
// returns -1 if value isn't a number between 0 and 255
|
|
private int ToNumber (string value)
|
|
{
|
|
if (value == "*")
|
|
return 256;
|
|
|
|
int len = value.Length;
|
|
if (len < 1 || len > 3)
|
|
return -1;
|
|
|
|
int val = 0;
|
|
for (int i = 0; i < len; i++) {
|
|
char c = value [i];
|
|
if ('0' <= c && c <= '9')
|
|
val = checked (val * 10 + (c - '0'));
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
return val <= 255 ? val : -1;
|
|
}
|
|
|
|
internal void Resolve ()
|
|
{
|
|
if (resolved)
|
|
return;
|
|
|
|
bool isHostname = false;
|
|
bool hasWildcard = false;
|
|
this.addresses = null;
|
|
|
|
string [] s = hostname.Split (dot_char);
|
|
|
|
if (s.Length != 4) {
|
|
isHostname = true;
|
|
} else {
|
|
for (int i = 0; i < 4; i++) {
|
|
int quad = ToNumber (s [i]);
|
|
if (quad == -1) {
|
|
isHostname = true;
|
|
break;
|
|
}
|
|
if (quad == 256)
|
|
hasWildcard = true;
|
|
}
|
|
}
|
|
|
|
if (isHostname) {
|
|
this.hasWildcard = false;
|
|
try {
|
|
this.addresses = Dns.GetHostAddresses (hostname);
|
|
} catch (System.Net.Sockets.SocketException) {
|
|
}
|
|
} else {
|
|
this.hasWildcard = hasWildcard;
|
|
if (!hasWildcard) {
|
|
addresses = new IPAddress [1];
|
|
addresses [0] = IPAddress.Parse (hostname);
|
|
}
|
|
}
|
|
|
|
this.resolved = true;
|
|
}
|
|
|
|
internal void UndoResolve ()
|
|
{
|
|
resolved = false;
|
|
}
|
|
}
|
|
}
|