Compare commits

..

29 Commits

Author SHA1 Message Date
Erich E. Hoover
d989770f24 Update changelog for release 1.7.18. 2014-05-02 13:05:45 -06:00
Michael MĂĽller
036250b6da Update timer patch 2014-05-02 20:50:58 +02:00
Erich E. Hoover
d787be6d20 Update changelog for release 1.7.17. 2014-04-18 16:04:47 -06:00
Erich E. Hoover
c35db80eae Split the storage of the ownership information into a separate patch. 2014-04-18 15:48:33 -06:00
Erich E. Hoover
4328f2e964 Update ACL patches to store user/group data instead of replacing it on the retrieval side. 2014-04-18 15:29:56 -06:00
Erich E. Hoover
eecf7c4a68 ACL data is now stored in binary instead of converting it to ASCII. 2014-04-17 16:53:10 -06:00
compholio
4d01de8fcd Update README.md with linguistic casing removal 2014-04-17 13:03:11 -06:00
Erich E. Hoover
f5ef032c89 Removed linguistic casing patches (accepted upstream). 2014-04-17 12:56:29 -06:00
Erich E. Hoover
f9eebd5599 Removed dynamic unwind patches (accepted upstream). 2014-04-16 16:52:37 -06:00
Erich E. Hoover
48bbae3fb7 Fix strndup move not being properly rebased. 2014-04-15 15:30:37 -06:00
Michael MĂĽller
fdbc47e09e Merge branch 'master' of https://github.com/compholio/wine-compholio-daily 2014-04-15 23:19:39 +02:00
Michael MĂĽller
2b4093a0ea Remove recommendation for gettext and libgif 2014-04-15 23:18:52 +02:00
Erich E. Hoover
580ff7c1c5 Move strndup call inside of file_get_parent_sd. 2014-04-15 15:14:15 -06:00
Erich E. Hoover
454c09ddbe Remove old test code for adding extra ACLs. 2014-04-15 15:08:23 -06:00
Erich E. Hoover
810202432b Ensure ACL buffers are NULL terminated for all string processing. 2014-04-15 15:05:36 -06:00
Erich E. Hoover
737eb1005a Add bounds checking on SubAuthorityCount. 2014-04-15 14:56:44 -06:00
Erich E. Hoover
58eeb19b3e Rebase security attribute retrieval patch. 2014-04-15 14:32:21 -06:00
Erich E. Hoover
c8be20f3cf Remove unnecessary check for INHERIT_ONLY_ACE. 2014-04-15 14:28:42 -06:00
Erich E. Hoover
b6d34ea7d2 Do not unnecessarily move 'struct stat st;'. 2014-04-15 14:20:06 -06:00
slackner
f6d14c47ec Merge pull request #3 from anish/patch-1
Update gitapply.sh (Turn off whitespace warnings)
2014-04-10 04:08:07 +02:00
Anish Bhatt
78d6102645 Update gitapply.sh
Turn off whitespace warnings
2014-04-09 19:03:06 -07:00
Erich E. Hoover
b862f600f5 Start putting changelog entries in prior to releases. 2014-04-05 17:46:37 -06:00
Erich E. Hoover
e0b037b82a Update the linguistic casing patches to print a FIXME that the flags are not fully supported. 2014-04-05 14:28:26 -06:00
Erich E. Hoover
69b0f7ebd7 Split Arial replacement into two patches. 2014-04-05 13:29:29 -06:00
Erich E. Hoover
7c95fad661 Dropped liblcms2-dev dependency for old Ubuntu versions. 2014-04-04 19:52:26 -06:00
Sebastian Lackner
67cc61ffca Update changelog. 2014-04-05 03:49:35 +02:00
Sebastian Lackner
0df720506a Fix build failure caused by dynamic unwind patches on 32-bit. 2014-04-05 03:47:22 +02:00
Sebastian Lackner
68c91b3113 Merge branch 'master' of github.com:compholio/wine-compholio-daily 2014-04-05 02:03:52 +02:00
Sebastian Lackner
ac36f88de1 11-Dynamic_Unwind: Add forward from kernel32 to ntdll. 2014-04-05 02:03:07 +02:00
30 changed files with 72321 additions and 42532 deletions

View File

