|
|
@@ -0,0 +1,348 @@
|
|
|
+//
|
|
|
+// System.Net.SocketPermission.cs
|
|
|
+//
|
|
|
+// Author:
|
|
|
+// Lawrence Pit ([email protected])
|
|
|
+//
|
|
|
+
|
|
|
+using System;
|
|
|
+using System.Collections;
|
|
|
+using System.Security;
|
|
|
+using System.Security.Permissions;
|
|
|
+
|
|
|
+namespace System.Net
|
|
|
+{
|
|
|
+ [Serializable]
|
|
|
+ public class SocketPermission : CodeAccessPermission, IUnrestrictedPermission
|
|
|
+ {
|
|
|
+ // Fields
|
|
|
+ ArrayList m_acceptList = new ArrayList ();
|
|
|
+ ArrayList m_connectList = new ArrayList ();
|
|
|
+ bool m_noRestriction;
|
|
|
+
|
|
|
+ // Constructors
|
|
|
+ public SocketPermission (PermissionState state) : base ()
|
|
|
+ {
|
|
|
+ m_noRestriction = (state == PermissionState.Unrestricted);
|
|
|
+ }
|
|
|
+
|
|
|
+ public SocketPermission (NetworkAccess access, TransportType transport,
|
|
|
+ string hostName, int portNumber) : base ()
|
|
|
+ {
|
|
|
+ m_noRestriction = false;
|
|
|
+ AddPermission (access, transport, hostName, portNumber);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Fields
|
|
|
+ public const int AllPorts = -1;
|
|
|
+
|
|
|
+ // Properties
|
|
|
+
|
|
|
+ public IEnumerator AcceptList {
|
|
|
+ get { return m_acceptList.GetEnumerator (); }
|
|
|
+ }
|
|
|
+
|
|
|
+ public IEnumerator ConnectList {
|
|
|
+ get { return m_connectList.GetEnumerator (); }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Methods
|
|
|
+
|
|
|
+ public void AddPermission (NetworkAccess access, TransportType transport,
|
|
|
+ string hostName, int portNumber)
|
|
|
+ {
|
|
|
+ if (m_noRestriction)
|
|
|
+ return;
|
|
|
+
|
|
|
+ EndpointPermission permission = new EndpointPermission (hostName, portNumber, transport);
|
|
|
+
|
|
|
+ if (access == NetworkAccess.Accept)
|
|
|
+ m_acceptList.Add (permission);
|
|
|
+ else
|
|
|
+ m_connectList.Add (permission);
|
|
|
+ }
|
|
|
+
|
|
|
+ public override IPermission Copy ()
|
|
|
+ {
|
|
|
+ SocketPermission permission;
|
|
|
+
|
|
|
+ permission = new SocketPermission (m_noRestriction ?
|
|
|
+ PermissionState.Unrestricted :
|
|
|
+ PermissionState.None);
|
|
|
+
|
|
|
+ // as EndpointPermission's are immutable it's safe to do a shallow copy.
|
|
|
+ permission.m_connectList = (ArrayList) this.m_connectList.Clone ();
|
|
|
+ permission.m_acceptList = (ArrayList) this.m_acceptList.Clone ();
|
|
|
+
|
|
|
+ return permission;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override IPermission Intersect (IPermission target)
|
|
|
+ {
|
|
|
+ if (target == null)
|
|
|
+ return null;
|
|
|
+
|
|
|
+ SocketPermission perm = target as SocketPermission;
|
|
|
+ if (perm == null)
|
|
|
+ throw new ArgumentException ("Argument not of type SocketPermission");
|
|
|
+
|
|
|
+ if (m_noRestriction)
|
|
|
+ return IntersectEmpty (perm) ? null : perm.Copy ();
|
|
|
+
|
|
|
+ if (perm.m_noRestriction)
|
|
|
+ return IntersectEmpty (this) ? null : this.Copy ();
|
|
|
+
|
|
|
+ SocketPermission newperm = new SocketPermission (PermissionState.None);
|
|
|
+ Intersect (this.m_connectList, perm.m_connectList, newperm.m_connectList);
|
|
|
+ Intersect (this.m_acceptList, perm.m_acceptList, newperm.m_acceptList);
|
|
|
+ return IntersectEmpty (newperm) ? null : newperm;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool IntersectEmpty (SocketPermission permission)
|
|
|
+ {
|
|
|
+ return !permission.m_noRestriction &&
|
|
|
+ (permission.m_connectList.Count == 0) &&
|
|
|
+ (permission.m_acceptList.Count == 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Intersect (ArrayList list1, ArrayList list2, ArrayList result)
|
|
|
+ {
|
|
|
+ foreach (EndpointPermission perm1 in list1) {
|
|
|
+ foreach (EndpointPermission perm2 in list2) {
|
|
|
+ EndpointPermission perm = perm1.Intersect (perm2);
|
|
|
+ if (perm != null) {
|
|
|
+ // instead of the below it's also okay to simply do:
|
|
|
+ // result.Add (perm);
|
|
|
+ // below is only done to avoid double entries
|
|
|
+ bool replaced = false;
|
|
|
+ for (int i = 0; i < result.Count; i++) {
|
|
|
+ EndpointPermission res = (EndpointPermission) result [i];
|
|
|
+ EndpointPermission resperm = perm.Intersect (res);
|
|
|
+ if (resperm != null) {
|
|
|
+ result [i] = resperm;
|
|
|
+ replaced = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!replaced)
|
|
|
+ result.Add (perm);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public override bool IsSubsetOf (IPermission target)
|
|
|
+ {
|
|
|
+ if (target == null)
|
|
|
+ return (!m_noRestriction && m_connectList.Count == 0 && m_acceptList.Count == 0);
|
|
|
+
|
|
|
+ SocketPermission perm = target as SocketPermission;
|
|
|
+
|
|
|
+ if (perm == null)
|
|
|
+ throw new ArgumentException ("Parameter target must be of type SocketPermission");
|
|
|
+
|
|
|
+ if (perm.m_noRestriction)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ if (this.m_noRestriction)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (this.m_acceptList.Count == 0 && this.m_connectList.Count == 0)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ if (perm.m_acceptList.Count == 0 && perm.m_connectList.Count == 0)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return IsSubsetOf (this.m_connectList, perm.m_connectList)
|
|
|
+ && IsSubsetOf (this.m_acceptList, perm.m_acceptList);
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool IsSubsetOf (ArrayList list1, ArrayList list2)
|
|
|
+ {
|
|
|
+ foreach (EndpointPermission perm1 in list1) {
|
|
|
+ bool issubset = false;
|
|
|
+ foreach (EndpointPermission perm2 in list2)
|
|
|
+ if (perm1.IsSubsetOf (perm2)) {
|
|
|
+ issubset = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!issubset)
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool IsUnrestricted ()
|
|
|
+ {
|
|
|
+ return m_noRestriction;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+
|
|
|
+ SocketPermission s = new SocketPermission (NetworkAccess.Connect, TransportType.Tcp, "www.google.com", 80);
|
|
|
+ s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", 8080);
|
|
|
+ s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", SocketPermission.AllPorts);
|
|
|
+ // s = new SocketPermission (PermissionState.None);
|
|
|
+ SecurityElement sec = s.ToXml ();
|
|
|
+ Console.WriteLine (sec.ToString ());
|
|
|
+
|
|
|
+ This is sample xml output:
|
|
|
+
|
|
|
+ <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
|
|
|
+ version="1">
|
|
|
+ <ConnectAccess>
|
|
|
+ <ENDPOINT host="www.google.com"
|
|
|
+ transport="Tcp"
|
|
|
+ port="80"/>
|
|
|
+ </ConnectAccess>
|
|
|
+ <AcceptAccess>
|
|
|
+ <ENDPOINT host="localhost"
|
|
|
+ transport="All"
|
|
|
+ port="8080"/>
|
|
|
+ <ENDPOINT host="localhost"
|
|
|
+ transport="All"
|
|
|
+ port="All"/>
|
|
|
+ </AcceptAccess>
|
|
|
+ </IPermission>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ This is a sample unrestricted socketpermission, no matter how many permissions you add:
|
|
|
+
|
|
|
+ <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
|
|
|
+ version="1"
|
|
|
+ Unrestricted="true"/>
|
|
|
+
|
|
|
+
|
|
|
+ This is a sample constructed restricted socketpermission with no permissions added:
|
|
|
+
|
|
|
+ <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
|
|
|
+ version="1"/>
|
|
|
+ */
|
|
|
+ public override SecurityElement ToXml ()
|
|
|
+ {
|
|
|
+
|
|
|
+ SecurityElement root = new SecurityElement ("IPermission");
|
|
|
+
|
|
|
+ root.AddAttribute ("class", this.GetType ().FullName + ", " +
|
|
|
+ "System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
|
|
|
+
|
|
|
+/*
|
|
|
+GetType ().Module doesn't work yet with Mono.. (2002-04-27)
|
|
|
+We need to do it as below though, because this class can be extended
|
|
|
+
|
|
|
+ root.AddAttribute ("class", this.GetType ().FullName + ", " +
|
|
|
+ this.GetType ().Module.Assembly.FullName);
|
|
|
+*/
|
|
|
+ root.AddAttribute ("version", "1");
|
|
|
+ if (m_noRestriction) {
|
|
|
+ root.AddAttribute ("Unrestricted", "true");
|
|
|
+ return root;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.m_connectList.Count > 0)
|
|
|
+ ToXml (root, "ConnectAccess", m_connectList.GetEnumerator ());
|
|
|
+
|
|
|
+ if (this.m_acceptList.Count > 0)
|
|
|
+ ToXml (root, "AcceptAccess", m_acceptList.GetEnumerator ());
|
|
|
+
|
|
|
+ return root;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ToXml (SecurityElement root, string childName, IEnumerator enumerator)
|
|
|
+ {
|
|
|
+ SecurityElement child = new SecurityElement (childName);
|
|
|
+ while (enumerator.MoveNext ()) {
|
|
|
+ EndpointPermission perm = enumerator.Current as EndpointPermission;
|
|
|
+ SecurityElement grandchild = new SecurityElement ("ENDPOINT");
|
|
|
+ grandchild.AddAttribute ("host", perm.Hostname);
|
|
|
+ grandchild.AddAttribute ("transport", perm.Transport.ToString ());
|
|
|
+ grandchild.AddAttribute ("port",
|
|
|
+ perm.Port == AllPorts
|
|
|
+ ? "All"
|
|
|
+ : ((Int32) perm.Port).ToString ());
|
|
|
+ child.AddChild (grandchild);
|
|
|
+ }
|
|
|
+ root.AddChild (child);
|
|
|
+ }
|
|
|
+
|
|
|
+ public override void FromXml (SecurityElement securityElement)
|
|
|
+ {
|
|
|
+ if (securityElement == null)
|
|
|
+ throw new ArgumentNullException ("securityElement");
|
|
|
+
|
|
|
+ // LAMESPEC: it says to throw an ArgumentNullException in this case
|
|
|
+ if (securityElement.Tag != "IPermission")
|
|
|
+ throw new ArgumentException ("securityElement");
|
|
|
+
|
|
|
+ string classStr = securityElement.Attribute ("class");
|
|
|
+ if (classStr == null || !classStr.StartsWith (this.GetType ().FullName + ","))
|
|
|
+ throw new ArgumentException ("securityElement");
|
|
|
+
|
|
|
+ string unrestricted = securityElement.Attribute ("Unrestricted");
|
|
|
+ if (unrestricted != null) {
|
|
|
+ this.m_noRestriction = (String.Compare (unrestricted, "true", true) == 0);
|
|
|
+ if (this.m_noRestriction)
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.m_noRestriction = false;
|
|
|
+ this.m_connectList = new ArrayList ();
|
|
|
+ this.m_acceptList = new ArrayList ();
|
|
|
+
|
|
|
+ ArrayList children = securityElement.Children;
|
|
|
+ foreach (SecurityElement child in children) {
|
|
|
+ if (child.Tag == "ConnectAccess")
|
|
|
+ FromXml (child.Children, NetworkAccess.Connect);
|
|
|
+ else if (child.Tag == "AcceptAccess")
|
|
|
+ FromXml (child.Children, NetworkAccess.Accept);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void FromXml (ArrayList endpoints, NetworkAccess access)
|
|
|
+ {
|
|
|
+ foreach (SecurityElement endpoint in endpoints) {
|
|
|
+ if (endpoint.Tag != "ENDPOINT")
|
|
|
+ continue;
|
|
|
+ string hostname = endpoint.Attribute ("host");
|
|
|
+ TransportType transport =
|
|
|
+ (TransportType) Enum.Parse (typeof (TransportType),
|
|
|
+ endpoint.Attribute ("transport"),
|
|
|
+ true);
|
|
|
+ string p = endpoint.Attribute ("port");
|
|
|
+ int port = 0;
|
|
|
+ if (p == "All")
|
|
|
+ port = SocketPermission.AllPorts;
|
|
|
+ else
|
|
|
+ port = Int32.Parse (p);
|
|
|
+
|
|
|
+ AddPermission (access, transport, hostname, port);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public override IPermission Union (IPermission target)
|
|
|
+ {
|
|
|
+ // LAMESPEC: according to spec we should throw an
|
|
|
+ // exception when target is null. We'll follow the
|
|
|
+ // behaviour of MS.Net instead of the spec, also
|
|
|
+ // because it matches the Intersect behaviour.
|
|
|
+ if (target == null)
|
|
|
+ return null;
|
|
|
+ // throw new ArgumentNullException ("target");
|
|
|
+
|
|
|
+ SocketPermission perm = target as SocketPermission;
|
|
|
+ if (perm == null)
|
|
|
+ throw new ArgumentException ("Argument not of type SocketPermission");
|
|
|
+
|
|
|
+ if (this.m_noRestriction || perm.m_noRestriction)
|
|
|
+ return new SocketPermission (PermissionState.Unrestricted);
|
|
|
+
|
|
|
+ SocketPermission copy = (SocketPermission) perm.Copy ();
|
|
|
+ copy.m_acceptList.InsertRange (copy.m_acceptList.Count, this.m_acceptList);
|
|
|
+ copy.m_connectList.InsertRange (copy.m_connectList.Count, this.m_connectList);
|
|
|
+
|
|
|
+ return copy;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+}
|