1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Collections.Generic;
6 using System.Security.Principal;
7 using Xunit;
8 
9 namespace System.Security.AccessControl.Tests
10 {
11     public class ObjectAce_Tests : QualifiedAce_Tests
12     {
VerifyObjectAce(ObjectAce ace, AceFlags aceFlags, AceQualifier qualifier, int accessMask, SecurityIdentifier sid, ObjectAceFlags flags, Guid type, Guid inheritedType, bool isCallback, byte[] opaque)13         protected static void VerifyObjectAce(ObjectAce ace, AceFlags aceFlags, AceQualifier qualifier, int accessMask, SecurityIdentifier sid, ObjectAceFlags flags, Guid type, Guid inheritedType, bool isCallback, byte[] opaque)
14         {
15             Assert.Equal(aceFlags, ace.AceFlags);
16             Assert.Equal(accessMask, ace.AccessMask);
17             Assert.Equal(sid, ace.SecurityIdentifier);
18             Assert.Equal(opaque, ace.GetOpaque());
19             Assert.Equal(qualifier, ace.AceQualifier);
20             Assert.Equal(isCallback, ace.IsCallback);
21             Assert.Equal(flags, ace.ObjectAceFlags);
22             Assert.Equal(type, ace.ObjectAceType);
23             Assert.Equal(inheritedType, ace.InheritedObjectAceType);
24         }
25 
ObjectAce_CreateTestData(int intFlags, int intQualifier, int accessMask, string stringsid, int intObjectAceFlags, string stringType, string stringInheritedType, bool isCallback, int opaqueLength, int offset)26         private static object[] ObjectAce_CreateTestData(int intFlags, int intQualifier, int accessMask, string stringsid, int intObjectAceFlags, string stringType, string stringInheritedType, bool isCallback, int opaqueLength, int offset)
27         {
28             AceFlags aceFlags = (AceFlags)intFlags;
29             AceQualifier qualifier = (AceQualifier)intQualifier;
30             SecurityIdentifier sid = new SecurityIdentifier(stringsid);
31             ObjectAceFlags flags = (ObjectAceFlags)intObjectAceFlags;
32             Guid type = new Guid(stringType);
33             Guid inheritedType = new Guid(stringInheritedType);
34             byte[] opaque = new byte[opaqueLength];
35 
36             ObjectAce ace = new ObjectAce(aceFlags, qualifier, accessMask, sid, flags, type, inheritedType, isCallback, opaque);
37             VerifyObjectAce(ace, aceFlags, qualifier, accessMask, sid, flags, type, inheritedType, isCallback, opaque);
38 
39             byte[] binaryForm = new byte[ace.BinaryLength + offset];
40             switch (qualifier)
41             {
42                 case AceQualifier.AccessAllowed:
43                     binaryForm[offset + 0] = isCallback ? (byte)AceType.AccessAllowedCallbackObject : (byte)AceType.AccessAllowedObject;
44                     break;
45                 case AceQualifier.AccessDenied:
46                     binaryForm[offset + 0] = isCallback ? (byte)AceType.AccessDeniedCallbackObject : (byte)AceType.AccessDeniedObject;
47                     break;
48                 case AceQualifier.SystemAudit:
49                     binaryForm[offset + 0] = isCallback ? (byte)AceType.SystemAuditCallbackObject : (byte)AceType.SystemAuditObject;
50                     break;
51                 case AceQualifier.SystemAlarm:
52                     binaryForm[offset + 0] = isCallback ? (byte)AceType.SystemAlarmCallbackObject : (byte)AceType.SystemAlarmObject;
53                     break;
54                 default:
55                     return null;
56             }
57             binaryForm[offset + 1] = (byte)aceFlags;
58             binaryForm[offset + 2] = (byte)(ace.BinaryLength >> 0);
59             binaryForm[offset + 3] = (byte)(ace.BinaryLength >> 8);
60 
61             int baseOffset = offset + 4;
62             int offsetLocal = 0;
63 
64             unchecked
65             {
66                 binaryForm[baseOffset + 0] = (byte)(accessMask >> 0);
67                 binaryForm[baseOffset + 1] = (byte)(accessMask >> 8);
68                 binaryForm[baseOffset + 2] = (byte)(accessMask >> 16);
69                 binaryForm[baseOffset + 3] = (byte)(accessMask >> 24);
70             }
71             offsetLocal += 4;
72 
73             binaryForm[baseOffset + offsetLocal + 0] = (byte)(((uint)flags) >> 0);
74             binaryForm[baseOffset + offsetLocal + 1] = (byte)(((uint)flags) >> 8);
75             binaryForm[baseOffset + offsetLocal + 2] = (byte)(((uint)flags) >> 16);
76             binaryForm[baseOffset + offsetLocal + 3] = (byte)(((uint)flags) >> 24);
77 
78             offsetLocal += 4;
79 
80             if ((flags & ObjectAceFlags.ObjectAceTypePresent) != 0)
81             {
82                 type.ToByteArray().CopyTo(binaryForm, baseOffset + offsetLocal);
83                 offsetLocal += 16;
84             }
85 
86             if ((flags & ObjectAceFlags.InheritedObjectAceTypePresent) != 0)
87             {
88                 inheritedType.ToByteArray().CopyTo(binaryForm, baseOffset + offsetLocal);
89                 offsetLocal += 16;
90             }
91 
92             sid.GetBinaryForm(binaryForm, baseOffset + offsetLocal);
93             offsetLocal += sid.BinaryLength;
94             opaque.CopyTo(binaryForm, baseOffset + offsetLocal);
95 
96             return new object[] { ace, binaryForm, offset };
97         }
98 
99 
ObjectAce_TestObjects()100         public static IEnumerable<object[]> ObjectAce_TestObjects()
101         {
102             yield return ObjectAce_CreateTestData(0, 0, 1, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", false, 8, 0);
103             yield return ObjectAce_CreateTestData(1, 1, 0, "S-1-5-11", 2, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", false, 8, 0);
104             yield return ObjectAce_CreateTestData(2, 2, -1, "S-1-5-11", 3, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
105             yield return ObjectAce_CreateTestData(4, 3, 0, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
106             yield return ObjectAce_CreateTestData(8, 3, 1, "S-1-5-11", 2, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
107             yield return ObjectAce_CreateTestData(16, 0, 3, "S-1-5-11", 0, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
108             yield return ObjectAce_CreateTestData(32, 1, 3, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
109             yield return ObjectAce_CreateTestData(64, 2, 3, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
110             yield return ObjectAce_CreateTestData(128, 3, 3, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
111             yield return ObjectAce_CreateTestData(15, 3, 3, "S-1-5-11", 2, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
112             yield return ObjectAce_CreateTestData(192, 3, 3, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
113             yield return ObjectAce_CreateTestData(2, 1, 999999, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0);
114             yield return ObjectAce_CreateTestData(2, 1, 2, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 8, 0);
115         }
116 
117         [Fact]
ObjectAce_Constructor_Invalid()118         public void ObjectAce_Constructor_Invalid()
119         {
120             AssertExtensions.Throws<ArgumentNullException>("securityIdentifier", () => new ObjectAce((AceFlags)0, (AceQualifier)0, 1, null, (ObjectAceFlags)1, new Guid("{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}"), new Guid("{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}"), true, new byte[4]));
121             AssertExtensions.Throws<ArgumentOutOfRangeException>("qualifier", () => ObjectAce_CreateTestData(8, 4, 1, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0));
122             AssertExtensions.Throws<ArgumentOutOfRangeException>("qualifier", () => ObjectAce_CreateTestData(8, -1, 1, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 4, 0));
123             AssertExtensions.Throws<ArgumentOutOfRangeException>("opaque", () => ObjectAce_CreateTestData(2, 1, 2, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 1, 0));
124             AssertExtensions.Throws<ArgumentOutOfRangeException>("opaque", () => ObjectAce_CreateTestData(2, 1, 2, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", true, 17, 0));
125         }
126 
127         [Fact]
ObjectAce_CreateBinaryForm_Invalid()128         public void ObjectAce_CreateBinaryForm_Invalid()
129         {
130             ObjectAce ace = (ObjectAce)ObjectAce_CreateTestData(0, 0, 1, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", false, 8, 0)[0];
131             AssertExtensions.Throws<ArgumentNullException>("binaryForm", () => ObjectAce.CreateFromBinaryForm(null, 1));
132             AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => ObjectAce.CreateFromBinaryForm(new byte[1], -1));
133             AssertExtensions.Throws<ArgumentException>("binaryForm", () => ObjectAce.CreateFromBinaryForm(new byte[ace.BinaryLength + 1], 2));
134             AssertExtensions.Throws<ArgumentException>("binaryForm", () => ObjectAce.CreateFromBinaryForm(new byte[ace.BinaryLength], 1));
135         }
136 
137         [Fact]
ObjectAce_GetBinaryForm_Invalid()138         public void ObjectAce_GetBinaryForm_Invalid()
139         {
140             ObjectAce ace = (ObjectAce)ObjectAce_CreateTestData(0, 0, 1, "S-1-5-11", 1, "{73D03E18-5C03-422c-9EC7-C4C5B1CB1612}", "{3CFD5DF9-9146-43c8-BF99-78E7E2DE4BAF}", false, 8, 0)[0];
141             AssertExtensions.Throws<ArgumentNullException>("binaryForm", () => ace.GetBinaryForm(null, 1));
142             AssertExtensions.Throws<ArgumentOutOfRangeException>("offset", () => ace.GetBinaryForm(new byte[1], -1));
143             AssertExtensions.Throws<ArgumentOutOfRangeException>("binaryForm", () => ace.GetBinaryForm(new byte[ace.BinaryLength + 1], 2));
144             AssertExtensions.Throws<ArgumentOutOfRangeException>("binaryForm", () => ace.GetBinaryForm(new byte[ace.BinaryLength], 1));
145         }
146 
147         [Theory]
148         [MemberData(nameof(ObjectAce_TestObjects))]
ObjectAce_GetBinaryForm(GenericAce testAce, byte[] expectedBinaryForm, int testOffset)149         public void ObjectAce_GetBinaryForm(GenericAce testAce, byte[] expectedBinaryForm, int testOffset)
150         {
151             byte[] resultBinaryForm = new byte[testAce.BinaryLength + testOffset];
152             testAce.GetBinaryForm(resultBinaryForm, testOffset);
153             GenericAce_VerifyBinaryForms(expectedBinaryForm, resultBinaryForm, testOffset);
154         }
155 
156         [Theory]
157         [MemberData(nameof(ObjectAce_TestObjects))]
ObjectAce_CreateFromBinaryForm(GenericAce expectedAce, byte[] testBinaryForm, int testOffset)158         public void ObjectAce_CreateFromBinaryForm(GenericAce expectedAce, byte[] testBinaryForm, int testOffset)
159         {
160             GenericAce resultAce = ObjectAce.CreateFromBinaryForm(testBinaryForm, testOffset);
161             GenericAce_VerifyAces(expectedAce, resultAce);
162         }
163     }
164 }
165