@@ -11,7 +11,6 @@ Current patches include:
* Support for TransmitFile (http://bugs.winehq.org/show_bug.cgi?id=5048)
* Support for GetVolumePathName
* Implement an Arial replacement font (http://bugs.winehq.org/show_bug.cgi?id=32323)
* Allow CompareStringEx flag NORM_LINGUISTIC_CASING (http://bugs.winehq.org/show_bug.cgi?id=34269)
* Workaround for TransactNamedPipe not being supported (http://bugs.winehq.org/show_bug.cgi?id=17273)
* XEMBED support for embedding Wine windows inside Linux applications
* Reduced SetTimer minimum value from 15 ms to 5 ms (improves Silverlight framerates)

16
debian/changelog vendored
View File

@@ -1,3 +1,19 @@
wine-compholio (1.7.18) unstable; urgency=low
* Updated SetTimer patch (10 ms accepted upstream).
-- Erich E. Hoover <erich.e.hoover@gmail.com> Fri, 02 May 2014 13:05:13 -0600
wine-compholio (1.7.17) unstable; urgency=low
* Split Arial replacement into two patches.
* Removed dynamic unwind patches (accepted upstream).
* Removed linguistic casing patches (accepted upstream).
* ACL data is now stored in binary instead of converting it to ASCII.
-- Erich E. Hoover <erich.e.hoover@gmail.com> Fri, 18 Apr 2014 16:03:57 -0600
wine-compholio (1.7.16-1) unstable; urgency=low
* Fix build failure caused by dynamic unwind functions.
* Dropped liblcms2-dev dependency for old Ubuntu versions.
-- Sebastian Lackner <sebastian@fds-team.de> Sat, 05 Apr 2014 03:48:25 +0200
wine-compholio (1.7.16) unstable; urgency=low
* Add stub for RtlInstallFunctionTableCallback.
* Further split out the SIO_ADDRESS_LIST_CHANGE patches.

11
debian/control vendored
View File

@@ -27,7 +27,6 @@ Build-Depends: autotools-dev,
libesd0-dev,
libfontconfig1-dev | libfontconfig-dev,
libfreetype6-dev,
libgif-dev | libungif4-dev,
libgl1-mesa-dev | nvidia-glx-dev | fglrx-driver-dev | libgl-dev,
libglu1-mesa-dev | libglu-dev,
libgnutls-dev,
@@ -37,7 +36,7 @@ Build-Depends: autotools-dev,
libgstreamer0.10-dev,
libice-dev,
libjpeg-dev,
liblcms2-dev,
liblcms2-dev | ubuntu-desktop (<< 1.267),
libldap2-dev, libldap-dev,
libmpg123-dev,
libncurses5-dev | libncurses-dev,
@@ -77,13 +76,11 @@ Pre-Depends: dpkg (>= 1.14.12ubuntu3), ${misc:Pre-Depends}
Depends: ${shlibs:Depends},
libasound2-plugins,
libncurses5
Recommends: gettext,
libcapi20-3,
Recommends: libcapi20-3,
libcups2,
libdbus-1-3,
libfontconfig1 | libfontconfig,
libfreetype6,
libgif4,
libgnutls26,
libgphoto2-6 | libgphoto2-2 (>= 2.4.6),
libgphoto2-port10 | libgphoto2-port0 (>= 2.4.6),
@@ -136,13 +133,11 @@ Pre-Depends: dpkg (>= 1.14.12ubuntu3), ${misc:Pre-Depends}
Depends: ${shlibs:Depends},
libasound2-plugins,
libncurses5
Recommends: gettext,
libcapi20-3,
Recommends: libcapi20-3,
libcups2,
libdbus-1-3,
libfontconfig1 | libfontconfig,
libfreetype6,
libgif4,
libgnutls26,
libgphoto2-6 | libgphoto2-2 (>= 2.4.6),
libgphoto2-port10 | libgphoto2-port0 (>= 2.4.6),

View File

@@ -78,7 +78,7 @@ done
# Redirect to git apply if available
if [ "$nogit" -eq 0 ] && command -v git >/dev/null 2>&1; then
exec git apply "$@"
exec git apply --whitespace=nowarn "$@"
exit 1
fi

View File

@@ -1,6 +1,6 @@
From ee79e1be71635431d0d05841c7f9cea720411ba6 Mon Sep 17 00:00:00 2001
From 379e01b2aea67fa305d2ccd08b589d2d31cd0da0 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 13 Feb 2014 15:45:41 -0700
Date: Thu, 17 Apr 2014 16:07:46 -0600
Subject: server: Unify the storage of security attributes for files and
directories.
@@ -11,7 +11,7 @@ Subject: server: Unify the storage of security attributes for files and
3 files changed, 25 insertions(+), 48 deletions(-)
diff --git a/server/change.c b/server/change.c
index f6d56b0..76fc9f7 100644
index f6d56b0..7cea06b 100644
--- a/server/change.c
+++ b/server/change.c
@@ -317,49 +317,15 @@ static struct security_descriptor *dir_get_sd( struct object *obj )
@@ -64,14 +64,14 @@ index f6d56b0..76fc9f7 100644
- }
- return 1;
+ fd = dir_get_fd( obj );
+ ret = file_set_acls( obj, fd, sd, set_info );
+ ret = set_file_sd( obj, fd, sd, set_info );
+ release_object( fd );
+ return ret;
}
static struct change_record *get_first_change_record( struct dir *dir )
diff --git a/server/file.c b/server/file.c
index cceb8ad..13ebaf9 100644
index cceb8ad..fb89272 100644
--- a/server/file.c
+++ b/server/file.c
@@ -534,18 +534,13 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner )
@@ -80,8 +80,8 @@ index cceb8ad..13ebaf9 100644
-static int file_set_sd( struct object *obj, const struct security_descriptor *sd,
- unsigned int set_info )
+int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
+ unsigned int set_info )
+int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
+ unsigned int set_info )
{
- struct file *file = (struct file *)obj;
+ int unix_fd = get_unix_fd( fd );
@@ -109,7 +109,7 @@ index cceb8ad..13ebaf9 100644
+ assert( obj->ops == &file_ops );
+
+ fd = file_get_fd( obj );
+ ret = file_set_acls( obj, fd, sd, set_info );
+ ret = set_file_sd( obj, fd, sd, set_info );
+ release_object( fd );
+ return ret;
+}
@@ -118,15 +118,15 @@ index cceb8ad..13ebaf9 100644
{
struct file *file = (struct file *)obj;
diff --git a/server/file.h b/server/file.h
index 493d30b..11c3220 100644
index 493d30b..76cb383 100644
--- a/server/file.h
+++ b/server/file.h
@@ -122,6 +122,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 int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
+ unsigned int set_info );
+extern int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
+ unsigned int set_info );
/* file mapping functions */

View File

@@ -1,17 +1,17 @@
From b83ae7cc77483519ed870ead3a167e83acbf1cff Mon Sep 17 00:00:00 2001
From e20db446df6bb0177f90964cd09dd9a993d120f3 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 13 Feb 2014 15:45:48 -0700
Date: Thu, 17 Apr 2014 16:07:50 -0600
Subject: server: Unify the retrieval of security attributes for files and
directories.
---
server/change.c | 32 +++++---------------------------
server/file.c | 34 ++++++++++++++++++++++------------
server/file.c | 32 +++++++++++++++++++++-----------
server/file.h | 2 ++
3 files changed, 29 insertions(+), 39 deletions(-)
3 files changed, 28 insertions(+), 38 deletions(-)
diff --git a/server/change.c b/server/change.c
index 76fc9f7..eb16923 100644
index 7cea06b..c391180 100644
--- a/server/change.c
+++ b/server/change.c
@@ -278,39 +278,17 @@ static struct fd *dir_get_fd( struct object *obj )
@@ -54,13 +54,13 @@ index 76fc9f7..eb16923 100644
- free( obj->sd );
- obj->sd = sd;
+ fd = dir_get_fd( obj );
+ sd = file_get_acls( obj, fd, &dir->mode, &dir->uid );
+ sd = set_file_sd( obj, fd, &dir->mode, &dir->uid );
+ release_object( fd );
return sd;
}
diff --git a/server/file.c b/server/file.c
index 13ebaf9..8baa712 100644
index fb89272..1f008ea 100644
--- a/server/file.c
+++ b/server/file.c
@@ -424,23 +424,19 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
@@ -68,20 +68,19 @@ index 13ebaf9..8baa712 100644
}
-static struct security_descriptor *file_get_sd( struct object *obj )
+struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode,
+ uid_t *uid )
+struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode,
+ uid_t *uid )
{
- struct file *file = (struct file *)obj;
- struct stat st;
- int unix_fd;
+ int unix_fd = get_unix_fd( fd );
struct stat st;
- int unix_fd;
struct security_descriptor *sd;
-
- assert( obj->ops == &file_ops );
-
- unix_fd = get_file_unix_fd( file );
+ struct stat st;
-
if (unix_fd == -1 || fstat( unix_fd, &st ) == -1)
return obj->sd;
@@ -115,7 +114,7 @@ index 13ebaf9..8baa712 100644
+ assert( obj->ops == &file_ops );
+
+ fd = file_get_fd( obj );
+ sd = file_get_acls( obj, fd, &file->mode, &file->uid );
+ sd = get_file_sd( obj, fd, &file->mode, &file->uid );
+ release_object( fd );
+ return sd;
+}
@@ -124,15 +123,15 @@ index 13ebaf9..8baa712 100644
{
mode_t mode = 0;
diff --git a/server/file.h b/server/file.h
index 11c3220..89b5888 100644
index 76cb383..43a234f 100644
--- a/server/file.h
+++ b/server/file.h
@@ -124,6 +124,8 @@ extern struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, con
extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner );
extern int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
unsigned int set_info );
+extern struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode,
+ uid_t *uid );
extern int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
unsigned int set_info );
+extern struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode,
+ uid_t *uid );
/* file mapping functions */

