https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d8cc88ca808274a1d5961…
commit d8cc88ca808274a1d5961aa1503222c34a7a9ad2
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sun Oct 30 22:42:22 2022 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Nov 1 02:34:04 2022 +0100
[KERNEL32][BASESRV] Fix interoperability with Win2k3 regarding NLS section security.
(#4828)
Partially revert some aspects of commits 5696e4ba4 and bf40c7a31.
(See PR #4340.)
In order for Win2k3 kernel32.dll to operate with our basesrv.dll (or our
kernel32.dll to operate with Win2k3 basesrv.dll), we need in particular
to have the CreateNlsSecurityDescriptor() helper to exactly take the
expected parameters. Namely, a pointer to a **user-allocated**
SECURITY_DESCRIPTOR buffer, its size (and an access mask).
The function expects its caller to provide all this, and the caller expects
the function to initialize the security descriptor buffer. Note that the
function does *NOT* allocate a new descriptor buffer to be returned!
Indeed, with the way it currently is in master, using Win2k3 kernel32
with our basesrv is now failing with the errors:
```
NLSAPI: Could NOT Create ACL - c0000023.
(subsystems/win/basesrv/nls.c:279) NLS: CreateNlsSecurityDescriptor FAILED!: c0000023
NLSAPI: Could NOT initialize Server - c0000023.
(dll/ntdll/ldr/ldrinit.c:867) LDR: DLL_PROCESS_ATTACH for dll "kernel32.dll"
(InitRoutine: 77E40D95) failed
```
(and, if we ever attempted to increase the so-claimed "dummy parameter"
descriptor size in the basesrv call, we would end up with its stack
corrupted and a crash).
Conversely, using our kernel32 with Win2k3 basesrv, would end up with
basesrv receiving a wrongly-initialized descriptor that would not work
(the buffer not being initialized with the contents of a descriptor, but
instead receiving some address to a descriptor allocated somewhere else).
---
dll/win32/kernel32/winnls/string/nls.c | 458 +++++++++++----------------------
sdk/include/reactos/subsys/win/base.h | 8 +
subsystems/win/basesrv/basesrv.h | 3 -
subsystems/win/basesrv/nls.c | 16 +-
4 files changed, 172 insertions(+), 313 deletions(-)
diff --git a/dll/win32/kernel32/winnls/string/nls.c
b/dll/win32/kernel32/winnls/string/nls.c
index d810c429069..f6fb3576f74 100644
--- a/dll/win32/kernel32/winnls/string/nls.c
+++ b/dll/win32/kernel32/winnls/string/nls.c
@@ -57,13 +57,89 @@ BOOL WINAPI
GetCPFileNameFromRegistry(UINT CodePage, LPWSTR FileName, ULONG FileNameSize);
NTSTATUS
-CreateNlsDirectorySecurity(_Out_ PSECURITY_DESCRIPTOR *NlsSecurityDescriptor);
-
-NTSTATUS WINAPI
-CreateNlsSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor, _In_ SIZE_T
DescriptorSize, _In_ ULONG AccessMask);
+WINAPI
+CreateNlsSecurityDescriptor(
+ _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ _In_ SIZE_T DescriptorSize,
+ _In_ ULONG AccessMask);
/* PRIVATE FUNCTIONS **********************************************************/
+/**
+ * @brief
+ * Creates a security descriptor for the NLS object directory.
+ *
+ * @param[out] SecurityDescriptor
+ * @param[in] DescriptorSize
+ * Same parameters as for CreateNlsSecurityDescriptor().
+ *
+ * @remark
+ * Everyone (World SID) is given read access to the NLS directory,
+ * whereas Admins are given full access.
+ */
+static NTSTATUS
+CreateNlsDirectorySecurity(
+ _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ _In_ SIZE_T DescriptorSize)
+{
+ static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+ NTSTATUS Status;
+ PSID AdminsSid;
+ PACL Dacl;
+ BOOLEAN DaclPresent, DaclDefaulted;
+
+ /* Give everyone basic directory access */
+ Status = CreateNlsSecurityDescriptor(SecurityDescriptor,
+ DescriptorSize,
+ DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create basic NLS SD (Status 0x%08x)\n", Status);
+ return Status;
+ }
+
+ /* Create the Admins SID */
+ // NOTE: Win <= 2k3 uses SYSTEM instead (SECURITY_LOCAL_SYSTEM_RID with one
SubAuthority)
+ Status = RtlAllocateAndInitializeSid(&NtAuthority,
+ 2,
+ SECURITY_BUILTIN_DOMAIN_RID,
+ DOMAIN_ALIAS_RID_ADMINS,
+ 0, 0, 0, 0, 0, 0,
+ &AdminsSid);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create Admins SID (Status 0x%08x)\n", Status);
+ goto Quit;
+ }
+
+ /* Retrieve the DACL from the descriptor */
+ Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
+ &DaclPresent,
+ &Dacl,
+ &DaclDefaulted);
+ if (!NT_SUCCESS(Status) || !DaclPresent || !Dacl)
+ {
+ DPRINT1("Failed to get DACL from descriptor (Status 0x%08x)\n",
Status);
+ goto Quit;
+ }
+
+ /* Add an allowed access ACE to the Admins SID with full access.
+ * The function verifies the DACL is large enough to accommodate it. */
+ Status = RtlAddAccessAllowedAce(Dacl,
+ ACL_REVISION,
+ DIRECTORY_ALL_ACCESS,
+ AdminsSid);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to add allowed access ACE for Admins SID (Status
0x%08x)\n", Status);
+ goto Quit;
+ }
+
+Quit:
+ RtlFreeSid(AdminsSid);
+ return Status;
+}
+
/**
* @name NlsInit
*
@@ -74,11 +150,12 @@ BOOL
FASTCALL
NlsInit(VOID)
{
+ NTSTATUS Status;
UNICODE_STRING DirName;
OBJECT_ATTRIBUTES ObjectAttributes;
- PSECURITY_DESCRIPTOR NlsDirSd;
HANDLE Handle;
- NTSTATUS Status;
+ UCHAR SecurityDescriptor[NLS_SECTION_SECURITY_DESCRIPTOR_SIZE +
+ NLS_SIZEOF_ACE_AND_SIDS(2)];
InitializeListHead(&CodePageListHead);
RtlInitializeCriticalSection(&CodePageListLock);
@@ -86,12 +163,13 @@ NlsInit(VOID)
/*
* FIXME: Eventually this should be done only for the NLS Server
* process, but since we don't have anything like that (yet?) we
- * always try to create the "\Nls" directory here.
+ * always try to create the "\NLS" directory here.
*/
- RtlInitUnicodeString(&DirName, L"\\Nls");
+ RtlInitUnicodeString(&DirName, L"\\NLS");
- /* Create a security descriptor for NLS directory */
- Status = CreateNlsDirectorySecurity(&NlsDirSd);
+ /* Create a security descriptor for the NLS directory */
+ Status = CreateNlsDirectorySecurity(&SecurityDescriptor,
+ sizeof(SecurityDescriptor));
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create NLS directory security (Status 0x%08x)\n",
Status);
@@ -102,9 +180,12 @@ NlsInit(VOID)
&DirName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL,
- NlsDirSd);
+ &SecurityDescriptor);
- if (NT_SUCCESS(NtCreateDirectoryObject(&Handle, DIRECTORY_TRAVERSE |
DIRECTORY_CREATE_OBJECT, &ObjectAttributes)))
+ Status = NtCreateDirectoryObject(&Handle,
+ DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT,
+ &ObjectAttributes);
+ if (NT_SUCCESS(Status))
{
NtClose(Handle);
}
@@ -128,7 +209,6 @@ NlsInit(VOID)
OemCodePage.CodePage = OemCodePage.CodePageTable.CodePage;
InsertTailList(&CodePageListHead, &OemCodePage.Entry);
- RtlFreeHeap(RtlGetProcessHeap(), 0, NlsDirSd);
return TRUE;
}
@@ -212,17 +292,18 @@ PCODEPAGE_ENTRY
FASTCALL
IntGetCodePageEntry(UINT CodePage)
{
- CHAR SectionName[40];
NTSTATUS Status;
+ CHAR SectionName[40];
HANDLE SectionHandle = INVALID_HANDLE_VALUE, FileHandle;
PBYTE SectionMapping;
OBJECT_ATTRIBUTES ObjectAttributes;
+ UCHAR SecurityDescriptor[NLS_SECTION_SECURITY_DESCRIPTOR_SIZE];
ANSI_STRING AnsiName;
UNICODE_STRING UnicodeName;
WCHAR FileName[MAX_PATH + 1];
UINT FileNamePos;
PCODEPAGE_ENTRY CodePageEntry;
- PSECURITY_DESCRIPTOR NlsSd;
+
if (CodePage == CP_ACP)
{
return &AnsiCodePage;
@@ -294,17 +375,26 @@ IntGetCodePageEntry(UINT CodePage)
* However since we do not do that, let the kernel32 do the job
* by assigning security to NLS section names for the time being...
*/
- Status = CreateNlsSecurityDescriptor(&NlsSd, sizeof(SECURITY_DESCRIPTOR),
SECTION_MAP_READ);
+ Status = CreateNlsSecurityDescriptor(&SecurityDescriptor,
+ sizeof(SecurityDescriptor),
+ SECTION_MAP_READ);
if (!NT_SUCCESS(Status))
{
+ DPRINT1("CreateNlsSecurityDescriptor FAILED! (Status 0x%08x)\n",
Status);
RtlLeaveCriticalSection(&CodePageListLock);
return NULL;
}
- InitializeObjectAttributes(&ObjectAttributes, &UnicodeName, 0, NULL, NlsSd);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &UnicodeName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ SecurityDescriptor);
/* Try to open the section first */
- Status = NtOpenSection(&SectionHandle, SECTION_MAP_READ, &ObjectAttributes);
+ Status = NtOpenSection(&SectionHandle,
+ SECTION_MAP_READ,
+ &ObjectAttributes);
/* If the section doesn't exist, try to create it. */
if (Status == STATUS_UNSUCCESSFUL ||
@@ -349,7 +439,6 @@ IntGetCodePageEntry(UINT CodePage)
}
}
RtlFreeUnicodeString(&UnicodeName);
- HeapFree(GetProcessHeap(), 0, NlsSd);
if (!NT_SUCCESS(Status))
{
@@ -2274,33 +2363,49 @@ IsDBCSLeadByte(BYTE TestByte)
/**
* @brief
- * Creates a security descriptor for the NLS object directory
- * name.
+ * Creates a security descriptor for each NLS section. Typically used by
+ * BASESRV to give Everyone (World SID) read access to the sections.
+ *
+ * @param[out] SecurityDescriptor
+ * A pointer to a correctly sized user-allocated buffer, that receives
+ * a security descriptor containing one ACL with one World SID.
+ * Its size should be at least equal to NLS_SECTION_SECURITY_DESCRIPTOR_SIZE.
*
- * @param[out] SecurityDescriptor
- * A pointer to an allocated and created security descriptor
- * that is given to the caller.
+ * @param[in] DescriptorSize
+ * Size (in bytes) of the user-provided SecurityDescriptor buffer.
+ *
+ * @param[in] AccessMask
+ * An access mask that grants Everyone an access specific to that mask.
*
* @return
* STATUS_SUCCESS is returned if the function has successfully
* created a security descriptor for a NLS section name. Otherwise
* a NTSTATUS failure code is returned.
*
- * @remarks
- * Everyone (aka World SID) is given read access to the NLS directory
- * whereas admins are given full power.
- */
+ * @remark
+ * This implementation has to be made compatible with NT <= 5.2 in order
+ * to inter-operate with BASESRV. In particular, the security descriptor
+ * is a user-provided buffer correctly sized. The caller is responsible
+ * to submit the exact size of the descriptor.
+ **/
NTSTATUS
-CreateNlsDirectorySecurity(_Out_ PSECURITY_DESCRIPTOR *NlsSecurityDescriptor)
+WINAPI
+CreateNlsSecurityDescriptor(
+ _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ _In_ SIZE_T DescriptorSize,
+ _In_ ULONG AccessMask)
{
+ static SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
NTSTATUS Status;
+ PSID WorldSid;
PACL Dacl;
- PSID WorldSid = NULL, AdminsSid = NULL;
- ULONG DaclSize, RelSdSize = 0;
- PSECURITY_DESCRIPTOR RelativeSd = NULL;
- SECURITY_DESCRIPTOR AbsoluteSd;
- static SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
- static SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+ ULONG DaclSize;
+
+ if (DescriptorSize < NLS_SECTION_SECURITY_DESCRIPTOR_SIZE)
+ {
+ DPRINT1("Security descriptor size too small\n");
+ return STATUS_BUFFER_TOO_SMALL;
+ }
/* Create the World SID */
Status = RtlAllocateAndInitializeSid(&WorldAuthority,
@@ -2310,304 +2415,49 @@ CreateNlsDirectorySecurity(_Out_ PSECURITY_DESCRIPTOR
*NlsSecurityDescriptor)
&WorldSid);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CreateNlsDirectorySecurity(): Failed to create world SID (Status
0x%08x)\n", Status);
+ DPRINT1("Failed to create World SID (Status 0x%08x)\n", Status);
return Status;
}
- /* Create the admins SID */
- Status = RtlAllocateAndInitializeSid(&NtAuthority,
- 2,
- SECURITY_BUILTIN_DOMAIN_RID,
- DOMAIN_ALIAS_RID_ADMINS,
- 0, 0, 0, 0, 0, 0,
- &AdminsSid);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CreateNlsDirectorySecurity(): Failed to create admins SID (Status
0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Build up the size of our DACL, including the World and admins SIDs */
- DaclSize = sizeof(ACL) +
- sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(WorldSid) +
- sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(AdminsSid);
-
- /* Allocate memory for our DACL */
- Dacl = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, DaclSize);
- if (Dacl == NULL)
- {
- DPRINT1("CreateNlsDirectorySecurity(): Could not allocate memory for DACL,
not enough memory!\n");
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto Quit;
- }
-
- /* Create the DACL */
- Status = RtlCreateAcl(Dacl, DaclSize, ACL_REVISION);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CreateNlsDirectorySecurity(): Failed to create the DACL (Status
0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Give everyone basic directory access */
- Status = RtlAddAccessAllowedAce(Dacl,
- ACL_REVISION,
- DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT,
- WorldSid);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CreateNlsDirectorySecurity(): Failed to insert allowed access ACE
to DACL for World SID (Status 0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Give admins full power */
- Status = RtlAddAccessAllowedAce(Dacl,
- ACL_REVISION,
- DIRECTORY_ALL_ACCESS,
- AdminsSid);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CreateNlsDirectorySecurity(): Failed to insert allowed access ACE
to DACL for admins SID (Status 0x%08x)\n", Status);
- goto Quit;
- }
-
/* Initialize the security descriptor */
- Status = RtlCreateSecurityDescriptor(&AbsoluteSd,
+ Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CreateNlsDirectorySecurity(): Failed to initialize the security
descriptor (Status 0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Set the DACL to descriptor */
- Status = RtlSetDaclSecurityDescriptor(&AbsoluteSd,
- TRUE,
- Dacl,
- FALSE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CreateNlsDirectorySecurity(): Failed to insert DACL into the
descriptor (Status 0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Determine how much size is needed to convert the absolute SD into self-relative
one */
- Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
- NULL,
- &RelSdSize);
- if (Status != STATUS_BUFFER_TOO_SMALL)
- {
- DPRINT1("CreateNlsDirectorySecurity(): Unexpected status code, must be
STATUS_BUFFER_TOO_SMALL (Status 0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Allocate buffer for relative SD */
- RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, RelSdSize);
- if (RelativeSd == NULL)
- {
- DPRINT1("CreateNlsDirectorySecurity(): Could not allocate memory for
relative SD, not enough memory!\n");
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto Quit;
- }
-
- /* Convert it now */
- Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
- RelativeSd,
- &RelSdSize);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CreateNlsDirectorySecurity(): Failed to convert absolute SD to
self-relative format (Status 0x%08x)\n", Status);
+ DPRINT1("Failed to create security descriptor (Status 0x%08x)\n",
Status);
goto Quit;
}
- /* Give the security descriptor to the caller */
- *NlsSecurityDescriptor = RelativeSd;
-
-Quit:
- if (WorldSid != NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, WorldSid);
- }
-
- if (AdminsSid != NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, AdminsSid);
- }
-
- if (Dacl != NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
- }
-
- if (!NT_SUCCESS(Status))
- {
- if (RelativeSd != NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
- }
- }
-
- return Status;
-}
-
-/**
- * @brief
- * Creates a security descriptor for each NLS section
- * name.
- *
- * @param[in] AccessMask
- * An access mask bit to supply to the function. This
- * access mask grants everyone access specific to that
- * bit mask.
- *
- * @param[out] SecurityDescriptor
- * A pointer to an allocated and created security descriptor
- * that is given to the caller.
- *
- * @return
- * STATUS_SUCCESS is returned if the function has successfully
- * created a security descriptor for a NLS section name. Otherwise
- * a NTSTATUS failure code is returned.
- *
- * @remarks
- * The implementation of CreateNlsSecurityDescriptor on Windows Server
- * 2003 is slightly different compared to ours. The second parameter
- * takes the size of a security descriptor, in bytes. This is implied
- * that on Windows the caller is responsible to submit the exact
- * size of the descriptor. On ReactOS we're going to do it different,
- * let the function be responsible for security descriptor creation
- * and its size. DescriptorSize will act like a dummy parameter for us
- * in this case. Everyone (aka World SID) is given read access to each
- * NLS section name.
- */
-NTSTATUS WINAPI CreateNlsSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR
*SecurityDescriptor, _In_ SIZE_T DescriptorSize, _In_ ULONG AccessMask)
-{
- NTSTATUS Status;
- PACL Dacl;
- PSID WorldSid = NULL;
- ULONG DaclSize, RelSdSize = 0;
- PSECURITY_DESCRIPTOR RelativeSd = NULL;
- SECURITY_DESCRIPTOR AbsoluteSd;
- static SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
-
- /* DescriptorSize is just a dummy parameter */
- UNREFERENCED_PARAMETER(DescriptorSize);
-
- /* Create the World SID */
- Status = RtlAllocateAndInitializeSid(&WorldAuthority,
- 1,
- SECURITY_WORLD_RID,
- 0, 0, 0, 0, 0, 0, 0,
- &WorldSid);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CreateNlsSecurityDescriptor(): Failed to create world SID (Status
0x%08x)\n", Status);
- return Status;
- }
-
- /* Build up the size of our DACL, including the World SID */
- DaclSize = sizeof(ACL) +
- sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(WorldSid);
-
- /* Allocate memory for our DACL */
- Dacl = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, DaclSize);
- if (Dacl == NULL)
- {
- DPRINT1("CreateNlsSecurityDescriptor(): Could not allocate memory for DACL,
not enough memory!\n");
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto Quit;
- }
+ /* The DACL follows the security descriptor, and includes the World SID */
+ Dacl = (PACL)((ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR));
+ DaclSize = DescriptorSize - sizeof(SECURITY_DESCRIPTOR);
/* Create the DACL */
Status = RtlCreateAcl(Dacl, DaclSize, ACL_REVISION);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CreateNlsSecurityDescriptor(): Failed to create the DACL (Status
0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Add a ACE with allow access to the World SID */
- Status = RtlAddAccessAllowedAce(Dacl,
- ACL_REVISION,
- AccessMask,
- WorldSid);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CreateNlsSecurityDescriptor(): Failed to insert allowed access ACE
to DACL for World SID (Status 0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Initialize the security descriptor */
- Status = RtlCreateSecurityDescriptor(&AbsoluteSd,
- SECURITY_DESCRIPTOR_REVISION);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CreateNlsSecurityDescriptor(): Failed to insert allowed access ACE
to DACL for World SID (Status 0x%08x)\n", Status);
+ DPRINT1("Failed to create DACL (Status 0x%08x)\n", Status);
goto Quit;
}
- /* Set the DACL to descriptor */
- Status = RtlSetDaclSecurityDescriptor(&AbsoluteSd,
- TRUE,
- Dacl,
- FALSE);
+ /* Add an allowed access ACE to the World SID */
+ Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, AccessMask, WorldSid);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CreateNlsSecurityDescriptor(): Failed to insert DACL into the
descriptor (Status 0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Determine how much size is needed to convert the absolute SD into self-relative
one */
- Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
- NULL,
- &RelSdSize);
- if (Status != STATUS_BUFFER_TOO_SMALL)
- {
- DPRINT1("CreateNlsSecurityDescriptor(): Unexpected status code, must be
STATUS_BUFFER_TOO_SMALL (Status 0x%08x)\n", Status);
- goto Quit;
- }
-
- /* Allocate buffer for relative SD */
- RelativeSd = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, RelSdSize);
- if (RelativeSd == NULL)
- {
- DPRINT1("CreateNlsSecurityDescriptor(): Could not allocate memory for
relative SD, not enough memory!\n");
- Status = STATUS_INSUFFICIENT_RESOURCES;
+ DPRINT1("Failed to add allowed access ACE for World SID (Status
0x%08x)\n", Status);
goto Quit;
}
- /* Convert it now */
- Status = RtlAbsoluteToSelfRelativeSD(&AbsoluteSd,
- RelativeSd,
- &RelSdSize);
+ /* Set the DACL to the descriptor */
+ Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, TRUE, Dacl, FALSE);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CreateNlsSecurityDescriptor(): Failed to convert absolute SD to
self-relative format (Status 0x%08x)\n", Status);
+ DPRINT1("Failed to set DACL into descriptor (Status 0x%08x)\n",
Status);
goto Quit;
}
- /* Give the security descriptor to the caller */
- *SecurityDescriptor = RelativeSd;
-
Quit:
- if (WorldSid != NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, WorldSid);
- }
-
- if (Dacl != NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
- }
-
- if (!NT_SUCCESS(Status))
- {
- if (RelativeSd != NULL)
- {
- RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSd);
- }
- }
-
+ RtlFreeSid(WorldSid);
return Status;
}
diff --git a/sdk/include/reactos/subsys/win/base.h
b/sdk/include/reactos/subsys/win/base.h
index 61f5bfce56d..28f21bee7dd 100644
--- a/sdk/include/reactos/subsys/win/base.h
+++ b/sdk/include/reactos/subsys/win/base.h
@@ -23,6 +23,14 @@ VOID
NTAPI
BaseSetProcessCreateNotify(IN BASE_PROCESS_CREATE_NOTIFY_ROUTINE
ProcessCreateNotifyProc);
+#define NLS_SIZEOF_ACE_AND_SIDS(n) \
+ (FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) + \
+ FIELD_OFFSET(SID, SubAuthority) + (n)*RTL_FIELD_SIZE(SID, SubAuthority))
+
+/* Minimal size for the security descriptors of the "\NLS\NlsSection*" sections
*/
+#define NLS_SECTION_SECURITY_DESCRIPTOR_SIZE \
+ (sizeof(SECURITY_DESCRIPTOR) + sizeof(ACL) + NLS_SIZEOF_ACE_AND_SIDS(1))
+
typedef struct _NLS_USER_INFO
{
WCHAR sLanguage[80];
diff --git a/subsystems/win/basesrv/basesrv.h b/subsystems/win/basesrv/basesrv.h
index a1180f02348..8cae7fd5fd0 100644
--- a/subsystems/win/basesrv/basesrv.h
+++ b/subsystems/win/basesrv/basesrv.h
@@ -58,9 +58,6 @@ typedef BOOL (WINAPI *PGET_NLS_SECTION_NAME)(UINT CodePage,
ULONG ResultSize);
typedef BOOL (WINAPI *PVALIDATE_LOCALE)(IN ULONG LocaleId);
-typedef NTSTATUS (WINAPI *PCREATE_NLS_SECURTY_DESCRIPTOR)(_Out_ PVOID
*SecurityDescriptorBuffer,
- _In_ ULONG DescriptorSize,
- _In_ ULONG AccessMask);
/* Globals */
extern HANDLE BaseSrvHeap;
diff --git a/subsystems/win/basesrv/nls.c b/subsystems/win/basesrv/nls.c
index d8bcac32c48..630b94cad99 100644
--- a/subsystems/win/basesrv/nls.c
+++ b/subsystems/win/basesrv/nls.c
@@ -33,7 +33,12 @@ PVALIDATE_LOCALE pValidateLocale;
PGET_NLS_SECTION_NAME pGetNlsSectionName;
PVOID /*PGET_USER_DEFAULT_LANGID*/ pGetUserDefaultLangID;
PGET_CP_FILE_NAME_FROM_REGISTRY pGetCPFileNameFromRegistry;
-PCREATE_NLS_SECURTY_DESCRIPTOR pCreateNlsSecurityDescriptor;
+
+NTSTATUS
+(WINAPI *pCreateNlsSecurityDescriptor)(
+ _Out_ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ _In_ SIZE_T DescriptorSize,
+ _In_ ULONG AccessMask);
BASESRV_KERNEL_IMPORTS BaseSrvKernel32Imports[10] =
{
@@ -161,7 +166,7 @@ CSR_API(BaseSrvNlsCreateSection)
ULONG LocaleId;
UNICODE_STRING NlsSectionName;
PWCHAR NlsFileName;
- PSECURITY_DESCRIPTOR NlsSd;
+ UCHAR SecurityDescriptor[NLS_SECTION_SECURITY_DESCRIPTOR_SIZE];
OBJECT_ATTRIBUTES ObjectAttributes;
WCHAR FileNameBuffer[32];
WCHAR NlsSectionNameBuffer[32];
@@ -271,8 +276,8 @@ CSR_API(BaseSrvNlsCreateSection)
}
/* Create an SD for the section object */
- Status = pCreateNlsSecurityDescriptor(&NlsSd,
- sizeof(SECURITY_DESCRIPTOR),
+ Status = pCreateNlsSecurityDescriptor(&SecurityDescriptor,
+ sizeof(SecurityDescriptor),
SECTION_MAP_READ);
if (!NT_SUCCESS(Status))
{
@@ -286,7 +291,7 @@ CSR_API(BaseSrvNlsCreateSection)
&NlsSectionName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT | OBJ_OPENIF,
NULL,
- NlsSd);
+ &SecurityDescriptor);
Status = NtCreateSection(&SectionHandle,
SECTION_MAP_READ,
&ObjectAttributes,
@@ -295,7 +300,6 @@ CSR_API(BaseSrvNlsCreateSection)
SEC_COMMIT,
FileHandle);
NtClose(FileHandle);
- RtlFreeHeap(RtlGetProcessHeap(), 0, NlsSd);
if (!NT_SUCCESS(Status))
{
DPRINT1("NLS: Failed to create section! %lx\n", Status);