2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmse.c
5 * PURPOSE: Configuration Manager - Security Subsystem Interface
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 /* FUNCTIONS *****************************************************************/
22 CmpHiveRootSecurityDescriptor(VOID
)
25 PSECURITY_DESCRIPTOR SecurityDescriptor
;
28 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
29 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
30 ULONG AceLength
, AclLength
, SidLength
;
31 PACE_HEADER AceHeader
;
35 /* Phase 1: Allocate SIDs */
36 SidLength
= RtlLengthRequiredSid(1);
37 Sid
[0] = ExAllocatePoolWithTag(PagedPool
, SidLength
, TAG_CMSD
);
38 Sid
[1] = ExAllocatePoolWithTag(PagedPool
, SidLength
, TAG_CMSD
);
39 Sid
[2] = ExAllocatePoolWithTag(PagedPool
, SidLength
, TAG_CMSD
);
40 SidLength
= RtlLengthRequiredSid(2);
41 Sid
[3] = ExAllocatePoolWithTag(PagedPool
, SidLength
, TAG_CMSD
);
43 /* Make sure all SIDs were allocated */
44 if (!(Sid
[0]) || !(Sid
[1]) || !(Sid
[2]) || !(Sid
[3]))
47 KeBugCheckEx(REGISTRY_ERROR
, 11, 1, 0, 0);
50 /* Phase 2: Initialize all SIDs */
51 Status
= RtlInitializeSid(Sid
[0], &WorldAuthority
, 1);
52 Status
|= RtlInitializeSid(Sid
[1], &NtAuthority
, 1);
53 Status
|= RtlInitializeSid(Sid
[2], &NtAuthority
, 1);
54 Status
|= RtlInitializeSid(Sid
[3], &NtAuthority
, 2);
55 if (!NT_SUCCESS(Status
)) KeBugCheckEx(REGISTRY_ERROR
, 11, 2, 0, 0);
57 /* Phase 2: Setup SID Sub Authorities */
58 *RtlSubAuthoritySid(Sid
[0], 0) = SECURITY_WORLD_RID
;
59 *RtlSubAuthoritySid(Sid
[1], 0) = SECURITY_RESTRICTED_CODE_RID
;
60 *RtlSubAuthoritySid(Sid
[2], 0) = SECURITY_LOCAL_SYSTEM_RID
;
61 *RtlSubAuthoritySid(Sid
[3], 0) = SECURITY_BUILTIN_DOMAIN_RID
;
62 *RtlSubAuthoritySid(Sid
[3], 1) = DOMAIN_ALIAS_RID_ADMINS
;
64 /* Make sure all SIDs are valid */
65 ASSERT(RtlValidSid(Sid
[0]));
66 ASSERT(RtlValidSid(Sid
[1]));
67 ASSERT(RtlValidSid(Sid
[2]));
68 ASSERT(RtlValidSid(Sid
[3]));
70 /* Phase 3: Calculate ACL Length */
71 AclLength
= sizeof(ACL
);
72 for (i
= 0; i
< 4; i
++)
74 /* This is what MSDN says to do */
75 AceLength
= FIELD_OFFSET(ACCESS_ALLOWED_ACE
, SidStart
);
76 AceLength
+= SeLengthSid(Sid
[i
]);
77 AclLength
+= AceLength
;
80 /* Phase 3: Allocate the ACL */
81 Acl
= ExAllocatePoolWithTag(PagedPool
, AclLength
, TAG_CMSD
);
82 if (!Acl
) KeBugCheckEx(REGISTRY_ERROR
, 11, 3, 0, 0);
84 /* Phase 4: Create the ACL */
85 Status
= RtlCreateAcl(Acl
, AclLength
, ACL_REVISION
);
86 if (!NT_SUCCESS(Status
)) KeBugCheckEx(REGISTRY_ERROR
, 11, 4, Status
, 0);
88 /* Phase 5: Build the ACL */
89 Status
= RtlAddAccessAllowedAce(Acl
, ACL_REVISION
, KEY_ALL_ACCESS
, Sid
[2]);
90 Status
|= RtlAddAccessAllowedAce(Acl
, ACL_REVISION
, KEY_ALL_ACCESS
, Sid
[3]);
91 Status
|= RtlAddAccessAllowedAce(Acl
, ACL_REVISION
, KEY_READ
, Sid
[0]);
92 Status
|= RtlAddAccessAllowedAce(Acl
, ACL_REVISION
, KEY_READ
, Sid
[1]);
93 if (!NT_SUCCESS(Status
)) KeBugCheckEx(REGISTRY_ERROR
, 11, 5, Status
, 0);
95 /* Phase 5: Make the ACEs inheritable */
96 Status
= RtlGetAce(Acl
, 0, (PVOID
*)&AceHeader
);
97 ASSERT(NT_SUCCESS(Status
));
98 AceHeader
->AceFlags
|= CONTAINER_INHERIT_ACE
;
99 Status
= RtlGetAce(Acl
, 1, (PVOID
*)&AceHeader
);
100 ASSERT(NT_SUCCESS(Status
));
101 AceHeader
->AceFlags
|= CONTAINER_INHERIT_ACE
;
102 Status
= RtlGetAce(Acl
, 2, (PVOID
*)&AceHeader
);
103 ASSERT(NT_SUCCESS(Status
));
104 AceHeader
->AceFlags
|= CONTAINER_INHERIT_ACE
;
105 Status
= RtlGetAce(Acl
, 3, (PVOID
*)&AceHeader
);
106 ASSERT(NT_SUCCESS(Status
));
107 AceHeader
->AceFlags
|= CONTAINER_INHERIT_ACE
;
109 /* Phase 6: Allocate the security descriptor and make space for the ACL */
110 SecurityDescriptor
= ExAllocatePoolWithTag(PagedPool
,
111 sizeof(SECURITY_DESCRIPTOR
) +
114 if (!SecurityDescriptor
) KeBugCheckEx(REGISTRY_ERROR
, 11, 6, 0, 0);
116 /* Phase 6: Make a copy of the ACL */
117 AclCopy
= (PACL
)((PISECURITY_DESCRIPTOR
)SecurityDescriptor
+ 1);
118 RtlCopyMemory(AclCopy
, Acl
, AclLength
);
120 /* Phase 7: Create the security descriptor */
121 Status
= RtlCreateSecurityDescriptor(SecurityDescriptor
,
122 SECURITY_DESCRIPTOR_REVISION
);
123 if (!NT_SUCCESS(Status
)) KeBugCheckEx(REGISTRY_ERROR
, 11, 7, Status
, 0);
125 /* Phase 8: Set the ACL as a DACL */
126 Status
= RtlSetDaclSecurityDescriptor(SecurityDescriptor
,
130 if (!NT_SUCCESS(Status
)) KeBugCheckEx(REGISTRY_ERROR
, 11, 8, Status
, 0);
132 /* Free the SIDs and original ACL */
133 for (i
= 0; i
< 4; i
++) ExFreePoolWithTag(Sid
[i
], TAG_CMSD
);
134 ExFreePoolWithTag(Acl
, TAG_CMSD
);
136 /* Return the security descriptor */
137 return SecurityDescriptor
;
141 CmpQuerySecurityDescriptor(IN PCM_KEY_CONTROL_BLOCK Kcb
,
142 IN SECURITY_INFORMATION SecurityInformation
,
143 OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
144 IN OUT PULONG BufferLength
)
146 PISECURITY_DESCRIPTOR_RELATIVE RelSd
;
151 SECURITY_DESCRIPTOR_CONTROL Control
= 0;
156 DBG_UNREFERENCED_PARAMETER(Kcb
);
158 DPRINT("CmpQuerySecurityDescriptor()\n");
160 if (SecurityInformation
== 0)
162 return STATUS_ACCESS_DENIED
;
165 SidSize
= RtlLengthSid(SeWorldSid
);
166 RelSd
= SecurityDescriptor
;
167 SdSize
= sizeof(*RelSd
);
169 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
175 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
181 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
183 Control
|= SE_DACL_PRESENT
;
185 AclSize
= sizeof(ACL
) + sizeof(ACE
) + SidSize
;
189 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
191 Control
|= SE_SACL_PRESENT
;
194 if (*BufferLength
< SdSize
)
196 *BufferLength
= SdSize
;
197 return STATUS_BUFFER_TOO_SMALL
;
200 *BufferLength
= SdSize
;
202 Status
= RtlCreateSecurityDescriptorRelative(RelSd
,
203 SECURITY_DESCRIPTOR_REVISION
);
204 if (!NT_SUCCESS(Status
))
207 RelSd
->Control
|= Control
;
208 RelSd
->Owner
= Owner
;
209 RelSd
->Group
= Group
;
213 RtlCopyMemory((PUCHAR
)RelSd
+ Owner
,
218 RtlCopyMemory((PUCHAR
)RelSd
+ Group
,
224 Status
= RtlCreateAcl((PACL
)((PUCHAR
)RelSd
+ Dacl
),
227 if (NT_SUCCESS(Status
))
229 Status
= RtlAddAccessAllowedAce((PACL
)((PUCHAR
)RelSd
+ Dacl
),
236 ASSERT(Status
== STATUS_SUCCESS
);
241 CmpSetSecurityDescriptor(IN PCM_KEY_CONTROL_BLOCK Kcb
,
242 IN PSECURITY_INFORMATION SecurityInformation
,
243 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
244 IN POOL_TYPE PoolType
,
245 IN PGENERIC_MAPPING GenericMapping
)
247 DPRINT("CmpSetSecurityDescriptor()\n");
248 return STATUS_SUCCESS
;
252 CmpAssignSecurityDescriptor(IN PCM_KEY_CONTROL_BLOCK Kcb
,
253 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
255 DPRINT("CmpAssignSecurityDescriptor(%p %p)\n",
256 Kcb
, SecurityDescriptor
);
257 return STATUS_SUCCESS
;
262 CmpSecurityMethod(IN PVOID ObjectBody
,
263 IN SECURITY_OPERATION_CODE OperationCode
,
264 IN PSECURITY_INFORMATION SecurityInformation
,
265 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
266 IN OUT PULONG BufferLength
,
267 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
268 IN POOL_TYPE PoolType
,
269 IN PGENERIC_MAPPING GenericMapping
)
271 PCM_KEY_CONTROL_BLOCK Kcb
;
272 NTSTATUS Status
= STATUS_SUCCESS
;
274 DBG_UNREFERENCED_PARAMETER(OldSecurityDescriptor
);
275 DBG_UNREFERENCED_PARAMETER(GenericMapping
);
277 Kcb
= ((PCM_KEY_BODY
)ObjectBody
)->KeyControlBlock
;
279 /* Acquire the hive lock */
282 /* Acquire the KCB lock */
283 if (OperationCode
== QuerySecurityDescriptor
)
285 CmpAcquireKcbLockShared(Kcb
);
289 CmpAcquireKcbLockExclusive(Kcb
);
292 /* Don't touch deleted keys */
295 /* Release the KCB lock */
296 CmpReleaseKcbLock(Kcb
);
298 /* Release the hive lock */
300 return STATUS_KEY_DELETED
;
303 switch (OperationCode
)
305 case SetSecurityDescriptor
:
306 DPRINT("Set security descriptor\n");
307 ASSERT((PoolType
== PagedPool
) || (PoolType
== NonPagedPool
));
308 Status
= CmpSetSecurityDescriptor(Kcb
,
315 case QuerySecurityDescriptor
:
316 DPRINT("Query security descriptor\n");
317 Status
= CmpQuerySecurityDescriptor(Kcb
,
318 *SecurityInformation
,
323 case DeleteSecurityDescriptor
:
324 DPRINT("Delete security descriptor\n");
328 case AssignSecurityDescriptor
:
329 DPRINT("Assign security descriptor\n");
330 Status
= CmpAssignSecurityDescriptor(Kcb
,
335 KeBugCheckEx(SECURITY_SYSTEM
, 0, STATUS_INVALID_PARAMETER
, 0, 0);
338 /* Release the KCB lock */
339 CmpReleaseKcbLock(Kcb
);
341 /* Release the hive lock */