Skip to content

Commit 034c5a6

Browse files
authored
Add NamedPipeServerStream method that takes an ACL (#317)
Add NamedPipeServerStream method that takes an ACL Approved API proposal: dotnet/corefx#41657 We don't currently have a way to create a pipe with a given ACL in .NET Core. We can modify the ACL, but it would be more secure to have the proper ACL on the pipe from the start. This PR adds a new static class and method that can create an NamedPipeServerStream taking a PipeSecurity object, reusing code that can already perform this task.
1 parent 167e9f4 commit 034c5a6

13 files changed

+549
-58
lines changed

src/libraries/System.IO.Pipes.AccessControl/ref/System.IO.Pipes.AccessControl.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,9 @@ public static class AnonymousPipeServerStreamAcl
7171
{
7272
public static System.IO.Pipes.AnonymousPipeServerStream Create(System.IO.Pipes.PipeDirection direction, System.IO.HandleInheritability inheritability, int bufferSize, System.IO.Pipes.PipeSecurity pipeSecurity) { throw null; }
7373
}
74+
75+
public static class NamedPipeServerStreamAcl
76+
{
77+
public static System.IO.Pipes.NamedPipeServerStream Create(string pipeName, System.IO.Pipes.PipeDirection direction, int maxNumberOfServerInstances, System.IO.Pipes.PipeTransmissionMode transmissionMode, System.IO.Pipes.PipeOptions options, int inBufferSize, int outBufferSize, System.IO.Pipes.PipeSecurity pipeSecurity, System.IO.HandleInheritability inheritability = System.IO.HandleInheritability.None, System.IO.Pipes.PipeAccessRights additionalAccessRights = default) { throw null; }
78+
}
7479
}

