1 //
2 // System.Security.Permissions.EnvironmentPermission.cs
3 //
4 // Authors:
5 //	Tim Coleman <tim@timcoleman.com>
6 //	Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // Copyright (C) 2002, Tim Coleman
9 // Portions Copyright (C) 2003 Motus Technologies (http://www.motus.com)
10 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 
32 using System.Collections;
33 using System.Runtime.InteropServices;
34 using System.Text;
35 
36 namespace System.Security.Permissions {
37 
38 	[ComVisible (true)]
39 	[Serializable]
40 	public sealed class EnvironmentPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission {
41 
42 		#region Fields
43 
44 		private const int version = 1;
45 
46 //		EnvironmentPermissionAccess flags;
47 		PermissionState _state;
48 		ArrayList readList;
49 		ArrayList writeList;
50 
51 		#endregion // Fields
52 
53 		#region Constructors
54 
EnvironmentPermission(PermissionState state)55 		public EnvironmentPermission (PermissionState state) : base ()
56 		{
57 			_state = CheckPermissionState (state, true);
58 			readList = new ArrayList ();
59 			writeList = new ArrayList ();
60 		}
61 
EnvironmentPermission(EnvironmentPermissionAccess flag, string pathList)62 		public EnvironmentPermission (EnvironmentPermissionAccess flag, string pathList) : base ()
63 		{
64 			readList = new ArrayList ();
65 			writeList = new ArrayList ();
66 			SetPathList (flag, pathList);
67 		}
68 
69 		#endregion // Constructors
70 
71 		#region Methods
72 
AddPathList(EnvironmentPermissionAccess flag, string pathList)73 		public void AddPathList (EnvironmentPermissionAccess flag, string pathList)
74 		{
75 			if (pathList == null)
76 				throw new ArgumentNullException ("pathList");
77 
78 			string[] paths;
79 			switch (flag) {
80 				case EnvironmentPermissionAccess.AllAccess:
81 					paths = pathList.Split (';');
82 					foreach (string path in paths) {
83 						if (!readList.Contains (path))
84 							readList.Add (path);
85 						if (!writeList.Contains (path))
86 							writeList.Add (path);
87 					}
88 					break;
89 				case EnvironmentPermissionAccess.NoAccess:
90 					// ??? unit tests doesn't show removal using NoAccess ???
91 					break;
92 				case EnvironmentPermissionAccess.Read:
93 					paths = pathList.Split (';');
94 					foreach (string path in paths) {
95 						if (!readList.Contains (path))
96 							readList.Add (path);
97 					}
98 					break;
99 				case EnvironmentPermissionAccess.Write:
100 					paths = pathList.Split (';');
101 					foreach (string path in paths) {
102 						if (!writeList.Contains (path))
103 							writeList.Add (path);
104 					}
105 					break;
106 				default:
107 					ThrowInvalidFlag (flag, false);
108 					break;
109 			}
110 		}
111 
Copy()112 		public override IPermission Copy ()
113 		{
114 			EnvironmentPermission ep = new EnvironmentPermission (_state);
115 			string path = GetPathList (EnvironmentPermissionAccess.Read);
116 			if (path != null)
117 				ep.SetPathList (EnvironmentPermissionAccess.Read, path);
118 			path = GetPathList (EnvironmentPermissionAccess.Write);
119 			if (path != null)
120 				ep.SetPathList (EnvironmentPermissionAccess.Write, path);
121 			return ep;
122 		}
123 
FromXml(SecurityElement esd)124 		public override void FromXml (SecurityElement esd)
125 		{
126 			// General validation in CodeAccessPermission
127 			CheckSecurityElement (esd, "esd", version, version);
128 			// Note: we do not (yet) care about the return value
129 			// as we only accept version 1 (min/max values)
130 
131 			if (IsUnrestricted (esd))
132 				_state = PermissionState.Unrestricted;
133 
134 			string read = esd.Attribute ("Read");
135 			if ((read != null) && (read.Length > 0))
136 				SetPathList (EnvironmentPermissionAccess.Read, read);
137 
138 			string write = esd.Attribute ("Write");
139 			if ((write != null) && (write.Length > 0))
140 				SetPathList (EnvironmentPermissionAccess.Write, write);
141 		}
142 
GetPathList(EnvironmentPermissionAccess flag)143 		public string GetPathList (EnvironmentPermissionAccess flag)
144 		{
145 			switch (flag) {
146 				case EnvironmentPermissionAccess.AllAccess:
147 				case EnvironmentPermissionAccess.NoAccess:
148 					ThrowInvalidFlag (flag, true);
149 					break;
150 				case EnvironmentPermissionAccess.Read:
151 					return GetPathList (readList);
152 				case EnvironmentPermissionAccess.Write:
153 					return GetPathList (writeList);
154 				default:
155 					ThrowInvalidFlag (flag, false);
156 					break;
157 			}
158 			return null; // never reached
159 		}
160 
Intersect(IPermission target)161 		public override IPermission Intersect (IPermission target)
162 		{
163 			EnvironmentPermission ep = Cast (target);
164 			if (ep == null)
165 				return null;
166 
167 			if (IsUnrestricted ())
168 				return ep.Copy ();
169 			if (ep.IsUnrestricted ())
170 				return Copy ();
171 
172 			int n = 0;
173 			EnvironmentPermission result = new EnvironmentPermission (PermissionState.None);
174 			string readTarget = ep.GetPathList (EnvironmentPermissionAccess.Read);
175 			if (readTarget != null) {
176 				string[] targets = readTarget.Split (';');
177 				foreach (string t in targets) {
178 					if (readList.Contains (t)) {
179 						result.AddPathList (EnvironmentPermissionAccess.Read, t);
180 						n++;
181 					}
182 				}
183 			}
184 
185 			string writeTarget = ep.GetPathList (EnvironmentPermissionAccess.Write);
186 			if (writeTarget != null) {
187 				string[] targets = writeTarget.Split (';');
188 				foreach (string t in targets) {
189 					if (writeList.Contains (t)) {
190 						result.AddPathList (EnvironmentPermissionAccess.Write, t);
191 						n++;
192 					}
193 				}
194 			}
195 			return ((n > 0) ? result : null);
196 		}
197 
IsSubsetOf(IPermission target)198 		public override bool IsSubsetOf (IPermission target)
199 		{
200 			EnvironmentPermission ep = Cast (target);
201 			if (ep == null)
202 				return false;
203 
204 			if (IsUnrestricted ())
205 				return ep.IsUnrestricted ();
206 			else if (ep.IsUnrestricted ())
207 				return true;
208 
209 			foreach (string s in readList) {
210 				if (!ep.readList.Contains (s))
211 					return false;
212 			}
213 
214 			foreach (string s in writeList) {
215 				if (!ep.writeList.Contains (s))
216 					return false;
217 			}
218 
219 			return true;
220 		}
221 
IsUnrestricted()222 		public bool IsUnrestricted ()
223 		{
224 			return (_state == PermissionState.Unrestricted);
225 		}
226 
SetPathList(EnvironmentPermissionAccess flag, string pathList)227 		public void SetPathList (EnvironmentPermissionAccess flag, string pathList)
228 		{
229 			if (pathList == null)
230 				throw new ArgumentNullException ("pathList");
231 			string[] paths;
232 			switch (flag) {
233 				case EnvironmentPermissionAccess.AllAccess:
234 					readList.Clear ();
235 					writeList.Clear ();
236 					paths = pathList.Split (';');
237 					foreach (string path in paths) {
238 						readList.Add (path);
239 						writeList.Add (path);
240 					}
241 					break;
242 				case EnvironmentPermissionAccess.NoAccess:
243 					// ??? unit tests doesn't show removal using NoAccess ???
244 					break;
245 				case EnvironmentPermissionAccess.Read:
246 					readList.Clear ();
247 					paths = pathList.Split (';');
248 					foreach (string path in paths) {
249 						readList.Add (path);
250 					}
251 					break;
252 				case EnvironmentPermissionAccess.Write:
253 					writeList.Clear ();
254 					paths = pathList.Split (';');
255 					foreach (string path in paths) {
256 						writeList.Add (path);
257 					}
258 					break;
259 				default:
260 					ThrowInvalidFlag (flag, false);
261 					break;
262 			}
263 		}
264 
ToXml()265 		public override SecurityElement ToXml ()
266 		{
267 			SecurityElement se = Element (version);
268 
269 			if (_state == PermissionState.Unrestricted) {
270 				se.AddAttribute ("Unrestricted", "true");
271 			}
272 			else {
273 				string path = GetPathList (EnvironmentPermissionAccess.Read);
274 				if (path != null)
275 					se.AddAttribute ("Read", path);
276 				path = GetPathList (EnvironmentPermissionAccess.Write);
277 				if (path != null)
278 					se.AddAttribute ("Write", path);
279 			}
280 			return se;
281 		}
282 
Union(IPermission other)283 		public override IPermission Union (IPermission other)
284 		{
285 			EnvironmentPermission ep = Cast (other);
286 			if (ep == null)
287 				return Copy ();
288 
289 			if (IsUnrestricted () || ep.IsUnrestricted ())
290 				return new EnvironmentPermission (PermissionState.Unrestricted);
291 
292 			if (IsEmpty () && ep.IsEmpty ())
293 				return null;
294 
295 			EnvironmentPermission result = (EnvironmentPermission) Copy ();
296 			string path = ep.GetPathList (EnvironmentPermissionAccess.Read);
297 			if (path != null)
298 				result.AddPathList (EnvironmentPermissionAccess.Read, path);
299 			path = ep.GetPathList (EnvironmentPermissionAccess.Write);
300 			if (path != null)
301 				result.AddPathList (EnvironmentPermissionAccess.Write, path);
302 			return result;
303 		}
304 
305 		// IBuiltInPermission
IBuiltInPermission.GetTokenIndex()306 		int IBuiltInPermission.GetTokenIndex ()
307 		{
308 			return (int) BuiltInToken.Environment;
309 		}
310 
311 		// helpers
312 
IsEmpty()313 		private bool IsEmpty ()
314 		{
315 			return ((_state == PermissionState.None) && (readList.Count == 0) && (writeList.Count == 0));
316 		}
317 
Cast(IPermission target)318 		private EnvironmentPermission Cast (IPermission target)
319 		{
320 			if (target == null)
321 				return null;
322 
323 			EnvironmentPermission ep = (target as EnvironmentPermission);
324 			if (ep == null) {
325 				ThrowInvalidPermission (target, typeof (EnvironmentPermission));
326 			}
327 
328 			return ep;
329 		}
330 
ThrowInvalidFlag(EnvironmentPermissionAccess flag, bool context)331 		internal void ThrowInvalidFlag (EnvironmentPermissionAccess flag, bool context)
332 		{
333 			string msg = null;
334 			if (context)
335 				msg = Locale.GetText ("Unknown flag '{0}'.");
336 			else
337 				msg = Locale.GetText ("Invalid flag '{0}' in this context.");
338 			throw new ArgumentException (String.Format (msg, flag), "flag");
339 		}
340 
GetPathList(ArrayList list)341 		private string GetPathList (ArrayList list)
342 		{
343 			if (IsUnrestricted ())
344 				return String.Empty;
345 			if (list.Count == 0)
346 				return String.Empty;
347 			StringBuilder sb = new StringBuilder ();
348 			foreach (string path in list) {
349 				sb.Append (path);
350 				sb.Append (";");
351 			}
352 
353 			string result = sb.ToString ();
354 			// remove last ';'
355 			int n = result.Length;
356 			if (n > 0)
357 				return result.Substring (0, n - 1);
358 
359 			return String.Empty;
360 		}
361 
362 		#endregion // Methods
363 	}
364 }
365