server-{Stored,Inherited}_ACLs: Rework of ACL patches, use upstream code to inherit ACL attributes in advapi32 code.

This commit is contained in:
Sebastian Lackner
2015-04-15 16:09:11 +02:00
parent 96325cabed
commit 04e3ce9865
17 changed files with 649 additions and 1428 deletions

View File

@@ -1,4 +1,4 @@
From 42b83b84ee0ff3b0a9d2439e1d0154287630f192 Mon Sep 17 00:00:00 2001
From a6f078d87958db4e0eb404e7f7cc2d603b92869c Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Fri, 18 Apr 2014 14:08:36 -0600
Subject: server: Inherit security attributes from parent directories on
@@ -10,10 +10,10 @@ Subject: server: Inherit security attributes from parent directories on
2 files changed, 141 insertions(+), 4 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 4db46f5..c509d3c 100644
index 945542e..403c637 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3278,7 +3278,7 @@ static void test_CreateDirectoryA(void)
@@ -3280,7 +3280,7 @@ static void test_CreateDirectoryA(void)
(PSID *)&owner, NULL, &pDacl, NULL, &pSD);
ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
@@ -22,7 +22,7 @@ index 4db46f5..c509d3c 100644
LocalFree(pSD);
CloseHandle(hTemp);
@@ -3348,7 +3348,7 @@ static void test_CreateDirectoryA(void)
@@ -3349,7 +3349,7 @@ static void test_CreateDirectoryA(void)
(PSID *)&owner, NULL, &pDacl, NULL, &pSD);
ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
@@ -50,22 +50,22 @@ index 4db46f5..c509d3c 100644
CloseHandle(hTemp);
diff --git a/server/file.c b/server/file.c
index b6435d1..43be63b 100644
index 8bcf6ee..617c373 100644
--- a/server/file.c
+++ b/server/file.c
@@ -71,6 +71,7 @@ struct file
};
static unsigned int generic_file_map_access( unsigned int access );
+struct security_descriptor *get_xattr_sd( int fd );
+static struct security_descriptor *get_xattr_sd( int fd );
static void file_dump( struct object *obj, int verbose );
static struct fd *file_get_fd( struct object *obj );
@@ -252,11 +253,142 @@ void set_xattr_sd( int fd, const struct security_descriptor *sd, const SID *user
@@ -220,11 +221,142 @@ static void set_xattr_sd( int fd, const struct security_descriptor *sd )
xattr_fset( fd, WINE_XATTR_SD, buffer, len );
}
+struct security_descriptor *inherit_sd( const struct security_descriptor *parent_sd, int is_dir )
+static struct security_descriptor *inherit_sd( const struct security_descriptor *parent_sd, int is_dir )
+{
+ const DWORD inheritance_mask = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
+ struct security_descriptor *sd = NULL;
@@ -201,10 +201,10 @@ index b6435d1..43be63b 100644
const struct security_descriptor *sd )
{
+ struct security_descriptor *temp_sd = NULL;
const SID *owner = NULL, *group = NULL;
struct object *obj = NULL;
struct fd *fd;
@@ -286,6 +418,10 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
int flags;
@@ -253,6 +385,10 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
default: set_error( STATUS_INVALID_PARAMETER ); goto done;
}
@@ -214,8 +214,8 @@ index b6435d1..43be63b 100644
+
if (sd)
{
owner = sd_get_owner( sd );
@@ -329,6 +465,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
const SID *owner = sd_get_owner( sd );
@@ -292,6 +428,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
release_object( fd );
done:
@@ -224,5 +224,5 @@ index b6435d1..43be63b 100644
return obj;
}
--
2.3.3
2.3.5

View File