src/libraries/System.IO.Pipes.AccessControl/tests/AnonymousPipeTests/AnonymousPipeServerStreamAclTests.cs

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ namespace System.IO.Pipes.Tests
88
{
99
public class AnonymousPipeServerStreamAclTests : PipeServerStreamAclTestBase
1010
{
11-
private const PipeDirection DefaultPipeDirection = PipeDirection.In;
12-
private const HandleInheritability DefaultInheritability = HandleInheritability.None;
13-
private const int DefaultBufferSize = 1;
14-
1511
[Fact]
1612
public void Create_NullSecurity()
1713
{
@@ -28,10 +24,7 @@ public void Create_NotSupportedPipeDirection()
2824
}
2925

3026
[Theory]
31-
[InlineData((PipeDirection)(int.MinValue))]
32-
[InlineData((PipeDirection)0)]
33-
[InlineData((PipeDirection)4)]
34-
[InlineData((PipeDirection)(int.MaxValue))]
27+
[MemberData(nameof(Create_InvalidPipeDirection_MemberData))]
3528
public void Create_InvalidPipeDirection(PipeDirection direction)
3629
{
3730
Assert.Throws<ArgumentOutOfRangeException>(() =>
@@ -41,10 +34,7 @@ public void Create_InvalidPipeDirection(PipeDirection direction)
4134
}
4235

4336
[Theory]
44-
[InlineData((HandleInheritability)(int.MinValue))]
45-
[InlineData((HandleInheritability)(-1))]
46-
[InlineData((HandleInheritability)2)]
47-
[InlineData((HandleInheritability)(int.MaxValue))]
37+
[MemberData(nameof(Create_InvalidInheritability_MemberData))]
4838
public void Create_InvalidInheritability(HandleInheritability inheritability)
4939
{
5040
Assert.Throws<ArgumentOutOfRangeException>(() =>
@@ -54,8 +44,7 @@ public void Create_InvalidInheritability(HandleInheritability inheritability)
5444
}
5545

5646
[Theory]
57-
[InlineData(int.MinValue)]
58-
[InlineData(-1)]
47+
[MemberData(nameof(Create_InvalidBufferSize_MemberData))]
5948
public void Create_InvalidBufferSize(int bufferSize)
6049
{
6150
Assert.Throws<ArgumentOutOfRangeException>(() =>
@@ -66,7 +55,7 @@ public void Create_InvalidBufferSize(int bufferSize)
6655

6756
public static IEnumerable<object[]> Create_ValidParameters_MemberData() =>
6857
from direction in new[] { PipeDirection.In, PipeDirection.Out }
69-
from inheritability in Enum.GetValues(typeof(HandleInheritability)).Cast<HandleInheritability>()
58+
from inheritability in new[] { HandleInheritability.None, HandleInheritability.Inheritable }
7059
from bufferSize in new[] { 0, 1 }
7160
select new object[] { direction, inheritability, bufferSize };
7261

@@ -78,7 +67,7 @@ public void Create_ValidParameters(PipeDirection direction, HandleInheritability
7867
}
7968

8069
public static IEnumerable<object[]> Create_CombineRightsAndAccessControl_MemberData() =>
81-
from rights in Enum.GetValues(typeof(PipeAccessRights)).Cast<PipeAccessRights>()
70+
from rights in s_combinedPipeAccessRights
8271
from accessControl in new[] { AccessControlType.Allow, AccessControlType.Deny }
8372
select new object[] { rights, accessControl };
8473

@@ -87,22 +76,13 @@ from rights in Enum.GetValues(typeof(PipeAccessRights)).Cast<PipeAccessRights>()
8776
[MemberData(nameof(Create_CombineRightsAndAccessControl_MemberData))]
8877
public void Create_CombineRightsAndAccessControl(PipeAccessRights rights, AccessControlType accessControl)
8978
{
90-
// These are the two cases that create a valid pipe when using Allow
91-
if ((rights == PipeAccessRights.FullControl || rights == PipeAccessRights.ReadWrite) &&
92-
accessControl == AccessControlType.Allow)
79+
// These are the only two rights that allow creating a pipe when using Allow
80+
if (accessControl == AccessControlType.Allow &&
81+
(rights == PipeAccessRights.FullControl || rights == PipeAccessRights.ReadWrite))
9382
{
9483
VerifyValidSecurity(rights, accessControl);
9584
}
96-
// When creating the PipeAccessRule for the PipeSecurity, the PipeAccessRule constructor calls AccessMaskFromRights, which explicilty removes the Synchronize bit from rights when AccessControlType is Deny
97-
// and rights is not FullControl, so using Synchronize with Deny is not allowed
98-
else if (rights == PipeAccessRights.Synchronize && accessControl == AccessControlType.Deny)
99-
{
100-
Assert.Throws<ArgumentException>("accessMask", () =>
101-
{
102-
PipeSecurity security = GetPipeSecurity(WellKnownSidType.BuiltinUsersSid, PipeAccessRights.Synchronize, AccessControlType.Deny);
103-
});
104-
}
105-
// Any other case is not authorized
85+
// Any other combination is not authorized
10686
else
10787
{
10888
PipeSecurity security = GetPipeSecurity(WellKnownSidType.BuiltinUsersSid, rights, accessControl);
@@ -113,11 +93,12 @@ public void Create_CombineRightsAndAccessControl(PipeAccessRights rights, Access
11393
}
11494
}
11595

116-
[Theory]
117-
[InlineData(PipeAccessRights.ReadWrite | PipeAccessRights.Synchronize, AccessControlType.Allow)]
118-
public void Create_ValidBitwiseRightsSecurity(PipeAccessRights rights, AccessControlType accessControl)
96+
[Fact]
97+
public void Create_ValidBitwiseRightsSecurity()
11998
{
120-
VerifyValidSecurity(rights, accessControl);
99+
// Synchronize gets removed from the bitwise combination,
100+
// but ReadWrite (an allowed right) should remain untouched
101+
VerifyValidSecurity(PipeAccessRights.ReadWrite | PipeAccessRights.Synchronize, AccessControlType.Allow);
121102
}
122103

123104
private void VerifyValidSecurity(PipeAccessRights rights, AccessControlType accessControl)

0 commit comments

Comments
 (0)