View File

@@ -1,16 +1,16 @@
From 96470b6ee4c0e91700ac197e77784feb42d9a961 Mon Sep 17 00:00:00 2001
From 4ae376bebffe60ef378e08528d50c1e5723be739 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Sat, 15 Feb 2014 18:20:49 -0700
Date: Fri, 18 Apr 2014 15:34:47 -0600
Subject: server: Store file security attributes with extended file
attributes.
---
configure.ac | 12 +++++++++++
server/file.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
configure.ac | 12 ++++++++++++
server/file.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/configure.ac b/configure.ac
index 32730f3..96d796a 100644
index 46602d6..99fcb9b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,6 +73,7 @@ AC_ARG_WITH(pthread, AS_HELP_STRING([--without-pthread],[do not use the pthrea
@@ -21,7 +21,7 @@ index 32730f3..96d796a 100644
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]),
@@ -661,6 +662,17 @@ AC_CHECK_HEADERS([libprocstat.h],,,
@@ -664,6 +665,17 @@ AC_CHECK_HEADERS([libprocstat.h],,,
#include <sys/socket.h>
#endif])
@@ -40,7 +40,7 @@ index 32730f3..96d796a 100644
AC_SUBST(dlldir,"\${libdir}/wine")
diff --git a/server/file.c b/server/file.c
index 8baa712..c375c72 100644
index 1f008ea..ceb57be 100644
--- a/server/file.c
+++ b/server/file.c
@@ -32,6 +32,7 @@
@@ -61,86 +61,50 @@ index 8baa712..c375c72 100644
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -178,6 +182,66 @@ static struct object *create_file_obj( struct fd *fd, unsigned int access, mode_
@@ -178,6 +182,30 @@ static struct object *create_file_obj( struct fd *fd, unsigned int access, mode_
return &file->obj;
}
+void set_xattr_acls( int fd, const struct security_descriptor *sd )
+void set_xattr_sd( 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;
+ char buffer[XATTR_SIZE_MAX];
+ int present, len;
+ const ACL *dacl;
+
+ /* there's no point in storing the security descriptor if there's no 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;
+ len = 2 + sizeof(struct security_descriptor) + sd->owner_len + sd->group_len + sd->sacl_len
+ + sd->dacl_len;
+ if (len > XATTR_SIZE_MAX) return;
+
+ 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 );
+ /* include the descriptor revision and resource manager control bits */
+ buffer[0] = SECURITY_DESCRIPTOR_REVISION;
+ buffer[1] = 0;
+ memcpy( &buffer[2], sd, len - 2 );
+ fsetxattr( fd, "user.wine.sd", buffer, len, 0 );
+#endif
+}
+
static struct object *create_file( struct fd *root, const char *nameptr, data_size_t len,
unsigned int access, unsigned int sharing, int create,
unsigned int options, unsigned int attrs,
@@ -239,6 +303,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
@@ -239,6 +267,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
/* 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 );
if (!fd) goto done;
+ set_xattr_acls( get_unix_fd( fd ), sd );
+ set_xattr_sd( get_unix_fd( fd ), sd );
if (S_ISDIR(mode))
obj = create_dir_obj( fd, access, mode );
@@ -580,6 +645,8 @@ int file_set_acls( struct object *obj, struct fd *fd, const struct security_desc
@@ -580,6 +609,8 @@ int set_file_sd( struct object *obj, struct fd *fd, const struct security_descri
mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX);
mode |= sd_to_mode( sd, owner );
+ set_xattr_acls( unix_fd, sd );
+ set_xattr_sd( unix_fd, sd );
+
if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1)
{

View File

@@ -0,0 +1,162 @@
From ea0c98e71750a0a55273c8cfb4a9c8931d3cf510 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Fri, 18 Apr 2014 15:35:24 -0600
Subject: server: Store user and group inside stored extended file attribute
information.
---
server/file.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 70 insertions(+), 9 deletions(-)
diff --git a/server/file.c b/server/file.c
index ceb57be..b9106a8 100644
--- a/server/file.c
+++ b/server/file.c
@@ -182,11 +182,12 @@ static struct object *create_file_obj( struct fd *fd, unsigned int access, mode_
return &file->obj;
}
-void set_xattr_sd( int fd, const struct security_descriptor *sd )
+void set_xattr_sd( int fd, const struct security_descriptor *sd, const SID *user, const SID *group )
{
#ifdef HAVE_ATTR_XATTR_H
- char buffer[XATTR_SIZE_MAX];
- int present, len;
+ char buffer[XATTR_SIZE_MAX], *dst_ptr = &buffer[2], *src_ptr = (char *)sd;
+ int present, len, owner_len, group_len;
+ struct security_descriptor *dst_sd;
const ACL *dacl;
/* there's no point in storing the security descriptor if there's no DACL */
@@ -194,14 +195,52 @@ void set_xattr_sd( int fd, const struct security_descriptor *sd )
dacl = sd_get_dacl( sd, &present );
if (!present || !dacl) return;
- len = 2 + sizeof(struct security_descriptor) + sd->owner_len + sd->group_len + sd->sacl_len
+ /* make sure that we always store the ownership information */
+ if (!sd->owner_len)
+ owner_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]);
+ else
+ owner_len = sd->owner_len;
+ if (!sd->group_len)
+ group_len = FIELD_OFFSET(SID, SubAuthority[group->SubAuthorityCount]);
+ else
+ group_len = sd->group_len;
+ len = 2 + sizeof(struct security_descriptor) + owner_len + group_len + sd->sacl_len
+ sd->dacl_len;
if (len > XATTR_SIZE_MAX) return;
/* include the descriptor revision and resource manager control bits */
buffer[0] = SECURITY_DESCRIPTOR_REVISION;
buffer[1] = 0;
- memcpy( &buffer[2], sd, len - 2 );
+ memcpy( dst_ptr, sd, sizeof(struct security_descriptor) );
+ dst_sd = (struct security_descriptor *)dst_ptr;
+ src_ptr += sizeof(struct security_descriptor);
+ dst_ptr += sizeof(struct security_descriptor);
+ dst_sd->owner_len = owner_len;
+ dst_sd->group_len = group_len;
+ /* copy the appropriate ownership information (explicit or inferred) */
+ if (sd->owner_len)
+ {
+ memcpy( dst_ptr, src_ptr, sd->owner_len );
+ src_ptr += sd->owner_len;
+ }
+ else
+ memcpy( dst_ptr, user, owner_len );
+ dst_ptr += owner_len;
+ if (sd->group_len)
+ {
+ memcpy( dst_ptr, src_ptr, sd->group_len );
+ src_ptr += sd->group_len;
+ }
+ else
+ memcpy( dst_ptr, group, group_len );
+ dst_ptr += group_len;
+ /* copy the ACL information (explicit only) */
+ memcpy( dst_ptr, src_ptr, sd->sacl_len );
+ src_ptr += sd->sacl_len;
+ dst_ptr += sd->sacl_len;
+ memcpy( dst_ptr, src_ptr, sd->dacl_len );
+ src_ptr += sd->dacl_len;
+ dst_ptr += sd->dacl_len;
fsetxattr( fd, "user.wine.sd", buffer, len, 0 );
#endif
}
@@ -211,6 +250,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
unsigned int options, unsigned int attrs,
const struct security_descriptor *sd )
{
+ const SID *owner = NULL, *group = NULL;
struct object *obj = NULL;
struct fd *fd;
int flags;
@@ -241,9 +281,12 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
if (sd)
{
- const SID *owner = sd_get_owner( sd );
+ owner = sd_get_owner( sd );
if (!owner)
owner = token_get_user( current->process->token );
+ group = sd_get_group( sd );
+ if (!group)
+ group = token_get_primary_group( current->process->token );
mode = sd_to_mode( sd, owner );
}
else if (options & FILE_DIRECTORY_FILE)
@@ -267,7 +310,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
/* 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 );
if (!fd) goto done;
- set_xattr_sd( get_unix_fd( fd ), sd );
+ set_xattr_sd( get_unix_fd( fd ), sd, owner, group );
if (S_ISDIR(mode))
obj = create_dir_obj( fd, access, mode );
@@ -577,7 +620,7 @@ int set_file_sd( struct object *obj, struct fd *fd, const struct security_descri
unsigned int set_info )
{
int unix_fd = get_unix_fd( fd );
- const SID *owner;
+ const SID *owner, *group;
struct stat st;
mode_t mode;
@@ -601,6 +644,24 @@ int set_file_sd( struct object *obj, struct fd *fd, const struct security_descri
else
owner = token_get_user( current->process->token );
+ if (set_info & GROUP_SECURITY_INFORMATION)
+ {
+ group = sd_get_group( sd );
+ if (!group)
+ {
+ set_error( STATUS_INVALID_SECURITY_DESCR );
+ return 0;
+ }
+ if (!obj->sd || !security_equal_sid( group, sd_get_group( obj->sd ) ))
+ {
+ /* FIXME: get Unix uid and call fchown */
+ }
+ }
+ else if (obj->sd)
+ group = sd_get_group( obj->sd );
+ else
+ group = token_get_primary_group( current->process->token );
+
/* group and sacl not supported */
if (set_info & DACL_SECURITY_INFORMATION)
@@ -609,7 +670,7 @@ int set_file_sd( struct object *obj, struct fd *fd, const struct security_descri
mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX);
mode |= sd_to_mode( sd, owner );
- set_xattr_sd( unix_fd, sd );
+ set_xattr_sd( unix_fd, sd, owner, group );
if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1)
{
--
1.7.9.5

View File

@@ -1,16 +1,17 @@
From 66583f9f848becaa12d84270a2ebe7a79ac34724 Mon Sep 17 00:00:00 2001
From e031dc5069bebd63770a405d684ee75a14d1826b Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 13 Feb 2014 16:04:57 -0700
Date: Fri, 18 Apr 2014 14:01:35 -0600
Subject: server: Retrieve file security attributes with extended file
attributes.
---
dlls/advapi32/tests/security.c | 49 +++++++------
server/file.c | 156 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 177 insertions(+), 28 deletions(-)
dlls/advapi32/tests/security.c | 49 ++++++++++++++++++++--------------------
server/change.c | 2 +-
server/file.c | 28 ++++++++++++++++++++---
3 files changed, 50 insertions(+), 29 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index e2e9cd5..f107abc 100644
index bd45189..e5ef7e6 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3105,24 +3105,24 @@ static void test_CreateDirectoryA(void)
@@ -109,172 +110,58 @@ index e2e9cd5..f107abc 100644
}
CloseHandle(obj);
}
diff --git a/server/change.c b/server/change.c
index c391180..77c01bb 100644
--- a/server/change.c
+++ b/server/change.c
@@ -287,7 +287,7 @@ static struct security_descriptor *dir_get_sd( struct object *obj )
assert( obj->ops == &dir_ops );
fd = dir_get_fd( obj );
- sd = set_file_sd( obj, fd, &dir->mode, &dir->uid );
+ sd = get_file_sd( obj, fd, &dir->mode, &dir->uid );
release_object( fd );
return sd;
}
diff --git a/server/file.c b/server/file.c
index c375c72..b9135b9 100644
index b9106a8..c4706b6 100644
--- a/server/file.c
+++ b/server/file.c
@@ -489,11 +489,160 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
@@ -496,12 +496,33 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
return sd;
}
+struct security_descriptor *get_xattr_acls( int fd, const SID *user, const SID *group )
+struct security_descriptor *get_xattr_sd( int fd )
+{
+#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;
+ char buffer[XATTR_SIZE_MAX];
+ int n;
+
+ n = fgetxattr( fd, "user.wine.acl", buffer, sizeof(buffer) );
+ n = fgetxattr( fd, "user.wine.sd", 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;
+
+ /* 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;
+ }
+ /* validate that we can handle the descriptor */
+ if (buffer[0] != SECURITY_DESCRIPTOR_REVISION || buffer[1] != 0) return NULL;
+
+ sd = mem_alloc( n - 2 );
+ memcpy( sd, &buffer[2], n - 2 );
+ return sd;
+#else
+ return NULL;
+#endif
+}
+
struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode,
uid_t *uid )
struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode,
uid_t *uid )
{
int unix_fd = get_unix_fd( fd );
struct stat st;
struct security_descriptor *sd;
+ const SID *user, *group;
struct stat st;
if (unix_fd == -1 || fstat( unix_fd, &st ) == -1)
@@ -504,9 +653,10 @@ struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mo
return obj->sd;
@@ -511,9 +532,10 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode
(st.st_uid == *uid))
return obj->sd;
@@ -283,7 +170,7 @@ index c375c72..b9135b9 100644
- 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_xattr_acls( unix_fd, user, group );
+ sd = get_xattr_sd( unix_fd );
+ if (!sd) sd = mode_to_sd( st.st_mode, user, group);
if (!sd) return obj->sd;

