PageRenderTime 23ms CodeModel.GetById 9ms app.highlight 10ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System/System.Net/SocketPermission.cs

https://github.com/iainlane/mono
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}