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_INSUFFICIENT_RESOURCES
;
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_INSUFFICIENT_RESOURCES
;
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 PSECURITY_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_INSUFFICIENT_RESOURCES
;
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
,
234 /* check if the Administrators are the owner and at least a not-NULL DACL
236 if (OwnerSid
!= NULL
&&
237 RtlEqualSid(OwnerSid
,
239 DaclPresent
&& Dacl
!= NULL
)
241 /* check the DACL for an Allowed ACE for the SYSTEM account */
245 Status
= RtlGetAce(Dacl
,
248 if (!NT_SUCCESS(Status
))
252 else if (Ace
!= NULL
&& Ace
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
254 /* check if the the ACE is a set of allowed permissions for the
255 local SYSTEM account */
256 if (RtlEqualSid((PSID
)(Ace
+ 1),
259 /* check if the ACE is inherited by noncontainer and
260 container objects, if not attempt to change that */
261 if (!(Ace
->Header
.AceFlags
& OBJECT_INHERIT_ACE
) ||
262 !(Ace
->Header
.AceFlags
& CONTAINER_INHERIT_ACE
))
264 Ace
->Header
.AceFlags
|= OBJECT_INHERIT_ACE
| CONTAINER_INHERIT_ACE
;
265 Status
= ZwSetSecurityObject(DirectoryHandle
,
266 DACL_SECURITY_INFORMATION
,
271 /* all done, we have access */
272 Status
= STATUS_SUCCESS
;
278 } while (Ace
!= NULL
);
281 AbsSDSize
= DescriptorSize
;
283 /* because we need to change any existing data we need to convert it to
284 an absolute security descriptor first */
285 Status
= RtlSelfRelativeToAbsoluteSD2(RelSD
,
288 if (Status
== STATUS_BUFFER_TOO_SMALL
)
290 /* this error code can only be returned on 64 bit builds because
291 the size of an absolute security descriptor is greater than the
292 size of a self-relative security descriptor */
293 ASSERT(AbsSDSize
> DescriptorSize
);
295 AbsSD
= RtlpAllocateMemory(DescriptorSize
,
296 TAG('S', 'e', 'S', 'd'));
299 Status
= STATUS_INSUFFICIENT_RESOURCES
;
303 AbsSDAllocated
= TRUE
;
305 /* make a raw copy of the self-relative descriptor */
310 /* finally convert it */
311 Status
= RtlSelfRelativeToAbsoluteSD2(AbsSD
,
320 if (!NT_SUCCESS(Status
))
325 /* set the owner SID */
326 Status
= RtlSetOwnerSecurityDescriptor(AbsSD
,
329 if (!NT_SUCCESS(Status
))
334 /* set the DACL in the security descriptor */
335 Status
= RtlSetDaclSecurityDescriptor(AbsSD
,
337 SecurityDescriptor
->Dacl
,
339 if (!NT_SUCCESS(Status
))
344 /* convert it back to a self-relative descriptor, find out how much
346 Status
= RtlAbsoluteToSelfRelativeSD(AbsSD
,
349 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
354 /* allocate enough memory for the new self-relative descriptor */
355 NewRelSD
= RtlpAllocateMemory(RelSDSize
,
356 TAG('S', 'e', 'S', 'd'));
357 if (NewRelSD
== NULL
)
362 /* convert the security descriptor to self-relative format */
363 Status
= RtlAbsoluteToSelfRelativeSD(AbsSD
,
366 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
371 /* finally attempt to change the security information */
372 Status
= ZwSetSecurityObject(DirectoryHandle
,
373 OWNER_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
377 if (AdminSid
!= NULL
)
379 RtlFreeSid(AdminSid
);
382 if (LocalSystemSid
!= NULL
)
384 RtlFreeSid(LocalSystemSid
);
389 RtlpFreeMemory(RelSD
,
390 TAG('S', 'e', 'S', 'd'));
393 if (NewRelSD
!= NULL
)
395 RtlpFreeMemory(NewRelSD
,
396 TAG('S', 'e', 'S', 'd'));
402 RtlpFreeMemory(AbsSD
,
403 TAG('S', 'e', 'S', 'd'));
411 RtlpSysVolTakeOwnership(IN PUNICODE_STRING DirectoryPath
,
412 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
414 TOKEN_PRIVILEGES TokenPrivileges
;
415 OBJECT_ATTRIBUTES ObjectAttributes
;
416 SECURITY_DESCRIPTOR AbsSD
;
417 PSID AdminSid
= NULL
;
418 IO_STATUS_BLOCK IoStatusBlock
;
419 BOOLEAN TokenEnabled
= FALSE
;
420 HANDLE hToken
= NULL
;
421 HANDLE hDirectory
= NULL
;
424 Status
= ZwOpenProcessToken(NtCurrentProcess(),
425 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
427 if (!NT_SUCCESS(Status
))
432 /* attempt to enable the SE_TAKE_OWNERSHIP_PRIVILEGE privilege */
433 TokenPrivileges
.PrivilegeCount
= 1;
434 TokenPrivileges
.Privileges
[0].Luid
.LowPart
= SE_TAKE_OWNERSHIP_PRIVILEGE
;
435 TokenPrivileges
.Privileges
[0].Luid
.HighPart
= 0;
436 TokenPrivileges
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
437 Status
= ZwAdjustPrivilegesToken(hToken
,
440 sizeof(TokenPrivileges
),
443 if (!NT_SUCCESS(Status
))
447 TokenEnabled
= (TokenPrivileges
.PrivilegeCount
!= 0);
449 /* open the directory */
450 InitializeObjectAttributes(&ObjectAttributes
,
456 Status
= ZwOpenFile(&hDirectory
,
457 SYNCHRONIZE
| WRITE_OWNER
,
460 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
461 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
462 if (!NT_SUCCESS(Status
))
467 /* create the Administrators SID */
468 Status
= RtlAllocateAndInitializeSid(&LocalSystemAuthority
,
470 SECURITY_BUILTIN_DOMAIN_RID
,
471 DOMAIN_ALIAS_RID_ADMINS
,
479 if (!NT_SUCCESS(Status
))
484 /* create the security descriptor */
485 Status
= RtlCreateSecurityDescriptor(&AbsSD
,
486 SECURITY_DESCRIPTOR_REVISION
);
487 if (!NT_SUCCESS(Status
))
492 Status
= RtlSetOwnerSecurityDescriptor(&AbsSD
,
495 if (!NT_SUCCESS(Status
))
500 /* attempt to take ownership */
501 Status
= ZwSetSecurityObject(hDirectory
,
502 OWNER_SECURITY_INFORMATION
,
508 ZwAdjustPrivilegesToken(hToken
,
516 if (AdminSid
!= NULL
)
518 RtlFreeSid(AdminSid
);
521 if (hDirectory
!= NULL
)
539 RtlCreateSystemVolumeInformationFolder(
540 IN PUNICODE_STRING VolumeRootPath
543 OBJECT_ATTRIBUTES ObjectAttributes
;
544 IO_STATUS_BLOCK IoStatusBlock
;
546 UNICODE_STRING DirectoryName
, NewPath
;
548 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
549 PSID SystemSid
= NULL
;
550 BOOLEAN AddSep
= FALSE
;
555 RtlInitUnicodeString(&DirectoryName
,
556 L
"System Volume Information");
558 PathLen
= VolumeRootPath
->Length
+ DirectoryName
.Length
;
560 /* make sure we don't overflow while appending the strings */
561 if (PathLen
> 0xFFFC)
563 return STATUS_INVALID_PARAMETER
;
566 if (VolumeRootPath
->Buffer
[(VolumeRootPath
->Length
/ sizeof(WCHAR
)) - 1] != L
'\\')
569 PathLen
+= sizeof(WCHAR
);
572 /* allocate the new string */
573 NewPath
.MaximumLength
= (USHORT
)PathLen
+ sizeof(WCHAR
);
574 NewPath
.Buffer
= RtlpAllocateStringMemory(NewPath
.MaximumLength
,
576 if (NewPath
.Buffer
== NULL
)
578 return STATUS_INSUFFICIENT_RESOURCES
;
581 /* create the new path string */
582 NewPath
.Length
= VolumeRootPath
->Length
;
583 RtlCopyMemory(NewPath
.Buffer
,
584 VolumeRootPath
->Buffer
,
588 NewPath
.Buffer
[NewPath
.Length
/ sizeof(WCHAR
)] = L
'\\';
589 NewPath
.Length
+= sizeof(WCHAR
);
591 RtlCopyMemory(NewPath
.Buffer
+ (NewPath
.Length
/ sizeof(WCHAR
)),
592 DirectoryName
.Buffer
,
593 DirectoryName
.Length
);
594 NewPath
.Length
+= DirectoryName
.Length
;
595 NewPath
.Buffer
[NewPath
.Length
/ sizeof(WCHAR
)] = L
'\0';
597 ASSERT(NewPath
.Length
== PathLen
);
598 ASSERT(NewPath
.Length
== NewPath
.MaximumLength
- sizeof(WCHAR
));
600 /* create the security descriptor for the new directory */
601 Status
= RtlpSysVolCreateSecurityDescriptor(&SecurityDescriptor
,
603 if (NT_SUCCESS(Status
))
605 /* create or open the directory */
606 InitializeObjectAttributes(&ObjectAttributes
,
612 Status
= ZwCreateFile(&hDirectory
,
613 SYNCHRONIZE
| WRITE_OWNER
| WRITE_DAC
| READ_CONTROL
,
617 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
,
618 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
620 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
623 if (!NT_SUCCESS(Status
))
625 Status
= RtlpSysVolTakeOwnership(&NewPath
,
628 if (NT_SUCCESS(Status
))
630 /* successfully took ownership, attempt to open it */
631 Status
= ZwCreateFile(&hDirectory
,
632 SYNCHRONIZE
| WRITE_OWNER
| WRITE_DAC
| READ_CONTROL
,
636 FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
,
637 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
639 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
,
645 if (NT_SUCCESS(Status
))
647 /* check security now and adjust it if neccessary */
648 Status
= RtlpSysVolCheckOwnerAndSecurity(hDirectory
,
653 /* free allocated memory */
654 ASSERT(SecurityDescriptor
!= NULL
);
655 ASSERT(SecurityDescriptor
->Dacl
!= NULL
)
657 RtlpFreeMemory(SecurityDescriptor
->Dacl
,
658 TAG('S', 'e', 'A', 'c'));
659 RtlpFreeMemory(SecurityDescriptor
,
660 TAG('S', 'e', 'S', 'd'));
662 RtlFreeSid(SystemSid
);
665 RtlpFreeStringMemory(NewPath
.Buffer
,
675 RtlGetSetBootStatusData(
685 return STATUS_NOT_IMPLEMENTED
;
693 RtlLockBootStatusData(
698 return STATUS_NOT_IMPLEMENTED
;
706 RtlUnlockBootStatusData(
711 return STATUS_NOT_IMPLEMENTED
;