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
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;
\r
31 using System.Security;
\r
32 using System.Security.Permissions;
\r
34 namespace System.Net
\r
37 public sealed class SocketPermission : CodeAccessPermission, IUnrestrictedPermission
\r
40 ArrayList m_acceptList = new ArrayList ();
\r
41 ArrayList m_connectList = new ArrayList ();
\r
42 bool m_noRestriction;
\r
45 public SocketPermission (PermissionState state) : base ()
\r
47 m_noRestriction = (state == PermissionState.Unrestricted);
\r
50 public SocketPermission (NetworkAccess access, TransportType transport,
\r
51 string hostName, int portNumber) : base ()
\r
53 m_noRestriction = false;
\r
54 AddPermission (access, transport, hostName, portNumber);
\r
58 public const int AllPorts = -1;
\r
62 public IEnumerator AcceptList {
\r
63 get { return m_acceptList.GetEnumerator (); }
\r
66 public IEnumerator ConnectList {
\r
67 get { return m_connectList.GetEnumerator (); }
\r
72 public void AddPermission (NetworkAccess access, TransportType transport,
\r
73 string hostName, int portNumber)
\r
75 if (m_noRestriction)
\r
78 EndpointPermission permission = new EndpointPermission (hostName, portNumber, transport);
\r
80 if (access == NetworkAccess.Accept)
\r
81 m_acceptList.Add (permission);
\r
83 m_connectList.Add (permission);
\r
86 public override IPermission Copy ()
\r
88 SocketPermission permission;
\r
90 permission = new SocketPermission (m_noRestriction ?
\r
91 PermissionState.Unrestricted :
\r
92 PermissionState.None);
\r
94 // as EndpointPermission's are immutable it's safe to do a shallow copy.
\r
95 permission.m_connectList = (ArrayList) this.m_connectList.Clone ();
\r
96 permission.m_acceptList = (ArrayList) this.m_acceptList.Clone ();
\r
101 public override IPermission Intersect (IPermission target)
\r
103 if (target == null)
\r
106 SocketPermission perm = target as SocketPermission;
\r
108 throw new ArgumentException ("Argument not of type SocketPermission");
\r
110 if (m_noRestriction)
\r
111 return IntersectEmpty (perm) ? null : perm.Copy ();
\r
113 if (perm.m_noRestriction)
\r
114 return IntersectEmpty (this) ? null : this.Copy ();
\r
116 SocketPermission newperm = new SocketPermission (PermissionState.None);
\r
117 Intersect (this.m_connectList, perm.m_connectList, newperm.m_connectList);
\r
118 Intersect (this.m_acceptList, perm.m_acceptList, newperm.m_acceptList);
\r
119 return IntersectEmpty (newperm) ? null : newperm;
\r
122 private bool IntersectEmpty (SocketPermission permission)
\r
124 return !permission.m_noRestriction &&
\r
125 (permission.m_connectList.Count == 0) &&
\r
126 (permission.m_acceptList.Count == 0);
\r
129 private void Intersect (ArrayList list1, ArrayList list2, ArrayList result)
\r
131 foreach (EndpointPermission perm1 in list1) {
\r
132 foreach (EndpointPermission perm2 in list2) {
\r
133 EndpointPermission perm = perm1.Intersect (perm2);
\r
134 if (perm != null) {
\r
135 // instead of the below it's also okay to simply do:
\r
136 // result.Add (perm);
\r
137 // below is only done to avoid double entries
\r
138 bool replaced = false;
\r
139 for (int i = 0; i < result.Count; i++) {
\r
140 EndpointPermission res = (EndpointPermission) result [i];
\r
141 EndpointPermission resperm = perm.Intersect (res);
\r
142 if (resperm != null) {
\r
143 result [i] = resperm;
\r
155 public override bool IsSubsetOf (IPermission target)
\r
157 if (target == null)
\r
158 return (!m_noRestriction && m_connectList.Count == 0 && m_acceptList.Count == 0);
\r
160 SocketPermission perm = target as SocketPermission;
\r
163 throw new ArgumentException ("Parameter target must be of type SocketPermission");
\r
165 if (perm.m_noRestriction)
\r
168 if (this.m_noRestriction)
\r
171 if (this.m_acceptList.Count == 0 && this.m_connectList.Count == 0)
\r
174 if (perm.m_acceptList.Count == 0 && perm.m_connectList.Count == 0)
\r
177 return IsSubsetOf (this.m_connectList, perm.m_connectList)
\r
178 && IsSubsetOf (this.m_acceptList, perm.m_acceptList);
\r
181 private bool IsSubsetOf (ArrayList list1, ArrayList list2)
\r
183 foreach (EndpointPermission perm1 in list1) {
\r
184 bool issubset = false;
\r
185 foreach (EndpointPermission perm2 in list2)
\r
186 if (perm1.IsSubsetOf (perm2)) {
\r
196 public bool IsUnrestricted ()
\r
198 return m_noRestriction;
\r
203 SocketPermission s = new SocketPermission (NetworkAccess.Connect, TransportType.Tcp, "www.google.com", 80);
\r
204 s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", 8080);
\r
205 s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", SocketPermission.AllPorts);
\r
206 // s = new SocketPermission (PermissionState.None);
\r
207 SecurityElement sec = s.ToXml ();
\r
208 Console.WriteLine (sec.ToString ());
\r
210 This is sample xml output:
\r
212 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
\r
215 <ENDPOINT host="www.google.com"
\r
220 <ENDPOINT host="localhost"
\r
223 <ENDPOINT host="localhost"
\r
231 This is a sample unrestricted socketpermission, no matter how many permissions you add:
\r
233 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
\r
235 Unrestricted="true"/>
\r
238 This is a sample constructed restricted socketpermission with no permissions added:
\r
240 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
\r
243 public override SecurityElement ToXml ()
\r
246 SecurityElement root = new SecurityElement ("IPermission");
\r
248 root.AddAttribute ("class", this.GetType ().AssemblyQualifiedName);
\r
249 root.AddAttribute ("version", "1");
\r
250 if (m_noRestriction) {
\r
251 root.AddAttribute ("Unrestricted", "true");
\r
255 if (this.m_connectList.Count > 0)
\r
256 ToXml (root, "ConnectAccess", m_connectList.GetEnumerator ());
\r
258 if (this.m_acceptList.Count > 0)
\r
259 ToXml (root, "AcceptAccess", m_acceptList.GetEnumerator ());
\r
264 private void ToXml (SecurityElement root, string childName, IEnumerator enumerator)
\r
266 SecurityElement child = new SecurityElement (childName);
\r
267 while (enumerator.MoveNext ()) {
\r
268 EndpointPermission perm = enumerator.Current as EndpointPermission;
\r
269 SecurityElement grandchild = new SecurityElement ("ENDPOINT");
\r
270 grandchild.AddAttribute ("host", perm.Hostname);
\r
271 grandchild.AddAttribute ("transport", perm.Transport.ToString ());
\r
272 grandchild.AddAttribute ("port",
\r
273 perm.Port == AllPorts
\r
275 : ((Int32) perm.Port).ToString ());
\r
276 child.AddChild (grandchild);
\r
278 root.AddChild (child);
\r
281 public override void FromXml (SecurityElement securityElement)
\r
283 if (securityElement == null)
\r
284 throw new ArgumentNullException ("securityElement");
\r
286 // LAMESPEC: it says to throw an ArgumentNullException in this case
\r
287 if (securityElement.Tag != "IPermission")
\r
288 throw new ArgumentException ("securityElement");
\r
290 string classStr = securityElement.Attribute ("class");
\r
291 if (classStr == null || !classStr.StartsWith (this.GetType ().FullName + ","))
\r
292 throw new ArgumentException ("securityElement");
\r
294 string unrestricted = securityElement.Attribute ("Unrestricted");
\r
295 if (unrestricted != null) {
\r
296 this.m_noRestriction = (String.Compare (unrestricted, "true", true) == 0);
\r
297 if (this.m_noRestriction)
\r
301 this.m_noRestriction = false;
\r
302 this.m_connectList = new ArrayList ();
\r
303 this.m_acceptList = new ArrayList ();
\r
305 ArrayList children = securityElement.Children;
\r
306 foreach (SecurityElement child in children) {
\r
307 if (child.Tag == "ConnectAccess")
\r
308 FromXml (child.Children, NetworkAccess.Connect);
\r
309 else if (child.Tag == "AcceptAccess")
\r
310 FromXml (child.Children, NetworkAccess.Accept);
\r
314 private void FromXml (ArrayList endpoints, NetworkAccess access)
\r
316 foreach (SecurityElement endpoint in endpoints) {
\r
317 if (endpoint.Tag != "ENDPOINT")
\r
319 string hostname = endpoint.Attribute ("host");
\r
320 TransportType transport =
\r
321 (TransportType) Enum.Parse (typeof (TransportType),
\r
322 endpoint.Attribute ("transport"),
\r
324 string p = endpoint.Attribute ("port");
\r
327 port = SocketPermission.AllPorts;
\r
329 port = Int32.Parse (p);
\r
331 AddPermission (access, transport, hostname, port);
\r
335 public override IPermission Union (IPermission target)
\r
337 // LAMESPEC: according to spec we should throw an
\r
338 // exception when target is null. We'll follow the
\r
339 // behaviour of MS.Net instead of the spec, also
\r
340 // because it matches the Intersect behaviour.
\r
341 if (target == null)
\r
343 // throw new ArgumentNullException ("target");
\r
345 SocketPermission perm = target as SocketPermission;
\r
347 throw new ArgumentException ("Argument not of type SocketPermission");
\r
349 if (this.m_noRestriction || perm.m_noRestriction)
\r
350 return new SocketPermission (PermissionState.Unrestricted);
\r
352 SocketPermission copy = (SocketPermission) perm.Copy ();
\r
353 copy.m_acceptList.InsertRange (copy.m_acceptList.Count, this.m_acceptList);
\r
354 copy.m_connectList.InsertRange (copy.m_connectList.Count, this.m_connectList);
\r