mirror of
https://abf.rosa.ru/djam/wine.git
synced 2025-02-24 06:42:47 +00:00
499 lines
20 KiB
Diff
499 lines
20 KiB
Diff
From 78a5ebb94f3717bedd77f7c096e8fce1e9a640d1 Mon Sep 17 00:00:00 2001
|
|
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
|
Date: Mon, 18 Nov 2013 18:12:05 -0700
|
|
Subject: server: Store and return security attributes with extended file
|
|
attributes.
|
|
|
|
---
|
|
configure.ac | 6 ++
|
|
dlls/advapi32/tests/security.c | 25 +++---
|
|
server/change.c | 11 ++-
|
|
server/fd.c | 68 +++++++++++++++-
|
|
server/file.c | 176 +++++++++++++++++++++++++++++++++++++++-
|
|
server/file.h | 5 +-
|
|
6 files changed, 269 insertions(+), 22 deletions(-)
|
|
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 98a73f2..bb03667 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -71,6 +71,7 @@ AC_ARG_WITH(pthread, AS_HELP_STRING([--without-pthread],[do not use the pthrea
|
|
AC_ARG_WITH(sane, AS_HELP_STRING([--without-sane],[do not use SANE (scanner support)]))
|
|
AC_ARG_WITH(tiff, AS_HELP_STRING([--without-tiff],[do not use TIFF]))
|
|
AC_ARG_WITH(v4l, AS_HELP_STRING([--without-v4l],[do not use v4l1 (v4l support)]))
|
|
+AC_ARG_WITH(xattr, AS_HELP_STRING([--without-xattr],[do not use xattr (security attributes support)]))
|
|
AC_ARG_WITH(xcomposite,AS_HELP_STRING([--without-xcomposite],[do not use the Xcomposite extension]),
|
|
[if test "x$withval" = "xno"; then ac_cv_header_X11_extensions_Xcomposite_h=no; fi])
|
|
AC_ARG_WITH(xcursor, AS_HELP_STRING([--without-xcursor],[do not use the Xcursor extension]),
|
|
@@ -666,6 +667,11 @@ AC_CHECK_HEADERS([libprocstat.h],,,
|
|
#include <sys/socket.h>
|
|
#endif])
|
|
|
|
+if test "x$with_xattr" != "xno"
|
|
+then
|
|
+ AC_CHECK_HEADERS(attr/xattr.h)
|
|
+fi
|
|
+
|
|
dnl **** Check for working dll ****
|
|
|
|
AC_SUBST(dlldir,"\${libdir}/wine")
|
|
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
|
|
index fe31b5c..7d28c05 100644
|
|
--- a/dlls/advapi32/tests/security.c
|
|
+++ b/dlls/advapi32/tests/security.c
|
|
@@ -3088,10 +3088,10 @@ static void test_CreateDirectoryA(void)
|
|
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(bret, "Current User ACE != Current User SID.\n");
|
|
+ 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);
|
|
}
|
|
@@ -3100,10 +3100,10 @@ static void test_CreateDirectoryA(void)
|
|
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(bret, "Administators Group ACE != Administators Group SID.\n");
|
|
+ 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);
|
|
}
|
|
@@ -3277,7 +3277,7 @@ static void test_GetNamedSecurityInfoA(void)
|
|
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");
|
|
+ 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",
|
|
@@ -3288,8 +3288,7 @@ static void test_GetNamedSecurityInfoA(void)
|
|
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 || broken(!bret) /* win2k */,
|
|
- "Administators Group ACE != Administators Group SID.\n");
|
|
+ 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 */,
|
|
@@ -3943,7 +3942,7 @@ static void test_GetSecurityInfo(void)
|
|
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");
|
|
+ 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",
|
|
@@ -3954,7 +3953,7 @@ static void test_GetSecurityInfo(void)
|
|
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");
|
|
+ ok(bret, "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, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
|
diff --git a/server/change.c b/server/change.c
|
|
index f6d56b0..022c780 100644
|
|
--- a/server/change.c
|
|
+++ b/server/change.c
|
|
@@ -286,6 +286,7 @@ static int get_dir_unix_fd( struct dir *dir )
|
|
static struct security_descriptor *dir_get_sd( struct object *obj )
|
|
{
|
|
struct dir *dir = (struct dir *)obj;
|
|
+ const SID *user, *group;
|
|
int unix_fd;
|
|
struct stat st;
|
|
struct security_descriptor *sd;
|
|
@@ -302,9 +303,11 @@ static struct security_descriptor *dir_get_sd( struct object *obj )
|
|
(st.st_uid == dir->uid))
|
|
return obj->sd;
|
|
|
|
- sd = mode_to_sd( st.st_mode,
|
|
- security_unix_uid_to_sid( st.st_uid ),
|
|
- token_get_primary_group( current->process->token ));
|
|
+ user = security_unix_uid_to_sid( st.st_uid );
|
|
+ group = token_get_primary_group( current->process->token );
|
|
+ sd = get_file_acls( unix_fd, user, group );
|
|
+ if (!sd)
|
|
+ sd = mode_to_sd( st.st_mode, user, group );
|
|
if (!sd) return obj->sd;
|
|
|
|
dir->mode = st.st_mode;
|
|
@@ -353,6 +356,8 @@ static int dir_set_sd( struct object *obj, const struct security_descriptor *sd,
|
|
mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX);
|
|
mode |= sd_to_mode( sd, owner );
|
|
|
|
+ set_file_acls( unix_fd, sd );
|
|
+
|
|
if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1)
|
|
{
|
|
file_set_error();
|
|
diff --git a/server/fd.c b/server/fd.c
|
|
index fa8874c..98e3eca 100644
|
|
--- a/server/fd.c
|
|
+++ b/server/fd.c
|
|
@@ -91,6 +91,9 @@
|
|
#ifdef HAVE_SYS_SYSCALL_H
|
|
#include <sys/syscall.h>
|
|
#endif
|
|
+#ifdef HAVE_ATTR_XATTR_H
|
|
+#include <attr/xattr.h>
|
|
+#endif
|
|
|
|
#include "ntstatus.h"
|
|
#define WIN32_NO_STATUS
|
|
@@ -99,6 +102,7 @@
|
|
#include "handle.h"
|
|
#include "process.h"
|
|
#include "request.h"
|
|
+#include "security.h"
|
|
|
|
#include "winternl.h"
|
|
#include "winioctl.h"
|
|
@@ -1726,9 +1730,69 @@ static char *dup_fd_name( struct fd *root, const char *name )
|
|
return ret;
|
|
}
|
|
|
|
+void set_file_acls( int fd, const struct security_descriptor *sd )
|
|
+{
|
|
+#ifdef HAVE_ATTR_XATTR_H
|
|
+ char buffer[XATTR_SIZE_MAX], *p = buffer;
|
|
+ const ACE_HEADER *ace;
|
|
+ int present, i, j, n;
|
|
+ const ACL *dacl;
|
|
+
|
|
+ if (!sd) return;
|
|
+ dacl = sd_get_dacl( sd, &present );
|
|
+ if (!present || !dacl) return;
|
|
+ ace = (const ACE_HEADER *)(dacl + 1);
|
|
+
|
|
+ for (i = 0; i < dacl->AceCount; i++, ace = ace_next( ace ))
|
|
+ {
|
|
+ BYTE type = ace->AceType, flags;
|
|
+ const ACCESS_ALLOWED_ACE *aaa;
|
|
+ const ACCESS_DENIED_ACE *ada;
|
|
+ char sidtxt[100], *s;
|
|
+ const SID *sid;
|
|
+ DWORD mask;
|
|
+
|
|
+ if (type & INHERIT_ONLY_ACE) continue;
|
|
+
|
|
+ switch (type)
|
|
+ {
|
|
+ case ACCESS_DENIED_ACE_TYPE:
|
|
+ ada = (const ACCESS_DENIED_ACE *)ace;
|
|
+ flags = ada->Header.AceFlags;
|
|
+ mask = ada->Mask;
|
|
+ sid = (const SID *)&ada->SidStart;
|
|
+ break;
|
|
+ case ACCESS_ALLOWED_ACE_TYPE:
|
|
+ aaa = (const ACCESS_ALLOWED_ACE *)ace;
|
|
+ flags = aaa->Header.AceFlags;
|
|
+ mask = aaa->Mask;
|
|
+ sid = (const SID *)&aaa->SidStart;
|
|
+ break;
|
|
+ default:
|
|
+ continue;
|
|
+ }
|
|
+ n = sprintf( sidtxt, "S-%u-%d", sid->Revision,
|
|
+ MAKELONG(
|
|
+ MAKEWORD( sid->IdentifierAuthority.Value[5],
|
|
+ sid->IdentifierAuthority.Value[4] ),
|
|
+ MAKEWORD( sid->IdentifierAuthority.Value[3],
|
|
+ sid->IdentifierAuthority.Value[2] )
|
|
+ ) );
|
|
+ s = sidtxt + n;
|
|
+ for( j=0; j<sid->SubAuthorityCount; j++ )
|
|
+ s += sprintf( s, "-%u", sid->SubAuthority[j] );
|
|
+
|
|
+ p += snprintf( p, XATTR_SIZE_MAX-(p-buffer), "%s%x,%x,%x,%s",
|
|
+ (p != buffer ? ";" : ""), type, flags, mask, sidtxt );
|
|
+ }
|
|
+
|
|
+ fsetxattr( fd, "user.wine.acl", buffer, p-buffer, 0 );
|
|
+#endif
|
|
+}
|
|
+
|
|
/* open() wrapper that returns a struct fd with no fd user set */
|
|
struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode, unsigned int access,
|
|
- unsigned int sharing, unsigned int options )
|
|
+ unsigned int sharing, unsigned int options, const struct security_descriptor *sd )
|
|
{
|
|
struct stat st;
|
|
struct closed_fd *closed_fd;
|
|
@@ -1804,6 +1868,8 @@ struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
|
}
|
|
}
|
|
|
|
+ set_file_acls( fd->unix_fd, sd );
|
|
+
|
|
closed_fd->unix_fd = fd->unix_fd;
|
|
closed_fd->unlink[0] = 0;
|
|
fstat( fd->unix_fd, &st );
|
|
diff --git a/server/file.c b/server/file.c
|
|
index cceb8ad..9ac9188 100644
|
|
--- a/server/file.c
|
|
+++ b/server/file.c
|
|
@@ -32,6 +32,7 @@
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <time.h>
|
|
+#include <limits.h>
|
|
#include <unistd.h>
|
|
#ifdef HAVE_UTIME_H
|
|
#include <utime.h>
|
|
@@ -39,6 +40,9 @@
|
|
#ifdef HAVE_POLL_H
|
|
#include <poll.h>
|
|
#endif
|
|
+#ifdef HAVE_ATTR_XATTR_H
|
|
+#include <attr/xattr.h>
|
|
+#endif
|
|
|
|
#include "ntstatus.h"
|
|
#define WIN32_NO_STATUS
|
|
@@ -237,7 +241,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
|
|
access = generic_file_map_access( access );
|
|
|
|
/* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
|
|
- fd = open_fd( root, name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options );
|
|
+ fd = open_fd( root, name, flags | O_NONBLOCK | O_LARGEFILE, &mode, access, sharing, options, sd );
|
|
if (!fd) goto done;
|
|
|
|
if (S_ISDIR(mode))
|
|
@@ -424,9 +428,169 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
|
|
return sd;
|
|
}
|
|
|
|
+struct security_descriptor *get_file_acls( int fd, const SID *user, const SID *group )
|
|
+{
|
|
+#ifdef HAVE_ATTR_XATTR_H
|
|
+ int ace_count = 0, dacl_size = sizeof(ACL), i, n;
|
|
+ char buffer[XATTR_SIZE_MAX], *p = buffer, *pn;
|
|
+ struct security_descriptor *sd;
|
|
+ ACE_HEADER *current_ace;
|
|
+ ACCESS_ALLOWED_ACE *aaa;
|
|
+ ACCESS_DENIED_ACE *ada;
|
|
+ int type, flags, mask;
|
|
+ ACL *dacl;
|
|
+ char *ptr;
|
|
+
|
|
+ n = fgetxattr( fd, "user.wine.acl", buffer, sizeof(buffer) );
|
|
+ if (n == -1) return NULL;
|
|
+ buffer[n] = 0;
|
|
+
|
|
+ do
|
|
+ {
|
|
+ int sub_authority_count = 0;
|
|
+
|
|
+ pn = strchr(p, ';');
|
|
+ if (pn) pn++;
|
|
+ sscanf(p, "%x", &type);
|
|
+ do
|
|
+ {
|
|
+ p = strchr(p, '-');
|
|
+ if (p) p++;
|
|
+ sub_authority_count++;
|
|
+ }
|
|
+ while(p && (!pn || p < pn));
|
|
+ sub_authority_count -= 3; /* Revision and IdentifierAuthority don't count */
|
|
+
|
|
+ switch (type)
|
|
+ {
|
|
+ case ACCESS_DENIED_ACE_TYPE:
|
|
+ dacl_size += FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
|
|
+ FIELD_OFFSET(SID, SubAuthority[sub_authority_count]);
|
|
+ break;
|
|
+ case ACCESS_ALLOWED_ACE_TYPE:
|
|
+ dacl_size += FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
|
+ FIELD_OFFSET(SID, SubAuthority[sub_authority_count]);
|
|
+ break;
|
|
+ default:
|
|
+ continue;
|
|
+ }
|
|
+ ace_count++;
|
|
+ p = pn;
|
|
+ }
|
|
+ while(p);
|
|
+
|
|
+ sd = mem_alloc( sizeof(struct security_descriptor) +
|
|
+ FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]) +
|
|
+ FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]) +
|
|
+ dacl_size );
|
|
+
|
|
+ sd->control = SE_DACL_PRESENT;
|
|
+ sd->owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
|
|
+ sd->group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]);
|
|
+ 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;
|
|
+ aaa = (ACCESS_ALLOWED_ACE *)(dacl + 1);
|
|
+ current_ace = &aaa->Header;
|
|
+
|
|
+ p = buffer;
|
|
+ for(i=0; i<ace_count; i++)
|
|
+ {
|
|
+ char b[sizeof(SID) + sizeof(ULONG) * SID_MAX_SUB_AUTHORITIES];
|
|
+ int sub_authority_count = 0;
|
|
+ SID *sid = (SID *)&b[0];
|
|
+ char sidtxt[100];
|
|
+ int rev, ia, sa;
|
|
+
|
|
+ if (i != 0)
|
|
+ {
|
|
+ aaa = (ACCESS_ALLOWED_ACE *)ace_next( current_ace );
|
|
+ current_ace = &aaa->Header;
|
|
+ }
|
|
+ pn = strchr(p, ';');
|
|
+ if (pn) pn++;
|
|
+ sscanf(p, "%x,%x,%x,%[^;]", &type, &flags, &mask, sidtxt);
|
|
+ sscanf(sidtxt, "S-%u-%d", &rev, &ia);
|
|
+ sid->Revision = rev;
|
|
+ sid->IdentifierAuthority.Value[0] = 0;
|
|
+ sid->IdentifierAuthority.Value[1] = 0;
|
|
+ sid->IdentifierAuthority.Value[2] = HIBYTE(HIWORD(ia));
|
|
+ sid->IdentifierAuthority.Value[3] = LOBYTE(HIWORD(ia));
|
|
+ sid->IdentifierAuthority.Value[4] = HIBYTE(LOWORD(ia));
|
|
+ sid->IdentifierAuthority.Value[5] = LOBYTE(LOWORD(ia));
|
|
+ p = strchr(sidtxt, '-')+1;
|
|
+ p = strchr(p, '-')+1; /* Revision doesn't count */
|
|
+ p = strchr(p, '-')+1; /* IdentifierAuthority doesn't count */
|
|
+ do
|
|
+ {
|
|
+ sscanf(p, "%u", &sa);
|
|
+ sid->SubAuthority[sub_authority_count] = sa;
|
|
+ p = strchr(p, '-');
|
|
+ if (p) p++;
|
|
+ sub_authority_count++;
|
|
+ }
|
|
+ while(p);
|
|
+ sid->SubAuthorityCount = sub_authority_count;
|
|
+
|
|
+ /* Convert generic rights into standard access rights */
|
|
+ if (mask & GENERIC_ALL)
|
|
+ mask |= WRITE_DAC | WRITE_OWNER | DELETE | FILE_DELETE_CHILD;
|
|
+ if (mask & (GENERIC_ALL|GENERIC_READ))
|
|
+ mask |= FILE_GENERIC_READ;
|
|
+ if (mask & (GENERIC_ALL|GENERIC_WRITE))
|
|
+ mask |= FILE_GENERIC_WRITE;
|
|
+ if (mask & (GENERIC_ALL|GENERIC_EXECUTE))
|
|
+ mask |= FILE_GENERIC_EXECUTE;
|
|
+ mask &= 0x0FFFFFFF;
|
|
+
|
|
+ /* Handle the specific ACE */
|
|
+ switch (type)
|
|
+ {
|
|
+ case ACCESS_DENIED_ACE_TYPE:
|
|
+ ada = (ACCESS_DENIED_ACE *)aaa;
|
|
+ ada->Header.AceType = type;
|
|
+ ada->Header.AceFlags = flags;
|
|
+ ada->Header.AceSize = FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart) +
|
|
+ FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]);
|
|
+ ada->Mask = mask;
|
|
+ memcpy( &ada->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) );
|
|
+ break;
|
|
+ case ACCESS_ALLOWED_ACE_TYPE:
|
|
+ aaa->Header.AceType = type;
|
|
+ aaa->Header.AceFlags = flags;
|
|
+ aaa->Header.AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
|
|
+ FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]);
|
|
+ aaa->Mask = mask;
|
|
+ memcpy( &aaa->SidStart, sid, FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]) );
|
|
+ break;
|
|
+ default:
|
|
+ continue;
|
|
+ }
|
|
+ p = pn;
|
|
+ }
|
|
+
|
|
+ return sd;
|
|
+#else
|
|
+ return NULL;
|
|
+#endif
|
|
+}
|
|
+
|
|
static struct security_descriptor *file_get_sd( struct object *obj )
|
|
{
|
|
struct file *file = (struct file *)obj;
|
|
+ const SID *user, *group;
|
|
struct stat st;
|
|
int unix_fd;
|
|
struct security_descriptor *sd;
|
|
@@ -443,9 +607,11 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
|
(st.st_uid == file->uid))
|
|
return obj->sd;
|
|
|
|
- sd = mode_to_sd( st.st_mode,
|
|
- security_unix_uid_to_sid( st.st_uid ),
|
|
- token_get_primary_group( current->process->token ));
|
|
+ user = security_unix_uid_to_sid( st.st_uid );
|
|
+ group = token_get_primary_group( current->process->token );
|
|
+ sd = get_file_acls( unix_fd, user, group );
|
|
+ if (!sd)
|
|
+ sd = mode_to_sd( st.st_mode, user, group);
|
|
if (!sd) return obj->sd;
|
|
|
|
file->mode = st.st_mode;
|
|
@@ -575,6 +741,8 @@ static int file_set_sd( struct object *obj, const struct security_descriptor *sd
|
|
mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX);
|
|
mode |= sd_to_mode( sd, owner );
|
|
|
|
+ set_file_acls( unix_fd, sd );
|
|
+
|
|
if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1)
|
|
{
|
|
file_set_error();
|
|
diff --git a/server/file.h b/server/file.h
|
|
index 493d30b..721c087 100644
|
|
--- a/server/file.h
|
|
+++ b/server/file.h
|
|
@@ -56,7 +56,8 @@ extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct obje
|
|
unsigned int options );
|
|
extern void set_no_fd_status( struct fd *fd, unsigned int status );
|
|
extern struct fd *open_fd( struct fd *root, const char *name, int flags, mode_t *mode,
|
|
- unsigned int access, unsigned int sharing, unsigned int options );
|
|
+ unsigned int access, unsigned int sharing, unsigned int options,
|
|
+ const struct security_descriptor *sd );
|
|
extern struct fd *create_anonymous_fd( const struct fd_ops *fd_user_ops,
|
|
int unix_fd, struct object *user, unsigned int options );
|
|
extern struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing,
|
|
@@ -122,6 +123,8 @@ extern struct file *create_file_for_fd_obj( struct fd *fd, unsigned int access,
|
|
extern void file_set_error(void);
|
|
extern struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID *group );
|
|
extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner );
|
|
+extern void set_file_acls( int fd, const struct security_descriptor *sd );
|
|
+extern struct security_descriptor *get_file_acls( int fd, const SID *user, const SID *group );
|
|
|
|
/* file mapping functions */
|
|
|
|
--
|
|
1.7.9.5
|
|
|