View File

@@ -1,6 +1,6 @@
From e1b3d93adab31966d145ea41a9246d8f498c09d6 Mon Sep 17 00:00:00 2001
From 74d97eda7172d7eae8468c7a32d4e330382afca2 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 13 Feb 2014 16:06:54 -0700
Date: Fri, 18 Apr 2014 14:05:32 -0600
Subject: server: Convert return of file security masks with generic access
mappings.
@@ -10,7 +10,7 @@ Subject: server: Convert return of file security masks with generic access
2 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index f107abc..b71bad3 100644
index e5ef7e6..5b7e6a6 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3109,8 +3109,8 @@ static void test_CreateDirectoryA(void)
@@ -80,10 +80,10 @@ index f107abc..b71bad3 100644
CloseHandle(obj);
}
diff --git a/server/file.c b/server/file.c
index b9135b9..0df2245 100644
index c4706b6..75f015b 100644
--- a/server/file.c
+++ b/server/file.c
@@ -637,6 +637,27 @@ struct security_descriptor *get_xattr_acls( int fd, const SID *user, const SID *
@@ -516,6 +516,27 @@ struct security_descriptor *get_xattr_sd( int fd )
#endif
}
@@ -108,13 +108,13 @@ index b9135b9..0df2245 100644
+ }
+}
+
struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode,
uid_t *uid )
struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode,
uid_t *uid )
{
@@ -656,6 +677,7 @@ struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mo
@@ -535,6 +556,7 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode
user = security_unix_uid_to_sid( st.st_uid );
group = token_get_primary_group( current->process->token );
sd = get_xattr_acls( unix_fd, user, group );
sd = get_xattr_sd( unix_fd );
+ if (sd) convert_generic_sd( sd );
if (!sd) sd = mode_to_sd( st.st_mode, user, group);
if (!sd) return obj->sd;

View File

@@ -1,300 +0,0 @@
From 81bfee65674a81a826b32629e218e457b5ef6b4b Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 13 Feb 2014 16:07:15 -0700
Subject: server: Inherit security attributes from parent directories on
creation.
---
dlls/advapi32/tests/security.c | 40 ++++++++++-
server/change.c | 2 +-
server/file.c | 146 +++++++++++++++++++++++++++++++++++++++-
server/file.h | 2 +-
4 files changed, 184 insertions(+), 6 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index b71bad3..cad8ca9 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3030,10 +3030,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;
@@ -3125,6 +3126,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/server/change.c b/server/change.c
index 0b7b979..14f37c3 100644
--- a/server/change.c
+++ b/server/change.c
@@ -292,7 +292,7 @@ static struct security_descriptor *dir_get_sd( struct object *obj )
assert( obj->ops == &dir_ops );
fd = dir_get_fd( obj );
- sd = file_get_acls( obj, fd, &dir->mode, &dir->uid );
+ sd = file_get_acls( obj, fd, &dir->mode, &dir->uid, TRUE );
release_object( fd );
return sd;
}
diff --git a/server/file.c b/server/file.c
index 0df2245..c115ff7 100644
--- a/server/file.c
+++ b/server/file.c
@@ -242,11 +242,141 @@ void set_xattr_acls( int fd, const struct security_descriptor *sd )
#endif
}
+struct security_descriptor *inherit_sd( const struct security_descriptor *parent_sd, int is_dir )
+{
+ DWORD inheritance_mask = INHERIT_ONLY_ACE|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE;
+ struct security_descriptor *sd = NULL;
+ const ACL *parent_dacl;
+ int present;
+ ACL *dacl;
+
+ parent_dacl = sd_get_dacl( parent_sd, &present );
+ if (present && parent_dacl)
+ {
+ size_t dacl_size = sizeof(ACL), ace_count = 0;
+ const ACE_HEADER *parent_ace;
+ const SID *user, *group;
+ ACE_HEADER *ace;
+ char *ptr;
+ ULONG i;
+
+ /* Calculate the size of the DACL */
+ parent_ace = (const ACE_HEADER *)(parent_dacl + 1);
+ for (i = 0; i < parent_dacl->AceCount; i++, parent_ace = ace_next( parent_ace ))
+ {
+ int multiplier = 1;
+
+ if (!(parent_ace->AceFlags & inheritance_mask)) continue;
+
+ ace_count += multiplier;
+ dacl_size += multiplier * parent_ace->AceSize;
+ }
+ if(!ace_count) return sd; /* No inheritance */
+
+ /* Fill in the security descriptor so that it is compatible with our DACL */
+ user = (const SID *)(parent_sd + 1);
+ group = (const SID *)((char *)(parent_sd + 1) + parent_sd->owner_len);
+ sd = mem_alloc( sizeof(struct security_descriptor) + security_sid_len( user )
+ + security_sid_len( group ) + dacl_size );
+ if (!sd) return sd;
+ sd->control = SE_DACL_PRESENT;
+ sd->owner_len = parent_sd->owner_len;
+ sd->group_len = parent_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);
+
+ /* Build the new DACL, inheriting from the parent's information */
+ parent_ace = (const ACE_HEADER *)(parent_dacl + 1);
+ for (i = 0; i < parent_dacl->AceCount; i++, parent_ace = ace_next( parent_ace ))
+ {
+ DWORD flags = parent_ace->AceFlags;
+
+ if (!(flags & inheritance_mask)) continue;
+
+ ace->AceType = parent_ace->AceType;
+ if(is_dir && (flags & CONTAINER_INHERIT_ACE))
+ flags &= ~INHERIT_ONLY_ACE;
+ else if(!is_dir && (flags & OBJECT_INHERIT_ACE))
+ flags &= ~INHERIT_ONLY_ACE;
+ else if(is_dir && (flags & OBJECT_INHERIT_ACE))
+ flags |= INHERIT_ONLY_ACE;
+ if(is_dir)
+ ace->AceFlags = flags | INHERITED_ACE;
+ else
+ ace->AceFlags = (parent_ace->AceFlags & ~inheritance_mask) | INHERITED_ACE;
+ ace->AceSize = parent_ace->AceSize;
+ memcpy( ace + 1, parent_ace + 1, parent_ace->AceSize - sizeof(ACE_HEADER));
+ ace = (ACE_HEADER *)ace_next( ace );
+ }
+ }
+ return sd;
+}
+
+static struct security_descriptor *file_get_parent_sd( struct fd *root, char *parent_name,
+ int is_dir )
+{
+ struct security_descriptor *sd = NULL;
+ int len = strlen( parent_name );
+ mode_t parent_mode = 0555;
+ struct fd *parent_fd;
+ char *slash;
+
+ /* Even if the file is a directory we need its parent, so skip any terminating slash */
+ if (parent_name[len-1] == '/')
+ parent_name[len-1] = 0;
+ /* Find the last slash in the filename and terminate the name there */
+ slash = strrchr(parent_name, '/');
+ if (slash)
+ slash[0] = 0;
+ else
+ parent_name[0] = 0;
+
+ parent_fd = open_fd( root, parent_name, O_NONBLOCK | O_LARGEFILE, &parent_mode,
+ READ_CONTROL|ACCESS_SYSTEM_SECURITY,
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OPEN_FOR_BACKUP_INTENT );
+ if(parent_fd)
+ {
+ struct object *obj;
+
+ if ((obj = create_file_obj( parent_fd, READ_CONTROL|ACCESS_SYSTEM_SECURITY, parent_mode )))
+ {
+ struct file *file = (struct file *)obj;
+ struct fd *fd;
+
+ fd = file_get_fd( obj );
+ if (fd)
+ {
+ sd = file_get_acls( obj, fd, &file->mode, &file->uid, FALSE );
+ release_object( fd );
+ }
+ if (sd)
+ sd = inherit_sd( sd, is_dir );
+ release_object( obj );
+ }
+ release_object( parent_fd );
+ }
+ return sd;
+}
+
static struct object *create_file( struct fd *root, const char *nameptr, data_size_t len,
unsigned int access, unsigned int sharing, int create,
unsigned int options, unsigned int attrs,
const struct security_descriptor *sd )
{
+ struct security_descriptor *temp_sd = NULL;
struct object *obj = NULL;
struct fd *fd;
int flags;
@@ -275,6 +405,15 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
default: set_error( STATUS_INVALID_PARAMETER ); goto done;
}
+ if (!sd && (create == FILE_CREATE || create == FILE_OVERWRITE_IF))
+ {
+ /* Note: inheritance of security descriptors only occurs on creation when sd is NULL */
+ char *child_name = strndup( nameptr, len );
+
+ sd = temp_sd = file_get_parent_sd( root, child_name, options & FILE_DIRECTORY_FILE );
+ free(child_name);
+ }
+
if (sd)
{
const SID *owner = sd_get_owner( sd );
@@ -315,6 +454,7 @@ static struct object *create_file( struct fd *root, const char *nameptr, data_si
release_object( fd );
done:
+ free( temp_sd );
free( name );
return obj;
}
@@ -659,7 +799,7 @@ void convert_generic_sd( struct security_descriptor *sd )
}
struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode,
- uid_t *uid )
+ uid_t *uid, int convert_generic )
{
int unix_fd = get_unix_fd( fd );
struct security_descriptor *sd;
@@ -677,7 +817,7 @@ struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mo
user = security_unix_uid_to_sid( st.st_uid );
group = token_get_primary_group( current->process->token );
sd = get_xattr_acls( unix_fd, user, group );
- if (sd) convert_generic_sd( sd );
+ if (sd && convert_generic) convert_generic_sd( sd );
if (!sd) sd = mode_to_sd( st.st_mode, user, group);
if (!sd) return obj->sd;
@@ -697,7 +837,7 @@ static struct security_descriptor *file_get_sd( struct object *obj )
assert( obj->ops == &file_ops );
fd = file_get_fd( obj );
- sd = file_get_acls( obj, fd, &file->mode, &file->uid );
+ sd = file_get_acls( obj, fd, &file->mode, &file->uid, TRUE );
release_object( fd );
return sd;
}
diff --git a/server/file.h b/server/file.h
index 89b5888..0905fbb 100644
--- a/server/file.h
+++ b/server/file.h
@@ -125,7 +125,7 @@ extern mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner
extern int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
unsigned int set_info );
extern struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode,
- uid_t *uid );
+ uid_t *uid, int convert_generic );
/* file mapping functions */
--
1.7.9.5

