1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * PURPOSE: Boot Data implementation
4 * FILE: lib/rtl/bootdata.c
8 /* INCLUDES *****************************************************************/
15 /* FUNCTIONS *****************************************************************/
17 static SID_IDENTIFIER_AUTHORITY LocalSystemAuthority
= {SECURITY_NT_AUTHORITY
};
20 RtlpSysVolCreateSecurityDescriptor(OUT PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
23 PSECURITY_DESCRIPTOR AbsSD
= NULL
;
24 PSID LocalSystemSid
= NULL
;
29 /* create the local SYSTEM SID */
30 Status
= RtlAllocateAndInitializeSid(&LocalSystemAuthority
,
32 SECURITY_LOCAL_SYSTEM_RID
,
41 if (!NT_SUCCESS(Status
))
46 /* allocate and initialize the security descriptor */
47 AbsSD
= RtlpAllocateMemory(sizeof(SECURITY_DESCRIPTOR
),
48 TAG('S', 'e', 'S', 'd'));
51 Status
= STATUS_NO_MEMORY
;
55 Status
= RtlCreateSecurityDescriptor(AbsSD
,
56 SECURITY_DESCRIPTOR_REVISION
);
57 if (!NT_SUCCESS(Status
))
62 /* allocate and create the DACL */
63 DaclSize
= sizeof(ACL
) + sizeof(ACE
) +
64 RtlLengthSid(LocalSystemSid
);
65 Dacl
= RtlpAllocateMemory(DaclSize
,
66 TAG('S', 'e', 'A', 'c'));
69 Status
= STATUS_NO_MEMORY
;
73 Status
= RtlCreateAcl(Dacl
,
76 if (!NT_SUCCESS(Status
))
81 Status
= RtlAddAccessAllowedAceEx(Dacl
,
83 OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
,
84 STANDARD_RIGHTS_ALL
| SPECIFIC_RIGHTS_ALL
,
86 if (!NT_SUCCESS(Status
))
91 /* set the DACL in the security descriptor */
92 Status
= RtlSetDaclSecurityDescriptor(AbsSD
,
98 if (NT_SUCCESS(Status
))
100 *SecurityDescriptor
= AbsSD
;
101 *SystemSid
= LocalSystemSid
;
106 if (LocalSystemSid
!= NULL
)
108 RtlFreeSid(LocalSystemSid
);
114 TAG('S', 'e', 'A', 'c'));
119 RtlpFreeMemory(AbsSD
,
120 TAG('S', 'e', 'S', 'd'));
128 RtlpSysVolCheckOwnerAndSecurity(IN HANDLE DirectoryHandle
,
129 IN PISECURITY_DESCRIPTOR SecurityDescriptor
)
131 PSECURITY_DESCRIPTOR RelSD
= NULL
;
132 PSECURITY_DESCRIPTOR NewRelSD
= NULL
;
133 PSECURITY_DESCRIPTOR AbsSD
= NULL
;
135 BOOLEAN AbsSDAllocated
= FALSE
;
137 PSID AdminSid
= NULL
;
138 PSID LocalSystemSid
= NULL
;
139 ULONG DescriptorSize
;
140 ULONG AbsSDSize
, RelSDSize
= 0;
142 BOOLEAN DaclPresent
, DaclDefaulted
;
144 BOOLEAN OwnerDefaulted
;
149 /* find out how much memory we need to allocate for the self-relative
150 descriptor we're querying */
151 Status
= ZwQuerySecurityObject(DirectoryHandle
,
152 OWNER_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
156 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
158 /* looks like the FS doesn't support security... return success */
159 Status
= STATUS_SUCCESS
;
163 /* allocate enough memory for the security descriptor */
164 RelSD
= RtlpAllocateMemory(DescriptorSize
,
165 TAG('S', 'e', 'S', 'd'));
168 Status
= STATUS_NO_MEMORY
;
172 /* query the self-relative security descriptor */
173 Status
= ZwQuerySecurityObject(DirectoryHandle
,
174 OWNER_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
178 if (!NT_SUCCESS(Status
))
180 /* FIXME - handle the case where someone else modified the owner and/or
181 DACL while we allocated memory. But that should be *very*
186 /* query the owner and DACL from the descriptor */
187 Status
= RtlGetOwnerSecurityDescriptor(RelSD
,
190 if (!NT_SUCCESS(Status
))
195 Status
= RtlGetDaclSecurityDescriptor(RelSD
,
199 if (!NT_SUCCESS(Status
))
204 /* create the Administrators SID */
205 Status
= RtlAllocateAndInitializeSid(&LocalSystemAuthority
,
207 SECURITY_BUILTIN_DOMAIN_RID
,
208 DOMAIN_ALIAS_RID_ADMINS
,
216 if (!NT_SUCCESS(Status
))
221 /* create the local SYSTEM SID */
222 Status
= RtlAllocateAndInitializeSid(&LocalSystemAuthority
,
224 SECURITY_LOCAL_SYSTEM_RID
,
233 if (!NT_SUCCESS(Status
))
238 /* check if the Administrators are the owner and at least a not-NULL DACL
240 if (OwnerSid
!= NULL
&&
241 RtlEqualSid(OwnerSid
,
243 DaclPresent
&& Dacl
!= NULL
)
245 /* check the DACL for an Allowed ACE for the SYSTEM account */
249 Status
= RtlGetAce(Dacl
,
252 if (!NT_SUCCESS(Status
))
256 else if (Ace
!= NULL
&& Ace
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
258 /* check if the the ACE is a set of allowed permissions for the
259 local SYSTEM account */
260 if (RtlEqualSid((PSID
)(Ace
+ 1),
263 /* check if the ACE is inherited by noncontainer and
264 container objects, if not attempt to change that */
265 if (!(Ace
->Header
.AceFlags
& OBJECT_INHERIT_ACE
) ||
266 !(Ace
->Header
.AceFlags
& CONTAINER_INHERIT_ACE
))
268 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
269 Status
= ZwSetSecurityObject(DirectoryHandle
,
270 DACL_SECURITY_INFORMATION
,
275 /* all done, we have access */
276 Status
= STATUS_SUCCESS
;
282 } while (Ace
!= NULL
);
285 AbsSDSize
= DescriptorSize
;
287 /* because we need to change any existing data we need to convert it to
288 an absolute security descriptor first */
289 Status
= RtlSelfRelativeToAbsoluteSD2(RelSD
,
292 if (Status
== STATUS_BUFFER_TOO_SMALL
)
294 /* this error code can only be returned on 64 bit builds because
295 the size of an absolute security descriptor is greater than the
296 size of a self-relative security descriptor */
297 ASSERT(AbsSDSize
> DescriptorSize
);
299 AbsSD
= RtlpAllocateMemory(DescriptorSize
,
300 TAG('S', 'e', 'S', 'd'));
303 Status
= STATUS_NO_MEMORY
;
307 AbsSDAllocated
= TRUE
;
309 /* make a raw copy of the self-relative descriptor */
314 /* finally convert it */
315 Status
= RtlSelfRelativeToAbsoluteSD2(AbsSD
,
324 if (!NT_SUCCESS(Status
))
329 /* set the owner SID */
330 Status
= RtlSetOwnerSecurityDescriptor(AbsSD
,
333 if (!NT_SUCCESS(Status
))
338 /* set the DACL in the security descriptor */
339 Status
= RtlSetDaclSecurityDescriptor(AbsSD
,
341 SecurityDescriptor
->Dacl
,
343 if (!NT_SUCCESS(Status
))
348 /* convert it back to a self-relative descriptor, find out how much
350 Status
= RtlAbsoluteToSelfRelativeSD(AbsSD
,
353 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
358 /* allocate enough memory for the new self-relative descriptor */
359 NewRelSD
= RtlpAllocateMemory(RelSDSize
,
360 TAG('S', 'e', 'S', 'd'));
361 if (NewRelSD
== NULL
)
363 Status
= STATUS_NO_MEMORY
;
367 /* convert the security descriptor to self-relative format */
368 Status
= RtlAbsoluteToSelfRelativeSD(AbsSD
,
371 if (Status
== STATUS_BUFFER_TOO_SMALL
)
376 /* finally attempt to change the security information */
377 Status
= ZwSetSecurityObject(DirectoryHandle
,
378 OWNER_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
382 if (AdminSid
!= NULL
)
384 RtlFreeSid(AdminSid
);
387 if (LocalSystemSid
!= NULL
)
389 RtlFreeSid(LocalSystemSid
);
394 RtlpFreeMemory(RelSD
,
395 TAG('S', 'e', 'S', 'd'));
398 if (NewRelSD
!= NULL
)
400 RtlpFreeMemory(NewRelSD
,
401 TAG('S', 'e', 'S', 'd'));
407 RtlpFreeMemory(AbsSD
,
408 TAG('S', 'e', 'S', 'd'));
416 RtlpSysVolTakeOwnership(IN PUNICODE_STRING DirectoryPath
,
417 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
419 TOKEN_PRIVILEGES TokenPrivileges
;
420 OBJECT_ATTRIBUTES ObjectAttributes
;
421 SECURITY_DESCRIPTOR AbsSD
;
422 PSID AdminSid
= NULL
;
423 IO_STATUS_BLOCK IoStatusBlock
;
424 BOOLEAN TokenEnabled
= FALSE
;
425 HANDLE hToken
= NULL
;
426 HANDLE hDirectory
= NULL
;
429 Status
= ZwOpenProcessToken(NtCurrentProcess(),
430 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
432 if (!NT_SUCCESS(Status
))
437 /* attempt to enable the SE_TAKE_OWNERSHIP_PRIVILEGE privilege */
438 TokenPrivileges
.PrivilegeCount
= 1;
439 TokenPrivileges
.Privileges
[0].Luid
.LowPart
= SE_TAKE_OWNERSHIP_PRIVILEGE
;
440 TokenPrivileges
.Privileges
[0].Luid
.HighPart
= 0;
441 TokenPrivileges
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
442 Status
= ZwAdjustPrivilegesToken(hToken
,
445 sizeof(TokenPrivileges
),
448 if (!NT_SUCCESS(Status
))
452 TokenEnabled
= (TokenPrivileges
.PrivilegeCount
!= 0);
454 /* open the directory */
455 InitializeObjectAttributes(&ObjectAttributes
,
461 Status
= ZwOpenFile(&hDirectory
,
462 SYNCHRONIZE
| WRITE_OWNER
,
465 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
466 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
467 if (!NT_SUCCESS(Status
))
472 /* create the Administrators SID */
473 Status
= RtlAllocateAndInitializeSid(&LocalSystemAuthority
,
475 SECURITY_BUILTIN_DOMAIN_RID
,
476 DOMAIN_ALIAS_RID_ADMINS
,
484 if (!NT_SUCCESS(Status
))
489 /* create the security descriptor */
490 Status
= RtlCreateSecurityDescriptor(&AbsSD
,
491 SECURITY_DESCRIPTOR_REVISION
);
492 if (!NT_SUCCESS(Status
))
497 Status
= RtlSetOwnerSecurityDescriptor(&AbsSD
,
500 if (!NT_SUCCESS(Status
))
505 /* attempt to take ownership */
506 Status
= ZwSetSecurityObject(hDirectory
,
507 OWNER_SECURITY_INFORMATION
,
513 ZwAdjustPrivilegesToken(hToken
,
521 if (AdminSid
!= NULL
)
523 RtlFreeSid(AdminSid
);
526 if (hDirectory
!= NULL
)
544 RtlCreateSystemVolumeInformationFolder(
545 IN PUNICODE_STRING VolumeRootPath
548 OBJECT_ATTRIBUTES ObjectAttributes
;
549 IO_STATUS_BLOCK IoStatusBlock
;
551 UNICODE_STRING DirectoryName
, NewPath
;
553 PISECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
554 PSID SystemSid
= NULL
;
555 BOOLEAN AddSep
= FALSE
;
560 RtlInitUnicodeString(&DirectoryName
,
561 L
"System Volume Information");
563 PathLen
= VolumeRootPath
->Length
+ DirectoryName
.Length
;
565 /* make sure we don't overflow while appending the strings */
566 if (PathLen
> 0xFFFC)
568 return STATUS_INVALID_PARAMETER
;
571 if (VolumeRootPath
->Buffer
[(VolumeRootPath
->Length
/ sizeof(WCHAR
)) - 1] != L
'\\')
574 PathLen
+= sizeof(WCHAR
);
577 /* allocate the new string */
578 NewPath
.MaximumLength
= (USHORT
)PathLen
+ sizeof(WCHAR
);
579 NewPath
.Buffer
= RtlpAllocateStringMemory(NewPath
.MaximumLength
,
581 if (NewPath
.Buffer
== NULL
)
583 return STATUS_INSUFFICIENT_RESOURCES
;
586 /* create the new path string */
587 NewPath
.Length
= VolumeRootPath
->Length
;
588 RtlCopyMemory(NewPath
.Buffer
,
589 VolumeRootPath
->Buffer
,
593 NewPath
.Buffer
[NewPath
.Length
/ sizeof(WCHAR
)] = L
'\\';
594 NewPath
.Length
+= sizeof(WCHAR
);
596 RtlCopyMemory(NewPath
.Buffer
+ (NewPath
.Length
/ sizeof(WCHAR
)),
597 DirectoryName
.Buffer
,
598 DirectoryName
.Length
);
599 NewPath
.Length
+= DirectoryName
.Length
;
600 NewPath
.Buffer
[NewPath
.Length
/ sizeof(WCHAR
)] = L
'\0';
602 ASSERT(NewPath
.Length
== PathLen
);
603 ASSERT(NewPath
.Length
== NewPath
.MaximumLength
- sizeof(WCHAR
));
605 /* create the security descriptor for the new directory */
606 Status
= RtlpSysVolCreateSecurityDescriptor(&SecurityDescriptor
,
608 if (NT_SUCCESS(Status
))
610 /* create or open the directory */
611 InitializeObjectAttributes(&ObjectAttributes
,
617 Status
= ZwCreateFile(&hDirectory
,
618 SYNCHRONIZE
| WRITE_OWNER
| WRITE_DAC
| READ_CONTROL
,
622 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
,
623 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
625 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
628 if (!NT_SUCCESS(Status
))
630 Status
= RtlpSysVolTakeOwnership(&NewPath
,
633 if (NT_SUCCESS(Status
))
635 /* successfully took ownership, attempt to open it */
636 Status
= ZwCreateFile(&hDirectory
,
637 SYNCHRONIZE
| WRITE_OWNER
| WRITE_DAC
| READ_CONTROL
,
641 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
,
642 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
644 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
650 if (NT_SUCCESS(Status
))
652 /* check security now and adjust it if neccessary */
653 Status
= RtlpSysVolCheckOwnerAndSecurity(hDirectory
,
658 /* free allocated memory */
659 ASSERT(SecurityDescriptor
!= NULL
);
660 ASSERT(SecurityDescriptor
->Dacl
!= NULL
);
662 RtlpFreeMemory(SecurityDescriptor
->Dacl
,
663 TAG('S', 'e', 'A', 'c'));
664 RtlpFreeMemory(SecurityDescriptor
,
665 TAG('S', 'e', 'S', 'd'));
667 RtlFreeSid(SystemSid
);
670 RtlpFreeStringMemory(NewPath
.Buffer
,
680 RtlGetSetBootStatusData(
690 return STATUS_NOT_IMPLEMENTED
;
698 RtlLockBootStatusData(
703 return STATUS_NOT_IMPLEMENTED
;
711 RtlUnlockBootStatusData(
716 return STATUS_NOT_IMPLEMENTED
;