wine-staging/patches/0005-ntdll-Inherit-security-attributes-from-parent-direct.patch

181 lines
7.5 KiB
Diff

From 5e49f53a4bd591e67c9b7c4fdaf46933e319f9aa Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Mon, 18 Nov 2013 18:15:20 -0700
Subject: ntdll: Inherit security attributes from parent directories.
---
dlls/advapi32/tests/security.c | 40 ++++++++++++++++++-
dlls/ntdll/file.c | 85 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 123 insertions(+), 2 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 7d28c05..a8d136b 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3013,10 +3013,11 @@ static void test_CreateDirectoryA(void)
ACL_SIZE_INFORMATION acl_size;
ACCESS_ALLOWED_ACE *ace;
SECURITY_ATTRIBUTES sa;
+ char tmpfile[MAX_PATH];
char tmpdir[MAX_PATH];
+ HANDLE token, hTemp;
struct _SID *owner;
BOOL bret = TRUE;
- HANDLE token;
DWORD error;
PACL pDacl;
@@ -3108,6 +3109,43 @@ static void test_CreateDirectoryA(void)
ace->Mask);
}
+ /* Test inheritance of ACLs */
+ strcpy(tmpfile, tmpdir);
+ lstrcatA(tmpfile, "/tmpfile");
+ hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW,
+ FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, (PSID*)&owner,
+ NULL, &pDacl, NULL, &pSD);
+ ok(error == ERROR_SUCCESS, "Failed to get permissions on file.\n");
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ ok(acl_size.AceCount == 2, "GetAclInformation returned unexpected entry count (%d != 2).\n",
+ acl_size.AceCount);
+ if (acl_size.AceCount > 0)
+ {
+ bret = pGetAce(pDacl, 0, (VOID **)&ace);
+ ok(bret, "Inherited Failed to get Current User ACE.\n");
+ bret = EqualSid(&ace->SidStart, user_sid);
+ ok(bret, "Inherited Current User ACE != Current User SID.\n");
+ ok(((ACE_HEADER *)ace)->AceFlags == INHERITED_ACE,
+ "Inherited Current User ACE has unexpected flags (0x%x != 0x10)\n", ((ACE_HEADER *)ace)->AceFlags);
+ ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
+ ace->Mask);
+ }
+ if (acl_size.AceCount > 1)
+ {
+ bret = pGetAce(pDacl, 1, (VOID **)&ace);
+ ok(bret, "Inherited Failed to get Administators Group ACE.\n");
+ bret = EqualSid(&ace->SidStart, admin_sid);
+ ok(bret, "Inherited Administators Group ACE != Administators Group SID.\n");
+ ok(((ACE_HEADER *)ace)->AceFlags == INHERITED_ACE,
+ "Inherited Administators Group ACE has unexpected flags (0x%x != 0x10)\n", ((ACE_HEADER *)ace)->AceFlags);
+ ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
+ ace->Mask);
+ }
+ CloseHandle(hTemp);
+
done:
HeapFree(GetProcessHeap(), 0, user);
bret = RemoveDirectoryA(tmpdir);
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 1de2c61..8948bb7 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -103,6 +103,81 @@ mode_t FILE_umask = 0;
static const WCHAR ntfsW[] = {'N','T','F','S'};
+static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIBUTES attr,
+ PIO_STATUS_BLOCK io, PLARGE_INTEGER alloc_size,
+ ULONG attributes, ULONG sharing, ULONG disposition,
+ ULONG options, PVOID ea_buffer, ULONG ea_length );
+
+struct security_descriptor *FILE_get_parent_sd(UNICODE_STRING *filenameW)
+{
+ SECURITY_INFORMATION info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION
+ |DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
+ PSECURITY_DESCRIPTOR parentsd = NULL;
+ ACL_SIZE_INFORMATION acl_size;
+ BOOLEAN present, defaulted;
+ WCHAR *p, parent[MAX_PATH];
+ OBJECT_ATTRIBUTES pattr;
+ UNICODE_STRING parentW;
+ IO_STATUS_BLOCK io;
+ NTSTATUS status;
+ HANDLE hparent;
+ ULONG n1, n2;
+ PACL pDacl;
+ int i;
+
+ parentW.Buffer = parent;
+ parentW.Length = filenameW->Length;
+ memcpy(parentW.Buffer, filenameW->Buffer, filenameW->Length);
+ if ((p = strrchrW(parent, '\\')) != NULL)
+ {
+ p[0] = 0;
+ parentW.Length = (p-parent)*sizeof(WCHAR);
+ }
+ memset(&pattr, 0x0, sizeof(pattr));
+ pattr.Length = sizeof(pattr);
+ pattr.Attributes = OBJ_CASE_INSENSITIVE;
+ pattr.ObjectName = &parentW;
+ status = FILE_CreateFile( &hparent, READ_CONTROL|ACCESS_SYSTEM_SECURITY, &pattr, &io, NULL,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
+ FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
+ if (status == STATUS_SUCCESS)
+ status = NtQuerySecurityObject( hparent, info, NULL, 0, &n1 );
+ if (status == STATUS_BUFFER_TOO_SMALL && (parentsd = RtlAllocateHeap( GetProcessHeap(), 0, n1 )) != NULL)
+ status = NtQuerySecurityObject( hparent, info, parentsd, n1, &n2 );
+ if (status == STATUS_SUCCESS)
+ status = NtQuerySecurityObject( hparent, info, parentsd, n1, &n2 );
+ if (hparent != INVALID_HANDLE_VALUE)
+ NtClose( hparent );
+ if (status != STATUS_SUCCESS) return NULL;
+ status = RtlGetDaclSecurityDescriptor(parentsd, &present, &pDacl, &defaulted);
+ if (status != STATUS_SUCCESS || !present) return NULL;
+ status = RtlQueryInformationAcl(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ if (status != STATUS_SUCCESS) return NULL;
+
+ for (i=acl_size.AceCount-1; i>=0; i--)
+ {
+ DWORD inheritance_mask = INHERIT_ONLY_ACE|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE;
+ ACE_HEADER *ace;
+
+ status = RtlGetAce(pDacl, i, (VOID **)&ace);
+ if (status != STATUS_SUCCESS || !(ace->AceFlags & inheritance_mask))
+ {
+ RtlDeleteAce(pDacl, i);
+ acl_size.AceCount--;
+ }
+ else
+ ace->AceFlags = (ace->AceFlags & ~inheritance_mask) | INHERITED_ACE;
+ }
+
+ if (!acl_size.AceCount)
+ {
+ return NULL;
+ }
+ return parentsd;
+}
+
+
/**************************************************************************
* FILE_CreateFile (internal)
* Open a file.
@@ -161,10 +236,18 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
{
struct security_descriptor *sd;
struct object_attributes objattr;
+ PSECURITY_DESCRIPTOR parentsd = NULL, psd;
objattr.rootdir = wine_server_obj_handle( attr->RootDirectory );
objattr.name_len = 0;
- io->u.Status = NTDLL_create_struct_sd( attr->SecurityDescriptor, &sd, &objattr.sd_len );
+ psd = attr->SecurityDescriptor;
+ if (!psd && (disposition == FILE_CREATE||disposition == FILE_OVERWRITE_IF))
+ parentsd = FILE_get_parent_sd( attr->ObjectName );
+ if (parentsd)
+ psd = parentsd;
+ io->u.Status = NTDLL_create_struct_sd( psd, &sd, &objattr.sd_len );
+ if (parentsd)
+ RtlFreeHeap( GetProcessHeap(), 0, parentsd );
if (io->u.Status != STATUS_SUCCESS)
{
RtlFreeAnsiString( &unix_name );
--
1.7.9.5