@@ -1,342 +0,0 @@
From cf51d788cce57b6c5f99bfc15e81790fb5d449c4 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Fri, 18 Apr 2014 14:10:49 -0600
Subject: server: Inherit security attributes from parent directories on
SetSecurityInfo. (try 7)
---
dlls/advapi32/tests/security.c | 68 +++++++++++++++++++++
include/winnt.h | 7 ++-
server/fd.c | 13 +++-
server/file.c | 133 +++++++++++++++++++++++++++++++++++++++--
server/file.h | 1 +
5 files changed, 213 insertions(+), 9 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 3e88c2e..952d001 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3440,6 +3440,74 @@ static void test_GetNamedSecurityInfoA(void)
"Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
}
LocalFree(pSD);
+ CloseHandle(hTemp);
+
+ /* Create security descriptor with no inheritance and test that it comes back the same */
+ pSD = &sd;
+ pDacl = HeapAlloc(GetProcessHeap(), 0, 100);
+ InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+ pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
+ bret = InitializeAcl(pDacl, 100, ACL_REVISION);
+ ok(bret, "Failed to initialize ACL.\n");
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
+ ok(bret, "Failed to add Current User to ACL.\n");
+ bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, 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");
+ GetTempFileNameA(".", "foo", 0, tmpfile);
+ hTemp = CreateFileA(tmpfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ SetLastError(0xdeadbeef);
+ error = pSetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION|PROTECTED_DACL_SECURITY_INFORMATION,
+ NULL, NULL, pDacl, NULL);
+ HeapFree(GetProcessHeap(), 0, pDacl);
+ if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ win_skip("SetNamedSecurityInfoA is not implemented\n");
+ HeapFree(GetProcessHeap(), 0, user);
+ CloseHandle(hTemp);
+ return;
+ }
+ ok(!error, "SetNamedSecurityInfoA failed with error %d\n", error);
+ SetLastError(0xdeadbeef);
+ error = pGetNamedSecurityInfoA(tmpfile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, &pDacl, NULL, &pSD);
+ if (error != ERROR_SUCCESS && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
+ {
+ win_skip("GetNamedSecurityInfoA is not implemented\n");
+ HeapFree(GetProcessHeap(), 0, user);
+ CloseHandle(hTemp);
+ return;
+ }
+ ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
+
+ bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+ ok(bret, "GetAclInformation failed\n");
+ 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);
+ ok(bret, "Current User ACE != Current User SID.\n");
+ ok(((ACE_HEADER *)ace)->AceFlags == 0,
+ "Current User ACE has unexpected flags (0x%x != 0x0)\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);
+ ok(bret || broken(!bret) /* win2k */, "Administators Group ACE != Administators Group SID.\n");
+ ok(((ACE_HEADER *)ace)->AceFlags == 0,
+ "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
+ ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */,
+ "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
+ }
+ LocalFree(pSD);
HeapFree(GetProcessHeap(), 0, user);
CloseHandle(hTemp);
diff --git a/include/winnt.h b/include/winnt.h
index 709a93f..63882bb 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -5078,14 +5078,15 @@ typedef struct _TAPE_GET_MEDIA_PARAMETERS {
BOOLEAN WriteProtected;
} TAPE_GET_MEDIA_PARAMETERS, *PTAPE_GET_MEDIA_PARAMETERS;
-/* ----------------------------- begin registry ----------------------------- */
-
-/* Registry security values */
#define OWNER_SECURITY_INFORMATION 0x00000001
#define GROUP_SECURITY_INFORMATION 0x00000002
#define DACL_SECURITY_INFORMATION 0x00000004
#define SACL_SECURITY_INFORMATION 0x00000008
+#define PROTECTED_DACL_SECURITY_INFORMATION 0x80000000
+/* ----------------------------- begin registry ----------------------------- */
+
+/* Registry security values */
#define REG_OPTION_RESERVED 0x00000000
#define REG_OPTION_NON_VOLATILE 0x00000000
#define REG_OPTION_VOLATILE 0x00000001
diff --git a/server/fd.c b/server/fd.c
index e3b722c..e6ec90a 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1634,6 +1634,16 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
return fd;
}
+char *fd_get_unix_name( struct fd *obj )
+{
+ char *unix_name;
+ if (!obj->unix_name) return NULL;
+ unix_name = mem_alloc( strlen(obj->unix_name) + 1 );
+ if (!unix_name) return NULL;
+ strcpy( unix_name, obj->unix_name );
+ return unix_name;
+}
+
/* duplicate an fd object for a different user */
struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing, unsigned int options )
{
@@ -1647,8 +1657,7 @@ struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sha
if (orig->unix_name)
{
- if (!(fd->unix_name = mem_alloc( strlen(orig->unix_name) + 1 ))) goto failed;
- strcpy( fd->unix_name, orig->unix_name );
+ if (!(fd->unix_name = fd_get_unix_name( orig ))) goto failed;
}
if (orig->inode)
diff --git a/server/file.c b/server/file.c
index 431b8a1..a5d2de3 100644
--- a/server/file.c
+++ b/server/file.c
@@ -329,6 +329,106 @@ struct security_descriptor *inherit_sd( const struct security_descriptor *parent
return sd;
}
+struct security_descriptor *file_combine_sds( const struct security_descriptor *parent_sd,
+ const struct security_descriptor *child_sd )
+{
+ size_t dacl_size = sizeof(ACL), ace_count = 0;
+ const struct security_descriptor *old_sd;
+ struct security_descriptor *sd = NULL;
+ const ACL *child_dacl, *parent_dacl;
+ int child_present, parent_present;
+ const SID *user, *group;
+ const ACE_HEADER *old_ace;
+ ACE_HEADER *ace;
+ ACL *dacl;
+ char *ptr;
+ ULONG i;
+
+ child_dacl = sd_get_dacl( child_sd, &child_present );
+ if (child_present && child_dacl)
+ {
+ old_ace = (const ACE_HEADER *)(child_dacl + 1);
+ for (i = 0; i < child_dacl->AceCount; i++, old_ace = ace_next( old_ace ))
+ {
+ ace_count++;
+ dacl_size += sizeof(ACE_HEADER) + old_ace->AceSize;
+ }
+ }
+
+ parent_dacl = sd_get_dacl( parent_sd, &parent_present );
+ if (parent_present && parent_dacl)
+ {
+ old_ace = (const ACE_HEADER *)(parent_dacl + 1);
+ for (i = 0; i < parent_dacl->AceCount; i++, old_ace = ace_next( old_ace ))
+ {
+ ace_count++;
+ dacl_size += sizeof(ACE_HEADER) + old_ace->AceSize;
+ }
+ }
+
+ if(!ace_count) return sd; /* No inheritance */
+
+ /* FIXME: should use set_info flags? */
+ if (child_present && child_dacl)
+ old_sd = child_sd;
+ else
+ old_sd = parent_sd;
+
+ /* Fill in the security descriptor so that it is compatible with our DACL */
+ user = (const SID *)(old_sd + 1);
+ group = (const SID *)((char *)(old_sd + 1) + old_sd->owner_len);
+ sd = mem_alloc( sizeof(struct security_descriptor) + old_sd->owner_len
+ + old_sd->group_len + dacl_size );
+ if (!sd) return sd;
+ sd->control = SE_DACL_PRESENT;
+ sd->owner_len = old_sd->owner_len;
+ sd->group_len = old_sd->group_len;
+ sd->sacl_len = 0;
+ sd->dacl_len = dacl_size;
+ ptr = (char *)(sd + 1);
+ memcpy( ptr, user, sd->owner_len );
+ ptr += sd->owner_len;
+ memcpy( ptr, group, sd->group_len );
+ ptr += sd->group_len;
+ dacl = (ACL *)ptr;
+ dacl->AclRevision = ACL_REVISION;
+ dacl->Sbz1 = 0;
+ dacl->AclSize = dacl_size;
+ dacl->AceCount = ace_count;
+ dacl->Sbz2 = 0;
+ ace = (ACE_HEADER *)(dacl + 1);
+
+ if (parent_present && parent_dacl)
+ {
+ /* Build the new DACL, inheriting from the parent's information */
+ old_ace = (const ACE_HEADER *)(parent_dacl + 1);
+ for (i = 0; i < parent_dacl->AceCount; i++, old_ace = ace_next( old_ace ))
+ {
+ ace->AceType = old_ace->AceType;
+ ace->AceFlags = old_ace->AceFlags;
+ ace->AceSize = old_ace->AceSize;
+ memcpy( ace + 1, old_ace + 1, old_ace->AceSize - sizeof(ACE_HEADER));
+ ace = (ACE_HEADER *)ace_next( ace );
+ }
+ }
+
+ if (child_present && child_dacl)
+ {
+ /* Build the new DACL, inheriting from the child's information */
+ old_ace = (const ACE_HEADER *)(child_dacl + 1);
+ for (i = 0; i < child_dacl->AceCount; i++, old_ace = ace_next( old_ace ))
+ {
+ ace->AceType = old_ace->AceType;
+ ace->AceFlags = old_ace->AceFlags;
+ ace->AceSize = old_ace->AceSize;
+ memcpy( ace + 1, old_ace + 1, old_ace->AceSize - sizeof(ACE_HEADER));
+ ace = (ACE_HEADER *)ace_next( ace );
+ }
+ }
+
+ return sd;
+}
+
static struct security_descriptor *file_get_parent_sd( struct fd *root, const char *child_name,
int child_len, int is_dir )
{
@@ -800,20 +900,41 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner )
int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
unsigned int set_info )
{
+ struct security_descriptor *tmp_sd = NULL;
int unix_fd = get_unix_fd( fd );
const SID *owner, *group;
struct stat st;
mode_t mode;
+ int ret = 1;
if (unix_fd == -1 || fstat( unix_fd, &st ) == -1) return 1;
+ if (!(set_info & PROTECTED_DACL_SECURITY_INFORMATION))
+ {
+ char *child_name = fd_get_unix_name( fd );
+ if (child_name)
+ {
+ struct security_descriptor *parent_sd;
+ parent_sd = file_get_parent_sd( NULL, child_name, strlen(child_name),
+ S_ISDIR(st.st_mode) );
+ free( child_name );
+ if (parent_sd)
+ {
+ tmp_sd = file_combine_sds( parent_sd, sd );
+ if (tmp_sd) sd = tmp_sd; /* only used combined sd if successful */
+ free( parent_sd );
+ }
+ }
+ }
+
if (set_info & OWNER_SECURITY_INFORMATION)
{
owner = sd_get_owner( sd );
if (!owner)
{
set_error( STATUS_INVALID_SECURITY_DESCR );
- return 0;
+ ret = 0;
+ goto err;
}
if (!obj->sd || !security_equal_sid( owner, sd_get_owner( obj->sd ) ))
{
@@ -831,7 +952,8 @@ int set_file_sd( struct object *obj, struct fd *fd, const struct security_descri
if (!group)
{
set_error( STATUS_INVALID_SECURITY_DESCR );
- return 0;
+ ret = 0;
+ goto err;
}
if (!obj->sd || !security_equal_sid( group, sd_get_group( obj->sd ) ))
{
@@ -856,10 +978,13 @@ int set_file_sd( struct object *obj, struct fd *fd, const struct security_descri
if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1)
{
file_set_error();
- return 0;
+ ret = 0;
}
}
- return 1;
+
+err:
+ free( tmp_sd );
+ return ret;
}
static int file_set_sd( struct object *obj, const struct security_descriptor *sd,
diff --git a/server/file.h b/server/file.h
index be25fb6..b43f329 100644
--- a/server/file.h
+++ b/server/file.h
@@ -79,6 +79,7 @@ extern void allow_fd_caching( struct fd *fd );
extern void set_fd_signaled( struct fd *fd, int signaled );
extern int is_fd_signaled( struct fd *fd );
+extern char *fd_get_unix_name( struct fd *obj );
extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry );
extern unsigned int default_fd_map_access( struct object *obj, unsigned int access );
extern int default_fd_get_poll_events( struct fd *fd );
--
2.1.0