mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
206 lines
8.3 KiB
Diff
206 lines
8.3 KiB
Diff
|
From 8ffcfda480ef0475910eee359c8e447571b078cf Mon Sep 17 00:00:00 2001
|
||
|
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||
|
Date: Fri, 9 Aug 2013 20:56:15 -0600
|
||
|
Subject: server: Create directories with the specified security attributes.
|
||
|
|
||
|
---
|
||
|
dlls/kernel32/tests/directory.c | 135 +++++++++++++++++++++++++++++++++++++++
|
||
|
server/fd.c | 2 +-
|
||
|
server/file.c | 7 +-
|
||
|
3 files changed, 142 insertions(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/dlls/kernel32/tests/directory.c b/dlls/kernel32/tests/directory.c
|
||
|
index 9baae47..df434b6 100644
|
||
|
--- a/dlls/kernel32/tests/directory.c
|
||
|
+++ b/dlls/kernel32/tests/directory.c
|
||
|
@@ -24,6 +24,15 @@
|
||
|
#include "windef.h"
|
||
|
#include "winbase.h"
|
||
|
#include "winerror.h"
|
||
|
+#include "aclapi.h"
|
||
|
+
|
||
|
+static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
|
||
|
+ PSID*, PSID*, PACL*, PACL*,
|
||
|
+ PSECURITY_DESCRIPTOR*);
|
||
|
+static BOOL (WINAPI *pGetAclInformation)(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS);
|
||
|
+static BOOL (WINAPI *pCreateWellKnownSid)(WELL_KNOWN_SID_TYPE,PSID,PSID,DWORD*);
|
||
|
+static BOOL (WINAPI *pAddAccessAllowedAceEx)(PACL, DWORD, DWORD, DWORD, PSID);
|
||
|
+static BOOL (WINAPI *pGetAce)(PACL,DWORD,LPVOID*);
|
||
|
|
||
|
/* If you change something in these tests, please do the same
|
||
|
* for GetSystemDirectory tests.
|
||
|
@@ -486,8 +495,132 @@ static void test_SetCurrentDirectoryA(void)
|
||
|
ok( GetLastError() == ERROR_PATH_NOT_FOUND, "wrong error %d\n", GetLastError() );
|
||
|
}
|
||
|
|
||
|
+static void test_security_attributes(void)
|
||
|
+{
|
||
|
+ char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], *user;
|
||
|
+ DWORD sid_size = sizeof(admin_ptr), user_size;
|
||
|
+ PSID admin_sid = (PSID) admin_ptr, user_sid;
|
||
|
+ char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
|
||
|
+ PSECURITY_DESCRIPTOR pSD = &sd;
|
||
|
+ ACL_SIZE_INFORMATION acl_size;
|
||
|
+ ACCESS_ALLOWED_ACE *ace;
|
||
|
+ SECURITY_ATTRIBUTES sa;
|
||
|
+ char tmpdir[MAX_PATH];
|
||
|
+ struct _SID *owner;
|
||
|
+ BOOL bret = TRUE;
|
||
|
+ HANDLE token;
|
||
|
+ DWORD error;
|
||
|
+ PACL pDacl;
|
||
|
+
|
||
|
+ if (!pGetNamedSecurityInfoA || !pCreateWellKnownSid)
|
||
|
+ {
|
||
|
+ win_skip("Required functions are not available\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
|
||
|
+ {
|
||
|
+ if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
|
||
|
+ else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
|
||
|
+ }
|
||
|
+ if (!bret)
|
||
|
+ {
|
||
|
+ win_skip("Failed to get current user token\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ bret = GetTokenInformation(token, TokenUser, NULL, 0, &user_size);
|
||
|
+ ok(!bret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER),
|
||
|
+ "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
|
||
|
+ user = HeapAlloc(GetProcessHeap(), 0, user_size);
|
||
|
+ bret = GetTokenInformation(token, TokenUser, user, user_size, &user_size);
|
||
|
+ ok(bret, "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
|
||
|
+ CloseHandle( token );
|
||
|
+ user_sid = ((TOKEN_USER *)user)->User.Sid;
|
||
|
+
|
||
|
+ sa.nLength = sizeof(sa);
|
||
|
+ sa.lpSecurityDescriptor = pSD;
|
||
|
+ sa.bInheritHandle = TRUE;
|
||
|
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
|
||
|
+ pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
|
||
|
+ pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
|
||
|
+ bret = InitializeAcl(pDacl, 100, ACL_REVISION);
|
||
|
+ ok(bret, "Failed to initialize ACL.\n");
|
||
|
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
|
||
|
+ GENERIC_ALL, user_sid);
|
||
|
+ ok(bret, "Failed to add Current User to ACL.\n");
|
||
|
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
|
||
|
+ GENERIC_ALL, admin_sid);
|
||
|
+ ok(bret, "Failed to add Administrator Group to ACL.\n");
|
||
|
+ bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
|
||
|
+ ok(bret, "Failed to add ACL to security desciptor.\n");
|
||
|
+
|
||
|
+ GetTempPathA(MAX_PATH, tmpdir);
|
||
|
+ lstrcatA(tmpdir, "Please Remove Me");
|
||
|
+ bret = CreateDirectoryA(tmpdir, &sa);
|
||
|
+ ok(bret == TRUE, "CreateDirectoryA(%s) failed err=%d\n", tmpdir, GetLastError());
|
||
|
+ HeapFree(GetProcessHeap(), 0, pDacl);
|
||
|
+
|
||
|
+ SetLastError(0xdeadbeef);
|
||
|
+ error = pGetNamedSecurityInfoA(tmpdir, SE_FILE_OBJECT,
|
||
|
+ OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, (PSID*)&owner,
|
||
|
+ NULL, &pDacl, NULL, &pSD);
|
||
|
+ if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
|
||
|
+ {
|
||
|
+ win_skip("GetNamedSecurityInfoA is not implemented\n");
|
||
|
+ goto done;
|
||
|
+ }
|
||
|
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
|
||
|
+
|
||
|
+ 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, "Failed to get Current User ACE.\n");
|
||
|
+ bret = EqualSid(&ace->SidStart, user_sid);
|
||
|
+ todo_wine ok(bret, "Current User ACE != Current User SID.\n");
|
||
|
+ todo_wine ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||
|
+ "Current User ACE has unexpected flags (0x%x != 0x03)\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, "Failed to get Administators Group ACE.\n");
|
||
|
+ bret = EqualSid(&ace->SidStart, admin_sid);
|
||
|
+ todo_wine ok(bret, "Administators Group ACE != Administators Group SID.\n");
|
||
|
+ todo_wine ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||
|
+ "Administators Group ACE has unexpected flags (0x%x != 0x03)\n",
|
||
|
+ ((ACE_HEADER *)ace)->AceFlags);
|
||
|
+ ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
||
|
+ ace->Mask);
|
||
|
+ }
|
||
|
+
|
||
|
+done:
|
||
|
+ HeapFree(GetProcessHeap(), 0, user);
|
||
|
+ bret = RemoveDirectoryA(tmpdir);
|
||
|
+ ok(bret == TRUE, "RemoveDirectoryA should always succeed\n");
|
||
|
+}
|
||
|
+
|
||
|
+void init(void)
|
||
|
+{
|
||
|
+ HMODULE hmod = GetModuleHandle("advapi32.dll");
|
||
|
+
|
||
|
+ pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA");
|
||
|
+ pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx");
|
||
|
+ pCreateWellKnownSid = (void *)GetProcAddress(hmod, "CreateWellKnownSid");
|
||
|
+ pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation");
|
||
|
+ pGetAce = (void *)GetProcAddress(hmod, "GetAce");
|
||
|
+}
|
||
|
+
|
||
|
START_TEST(directory)
|
||
|
{
|
||
|
+ init();
|
||
|
+
|
||
|
test_GetWindowsDirectoryA();
|
||
|
test_GetWindowsDirectoryW();
|
||
|
|
||
|
@@ -501,4 +634,6 @@ START_TEST(directory)
|
||
|
test_RemoveDirectoryW();
|
||
|
|
||
|
test_SetCurrentDirectoryA();
|
||
|
+
|
||
|
+ test_security_attributes();
|
||
|
}
|
||
|
diff --git a/server/fd.c b/server/fd.c
|
||
|
index f3e42bd..248f15a 100644
|
||
|
--- a/server/fd.c
|
||
|
+++ b/server/fd.c
|
||
|
@@ -1765,7 +1765,7 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
||
|
/* create the directory if needed */
|
||
|
if ((options & FILE_DIRECTORY_FILE) && (flags & O_CREAT))
|
||
|
{
|
||
|
- if (mkdir( name, 0777 ) == -1)
|
||
|
+ if (mkdir( name, *mode ) == -1)
|
||
|
{
|
||
|
if (errno != EEXIST || (flags & O_EXCL))
|
||
|
{
|
||
|
diff --git a/server/file.c b/server/file.c
|
||
|
index 2ecf97c..9c6cb80 100644
|
||
|
--- a/server/file.c
|
||
|
+++ b/server/file.c
|
||
|
@@ -219,7 +219,12 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
|
||
|
mode = sd_to_mode( sd, owner );
|
||
|
}
|
||
|
else
|
||
|
- mode = (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
|
||
|
+ {
|
||
|
+ if (options & FILE_NON_DIRECTORY_FILE)
|
||
|
+ mode = (attrs & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
|
||
|
+ else
|
||
|
+ mode = (attrs & FILE_ATTRIBUTE_READONLY) ? 0555 : 0777;
|
||
|
+ }
|
||
|
|
||
|
if (len >= 4 &&
|
||
|
(!strcasecmp( name + len - 4, ".exe" ) || !strcasecmp( name + len - 4, ".com" )))
|
||
|
--
|
||
|
1.7.9.5
|
||
|
|