wine-staging/patches/0006-ntdll-Inherit-security-attributes-from-parent-direct.patch
2013-11-21 13:33:37 -07:00

181 lines
7.5 KiB
Diff

From c4219ad0d05c2e61b4d3408b2b8c57d762a58c4b Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Fri, 9 Aug 2013 20:57:23 -0600
Subject: ntdll: Inherit security attributes from parent directories.
---
dlls/kernel32/tests/directory.c | 40 +++++++++++++++++-
dlls/ntdll/file.c | 85 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 123 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/directory.c b/dlls/kernel32/tests/directory.c
index a8dfa81..a3a9580 100644
--- a/dlls/kernel32/tests/directory.c
+++ b/dlls/kernel32/tests/directory.c
@@ -505,10 +505,11 @@ static void test_security_attributes(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;
@@ -599,6 +600,43 @@ static void test_security_attributes(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 5147ef5..79a700c 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -94,6 +94,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.
@@ -152,10 +227,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