1 /* 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) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include "ntoskrnl.h" 12 #define NDEBUG 13 #include "debug.h" 14 15 /* GLOBALS *******************************************************************/ 16 17 /* FUNCTIONS *****************************************************************/ 18 19 //INIT_FUNCTION 20 PSECURITY_DESCRIPTOR 21 NTAPI 22 CmpHiveRootSecurityDescriptor(VOID) 23 { 24 NTSTATUS Status; 25 PSECURITY_DESCRIPTOR SecurityDescriptor; 26 PACL Acl, AclCopy; 27 PSID Sid[4]; 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; 32 ULONG i; 33 PAGED_CODE(); 34 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); 42 43 /* Make sure all SIDs were allocated */ 44 if (!(Sid[0]) || !(Sid[1]) || !(Sid[2]) || !(Sid[3])) 45 { 46 /* Bugcheck */ 47 KeBugCheckEx(REGISTRY_ERROR, 11, 1, 0, 0); 48 } 49 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); 56 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; 63 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])); 69 70 /* Phase 3: Calculate ACL Length */ 71 AclLength = sizeof(ACL); 72 for (i = 0; i < 4; i++) 73 { 74 /* This is what MSDN says to do */ 75 AceLength = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart); 76 AceLength += SeLengthSid(Sid[i]); 77 AclLength += AceLength; 78 } 79 80 /* Phase 3: Allocate the ACL */ 81 Acl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_CMSD); 82 if (!Acl) KeBugCheckEx(REGISTRY_ERROR, 11, 3, 0, 0); 83 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); 87 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); 94 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; 108 109 /* Phase 6: Allocate the security descriptor and make space for the ACL */ 110 SecurityDescriptor = ExAllocatePoolWithTag(PagedPool, 111 sizeof(SECURITY_DESCRIPTOR) + 112 AclLength, 113 TAG_CMSD); 114 if (!SecurityDescriptor) KeBugCheckEx(REGISTRY_ERROR, 11, 6, 0, 0); 115 116 /* Phase 6: Make a copy of the ACL */ 117 AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor + 1); 118 RtlCopyMemory(AclCopy, Acl, AclLength); 119 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); 124 125 /* Phase 8: Set the ACL as a DACL */ 126 Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, 127 TRUE, 128 AclCopy, 129 FALSE); 130 if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 8, Status, 0); 131 132 /* Free the SIDs and original ACL */ 133 for (i = 0; i < 4; i++) ExFreePoolWithTag(Sid[i], TAG_CMSD); 134 ExFreePoolWithTag(Acl, TAG_CMSD); 135 136 /* Return the security descriptor */ 137 return SecurityDescriptor; 138 } 139 140 NTSTATUS 141 CmpQuerySecurityDescriptor(IN PCM_KEY_CONTROL_BLOCK Kcb, 142 IN SECURITY_INFORMATION SecurityInformation, 143 OUT PSECURITY_DESCRIPTOR SecurityDescriptor, 144 IN OUT PULONG BufferLength) 145 { 146 PISECURITY_DESCRIPTOR_RELATIVE RelSd; 147 ULONG SidSize; 148 ULONG AclSize; 149 ULONG SdSize; 150 NTSTATUS Status; 151 SECURITY_DESCRIPTOR_CONTROL Control = 0; 152 ULONG Owner = 0; 153 ULONG Group = 0; 154 ULONG Dacl = 0; 155 156 DBG_UNREFERENCED_PARAMETER(Kcb); 157 158 DPRINT("CmpQuerySecurityDescriptor()\n"); 159 160 if (SecurityInformation == 0) 161 { 162 return STATUS_ACCESS_DENIED; 163 } 164 165 SidSize = RtlLengthSid(SeWorldSid); 166 RelSd = SecurityDescriptor; 167 SdSize = sizeof(*RelSd); 168 169 if (SecurityInformation & OWNER_SECURITY_INFORMATION) 170 { 171 Owner = SdSize; 172 SdSize += SidSize; 173 } 174 175 if (SecurityInformation & GROUP_SECURITY_INFORMATION) 176 { 177 Group = SdSize; 178 SdSize += SidSize; 179 } 180 181 if (SecurityInformation & DACL_SECURITY_INFORMATION) 182 { 183 Control |= SE_DACL_PRESENT; 184 Dacl = SdSize; 185 AclSize = sizeof(ACL) + sizeof(ACE) + SidSize; 186 SdSize += AclSize; 187 } 188 189 if (SecurityInformation & SACL_SECURITY_INFORMATION) 190 { 191 Control |= SE_SACL_PRESENT; 192 } 193 194 if (*BufferLength < SdSize) 195 { 196 *BufferLength = SdSize; 197 return STATUS_BUFFER_TOO_SMALL; 198 } 199 200 *BufferLength = SdSize; 201 202 Status = RtlCreateSecurityDescriptorRelative(RelSd, 203 SECURITY_DESCRIPTOR_REVISION); 204 if (!NT_SUCCESS(Status)) 205 return Status; 206 207 RelSd->Control |= Control; 208 RelSd->Owner = Owner; 209 RelSd->Group = Group; 210 RelSd->Dacl = Dacl; 211 212 if (Owner) 213 RtlCopyMemory((PUCHAR)RelSd + Owner, 214 SeWorldSid, 215 SidSize); 216 217 if (Group) 218 RtlCopyMemory((PUCHAR)RelSd + Group, 219 SeWorldSid, 220 SidSize); 221 222 if (Dacl) 223 { 224 Status = RtlCreateAcl((PACL)((PUCHAR)RelSd + Dacl), 225 AclSize, 226 ACL_REVISION); 227 if (NT_SUCCESS(Status)) 228 { 229 Status = RtlAddAccessAllowedAce((PACL)((PUCHAR)RelSd + Dacl), 230 ACL_REVISION, 231 GENERIC_ALL, 232 SeWorldSid); 233 } 234 } 235 236 ASSERT(Status == STATUS_SUCCESS); 237 return Status; 238 } 239 240 NTSTATUS 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) 246 { 247 DPRINT("CmpSetSecurityDescriptor()\n"); 248 return STATUS_SUCCESS; 249 } 250 251 NTSTATUS 252 CmpAssignSecurityDescriptor(IN PCM_KEY_CONTROL_BLOCK Kcb, 253 IN PSECURITY_DESCRIPTOR SecurityDescriptor) 254 { 255 DPRINT("CmpAssignSecurityDescriptor(%p %p)\n", 256 Kcb, SecurityDescriptor); 257 return STATUS_SUCCESS; 258 } 259 260 NTSTATUS 261 NTAPI 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) 270 { 271 PCM_KEY_CONTROL_BLOCK Kcb; 272 NTSTATUS Status = STATUS_SUCCESS; 273 274 DBG_UNREFERENCED_PARAMETER(OldSecurityDescriptor); 275 DBG_UNREFERENCED_PARAMETER(GenericMapping); 276 277 Kcb = ((PCM_KEY_BODY)ObjectBody)->KeyControlBlock; 278 279 /* Acquire the hive lock */ 280 CmpLockRegistry(); 281 282 /* Acquire the KCB lock */ 283 if (OperationCode == QuerySecurityDescriptor) 284 { 285 CmpAcquireKcbLockShared(Kcb); 286 } 287 else 288 { 289 CmpAcquireKcbLockExclusive(Kcb); 290 } 291 292 /* Don't touch deleted keys */ 293 if (Kcb->Delete) 294 { 295 /* Release the KCB lock */ 296 CmpReleaseKcbLock(Kcb); 297 298 /* Release the hive lock */ 299 CmpUnlockRegistry(); 300 return STATUS_KEY_DELETED; 301 } 302 303 switch (OperationCode) 304 { 305 case SetSecurityDescriptor: 306 DPRINT("Set security descriptor\n"); 307 ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool)); 308 Status = CmpSetSecurityDescriptor(Kcb, 309 SecurityInformation, 310 SecurityDescriptor, 311 PoolType, 312 GenericMapping); 313 break; 314 315 case QuerySecurityDescriptor: 316 DPRINT("Query security descriptor\n"); 317 Status = CmpQuerySecurityDescriptor(Kcb, 318 *SecurityInformation, 319 SecurityDescriptor, 320 BufferLength); 321 break; 322 323 case DeleteSecurityDescriptor: 324 DPRINT("Delete security descriptor\n"); 325 /* HACK */ 326 break; 327 328 case AssignSecurityDescriptor: 329 DPRINT("Assign security descriptor\n"); 330 Status = CmpAssignSecurityDescriptor(Kcb, 331 SecurityDescriptor); 332 break; 333 334 default: 335 KeBugCheckEx(SECURITY_SYSTEM, 0, STATUS_INVALID_PARAMETER, 0, 0); 336 } 337 338 /* Release the KCB lock */ 339 CmpReleaseKcbLock(Kcb); 340 341 /* Release the hive lock */ 342 CmpUnlockRegistry(); 343 344 return Status; 345 } 346