1 // PipeSecurityTest.cs - NUnit Test Cases for PipeSecurity
4 // James Bellinger <jfb@zer7.com>
6 // Copyright (C) 2012 James Bellinger
9 using System.Collections.Generic;
11 using System.IO.Pipes;
12 using System.Security.AccessControl;
13 using System.Security.Principal;
14 using System.Threading;
15 using NUnit.Framework;
17 namespace MonoTests.System.IO.Pipes
20 public class PipeSecurityTest
23 public void NamedPipeDefaultPermissionsWork ()
25 if (PlatformID.Win32NT != Environment.OSVersion.Platform) {
26 Assert.Ignore (); return;
29 string name = @"Local\MonoTestPipeNPNPW";
30 using (NamedPipeServerStream server = CreateNamedServer (false, name, null, 0)) {
31 PipeSecurity security = server.GetAccessControl ();
33 AuthorizationRuleCollection rules = security.GetAccessRules (true, false,
34 typeof (SecurityIdentifier));
35 Assert.AreNotEqual (0, rules.Count);
40 public void NamedPipeSetAccessControlFailsWithoutChangePermissionRight ()
42 if (PlatformID.Win32NT != Environment.OSVersion.Platform) {
43 Assert.Ignore (); return;
46 string name = @"Local\MonoTestPipeNPSACFWCPR";
47 using (NamedPipeServerStream server = CreateNamedServer (false, name, null, 0)) {
48 bool unauthorized = false;
50 AddDenyEveryone (server);
51 } catch (UnauthorizedAccessException) {
55 Assert.IsTrue (unauthorized, "PipeAccessRights.ChangePermissions was not required");
60 public void NamedPipePermissionsActuallyWorkSyncAllow ()
62 NamedPipePermissionsActuallyWorkSync (@"Local\MonoTestPipeNPPAWSA", false);
66 public void NamedPipePermissionsActuallyWorkSyncDeny ()
68 NamedPipePermissionsActuallyWorkSync (@"Local\MonoTestPipeNPPAWSD", true);
71 void NamedPipePermissionsActuallyWorkSync (string name, bool addDenyEveryone)
73 if (PlatformID.Win32NT != Environment.OSVersion.Platform) {
74 Assert.Ignore (); return;
77 PipeSecurity security = new PipeSecurity ();
78 SecurityIdentifier worldSid = new SecurityIdentifier ("WD");
79 PipeAccessRule rule = new PipeAccessRule (worldSid,
80 PipeAccessRights.FullControl,
81 AccessControlType.Allow);
82 security.AddAccessRule (rule);
84 using (NamedPipeServerStream server = CreateNamedServer (false, name, security,
85 PipeAccessRights.ChangePermissions)) {
86 security = server.GetAccessControl ();
88 AuthorizationRuleCollection rules;
89 rules = security.GetAccessRules (true, true, typeof (SecurityIdentifier));
90 Assert.AreEqual (1, rules.Count);
92 rule = (PipeAccessRule)rules [0];
93 Assert.AreEqual (AccessControlType.Allow, rule.AccessControlType);
94 Assert.AreEqual (worldSid, rule.IdentityReference);
95 Assert.AreEqual (PipeAccessRights.FullControl, rule.PipeAccessRights);
98 AddDenyEveryone (server);
100 bool unauthorized = false;
101 using (NamedPipeClientStream client = CreateNamedClient (false, name)) {
103 client.Connect (1000);
104 } catch (UnauthorizedAccessException) {
109 Assert.AreEqual (addDenyEveryone, unauthorized);
115 [Category ("NotWorking")] // Async is completely broken on Mono Win32 pipes.
116 public void NamedPipePermissionsActuallyWorkAsync ()
118 if (PlatformID.Win32NT != Environment.OSVersion.Platform) {
119 Assert.Ignore (); return;
122 IAsyncResult waitForConnection;
123 string name = @"Local\MonoTestPipeNPPAWA";
125 using (NamedPipeServerStream server = CreateNamedServer (true, name, null,
126 PipeAccessRights.ChangePermissions)) {
127 // Test connecting to make sure our later test throwing is due to permissions.
128 waitForConnection = server.BeginWaitForConnection (null, null);
130 using (NamedPipeClientStream client = CreateNamedClient (true, name)) {
131 client.Connect (1000);
133 if (!waitForConnection.AsyncWaitHandle.WaitOne (1000)) {
134 Assert.Fail ("No connection request received."); return;
136 server.EndWaitForConnection (waitForConnection);
137 server.Disconnect ();
140 // Let's add a Deny for Everyone.
141 AddDenyEveryone (server);
143 // This Connect call should fail.
144 waitForConnection = server.BeginWaitForConnection (null, null);
146 bool unauthorized = false;
147 using (NamedPipeClientStream client = CreateNamedClient (true, name)) {
149 client.Connect (1000);
150 } catch (UnauthorizedAccessException) {
155 Assert.IsTrue (unauthorized, "Client was allowed to connect despite Deny ACE.");
159 static void AddDenyEveryone (PipeStream stream)
161 PipeAccessRule rule; PipeSecurity security;
162 AuthorizationRuleCollection inRules, outRules;
164 // Let's add a Deny for Everyone.
165 security = stream.GetAccessControl ();
167 inRules = security.GetAccessRules (true, false, typeof (SecurityIdentifier));
168 Assert.AreNotEqual (0, inRules.Count);
170 rule = new PipeAccessRule (new SecurityIdentifier ("WD"),
171 PipeAccessRights.FullControl,
172 AccessControlType.Deny);
173 security.AddAccessRule (rule);
174 stream.SetAccessControl (security);
176 security = stream.GetAccessControl ();
177 outRules = security.GetAccessRules (true, false, typeof (SecurityIdentifier));
178 Assert.AreEqual (inRules.Count + 1, outRules.Count);
181 static NamedPipeClientStream CreateNamedClient (bool @async, string name)
183 return new NamedPipeClientStream (".", name,
185 @async ? PipeOptions.Asynchronous : PipeOptions.None);
188 static NamedPipeServerStream CreateNamedServer (bool @async, string name,
189 PipeSecurity security,
190 PipeAccessRights additionalRights)
192 return new NamedPipeServerStream (name,
193 PipeDirection.InOut, 1,
194 PipeTransmissionMode.Byte,
195 @async ? PipeOptions.Asynchronous : PipeOptions.None,
197 HandleInheritability.None,