View File

@@ -0,0 +1,324 @@
From 04bbc2e2841b01a5a5344bb1f62c94ff84b25350 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.
---
dlls/advapi32/tests/security.c | 68 ++++++++++++++++++++++
include/winnt.h | 7 ++-
server/fd.c | 13 ++++-
server/file.c | 126 +++++++++++++++++++++++++++++++++++++++-
server/file.h | 1 +
5 files changed, 207 insertions(+), 8 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 68b63a0..c981c1b 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3350,6 +3350,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 3f33c6b..5d2234f 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -5057,14 +5057,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 fa8874c..9e6b9a8 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1629,6 +1629,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;
+
+ 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 )
{
@@ -1642,8 +1652,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 6ce8806..e29d06b 100644
--- a/server/file.c
+++ b/server/file.c
@@ -325,6 +325,105 @@ 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 */
+
+ 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) + security_sid_len( user )
+ + security_sid_len( group ) + 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);
+ 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);
+ 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 )
{
@@ -795,16 +894,33 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner )
return new_mode & ~denied_mode;
}
-int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
+int set_file_sd( struct object *obj, struct fd *fd, const struct security_descriptor *new_sd,
unsigned int set_info )
{
+ const struct security_descriptor *sd = new_sd;
+ struct security_descriptor *parent_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)
+ {
+ parent_sd = file_get_parent_sd( NULL, child_name, strlen(child_name),
+ S_ISDIR(st.st_mode) );
+ free( child_name );
+ if (parent_sd)
+ sd = file_combine_sds( parent_sd, new_sd );
+ }
+ }
+
if (set_info & OWNER_SECURITY_INFORMATION)
{
owner = sd_get_owner( sd );
@@ -854,10 +970,14 @@ 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;
+
+ if (parent_sd)
+ free( parent_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 2f537cf..fa83001 100644
--- a/server/file.h
+++ b/server/file.h
@@ -77,6 +77,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 );
--
1.7.9.5

View File

@@ -0,0 +1,193 @@
From 0be335ce9c2c93a186cf35be0a99519868ab8a0d Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Fri, 18 Apr 2014 15:21:00 -0600
Subject: server: Add compatibility code for handling the old method of
storing ACLs.
---
server/file.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 162 insertions(+)
diff --git a/server/file.c b/server/file.c
index e29d06b..08231a7 100644
--- a/server/file.c
+++ b/server/file.c
@@ -750,6 +750,167 @@ struct security_descriptor *get_xattr_sd( int fd )
#endif
}
+struct security_descriptor *get_xattr_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; /* ensure NULL terminated buffer for string functions */
+
+ 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 */
+ p = pn; /* prepare for the next ACE */
+
+ /* verify that the SubAuthorityCount does not exceed the maximum permitted value */
+ if (sub_authority_count > SID_MAX_SUB_AUTHORITIES)
+ continue;
+
+ 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++;
+ }
+ 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
+ {
+ if (sub_authority_count == SID_MAX_SUB_AUTHORITIES)
+ {
+ sub_authority_count++; /* fail on this SID and move on to the next one */
+ break;
+ }
+ 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;
+ p = pn; /* prepare for the next ACE */
+
+ /* verify that the SubAuthorityCount does not exceed the maximum permitted value */
+ if (sub_authority_count > SID_MAX_SUB_AUTHORITIES)
+ continue;
+
+ /* 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;
+ }
+ }
+
+ return sd;
+#else
+ return NULL;
+#endif
+}
+
/* Convert generic rights into standard access rights */
void convert_generic_sd( struct security_descriptor *sd )
{
@@ -790,6 +951,7 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode
user = security_unix_uid_to_sid( st.st_uid );
group = token_get_primary_group( current->process->token );
sd = get_xattr_sd( unix_fd );
+ if (!sd) sd = get_xattr_acls( unix_fd, user, group );
if (sd && convert_generic) convert_generic_sd( sd );
if (!sd) sd = mode_to_sd( st.st_mode, user, group);
if (!sd) return obj->sd;
--
1.7.9.5

View File

@@ -1,3 +1,3 @@
Revision: 2
Revision: 4
Author: Erich E. Hoover
Title: Store and return security attributes with extended file attributes.

View File

@@ -1,244 +0,0 @@
From cfd4d6f8d11668e8dba511bc74c805fb53a52d9d Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Wed, 12 Feb 2014 13:26:57 -0700
Subject: kernel32/tests: Add a variety of tests for CompareStringEx.
---
dlls/kernel32/tests/locale.c | 200 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 200 insertions(+)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 62e9f01..9aab6b0 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -88,6 +88,8 @@ static INT (WINAPI *pIdnToUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
static INT (WINAPI *pGetLocaleInfoEx)(LPCWSTR, LCTYPE, LPWSTR, INT);
static BOOL (WINAPI *pIsValidLocaleName)(LPCWSTR);
static INT (WINAPI *pCompareStringOrdinal)(const WCHAR *, INT, const WCHAR *, INT, BOOL);
+static INT (WINAPI *pCompareStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPCWSTR, INT,
+ LPNLSVERSIONINFO, LPVOID, LPARAM);
static void InitFunctionPointers(void)
{
@@ -108,6 +110,7 @@ static void InitFunctionPointers(void)
pGetLocaleInfoEx = (void*)GetProcAddress(hKernel32, "GetLocaleInfoEx");
pIsValidLocaleName = (void*)GetProcAddress(hKernel32, "IsValidLocaleName");
pCompareStringOrdinal = (void*)GetProcAddress(hKernel32, "CompareStringOrdinal");
+ pCompareStringEx = (void*)GetProcAddress(hKernel32, "CompareStringEx");
}
#define eq(received, expected, label, type) \
@@ -1472,6 +1475,202 @@ static void test_CompareStringA(void)
"ret %d, error %d, expected value %d\n", ret, GetLastError(), CSTR_EQUAL);
}
+struct comparestringex_test {
+ const char *locale;
+ DWORD flags;
+ const WCHAR first[2];
+ const WCHAR second[2];
+ INT ret;
+ INT broken;
+ BOOL todo;
+};
+
+static const struct comparestringex_test comparestringex_tests[] = {
+ /* default behavior */
+ { /* 0 */
+ "tr-TR", 0,
+ {'i',0}, {'I',0}, CSTR_LESS_THAN, -1, FALSE
+ },
+ { /* 1 */
+ "tr-TR", 0,
+ {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
+ },
+ { /* 2 */
+ "tr-TR", 0,
+ {'i',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
+ },
+ { /* 3 */
+ "tr-TR", 0,
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 4 */
+ "tr-TR", 0,
+ {'I',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
+ },
+ { /* 5 */
+ "tr-TR", 0,
+ {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
+ },
+ /* with NORM_IGNORECASE */
+ { /* 6 */
+ "tr-TR", NORM_IGNORECASE,
+ {'i',0}, {'I',0}, CSTR_EQUAL, -1, FALSE
+ },
+ { /* 7 */
+ "tr-TR", NORM_IGNORECASE,
+ {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 8 */
+ "tr-TR", NORM_IGNORECASE,
+ {'i',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
+ },
+ { /* 9 */
+ "tr-TR", NORM_IGNORECASE,
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 10 */
+ "tr-TR", NORM_IGNORECASE,
+ {'I',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
+ },
+ { /* 11 */
+ "tr-TR", NORM_IGNORECASE,
+ {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
+ },
+ /* with NORM_LINGUISTIC_CASING */
+ { /* 12 */
+ "tr-TR", NORM_LINGUISTIC_CASING,
+ {'i',0}, {'I',0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
+ },
+ { /* 13 */
+ "tr-TR", NORM_LINGUISTIC_CASING,
+ {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 14 */
+ "tr-TR", NORM_LINGUISTIC_CASING,
+ {'i',0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
+ },
+ { /* 15 */
+ "tr-TR", NORM_LINGUISTIC_CASING,
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 16 */
+ "tr-TR", NORM_LINGUISTIC_CASING,
+ {'I',0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
+ },
+ { /* 17 */
+ "tr-TR", NORM_LINGUISTIC_CASING,
+ {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
+ },
+ /* with LINGUISTIC_IGNORECASE */
+ { /* 18 */
+ "tr-TR", LINGUISTIC_IGNORECASE,
+ {'i',0}, {'I',0}, CSTR_EQUAL, -1, TRUE
+ },
+ { /* 19 */
+ "tr-TR", LINGUISTIC_IGNORECASE,
+ {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 20 */
+ "tr-TR", LINGUISTIC_IGNORECASE,
+ {'i',0}, {0x131,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 21 */
+ "tr-TR", LINGUISTIC_IGNORECASE,
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 22 */
+ "tr-TR", LINGUISTIC_IGNORECASE,
+ {'I',0}, {0x131,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 23 */
+ "tr-TR", LINGUISTIC_IGNORECASE,
+ {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
+ },
+ /* with NORM_LINGUISTIC_CASING | NORM_IGNORECASE */
+ { /* 24 */
+ "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+ {'i',0}, {'I',0}, CSTR_GREATER_THAN, CSTR_EQUAL, TRUE
+ },
+ { /* 25 */
+ "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+ {'i',0}, {0x130,0}, CSTR_EQUAL, CSTR_LESS_THAN, TRUE
+ },
+ { /* 26 */
+ "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+ {'i',0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
+ },
+ { /* 27 */
+ "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 28 */
+ "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+ {'I',0}, {0x131,0}, CSTR_EQUAL, CSTR_LESS_THAN, TRUE
+ },
+ { /* 29 */
+ "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+ {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1, TRUE
+ },
+ /* with NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE */
+ { /* 30 */
+ "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+ {'i',0}, {'I',0}, CSTR_GREATER_THAN, CSTR_EQUAL, TRUE
+ },
+ { /* 31 */
+ "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+ {'i',0}, {0x130,0}, CSTR_EQUAL, CSTR_LESS_THAN, TRUE
+ },
+ { /* 32 */
+ "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+ {'i',0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
+ },
+ { /* 33 */
+ "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+ {'I',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ },
+ { /* 34 */
+ "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+ {'I',0}, {0x131,0}, CSTR_EQUAL, CSTR_LESS_THAN, TRUE
+ },
+ { /* 35 */
+ "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+ {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN, TRUE
+ }
+};
+
+static void test_CompareStringEx(void)
+{
+ const char *op[] = {"ERROR", "CSTR_LESS_THAN", "CSTR_EQUAL", "CSTR_GREATER_THAN"};
+ WCHAR locale[6];
+ INT ret, i;
+
+ /* CompareStringEx is only available on Vista+ */
+ if (!pCompareStringEx)
+ {
+ win_skip("CompareStringEx not supported\n");
+ return;
+ }
+
+ for (i = 0; i < sizeof(comparestringex_tests)/sizeof(comparestringex_tests[0]); i++)
+ {
+ const struct comparestringex_test *e = &comparestringex_tests[i];
+
+ MultiByteToWideChar(CP_ACP, 0, e->locale, -1, locale, sizeof(locale)/sizeof(WCHAR));
+ ret = pCompareStringEx(locale, e->flags, e->first, -1, e->second, -1, NULL, NULL, 0);
+ if (e->todo)
+ {
+ todo_wine ok(ret == e->ret || broken(ret == e->broken),
+ "%d: got %s, expected %s\n", i, op[ret], op[e->ret]);
+ }
+ else
+ {
+ ok(ret == e->ret || broken(ret == e->broken),
+ "%d: got %s, expected %s\n", i, op[ret], op[e->ret]);
+ }
+ }
+
+}
+
static void test_LCMapStringA(void)
{
int ret, ret2;
@@ -3608,6 +3807,7 @@ START_TEST(locale)
test_GetCurrencyFormatA(); /* Also tests the W version */
test_GetNumberFormatA(); /* Also tests the W version */
test_CompareStringA();
+ test_CompareStringEx();
test_LCMapStringA();
test_LCMapStringW();
test_LCMapStringEx();
--
1.7.9.5

View File

@@ -1,48 +0,0 @@
From 216cec49d8aa2698a30351c56e9eb97bde71f587 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Wed, 12 Feb 2014 13:27:10 -0700
Subject: kernel32: Allow CompareStringEx NORM_LINGUISTIC_CASING flag.
---
dlls/kernel32/locale.c | 2 +-
dlls/kernel32/tests/locale.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index 22903d5..24ca804 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -2935,7 +2935,7 @@ INT WINAPI CompareStringEx(LPCWSTR locale, DWORD flags, LPCWSTR str1, INT len1,
return 0;
}
- if( flags & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|
+ if( flags & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|NORM_LINGUISTIC_CASING|
SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP|0x10000000) )
{
SetLastError(ERROR_INVALID_FLAGS);
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 9aab6b0..bb6fbdc 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -1543,7 +1543,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 13 */
"tr-TR", NORM_LINGUISTIC_CASING,
- {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 14 */
"tr-TR", NORM_LINGUISTIC_CASING,
@@ -1593,7 +1593,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 25 */
"tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
- {'i',0}, {0x130,0}, CSTR_EQUAL, CSTR_LESS_THAN, TRUE
+ {'i',0}, {0x130,0}, CSTR_EQUAL, CSTR_LESS_THAN, FALSE
},
{ /* 26 */
"tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
--
1.7.9.5

View File

@@ -1,54 +0,0 @@
From aa81fa5f638112147fc7fd0ace9b7454f7ebf960 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Wed, 12 Feb 2014 13:27:24 -0700
Subject: kernel32: Allow CompareStringEx LINGUISTIC_IGNORECASE flag.
---
dlls/kernel32/locale.c | 3 ++-
dlls/kernel32/tests/locale.c | 6 +++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index 24ca804..3009df5 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -2936,7 +2936,8 @@ INT WINAPI CompareStringEx(LPCWSTR locale, DWORD flags, LPCWSTR str1, INT len1,
}
if( flags & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|NORM_LINGUISTIC_CASING|
- SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP|0x10000000) )
+ SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP|
+ LINGUISTIC_IGNORECASE|0x10000000) )
{
SetLastError(ERROR_INVALID_FLAGS);
return 0;
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index bb6fbdc..5eda11b 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -1568,11 +1568,11 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 19 */
"tr-TR", LINGUISTIC_IGNORECASE,
- {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, TRUE
+ {'i',0}, {0x130,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 20 */
"tr-TR", LINGUISTIC_IGNORECASE,
- {'i',0}, {0x131,0}, CSTR_LESS_THAN, -1, TRUE
+ {'i',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 21 */
"tr-TR", LINGUISTIC_IGNORECASE,
@@ -1580,7 +1580,7 @@ static const struct comparestringex_test comparestringex_tests[] = {
},
{ /* 22 */
"tr-TR", LINGUISTIC_IGNORECASE,
- {'I',0}, {0x131,0}, CSTR_LESS_THAN, -1, TRUE
+ {'I',0}, {0x131,0}, CSTR_LESS_THAN, -1, FALSE
},
{ /* 23 */
"tr-TR", LINGUISTIC_IGNORECASE,
--
1.7.9.5

View File

@@ -1,3 +0,0 @@
Revision: 2
Author: Erich E. Hoover
Title: Allow string comparison with linguistic casing.

Some files were not shown because too many files have changed in this diff Show More