2 // System.Net.SocketPermission.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
29 using System.Collections;
\r
30 using System.Security;
\r
31 using System.Security.Permissions;
\r
33 namespace System.Net {
\r
36 public sealed class SocketPermission : CodeAccessPermission, IUnrestrictedPermission
\r
39 ArrayList m_acceptList = new ArrayList ();
\r
40 ArrayList m_connectList = new ArrayList ();
\r
41 bool m_noRestriction;
\r
44 public SocketPermission (PermissionState state) : base ()
\r
46 m_noRestriction = (state == PermissionState.Unrestricted);
\r
49 public SocketPermission (NetworkAccess access, TransportType transport,
\r
50 string hostName, int portNumber) : base ()
\r
52 m_noRestriction = false;
\r
53 AddPermission (access, transport, hostName, portNumber);
\r
57 public const int AllPorts = -1;
\r
61 public IEnumerator AcceptList {
\r
62 get { return m_acceptList.GetEnumerator (); }
\r
65 public IEnumerator ConnectList {
\r
66 get { return m_connectList.GetEnumerator (); }
\r
71 public void AddPermission (NetworkAccess access, TransportType transport,
\r
72 string hostName, int portNumber)
\r
74 if (m_noRestriction)
\r
77 EndpointPermission permission = new EndpointPermission (hostName, portNumber, transport);
\r
79 if (access == NetworkAccess.Accept)
\r
80 m_acceptList.Add (permission);
\r
82 m_connectList.Add (permission);
\r
85 public override IPermission Copy ()
\r
87 SocketPermission permission;
\r
89 permission = new SocketPermission (m_noRestriction ?
\r
90 PermissionState.Unrestricted :
\r
91 PermissionState.None);
\r
93 // as EndpointPermission's are immutable it's safe to do a shallow copy.
\r
94 permission.m_connectList = (ArrayList) this.m_connectList.Clone ();
\r
95 permission.m_acceptList = (ArrayList) this.m_acceptList.Clone ();
\r
100 public override IPermission Intersect (IPermission target)
\r
102 if (target == null)
\r
105 SocketPermission perm = target as SocketPermission;
\r
107 throw new ArgumentException ("Argument not of type SocketPermission");
\r
109 if (m_noRestriction)
\r
110 return IntersectEmpty (perm) ? null : perm.Copy ();
\r
112 if (perm.m_noRestriction)
\r
113 return IntersectEmpty (this) ? null : this.Copy ();
\r
115 SocketPermission newperm = new SocketPermission (PermissionState.None);
\r
116 Intersect (this.m_connectList, perm.m_connectList, newperm.m_connectList);
\r
117 Intersect (this.m_acceptList, perm.m_acceptList, newperm.m_acceptList);
\r
118 return IntersectEmpty (newperm) ? null : newperm;
\r
121 private bool IntersectEmpty (SocketPermission permission)
\r
123 return !permission.m_noRestriction &&
\r
124 (permission.m_connectList.Count == 0) &&
\r
125 (permission.m_acceptList.Count == 0);
\r
128 private void Intersect (ArrayList list1, ArrayList list2, ArrayList result)
\r
130 foreach (EndpointPermission perm1 in list1) {
\r
131 foreach (EndpointPermission perm2 in list2) {
\r
132 EndpointPermission perm = perm1.Intersect (perm2);
\r
133 if (perm != null) {
\r
134 // instead of the below it's also okay to simply do:
\r
135 // result.Add (perm);
\r
136 // below is only done to avoid double entries
\r
137 bool replaced = false;
\r
138 for (int i = 0; i < result.Count; i++) {
\r
139 EndpointPermission res = (EndpointPermission) result [i];
\r
140 EndpointPermission resperm = perm.Intersect (res);
\r
141 if (resperm != null) {
\r
142 result [i] = resperm;
\r
154 public override bool IsSubsetOf (IPermission target)
\r
156 if (target == null)
\r
157 return (!m_noRestriction && m_connectList.Count == 0 && m_acceptList.Count == 0);
\r
159 SocketPermission perm = target as SocketPermission;
\r
162 throw new ArgumentException ("Parameter target must be of type SocketPermission");
\r
164 if (perm.m_noRestriction)
\r
167 if (this.m_noRestriction)
\r
170 if (this.m_acceptList.Count == 0 && this.m_connectList.Count == 0)
\r
173 if (perm.m_acceptList.Count == 0 && perm.m_connectList.Count == 0)
\r
176 return IsSubsetOf (this.m_connectList, perm.m_connectList)
\r
177 && IsSubsetOf (this.m_acceptList, perm.m_acceptList);
\r
180 private bool IsSubsetOf (ArrayList list1, ArrayList list2)
\r
182 foreach (EndpointPermission perm1 in list1) {
\r
183 bool issubset = false;
\r
184 foreach (EndpointPermission perm2 in list2)
\r
185 if (perm1.IsSubsetOf (perm2)) {
\r
195 public bool IsUnrestricted ()
\r
197 return m_noRestriction;
\r
202 SocketPermission s = new SocketPermission (NetworkAccess.Connect, TransportType.Tcp, "www.google.com", 80);
\r
203 s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", 8080);
\r
204 s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", SocketPermission.AllPorts);
\r
205 // s = new SocketPermission (PermissionState.None);
\r
206 SecurityElement sec = s.ToXml ();
\r
207 Console.WriteLine (sec.ToString ());
\r
209 This is sample xml output:
\r
211 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
\r
214 <ENDPOINT host="www.google.com"
\r
219 <ENDPOINT host="localhost"
\r
222 <ENDPOINT host="localhost"
\r
230 This is a sample unrestricted socketpermission, no matter how many permissions you add:
\r
232 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
\r
234 Unrestricted="true"/>
\r
237 This is a sample constructed restricted socketpermission with no permissions added:
\r
239 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
\r
242 public override SecurityElement ToXml ()
\r
245 SecurityElement root = new SecurityElement ("IPermission");
\r
247 root.AddAttribute ("class", this.GetType ().AssemblyQualifiedName);
\r
248 root.AddAttribute ("version", "1");
\r
249 if (m_noRestriction) {
\r
250 root.AddAttribute ("Unrestricted", "true");
\r
254 if (this.m_connectList.Count > 0)
\r
255 ToXml (root, "ConnectAccess", m_connectList.GetEnumerator ());
\r
257 if (this.m_acceptList.Count > 0)
\r
258 ToXml (root, "AcceptAccess", m_acceptList.GetEnumerator ());
\r
263 private void ToXml (SecurityElement root, string childName, IEnumerator enumerator)
\r
265 SecurityElement child = new SecurityElement (childName);
\r
266 while (enumerator.MoveNext ()) {
\r
267 EndpointPermission perm = enumerator.Current as EndpointPermission;
\r
268 SecurityElement grandchild = new SecurityElement ("ENDPOINT");
\r
269 grandchild.AddAttribute ("host", perm.Hostname);
\r
270 grandchild.AddAttribute ("transport", perm.Transport.ToString ());
\r
271 grandchild.AddAttribute ("port",
\r
272 perm.Port == AllPorts
\r
274 : ((Int32) perm.Port).ToString ());
\r
275 child.AddChild (grandchild);
\r
277 root.AddChild (child);
\r
280 public override void FromXml (SecurityElement securityElement)
\r
282 if (securityElement == null)
\r
283 throw new ArgumentNullException ("securityElement");
\r
285 // LAMESPEC: it says to throw an ArgumentNullException in this case
\r
286 if (securityElement.Tag != "IPermission")
\r
287 throw new ArgumentException ("securityElement");
\r
289 string unrestricted = securityElement.Attribute ("Unrestricted");
\r
290 if (unrestricted != null) {
\r
291 this.m_noRestriction = (String.Compare (unrestricted, "true", true) == 0);
\r
292 if (this.m_noRestriction)
\r
296 this.m_noRestriction = false;
\r
297 this.m_connectList = new ArrayList ();
\r
298 this.m_acceptList = new ArrayList ();
\r
300 ArrayList children = securityElement.Children;
\r
301 foreach (SecurityElement child in children) {
\r
302 if (child.Tag == "ConnectAccess")
\r
303 FromXml (child.Children, NetworkAccess.Connect);
\r
304 else if (child.Tag == "AcceptAccess")
\r
305 FromXml (child.Children, NetworkAccess.Accept);
\r
309 private void FromXml (ArrayList endpoints, NetworkAccess access)
\r
311 foreach (SecurityElement endpoint in endpoints) {
\r
312 if (endpoint.Tag != "ENDPOINT")
\r
314 string hostname = endpoint.Attribute ("host");
\r
315 TransportType transport =
\r
316 (TransportType) Enum.Parse (typeof (TransportType),
\r
317 endpoint.Attribute ("transport"),
\r
319 string p = endpoint.Attribute ("port");
\r
322 port = SocketPermission.AllPorts;
\r
324 port = Int32.Parse (p);
\r
326 AddPermission (access, transport, hostname, port);
\r
330 public override IPermission Union (IPermission target)
\r
332 // LAMESPEC: according to spec we should throw an
\r
333 // exception when target is null. We'll follow the
\r
334 // behaviour of MS.Net instead of the spec, also
\r
335 // because it matches the Intersect behaviour.
\r
336 if (target == null)
\r
338 // throw new ArgumentNullException ("target");
\r
340 SocketPermission perm = target as SocketPermission;
\r
342 throw new ArgumentException ("Argument not of type SocketPermission");
\r
344 if (this.m_noRestriction || perm.m_noRestriction)
\r
345 return new SocketPermission (PermissionState.Unrestricted);
\r
347 SocketPermission copy = (SocketPermission) perm.Copy ();
\r
348 copy.m_acceptList.InsertRange (copy.m_acceptList.Count, this.m_acceptList);
\r
349 copy.m_connectList.InsertRange (copy.m_connectList.Count, this.m_connectList);
\r