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_CM
);
38 Sid
[1] = ExAllocatePoolWithTag(PagedPool
, SidLength
, TAG_CM
);
39 Sid
[2] = ExAllocatePoolWithTag(PagedPool
, SidLength
, TAG_CM
);
40 SidLength
= RtlLengthRequiredSid(2);
41 Sid
[3] = ExAllocatePoolWithTag(PagedPool
, SidLength
, TAG_CM
);
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_CM
);
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
[0]);
90 Status
|= RtlAddAccessAllowedAce(Acl
, ACL_REVISION
, KEY_ALL_ACCESS
, Sid
[1]);
91 Status
|= RtlAddAccessAllowedAce(Acl
, ACL_REVISION
, KEY_READ
, Sid
[2]);
92 Status
|= RtlAddAccessAllowedAce(Acl
, ACL_REVISION
, KEY_READ
, Sid
[3]);
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_CM
);
134 ExFreePoolWithTag(Acl
, TAG_CM
);
136 /* Return the security descriptor */
137 return SecurityDescriptor
;
141 CmpQuerySecurityDescriptor(IN PCM_KEY_BODY KeyBody
,
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(KeyBody
);
158 if (SecurityInformation
== 0)
160 return STATUS_ACCESS_DENIED
;
163 SidSize
= RtlLengthSid(SeWorldSid
);
164 RelSd
= SecurityDescriptor
;
165 SdSize
= sizeof(*RelSd
);
167 if (SecurityInformation
& OWNER_SECURITY_INFORMATION
)
173 if (SecurityInformation
& GROUP_SECURITY_INFORMATION
)
179 if (SecurityInformation
& DACL_SECURITY_INFORMATION
)
181 Control
|= SE_DACL_PRESENT
;
183 AclSize
= sizeof(ACL
) + sizeof(ACE
) + SidSize
;
187 if (SecurityInformation
& SACL_SECURITY_INFORMATION
)
189 Control
|= SE_SACL_PRESENT
;
192 if (*BufferLength
< SdSize
)
194 *BufferLength
= SdSize
;
195 return STATUS_BUFFER_TOO_SMALL
;
198 *BufferLength
= SdSize
;
200 Status
= RtlCreateSecurityDescriptorRelative(RelSd
,
201 SECURITY_DESCRIPTOR_REVISION
);
202 if (!NT_SUCCESS(Status
))
205 RelSd
->Control
|= Control
;
206 RelSd
->Owner
= Owner
;
207 RelSd
->Group
= Group
;
211 RtlCopyMemory((PUCHAR
)RelSd
+ Owner
,
216 RtlCopyMemory((PUCHAR
)RelSd
+ Group
,
222 Status
= RtlCreateAcl((PACL
)((PUCHAR
)RelSd
+ Dacl
),
225 if (NT_SUCCESS(Status
))
227 Status
= RtlAddAccessAllowedAce((PACL
)((PUCHAR
)RelSd
+ Dacl
),
234 ASSERT(Status
== STATUS_SUCCESS
);
240 CmpSecurityMethod(IN PVOID ObjectBody
,
241 IN SECURITY_OPERATION_CODE OperationCode
,
242 IN PSECURITY_INFORMATION SecurityInformation
,
243 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
244 IN OUT PULONG BufferLength
,
245 IN OUT PSECURITY_DESCRIPTOR
*OldSecurityDescriptor
,
246 IN POOL_TYPE PoolType
,
247 IN PGENERIC_MAPPING GenericMapping
)
249 DBG_UNREFERENCED_PARAMETER(OldSecurityDescriptor
);
250 DBG_UNREFERENCED_PARAMETER(GenericMapping
);
252 switch (OperationCode
)
254 case SetSecurityDescriptor
:
255 DPRINT("Set security descriptor\n");
256 ASSERT((PoolType
== PagedPool
) || (PoolType
== NonPagedPool
));
260 case QuerySecurityDescriptor
:
261 DPRINT("Query security descriptor\n");
262 return CmpQuerySecurityDescriptor(ObjectBody
,
263 *SecurityInformation
,
267 case DeleteSecurityDescriptor
:
268 DPRINT("Delete security descriptor\n");
272 case AssignSecurityDescriptor
:
273 DPRINT("Assign security descriptor\n");
278 KeBugCheckEx(SECURITY_SYSTEM
, 0, STATUS_INVALID_PARAMETER
, 0, 0);
282 return STATUS_SUCCESS
;