2009-07-11 Michael Barker <mike@middlesoft.co.uk>
[mono.git] / mcs / class / corlib / Test / System.Security.Permissions / FileIOPermissionTest.cs
1 //
2 // MonoTests.System.Security.Permissions.FileIOPermissionTest.cs
3 //
4 // Author:
5 //   Nick Drochak (ndrochak@gol.com)
6 //
7 // (C) 2001-2002 Nick Drochak II
8 //
9 // Note: Only Unix and Windows file paths are tested.  To run the tests on Mac OS's
10 // search for the "FIXME" notes below and adjust accordingly.
11
12 using System;
13 using System.IO;
14 using System.Runtime.InteropServices;
15 using System.Reflection;
16 using System.Security;
17 using System.Security.Permissions;
18 using System.Text;
19
20 using NUnit.Framework;
21
22 namespace MonoTests.System.Security.Permissions {
23 #if !TARGET_JVM
24         public class FilePathUtil {
25                 [DllImport("kernel32.dll")]
26                 private static extern uint GetLongPathName (string shortPath, 
27                         StringBuilder buffer, uint bufLength);
28
29                 static public string GetLongPathName (string somePath) 
30                 {
31                         StringBuilder buffer = new StringBuilder(260);
32                         if (0 != GetLongPathName (somePath, buffer, (uint) buffer.Capacity))
33                                 return buffer.ToString ();
34                         else
35                                 return null;
36                 }
37
38                 [DllImport("kernel32.dll", SetLastError=true)] 
39                 private static extern uint GetShortPathName ( string longPath, 
40                         StringBuilder buffer, uint bufLength);
41
42                 static public string GetShortPathName (string somePath) 
43                 {
44                         StringBuilder buffer = new StringBuilder(260);
45                         if (0 != GetShortPathName (somePath, buffer, (uint) buffer.Capacity))
46                                 return buffer.ToString ();
47                         else
48                                 return null;
49                 }
50         }
51 #endif
52
53         [TestFixture]
54         public class FileIOPermissionTest {
55                 
56                 string[] pathArrayGood;
57                 string[] pathArrayBad;
58                 FileIOPermission p;
59                 FileIOPermission p2;
60                 string[] pathsInPermission;
61                 string[] pathArrayGood2;
62                 FileIOPermission unrestricted;
63
64                 private string filename;
65                 private bool unix;
66
67                 [SetUp]
68                 public void SetUp () 
69                 {
70                         Environment.CurrentDirectory = Path.GetTempPath();
71                         filename = Path.GetTempFileName ();
72
73                         int os = (int) Environment.OSVersion.Platform;
74                         unix = ((os == 4) || (os == 128) || (os == 6));
75
76                         p = null;
77                         pathsInPermission = null;
78                         pathArrayGood = new string[2];
79                         pathArrayBad = new string[2];
80                         pathArrayGood2 = new string[3];
81                         // FIXME: Adjust to run on Mac OS's
82                         if (Path.VolumeSeparatorChar == ':') {
83                                 pathArrayGood[0] = "c:\\temp1";
84                                 pathArrayGood[1] = "d:\\temp2";
85                                 pathArrayBad[0] = "c:\\temp1";
86                                 pathArrayBad[1] = "d:\\temp*";
87                                 pathArrayGood2[0] = "c:\\temp1";
88                                 pathArrayGood2[1] = "d:\\temp2";
89                                 pathArrayGood2[2] = "z:\\something";
90                         }
91                         else {
92                                 pathArrayGood[0] = "/temp1";
93                                 pathArrayGood[1] = "/usr/temp2";
94                                 pathArrayBad[0] = "/temp1";
95                                 pathArrayBad[1] = "/usr/temp*"; // not really bad under Unix...
96                                 pathArrayGood2[0] = "/temp1";
97                                 pathArrayGood2[1] = "/usr/temp2";
98                                 pathArrayGood2[2] = "/usr/bin/something";
99                         }
100                 }
101
102                 [TearDown]
103                 public void TearDown () 
104                 {
105                         if (File.Exists (filename))
106                                 File.Delete (filename);
107                 }
108
109                 [Test]
110                 public void ConstructorPermissionState ()
111                 {
112                         p = new FileIOPermission(PermissionState.None);
113                         Assert.AreEqual(false, p.IsUnrestricted(), "Should be Restricted");
114                         p = new FileIOPermission(PermissionState.Unrestricted);
115                         Assert.AreEqual(true, p.IsUnrestricted(), "Should be Unrestricted");
116                         try{
117                                 p = new FileIOPermission((PermissionState)77);
118                                 Assert.Fail("Should have thrown an exception on invalid PermissionState");
119                         }
120                         catch{
121                                 // we should be here if things are working.  nothing to do
122                         }
123                 }
124
125                 [Test]
126                 [ExpectedException (typeof (ArgumentNullException))]
127                 public void ConstructorString_Null () 
128                 {
129                         p = new FileIOPermission(FileIOPermissionAccess.Append, (string)null);
130                 }
131
132                 [Test]
133                 [ExpectedException (typeof (ArgumentException))]
134                 public void ConstructorString_NotRooted ()
135                 {
136                         p = new FileIOPermission(FileIOPermissionAccess.Append, "this path is not rooted");
137                 }
138
139                 [Test]
140                 [ExpectedException (typeof (ArgumentException))]
141                 public void ConstructorString_InvalidPath () 
142                 {
143                         p = new FileIOPermission(FileIOPermissionAccess.Append, "<this is not a valid path>");
144                 }
145
146                 [Test]
147                 public void ConstructorString_Wildcard () 
148                 {
149                         try {
150                                 // note: this is a valid path on UNIX so we must be able to protect it
151                                 p = new FileIOPermission(FileIOPermissionAccess.Append, pathArrayBad [1]);
152                         }
153                         catch (ArgumentException) {
154                                 if (unix)
155                                         Assert.Fail ("Wildcard * is valid in filenames");
156                                 // else it's normal for Windows to throw ArgumentException
157                         }
158                         catch (Exception e) {
159                                 Assert.Fail ("Bad or wrong exception: " + e.ToString ());
160                         }
161                 }
162
163                 [Test]
164                 [ExpectedException (typeof (ArgumentException))]
165                 public void ConstructorString_InvalidAccess () 
166                 {
167                         p = new FileIOPermission((FileIOPermissionAccess)77, "c:\\temp");
168                 }
169
170                 [Test]
171                 public void ConstructorString ()
172                 {
173                         string pathToAdd;
174                         // FIXME: Adjust to run on Mac OS's
175                         if (Path.VolumeSeparatorChar == ':')
176                                 pathToAdd = "c:\\temp";
177                         else
178                                 pathToAdd = "/temp";
179
180                         p = new FileIOPermission(FileIOPermissionAccess.Read, pathToAdd);
181                         pathsInPermission = p.GetPathList(FileIOPermissionAccess.Read);
182                         Assert.IsTrue (pathsInPermission.Length == 1, "Does not contain correct number of paths. Expected 1 but got: "+pathsInPermission.Length);
183                         Assert.IsTrue(pathsInPermission[0] == pathToAdd, "Does not contain expected path from constructor: "+pathToAdd);
184                 }
185
186                 [Test]
187                 [ExpectedException (typeof (ArgumentNullException))]
188                 public void ConstructorStringArray_Null () 
189                 {
190                         p = new FileIOPermission(FileIOPermissionAccess.Append, (string[])null);
191                 }
192
193                 [Test]
194                 public void ConstructorStringArray_Wildcard () 
195                 {
196                         try {
197                                 // note: this is a valid path on UNIX so we must be able to protect it
198                                 p = new FileIOPermission(FileIOPermissionAccess.Append, pathArrayBad);
199                         }
200                         catch (ArgumentException) {
201                                 if (unix)
202                                         Assert.Fail ("Wildcard * is valid in filenames");
203                                 // else it's normal for Windows to throw ArgumentException
204                         }
205                         catch (Exception e) {
206                                 Assert.Fail ("Bad or wrong exception: " + e.ToString ());
207                         }
208                 }
209
210                 [Test]
211                 [ExpectedException (typeof (ArgumentException))]
212                 public void ConstructorStringArray_InvalidAccess () 
213                 {
214                         p = new FileIOPermission((FileIOPermissionAccess)77, pathArrayGood);
215                 }
216
217                 [Test]
218                 public void ConstructorStringArray () 
219                 {
220                         p = new FileIOPermission(FileIOPermissionAccess.Read, pathArrayGood);
221                         pathsInPermission = p.GetPathList(FileIOPermissionAccess.Read);
222                         Assert.IsTrue (pathsInPermission.Length == 2, "Does not contain correct number of paths. Expected 2 but got: "+pathsInPermission.Length);
223                         foreach (string s in pathsInPermission){
224                                 Assert.IsTrue (Array.IndexOf(pathsInPermission, s) >=0, "Unexpected path in the Permission: " + s);
225                         }
226                 }
227
228                 [Test]
229                 public void AddPathListStringArray ()
230                 {
231                         p = new FileIOPermission(FileIOPermissionAccess.Read, pathArrayGood);
232                         pathsInPermission = p.GetPathList(FileIOPermissionAccess.Read);
233                         Assert.IsTrue (pathsInPermission.Length == 2, "Does not contain correct number of paths. Expected 2 but got: "+pathsInPermission.Length);
234                         foreach (string s in pathsInPermission){
235                                 Assert.IsTrue (Array.IndexOf(pathsInPermission, s) >=0, "Unexpected path in the Permission: " + s);
236                         }
237
238                         p.AddPathList(FileIOPermissionAccess.Append, pathArrayGood);
239                         pathsInPermission = p.GetPathList(FileIOPermissionAccess.Read);
240                         Assert.IsTrue (pathsInPermission.Length == 2, "Should still contain correct number Read paths. Expected 2 but got: "+pathsInPermission.Length);
241                         foreach (string s in pathsInPermission){
242                                 Assert.IsTrue (Array.IndexOf(pathsInPermission, s) >=0, "Unexpected path in the Permission: " + s);
243                         }
244                         pathsInPermission = p.GetPathList(FileIOPermissionAccess.Append);
245                         Assert.IsTrue (pathsInPermission.Length == 2, "Should contain correct number of Append paths. Expected 2 but got: "+pathsInPermission.Length);
246                         foreach (string s in pathsInPermission){
247                                 Assert.IsTrue (Array.IndexOf(pathsInPermission, s) >=0, "Unexpected path in the Permission: " + s);
248                         }
249                 }
250
251                 [Test]
252                 public void Intersect ()
253                 {
254                         p = new FileIOPermission(FileIOPermissionAccess.Read, pathArrayGood);
255                         p.AllFiles = FileIOPermissionAccess.Append;
256                         p.AllLocalFiles = FileIOPermissionAccess.Write;
257                         
258                         unrestricted = new FileIOPermission(PermissionState.Unrestricted);
259                         
260                         FileIOPermission intersection = (FileIOPermission)p.Intersect(unrestricted);
261                         pathsInPermission = intersection.GetPathList(FileIOPermissionAccess.Read);
262                         Assert.IsTrue (pathsInPermission.Length == 2, "Should contain correct number of Read paths. Expected 2 but got: "+pathsInPermission.Length);
263                         Assert.IsTrue((intersection.AllFiles & FileIOPermissionAccess.Append) != 0, "Should have Append bit in AllFiles.");
264                         Assert.IsTrue((intersection.AllLocalFiles & FileIOPermissionAccess.Write) != 0, "Should have Write bit in AllLocalFiles.");
265
266                         intersection = (FileIOPermission)unrestricted.Intersect(p);
267                         pathsInPermission = intersection.GetPathList(FileIOPermissionAccess.Read);
268                         Assert.IsTrue (pathsInPermission.Length == 2, "Should contain correct number of Read paths. Expected 2 but got: "+pathsInPermission.Length);
269                         Assert.IsTrue((intersection.AllFiles & FileIOPermissionAccess.Append) != 0, "Should have Append bit in AllFiles.");
270                         Assert.IsTrue((intersection.AllLocalFiles & FileIOPermissionAccess.Write) != 0, "Should have Write bit in AllLocalFiles.");
271
272                         p2 = new FileIOPermission(FileIOPermissionAccess.Append | FileIOPermissionAccess.Read, pathArrayGood2);
273                         p2.AllFiles = FileIOPermissionAccess.Append | FileIOPermissionAccess.Write;
274                         p2.AllLocalFiles = FileIOPermissionAccess.Write | FileIOPermissionAccess.Read;
275                         intersection = (FileIOPermission)p.Intersect(p2);
276                         pathsInPermission = intersection.GetPathList(FileIOPermissionAccess.Read);
277                         Assert.IsNotNull (pathsInPermission, "Should have some paths");
278                         Assert.AreEqual (2, pathsInPermission.Length, "Should contain correct number of Read paths");
279                         Assert.AreEqual ( FileIOPermissionAccess.Append, intersection.AllFiles, "Should have only Append bit in AllFiles.");
280                         Assert.AreEqual ( FileIOPermissionAccess.Write, intersection.AllLocalFiles, "Should have only Write bit in AllLocalFiles.");
281
282                         intersection = (FileIOPermission)p2.Intersect(p);
283                         pathsInPermission = intersection.GetPathList(FileIOPermissionAccess.Read);
284                         Assert.IsTrue (pathsInPermission.Length == 2, "Should contain correct number of Read paths. Expected 2 but got: "+pathsInPermission.Length);
285                         Assert.IsTrue(intersection.AllFiles == FileIOPermissionAccess.Append, "Should have only Append bit in AllFiles.");
286                         Assert.IsTrue(intersection.AllLocalFiles == FileIOPermissionAccess.Write, "Should have only Write bit in AllLocalFiles.");
287                 }
288
289                 [Test]
290                 public void IsSubsetOf ()
291                 {
292                         unrestricted = new FileIOPermission(PermissionState.Unrestricted);
293                         Assert.IsTrue(unrestricted.IsSubsetOf(unrestricted), "IsSubsetOf reflective test failed");
294
295                         p = new FileIOPermission(FileIOPermissionAccess.Read, pathArrayGood);
296                         p.AllFiles = FileIOPermissionAccess.Append;
297                         p.AllLocalFiles = FileIOPermissionAccess.Write;
298                         Assert.IsTrue(p.IsSubsetOf(p), "#1 IsSubsetOf reflective test failed");
299                         Assert.IsTrue(!unrestricted.IsSubsetOf(p), "#1 IsSubsetOf false test failed");
300                         Assert.IsTrue(p.IsSubsetOf(unrestricted), "#1 IsSubsetOf true test failed");
301
302                         p2 = new FileIOPermission(FileIOPermissionAccess.Append | FileIOPermissionAccess.Read, pathArrayGood2);
303                         p2.AllFiles = FileIOPermissionAccess.Append | FileIOPermissionAccess.Write;
304                         p2.AllLocalFiles = FileIOPermissionAccess.Write | FileIOPermissionAccess.Read;
305                         Assert.IsTrue(p2.IsSubsetOf(p2), "#2 IsSubsetOf reflective test failed");
306                         Assert.IsTrue(p.IsSubsetOf(p2), "#2 IsSubsetOf true test failed");
307                         Assert.IsTrue(!p2.IsSubsetOf(p), "#2 IsSubsetOf false test failed");
308                 }
309
310                 [Test]
311                 public void Union ()
312                 {
313                         unrestricted = new FileIOPermission(PermissionState.Unrestricted);
314                         p = new FileIOPermission(FileIOPermissionAccess.Read, pathArrayGood);
315
316                         FileIOPermission union = (FileIOPermission)unrestricted.Union(p);
317                         pathsInPermission = union.GetPathList(FileIOPermissionAccess.Read);
318                         Assert.IsTrue(union.IsUnrestricted(), "Should get an unrestricted permission");
319                         Assert.IsTrue(pathsInPermission == null, "Path list should be empty");
320
321                         union = (FileIOPermission)p.Union(unrestricted);
322                         pathsInPermission = union.GetPathList(FileIOPermissionAccess.Read);
323                         Assert.IsTrue(union.IsUnrestricted(), "Should get an unrestricted permission");
324                         Assert.IsTrue(pathsInPermission == null, "Path list should be empty");
325
326                         p2 = new FileIOPermission(FileIOPermissionAccess.Append, pathArrayGood2);
327
328                         union = (FileIOPermission)p.Union(p2);
329                         pathsInPermission = union.GetPathList(FileIOPermissionAccess.Read);
330                         Assert.IsTrue(pathsInPermission.Length == pathArrayGood.Length, "Path list should have 2 for Read");
331                         pathsInPermission = union.GetPathList(FileIOPermissionAccess.Append);
332                         Assert.IsTrue(pathsInPermission.Length == pathArrayGood2.Length, "Path list should have 3 for Append");
333
334                         union = (FileIOPermission)p2.Union(p);
335                         pathsInPermission = union.GetPathList(FileIOPermissionAccess.Read);
336                         Assert.IsTrue(pathsInPermission.Length == pathArrayGood.Length, "Path list should have 2 for Read");
337                         pathsInPermission = union.GetPathList(FileIOPermissionAccess.Append);
338                         Assert.IsTrue(pathsInPermission.Length == pathArrayGood2.Length, "Path list should have 3 for Append");
339                 }
340
341                 [Test]
342                 public void Union_Bug79118 ()
343                 {
344                         string[] f1 = unix ? new string[] { "/tmp/one", "/tmp/two" } : new string[] { "c:\\temp\\one", "c:\\temp\\two" };
345                         string[] f2 = unix ? new string[] { "/tmp/two" } : new string[] { "c:\\temp\\two" };
346
347                         p = new FileIOPermission (FileIOPermissionAccess.Read, f1);
348                         p2 = new FileIOPermission (FileIOPermissionAccess.Read, f2);
349                         FileIOPermission union = (FileIOPermission) p.Union (p2);
350
351                         string[] paths = union.GetPathList(FileIOPermissionAccess.Read);
352                         Assert.AreEqual (2, paths.Length, "Length");
353                         Assert.AreEqual (f1[0], paths[0], "0");
354                         Assert.AreEqual (f1[1], paths[1], "1");
355                 }
356
357                 private void Partial (string msg, string[] path1, string[] path2, int expected)
358                 {
359                         p = new FileIOPermission (FileIOPermissionAccess.Read, path1);
360                         p2 = new FileIOPermission (FileIOPermissionAccess.Read, path2);
361                         FileIOPermission union = (FileIOPermission) p.Union (p2);
362
363                         string[] paths = union.GetPathList(FileIOPermissionAccess.Read);
364                         Assert.AreEqual (expected, paths.Length, msg + ".Length");
365                         Assert.AreEqual (path1[0], paths[0], msg + "[0]");
366                         if (expected > 1)
367                                 Assert.AreEqual (path2[0], paths[1], msg + "[1]");
368                 }
369
370                 [Test]
371                 public void Union_Partial ()
372                 {
373                         string[] f1 = unix ? new string[] { "/dir/part" } : new string[] { "c:\\dir\\part" };
374                         string[] f2 = unix ? new string[] { "/dir/partial" } : new string[] { "c:\\dir\\partial" };
375                         Partial ("1", f1, f2, 2);
376                         Partial ("2", f2, f1, 2);
377
378                         f1 = unix ? new string[] { "/dir/part/" } : new string[] { "c:\\dir\\part\\" };
379                         f2 = unix ? new string[] { "/dir/partial/" } : new string[] { "c:\\dir\\partial\\" };
380                         Partial ("3", f1, f2, 2);
381                         Partial ("4", f2, f1, 2);
382
383                         f1 = unix ? new string[] { "/dir/part/ial" } : new string[] { "c:\\dir\\part\\ial" };
384                         f2 = unix ? new string[] { "/dir/part/ial" } : new string[] { "c:\\dir\\part\\ial" };
385                         Partial ("5", f1, f2, 1);
386                         Partial ("6", f2, f1, 1);
387                 }
388
389                 [Test]
390                 public void FromXML ()
391                 {
392                         p = new FileIOPermission(PermissionState.None);
393                         SecurityElement esd = new SecurityElement("IPermission");
394                         esd.AddAttribute("class", "FileIOPermission");
395                         esd.AddAttribute("version", "1");
396                         esd.AddAttribute("Unrestricted", "true");
397                         p.FromXml(esd);
398                         Assert.IsTrue(p.IsUnrestricted(), "Should get an unrestricted permission");
399
400                         esd = new SecurityElement("IPermission");
401                         esd.AddAttribute("class", "FileIOPermission");
402                         esd.AddAttribute("version", "1");
403                         // FIXME: Adjust to run on Mac OS's
404                         if (Path.VolumeSeparatorChar == ':') {
405                                 esd.AddAttribute("Read", "c:\\temp;d:\\temp2");
406                                 esd.AddAttribute("Write", "c:\\temp;d:\\temp2;z:\\temp3");
407                         }
408                         else {
409                                 esd.AddAttribute("Read", "/temp;/usr/temp2");
410                                 esd.AddAttribute("Write", "/temp;/usr/temp2;/usr/bin/temp3");
411                         }
412                         p = new FileIOPermission(PermissionState.None);
413                         p.FromXml(esd);
414                         pathsInPermission = p.GetPathList(FileIOPermissionAccess.Read);
415                         Assert.IsTrue(pathsInPermission.Length == 2, "Path list should have 2 for Read");
416                         pathsInPermission = p.GetPathList(FileIOPermissionAccess.Write);
417                         Assert.IsTrue(pathsInPermission.Length == 3, "Path list should have 2 for Write");
418                 }
419
420                 [Test]
421                 public void ToXML ()
422                 {
423                         p = new FileIOPermission(FileIOPermissionAccess.Read, pathArrayGood);
424                         SecurityElement esd = p.ToXml();
425                         Assert.IsTrue(esd.Tag == "IPermission", "Esd tag incorrect");
426                         Assert.IsTrue((String)esd.Attributes["version"] == "1", "Esd version incorrect");
427                         string read = (String)esd.Attributes["Read"];
428                         pathsInPermission = read.Split(';');
429                         Assert.IsTrue(pathsInPermission.Length == 2, "Path list should have 2 for Read");
430                 }
431 #if !TARGET_JVM
432                 [Test]
433                 [Ignore("should compatibility go that far ?")]
434                 public void ShortToLong () 
435                 {
436                         // on windows this returns a "short" (8.3) path and filename
437                         string filename = Path.GetTempFileName ();
438                         p = new FileIOPermission(FileIOPermissionAccess.Read, filename);
439                         string[] files = p.GetPathList (FileIOPermissionAccess.Read);
440                         Assert.AreEqual (1, files.Length, "GetPathList.Count");
441                         // FIXME: here GetTempFileName != GetPathList[0] for MS but == for Mono
442                         Assert.AreEqual (Path.GetFileName (filename), Path.GetFileName (files [0]), "Path.GetFileName(GetTempFileName)==Path.GetFileName(GetPathList[0])");
443                         // note: this will fail on Linux as kernel32.dll isn't available
444                         Assert.AreEqual (FilePathUtil.GetLongPathName (filename), files [0], "GetLongPathName(GetTempFileName)==GetPathList[0]");
445                 }
446 #endif
447                 [Test]
448                 [ExpectedException (typeof (ArgumentException))]
449                 public void FileUrl ()
450                 {
451                         // file://... isn't accepted
452                         string filename = Assembly.GetExecutingAssembly ().CodeBase;
453                         p = new FileIOPermission (FileIOPermissionAccess.Read, filename);
454                 }
455         }
456 }