/mcs/class/System/System.Net/SocketPermission.cs
C# | 354 lines | 217 code | 54 blank | 83 comment | 67 complexity | 2518bd8957c2a38832d706e6d14b0375 MD5 | raw file
1//
2// System.Net.SocketPermission.cs
3//
4// Author:
5// Lawrence Pit (loz@cable.a2000.nl)
6//
7
8//
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:
16//
17// The above copyright notice and this permission notice shall be
18// included in all copies or substantial portions of the Software.
19//
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.
27//
28
29using System.Collections;
30using System.Security;
31using System.Security.Permissions;
32
33namespace System.Net {
34
35 [Serializable]
36 public sealed class SocketPermission : CodeAccessPermission, IUnrestrictedPermission
37 {
38 // Fields
39 ArrayList m_acceptList = new ArrayList ();
40 ArrayList m_connectList = new ArrayList ();
41 bool m_noRestriction;
42
43 // Constructors
44 public SocketPermission (PermissionState state) : base ()
45 {
46 m_noRestriction = (state == PermissionState.Unrestricted);
47 }
48
49 public SocketPermission (NetworkAccess access, TransportType transport,
50 string hostName, int portNumber) : base ()
51 {
52 m_noRestriction = false;
53 AddPermission (access, transport, hostName, portNumber);
54 }
55
56 // Fields
57 public const int AllPorts = -1;
58
59 // Properties
60
61 public IEnumerator AcceptList {
62 get { return m_acceptList.GetEnumerator (); }
63 }
64
65 public IEnumerator ConnectList {
66 get { return m_connectList.GetEnumerator (); }
67 }
68
69 // Methods
70
71 public void AddPermission (NetworkAccess access, TransportType transport,
72 string hostName, int portNumber)
73 {
74 if (m_noRestriction)
75 return;
76
77 EndpointPermission permission = new EndpointPermission (hostName, portNumber, transport);
78
79 if (access == NetworkAccess.Accept)
80 m_acceptList.Add (permission);
81 else
82 m_connectList.Add (permission);
83 }
84
85 public override IPermission Copy ()
86 {
87 SocketPermission permission;
88
89 permission = new SocketPermission (m_noRestriction ?
90 PermissionState.Unrestricted :
91 PermissionState.None);
92
93 // as EndpointPermission's are immutable it's safe to do a shallow copy.
94 permission.m_connectList = (ArrayList) this.m_connectList.Clone ();
95 permission.m_acceptList = (ArrayList) this.m_acceptList.Clone ();
96
97 return permission;
98 }
99
100 public override IPermission Intersect (IPermission target)
101 {
102 if (target == null)
103 return null;
104
105 SocketPermission perm = target as SocketPermission;
106 if (perm == null)
107 throw new ArgumentException ("Argument not of type SocketPermission");
108
109 if (m_noRestriction)
110 return IntersectEmpty (perm) ? null : perm.Copy ();
111
112 if (perm.m_noRestriction)
113 return IntersectEmpty (this) ? null : this.Copy ();
114
115 SocketPermission newperm = new SocketPermission (PermissionState.None);
116 Intersect (this.m_connectList, perm.m_connectList, newperm.m_connectList);
117 Intersect (this.m_acceptList, perm.m_acceptList, newperm.m_acceptList);
118 return IntersectEmpty (newperm) ? null : newperm;
119 }
120
121 private bool IntersectEmpty (SocketPermission permission)
122 {
123 return !permission.m_noRestriction &&
124 (permission.m_connectList.Count == 0) &&
125 (permission.m_acceptList.Count == 0);
126 }
127
128 private void Intersect (ArrayList list1, ArrayList list2, ArrayList result)
129 {
130 foreach (EndpointPermission perm1 in list1) {
131 foreach (EndpointPermission perm2 in list2) {
132 EndpointPermission perm = perm1.Intersect (perm2);
133 if (perm != null) {
134 // instead of the below it's also okay to simply do:
135 // result.Add (perm);
136 // below is only done to avoid double entries
137 bool replaced = false;
138 for (int i = 0; i < result.Count; i++) {
139 EndpointPermission res = (EndpointPermission) result [i];
140 EndpointPermission resperm = perm.Intersect (res);
141 if (resperm != null) {
142 result [i] = resperm;
143 replaced = true;
144 break;
145 }
146 }
147 if (!replaced)
148 result.Add (perm);
149 }
150 }
151 }
152 }
153
154 public override bool IsSubsetOf (IPermission target)
155 {
156 if (target == null)
157 return (!m_noRestriction && m_connectList.Count == 0 && m_acceptList.Count == 0);
158
159 SocketPermission perm = target as SocketPermission;
160
161 if (perm == null)
162 throw new ArgumentException ("Parameter target must be of type SocketPermission");
163
164 if (perm.m_noRestriction)
165 return true;
166
167 if (this.m_noRestriction)
168 return false;
169
170 if (this.m_acceptList.Count == 0 && this.m_connectList.Count == 0)
171 return true;
172
173 if (perm.m_acceptList.Count == 0 && perm.m_connectList.Count == 0)
174 return false;
175
176 return IsSubsetOf (this.m_connectList, perm.m_connectList)
177 && IsSubsetOf (this.m_acceptList, perm.m_acceptList);
178 }
179
180 private bool IsSubsetOf (ArrayList list1, ArrayList list2)
181 {
182 foreach (EndpointPermission perm1 in list1) {
183 bool issubset = false;
184 foreach (EndpointPermission perm2 in list2)
185 if (perm1.IsSubsetOf (perm2)) {
186 issubset = true;
187 break;
188 }
189 if (!issubset)
190 return false;
191 }
192 return true;
193 }
194
195 public bool IsUnrestricted ()
196 {
197 return m_noRestriction;
198 }
199
200 /*
201
202 SocketPermission s = new SocketPermission (NetworkAccess.Connect, TransportType.Tcp, "www.google.com", 80);
203 s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", 8080);
204 s.AddPermission (NetworkAccess.Accept, TransportType.All, "localhost", SocketPermission.AllPorts);
205 // s = new SocketPermission (PermissionState.None);
206 SecurityElement sec = s.ToXml ();
207 Console.WriteLine (sec.ToString ());
208
209 This is sample xml output:
210
211 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
212 version="1">
213 <ConnectAccess>
214 <ENDPOINT host="www.google.com"
215 transport="Tcp"
216 port="80"/>
217 </ConnectAccess>
218 <AcceptAccess>
219 <ENDPOINT host="localhost"
220 transport="All"
221 port="8080"/>
222 <ENDPOINT host="localhost"
223 transport="All"
224 port="All"/>
225 </AcceptAccess>
226 </IPermission>
227
228
229
230 This is a sample unrestricted socketpermission, no matter how many permissions you add:
231
232 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
233 version="1"
234 Unrestricted="true"/>
235
236
237 This is a sample constructed restricted socketpermission with no permissions added:
238
239 <IPermission class="System.Net.SocketPermission, System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
240 version="1"/>
241 */
242 public override SecurityElement ToXml ()
243 {
244
245 SecurityElement root = new SecurityElement ("IPermission");
246
247 root.AddAttribute ("class", this.GetType ().AssemblyQualifiedName);
248 root.AddAttribute ("version", "1");
249 if (m_noRestriction) {
250 root.AddAttribute ("Unrestricted", "true");
251 return root;
252 }
253
254 if (this.m_connectList.Count > 0)
255 ToXml (root, "ConnectAccess", m_connectList.GetEnumerator ());
256
257 if (this.m_acceptList.Count > 0)
258 ToXml (root, "AcceptAccess", m_acceptList.GetEnumerator ());
259
260 return root;
261 }
262
263 private void ToXml (SecurityElement root, string childName, IEnumerator enumerator)
264 {
265 SecurityElement child = new SecurityElement (childName);
266 while (enumerator.MoveNext ()) {
267 EndpointPermission perm = enumerator.Current as EndpointPermission;
268 SecurityElement grandchild = new SecurityElement ("ENDPOINT");
269 grandchild.AddAttribute ("host", perm.Hostname);
270 grandchild.AddAttribute ("transport", perm.Transport.ToString ());
271 grandchild.AddAttribute ("port",
272 perm.Port == AllPorts
273 ? "All"
274 : ((Int32) perm.Port).ToString ());
275 child.AddChild (grandchild);
276 }
277 root.AddChild (child);
278 }
279
280 public override void FromXml (SecurityElement securityElement)
281 {
282 if (securityElement == null)
283 throw new ArgumentNullException ("securityElement");
284
285 // LAMESPEC: it says to throw an ArgumentNullException in this case
286 if (securityElement.Tag != "IPermission")
287 throw new ArgumentException ("securityElement");
288
289 string unrestricted = securityElement.Attribute ("Unrestricted");
290 if (unrestricted != null) {
291 this.m_noRestriction = (String.Compare (unrestricted, "true", true) == 0);
292 if (this.m_noRestriction)
293 return;
294 }
295
296 this.m_noRestriction = false;
297 this.m_connectList = new ArrayList ();
298 this.m_acceptList = new ArrayList ();
299
300 ArrayList children = securityElement.Children;
301 foreach (SecurityElement child in children) {
302 if (child.Tag == "ConnectAccess")
303 FromXml (child.Children, NetworkAccess.Connect);
304 else if (child.Tag == "AcceptAccess")
305 FromXml (child.Children, NetworkAccess.Accept);
306 }
307 }
308
309 private void FromXml (ArrayList endpoints, NetworkAccess access)
310 {
311 foreach (SecurityElement endpoint in endpoints) {
312 if (endpoint.Tag != "ENDPOINT")
313 continue;
314 string hostname = endpoint.Attribute ("host");
315 TransportType transport =
316 (TransportType) Enum.Parse (typeof (TransportType),
317 endpoint.Attribute ("transport"),
318 true);
319 string p = endpoint.Attribute ("port");
320 int port = 0;
321 if (p == "All")
322 port = SocketPermission.AllPorts;
323 else
324 port = Int32.Parse (p);
325
326 AddPermission (access, transport, hostname, port);
327 }
328 }
329
330 public override IPermission Union (IPermission target)
331 {
332 // LAMESPEC: according to spec we should throw an
333 // exception when target is null. We'll follow the
334 // behaviour of MS.Net instead of the spec, also
335 // because it matches the Intersect behaviour.
336 if (target == null)
337 return null;
338 // throw new ArgumentNullException ("target");
339
340 SocketPermission perm = target as SocketPermission;
341 if (perm == null)
342 throw new ArgumentException ("Argument not of type SocketPermission");
343
344 if (this.m_noRestriction || perm.m_noRestriction)
345 return new SocketPermission (PermissionState.Unrestricted);
346
347 SocketPermission copy = (SocketPermission) perm.Copy ();
348 copy.m_acceptList.InsertRange (copy.m_acceptList.Count, this.m_acceptList);
349 copy.m_connectList.InsertRange (copy.m_connectList.Count, this.m_connectList);
350
351 return copy;
352 }
353 }
354}