You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-04-13 14:42:51 -07:00
Compare commits
61 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
47ddb3a6d1 | ||
|
5a4ba9a546 | ||
|
b51c16c86a | ||
|
c1edf8d5c4 | ||
|
ebf2fb3d7d | ||
|
ca1e83ef3f | ||
|
054930fd52 | ||
|
56fd91825e | ||
|
a6b295029c | ||
|
ddf6dd7f6a | ||
|
524c64dd2a | ||
|
e470b33f7c | ||
|
556aa9335e | ||
|
0817bd1a57 | ||
|
2f7523bffe | ||
|
9fd0a6eb9d | ||
|
f5f50d333c | ||
|
2d3f9334f8 | ||
|
9466f14d52 | ||
|
79c4f4391e | ||
|
820cc2e861 | ||
|
29d69db459 | ||
|
7642c422ed | ||
|
d56138d8ec | ||
|
b5687dc502 | ||
|
7a15599a3a | ||
|
7e5038e76c | ||
|
30f3d023d5 | ||
|
a7a1f83013 | ||
|
53053927fd | ||
|
35cab4ef93 | ||
|
43b0d84ae9 | ||
|
825145217c | ||
|
99c6fe660f | ||
|
4a69f63a78 | ||
|
39fa530c33 | ||
|
564f8aeafc | ||
|
e77f05ee52 | ||
|
f352182c20 | ||
|
7bb4be5d03 | ||
|
ef956caf59 | ||
|
8e45d4c99f | ||
|
004109b3bd | ||
|
dd5b1514b2 | ||
|
34a6c25071 | ||
|
6dc4078d74 | ||
|
6fcc7f732d | ||
|
997c04f7f8 | ||
|
658fe4e3ae | ||
|
40aaeb61f8 | ||
|
6274002623 | ||
|
24af73d1d2 | ||
|
155a364280 | ||
|
9c1492069b | ||
|
c3d5bcab99 | ||
|
c3052d2e31 | ||
|
87fd81b9d8 | ||
|
062426558b | ||
|
1c6aeef3b4 | ||
|
f7de528788 | ||
|
8d45dc126d |
15
README.md
15
README.md
@@ -2,3 +2,18 @@ wine-compholio-daily
|
||||
====================
|
||||
|
||||
Daily updates for the Wine "Compholio" Edition.
|
||||
|
||||
Current patches include:
|
||||
* Support for interface change notifications (http://bugs.winehq.org/show_bug.cgi?id=32328)
|
||||
* Support for stored file ACLs (http://bugs.winehq.org/show_bug.cgi?id=31858)
|
||||
* Support for inherited file ACLs (http://bugs.winehq.org/show_bug.cgi?id=34406)
|
||||
* Support for Junction Points (http://bugs.winehq.org/show_bug.cgi?id=12401)
|
||||
* 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)
|
||||
* Workaround for shlwapi URLs with relative paths
|
||||
* Support for PulseAudio backend for audio
|
||||
|
50
debian/changelog
vendored
50
debian/changelog
vendored
@@ -1,3 +1,53 @@
|
||||
wine-compholio (1.7.15) unstable; urgency=low
|
||||
* Fixed build dependencies for Debian Sid.
|
||||
* Fixed free() of a const variable (Bug #1).
|
||||
* Removed get_dir_unix_fd (no longer used, fixes compiling with "-Werror").
|
||||
* Removed 'register user administrative tools shell folder' patch (accepted upstream).
|
||||
-- Erich E. Hoover <erich.e.hoover@gmail.com> Sun, 23 Mar 2014 12:53:32 +0100
|
||||
|
||||
wine-compholio (1.7.14) unstable; urgency=low
|
||||
* Minor updates to the ACL patches.
|
||||
* Added Liberation Sans (SIL Open Font License) as an Arial replacement.
|
||||
-- Erich E. Hoover <erich.e.hoover@gmail.com> Fri, 07 Mar 2014 13:59:11 -0700
|
||||
|
||||
wine-compholio (1.7.13-1) unstable; urgency=low
|
||||
* Fixed a typo in the configure check for extended attributes.
|
||||
-- Erich E. Hoover <erich.e.hoover@gmail.com> Fri, 21 Feb 2014 09:00:00 -0700
|
||||
|
||||
wine-compholio (1.7.13) unstable; urgency=low
|
||||
* Added support for inherited file ACLs.
|
||||
* Further separated the file ACL patches.
|
||||
* Updated linguistic casing patches to include tests.
|
||||
* Updated the patch list template to be compatible with 'git am'.
|
||||
* Moved the patching code out of the debian rules into a Makefile.
|
||||
* Removed the named pipe security access patch (accepted upstream).
|
||||
* Explicitly run configure with '--with-xattr' when building debian packages.
|
||||
* Will now fail on configure when '--with-xattr' is passed and xattr.h cannot be found.
|
||||
-- Erich E. Hoover <erich.e.hoover@gmail.com> Thu, 20 Feb 2014 18:48:03 -0700
|
||||
|
||||
wine-compholio (1.7.12-1) unstable; urgency=low
|
||||
* Fixed PulseAudio patches to apply with 'git am'.
|
||||
* Fixed PulseAudio driver configure file for upstream Wine 1.7.12.
|
||||
* Fixed PulseAudio driver pthread dependency for upstream Wine 1.7.12.
|
||||
-- Erich E. Hoover <erich.e.hoover@gmail.com> Fri, 07 Feb 2014 17:52:32 -0700
|
||||
|
||||
wine-compholio (1.7.12) unstable; urgency=low
|
||||
* Added new patches to support GetVolumePathName.
|
||||
-- Erich E. Hoover <erich.e.hoover@gmail.com> Fri, 07 Feb 2014 14:57:33 -0700
|
||||
|
||||
wine-compholio (1.7.11) unstable; urgency=low
|
||||
* Added SRWLock patch.
|
||||
* Added new patches to support TransmitFile.
|
||||
* Added new patches to support Junction Points.
|
||||
* Moved pipelight-specific patches to a separate folder.
|
||||
* Removed SRWLock patch included in upstream Wine 1.7.11.
|
||||
* Reduced SetTimer minimum limitation from 15 ms to 5 ms.
|
||||
* Added support for security access parameters for named pipes.
|
||||
* Added WINE_STRICT_DRAW_ORDERING command line environment variable.
|
||||
* Fixed a path length bug in the ACL inheritance patch (assumed DOS limitation).
|
||||
* Added some workarounds for shlwapi url functions not handling relative paths well.
|
||||
-- Erich E. Hoover <erich.e.hoover@gmail.com> Fri, 17 Jan 2014 12:27:32 -0700
|
||||
|
||||
wine-compholio (1.7.10) unstable; urgency=low
|
||||
* Removed monitor enumeration patch included in upstream Wine 1.7.10.
|
||||
* Updated SIO_ADDRESS_LIST_CHANGE patch with latest proposed version.
|
||||
|
6
debian/control
vendored
6
debian/control
vendored
@@ -7,16 +7,20 @@ Build-Depends: autotools-dev,
|
||||
autoconf,
|
||||
bind9-host,
|
||||
bison,
|
||||
bsdmainutils,
|
||||
coreutils,
|
||||
debhelper (>= 7),
|
||||
docbook-to-man,
|
||||
docbook-utils,
|
||||
docbook-xsl,
|
||||
flex,
|
||||
fontforge,
|
||||
gawk,
|
||||
gcc-4.5 | gcc-4.7 | ubuntu-desktop (<< 1.207),
|
||||
gcc-4.5-multilib [amd64] | ubuntu-desktop (<< 1.207) [amd64],
|
||||
gcc-multilib [amd64],
|
||||
gettext,
|
||||
gzip,
|
||||
ia32-libs [amd64],
|
||||
ia32-libs-dev [amd64] | ubuntu-desktop (<< 1.267) [amd64],
|
||||
ia32-libs-multiarch [amd64] | ubuntu-desktop (<< 1.267) [amd64],
|
||||
@@ -92,7 +96,7 @@ Recommends: gettext,
|
||||
libgif4,
|
||||
libgnutls26,
|
||||
libgphoto2-6 | libgphoto2-2 (>= 2.4.6),
|
||||
libgphoto2-port0 (>= 2.4.6),
|
||||
libgphoto2-port10 | libgphoto2-port0 (>= 2.4.6),
|
||||
libjpeg8,
|
||||
libopenal1 (>= 1:1.12),
|
||||
libosmesa6,
|
||||
|
17
debian/rules
vendored
17
debian/rules
vendored
@@ -63,20 +63,11 @@ ifneq "$(wildcard /usr/share/misc/config.guess)" ""
|
||||
cp -f /usr/share/misc/config.guess config.guess
|
||||
endif
|
||||
|
||||
# Apply our patches to Wine
|
||||
for DIR in $$(find $(CURDIR)/patches/ -type d | sort); do \
|
||||
for FILE in $$(ls $$DIR | sort | grep '\.patch$$'); do \
|
||||
patch -N -p0 --strip=1 < $$DIR/$$FILE || exit 1; \
|
||||
done \
|
||||
done
|
||||
|
||||
# Update the configure script
|
||||
autoreconf
|
||||
# Apply our patches, reconfigure, and update the wineserver protocol request data
|
||||
make -C "$(CURDIR)/patches/" DESTDIR="$(CURDIR)" install
|
||||
|
||||
# Configure
|
||||
CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/opt/wine-compholio --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info $(CONFFLAGS)
|
||||
|
||||
|
||||
CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/opt/wine-compholio --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info --with-xattr $(CONFFLAGS)
|
||||
|
||||
build: build-stamp
|
||||
|
||||
@@ -119,7 +110,7 @@ binary-arch: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
# dh_installchangelogs ChangeLog
|
||||
dh_installdocs
|
||||
# dh_installdocs
|
||||
dh_installexamples
|
||||
# dh_install
|
||||
# dh_installmenu
|
||||
|
29
patch-list-template.diff → debian/tools/generate-patchlist.sh
vendored
Normal file → Executable file
29
patch-list-template.diff → debian/tools/generate-patchlist.sh
vendored
Normal file → Executable file
@@ -1,3 +1,31 @@
|
||||
#!/bin/sh
|
||||
PATCH_DATA="";
|
||||
|
||||
for FILE in patches/*/*.def; do
|
||||
UUID=$(echo "${FILE}" | sed -e 's|^.*/||g' -e 's|\.def$||g');
|
||||
REVISION=$(cat "${FILE}" | sed -n 's|Revision: \(.*\)|\1|p');
|
||||
AUTHOR=$(cat "${FILE}" | sed -n 's|Author: \(.*\)|\1|p');
|
||||
TITLE=$(cat "${FILE}" | sed -n 's|Title: \(.*\)|\1|p');
|
||||
if [ "${AUTHOR}" = "" ] && [ "${TITLE}" = "" ]; then
|
||||
continue;
|
||||
fi
|
||||
if [ "${PATCH_DATA}" != "" ]; then
|
||||
PATCH_DATA="${PATCH_DATA}
|
||||
";
|
||||
fi
|
||||
PATCH_DATA="${PATCH_DATA}+ { \"${UUID}:${REVISION}\", \"${AUTHOR}\", \"${TITLE}\" },";
|
||||
done
|
||||
|
||||
PATCH_LINES=$(echo "${PATCH_DATA}" | grep -c '\n');
|
||||
PATCH_LINES=$((${PATCH_LINES}+20));
|
||||
PATCH_DATA=$(echo "${PATCH_DATA}" | sed ':a;N;$!ba;s/\n/\\n/g');
|
||||
|
||||
cat <<EOF | sed -e "s|##PATCH_LINES##|${PATCH_LINES}|" \
|
||||
-e "s|##PATCH_DATA##|${PATCH_DATA}|"
|
||||
From: "FDS-Team" <webmaster@fds-team.de>
|
||||
Subject: Autogenerated patch list.
|
||||
|
||||
---
|
||||
diff --git a/dlls/ntdll/misc.c b/dlls/ntdll/misc.c
|
||||
index 8bd4eb7..4b4c318 100644
|
||||
--- a/dlls/ntdll/misc.c
|
||||
@@ -135,3 +163,4 @@ index 242bb69..aa9e585 100644
|
||||
extern const char *wine_get_build_id(void);
|
||||
extern void wine_init_argv0_path( const char *argv0 );
|
||||
extern void wine_exec_wine_binary( const char *name, char **argv, const char *env_var );
|
||||
EOF
|
572
debian/tools/gitapply.sh
vendored
Executable file
572
debian/tools/gitapply.sh
vendored
Executable file
File diff suppressed because it is too large
Load Diff
@@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
PATCH_DATA="";
|
||||
for FILE in patches/*/*.def; do
|
||||
UUID=$(echo "${FILE}" | sed -e 's|^.*/||g' -e 's|\.def$||g');
|
||||
REVISION=$(cat "${FILE}" | sed -n 's|Revision: \(.*\)|\1|p');
|
||||
AUTHOR=$(cat "${FILE}" | sed -n 's|Author: \(.*\)|\1|p');
|
||||
TITLE=$(cat "${FILE}" | sed -n 's|Title: \(.*\)|\1|p');
|
||||
if [ "${AUTHOR}" = "" ] && [ "${TITLE}" = "" ]; then
|
||||
continue;
|
||||
fi
|
||||
if [ "${PATCH_DATA}" != "" ]; then
|
||||
PATCH_DATA="${PATCH_DATA}
|
||||
";
|
||||
fi
|
||||
PATCH_DATA="${PATCH_DATA}+ { \"${UUID}:${REVISION}\", \"${AUTHOR}\", \"${TITLE}\" },";
|
||||
done
|
||||
PATCH_LINES=$(echo "${PATCH_DATA}" | grep -c '\n');
|
||||
PATCH_LINES=$((${PATCH_LINES}+20));
|
||||
PATCH_DATA=$(echo "${PATCH_DATA}" | sed ':a;N;$!ba;s/\n/\\n/g');
|
||||
cat patch-list-template.diff | sed \
|
||||
-e "s|##PATCH_LINES##|${PATCH_LINES}|" \
|
||||
-e "s|##PATCH_DATA##|${PATCH_DATA}|"
|
||||
#
|
@@ -1,17 +1,17 @@
|
||||
From 362ec39591ce54bcb5ce825c1baab8f5d0885193 Mon Sep 17 00:00:00 2001
|
||||
From a1ad64b059de5325b15ed09a39083f5eb973a2f6 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 5 Dec 2013 13:32:34 -0700
|
||||
Date: Wed, 12 Feb 2014 13:46:28 -0700
|
||||
Subject: ws2_32: Ask the server to process unsupported WSAIoctl operations.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 56 +++++++++++++++++++++++++++++++++++++++++++-------
|
||||
1 file changed, 49 insertions(+), 7 deletions(-)
|
||||
dlls/ws2_32/socket.c | 60 ++++++++++++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 53 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index 304b0eb..170dde7 100644
|
||||
index 1c558bf..fe5577c 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -3608,6 +3608,36 @@ static const char *debugstr_wsaioctl(DWORD ioctl)
|
||||
@@ -3668,6 +3668,40 @@ static const char *debugstr_wsaioctl(DWORD ioctl)
|
||||
(USHORT)(ioctl & 0xffff));
|
||||
}
|
||||
|
||||
@@ -37,8 +37,12 @@ index 304b0eb..170dde7 100644
|
||||
+ status = NtDeviceIoControlFile( handle, event, (PIO_APC_ROUTINE)ws2_async_apc, wsa, io, code,
|
||||
+ in_buff, in_size, out_buff, out_size );
|
||||
+ if (status == STATUS_NOT_SUPPORTED)
|
||||
+ {
|
||||
+ FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n",
|
||||
+ code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
|
||||
+ }
|
||||
+ else if (status == STATUS_SUCCESS)
|
||||
+ *ret_size = io->Information; /* "Information" is the size written to the output buffer */
|
||||
+
|
||||
+ if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, wsa );
|
||||
+
|
||||
@@ -48,7 +52,7 @@ index 304b0eb..170dde7 100644
|
||||
/**********************************************************************
|
||||
* WSAIoctl (WS2_32.50)
|
||||
*
|
||||
@@ -3799,12 +3829,6 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
|
||||
@@ -3859,12 +3893,6 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -61,7 +65,7 @@ index 304b0eb..170dde7 100644
|
||||
case WS_SIO_ADDRESS_LIST_QUERY:
|
||||
{
|
||||
DWORD size;
|
||||
@@ -4040,11 +4064,29 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
|
||||
@@ -4100,11 +4128,29 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
|
||||
WSASetLastError(WSAEOPNOTSUPP);
|
||||
return SOCKET_ERROR;
|
||||
default:
|
||||
@@ -72,7 +76,7 @@ index 304b0eb..170dde7 100644
|
||||
|
||||
+ if (status == WSAEOPNOTSUPP)
|
||||
+ {
|
||||
+ status = server_ioctl_sock(s, code, in_buff, in_size, out_buff, out_size, ret_size,
|
||||
+ status = server_ioctl_sock(s, code, in_buff, in_size, out_buff, out_size, &total,
|
||||
+ overlapped, completion);
|
||||
+ if (status != WSAEOPNOTSUPP)
|
||||
+ {
|
||||
|
@@ -8,10 +8,10 @@ Subject: ws2_32: Add an interactive test for interface change notifications.
|
||||
1 file changed, 68 insertions(+)
|
||||
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index ac6ee10..b6da0e7 100644
|
||||
index 0abf732..4703e59 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6225,6 +6225,73 @@ static void test_sioRoutingInterfaceQuery(void)
|
||||
@@ -6487,6 +6487,73 @@ static void test_sioRoutingInterfaceQuery(void)
|
||||
closesocket(sock);
|
||||
}
|
||||
|
||||
@@ -85,14 +85,14 @@ index ac6ee10..b6da0e7 100644
|
||||
static void test_synchronous_WSAIoctl(void)
|
||||
{
|
||||
HANDLE previous_port, io_port;
|
||||
@@ -7101,6 +7168,7 @@ START_TEST( sock )
|
||||
@@ -7570,6 +7637,7 @@ START_TEST( sock )
|
||||
test_ConnectEx();
|
||||
|
||||
test_sioRoutingInterfaceQuery();
|
||||
+ test_sioAddressListChange();
|
||||
|
||||
test_WSAAsyncGetServByPort();
|
||||
test_WSAAsyncGetServByName();
|
||||
test_WSALookupService();
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
||||
|
@@ -1,499 +0,0 @@
|
||||
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
|
||||
|
@@ -0,0 +1,135 @@
|
||||
From ee79e1be71635431d0d05841c7f9cea720411ba6 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
|
||||
Subject: server: Unify the storage of security attributes for files and
|
||||
directories.
|
||||
|
||||
---
|
||||
server/change.c | 46 ++++++----------------------------------------
|
||||
server/file.c | 25 +++++++++++++++++--------
|
||||
server/file.h | 2 ++
|
||||
3 files changed, 25 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/server/change.c b/server/change.c
|
||||
index f6d56b0..76fc9f7 100644
|
||||
--- a/server/change.c
|
||||
+++ b/server/change.c
|
||||
@@ -317,49 +317,15 @@ static struct security_descriptor *dir_get_sd( struct object *obj )
|
||||
static int dir_set_sd( struct object *obj, const struct security_descriptor *sd,
|
||||
unsigned int set_info )
|
||||
{
|
||||
- struct dir *dir = (struct dir *)obj;
|
||||
- const SID *owner;
|
||||
- struct stat st;
|
||||
- mode_t mode;
|
||||
- int unix_fd;
|
||||
+ struct fd *fd;
|
||||
+ int ret;
|
||||
|
||||
assert( obj->ops == &dir_ops );
|
||||
|
||||
- unix_fd = get_dir_unix_fd( dir );
|
||||
-
|
||||
- if (unix_fd == -1 || fstat( unix_fd, &st ) == -1) return 1;
|
||||
-
|
||||
- if (set_info & OWNER_SECURITY_INFORMATION)
|
||||
- {
|
||||
- owner = sd_get_owner( sd );
|
||||
- if (!owner)
|
||||
- {
|
||||
- set_error( STATUS_INVALID_SECURITY_DESCR );
|
||||
- return 0;
|
||||
- }
|
||||
- if (!obj->sd || !security_equal_sid( owner, sd_get_owner( obj->sd ) ))
|
||||
- {
|
||||
- /* FIXME: get Unix uid and call fchown */
|
||||
- }
|
||||
- }
|
||||
- else if (obj->sd)
|
||||
- owner = sd_get_owner( obj->sd );
|
||||
- else
|
||||
- owner = token_get_user( current->process->token );
|
||||
-
|
||||
- if (set_info & DACL_SECURITY_INFORMATION)
|
||||
- {
|
||||
- /* keep the bits that we don't map to access rights in the ACL */
|
||||
- mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX);
|
||||
- mode |= sd_to_mode( sd, owner );
|
||||
-
|
||||
- if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1)
|
||||
- {
|
||||
- file_set_error();
|
||||
- return 0;
|
||||
- }
|
||||
- }
|
||||
- return 1;
|
||||
+ fd = dir_get_fd( obj );
|
||||
+ ret = file_set_acls( 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
|
||||
--- 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 )
|
||||
return new_mode & ~denied_mode;
|
||||
}
|
||||
|
||||
-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 )
|
||||
{
|
||||
- struct file *file = (struct file *)obj;
|
||||
+ int unix_fd = get_unix_fd( fd );
|
||||
const SID *owner;
|
||||
struct stat st;
|
||||
mode_t mode;
|
||||
- int unix_fd;
|
||||
-
|
||||
- assert( obj->ops == &file_ops );
|
||||
-
|
||||
- unix_fd = get_file_unix_fd( file );
|
||||
|
||||
if (unix_fd == -1 || fstat( unix_fd, &st ) == -1) return 1;
|
||||
|
||||
@@ -584,6 +579,20 @@ static int file_set_sd( struct object *obj, const struct security_descriptor *sd
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int file_set_sd( struct object *obj, const struct security_descriptor *sd,
|
||||
+ unsigned int set_info )
|
||||
+{
|
||||
+ struct fd *fd;
|
||||
+ int ret;
|
||||
+
|
||||
+ assert( obj->ops == &file_ops );
|
||||
+
|
||||
+ fd = file_get_fd( obj );
|
||||
+ ret = file_set_acls( obj, fd, sd, set_info );
|
||||
+ release_object( fd );
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void file_destroy( struct object *obj )
|
||||
{
|
||||
struct file *file = (struct file *)obj;
|
||||
diff --git a/server/file.h b/server/file.h
|
||||
index 493d30b..11c3220 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 );
|
||||
|
||||
/* file mapping functions */
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -1,180 +0,0 @@
|
||||
From 5e49f53a4bd591e67c9b7c4fdaf46933e319f9aa Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Mon, 18 Nov 2013 18:15:20 -0700
|
||||
Subject: ntdll: Inherit security attributes from parent directories.
|
||||
|
||||
---
|
||||
dlls/advapi32/tests/security.c | 40 ++++++++++++++++++-
|
||||
dlls/ntdll/file.c | 85 +++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 123 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
|
||||
index 7d28c05..a8d136b 100644
|
||||
--- a/dlls/advapi32/tests/security.c
|
||||
+++ b/dlls/advapi32/tests/security.c
|
||||
@@ -3013,10 +3013,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;
|
||||
|
||||
@@ -3108,6 +3109,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/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 1de2c61..8948bb7 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -103,6 +103,81 @@ mode_t FILE_umask = 0;
|
||||
|
||||
static const WCHAR ntfsW[] = {'N','T','F','S'};
|
||||
|
||||
+static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIBUTES attr,
|
||||
+ PIO_STATUS_BLOCK io, PLARGE_INTEGER alloc_size,
|
||||
+ ULONG attributes, ULONG sharing, ULONG disposition,
|
||||
+ ULONG options, PVOID ea_buffer, ULONG ea_length );
|
||||
+
|
||||
+struct security_descriptor *FILE_get_parent_sd(UNICODE_STRING *filenameW)
|
||||
+{
|
||||
+ SECURITY_INFORMATION info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION
|
||||
+ |DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION;
|
||||
+ PSECURITY_DESCRIPTOR parentsd = NULL;
|
||||
+ ACL_SIZE_INFORMATION acl_size;
|
||||
+ BOOLEAN present, defaulted;
|
||||
+ WCHAR *p, parent[MAX_PATH];
|
||||
+ OBJECT_ATTRIBUTES pattr;
|
||||
+ UNICODE_STRING parentW;
|
||||
+ IO_STATUS_BLOCK io;
|
||||
+ NTSTATUS status;
|
||||
+ HANDLE hparent;
|
||||
+ ULONG n1, n2;
|
||||
+ PACL pDacl;
|
||||
+ int i;
|
||||
+
|
||||
+ parentW.Buffer = parent;
|
||||
+ parentW.Length = filenameW->Length;
|
||||
+ memcpy(parentW.Buffer, filenameW->Buffer, filenameW->Length);
|
||||
+ if ((p = strrchrW(parent, '\\')) != NULL)
|
||||
+ {
|
||||
+ p[0] = 0;
|
||||
+ parentW.Length = (p-parent)*sizeof(WCHAR);
|
||||
+ }
|
||||
+ memset(&pattr, 0x0, sizeof(pattr));
|
||||
+ pattr.Length = sizeof(pattr);
|
||||
+ pattr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
+ pattr.ObjectName = &parentW;
|
||||
+ status = FILE_CreateFile( &hparent, READ_CONTROL|ACCESS_SYSTEM_SECURITY, &pattr, &io, NULL,
|
||||
+ FILE_FLAG_BACKUP_SEMANTICS,
|
||||
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN,
|
||||
+ FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 );
|
||||
+ if (status == STATUS_SUCCESS)
|
||||
+ status = NtQuerySecurityObject( hparent, info, NULL, 0, &n1 );
|
||||
+ if (status == STATUS_BUFFER_TOO_SMALL && (parentsd = RtlAllocateHeap( GetProcessHeap(), 0, n1 )) != NULL)
|
||||
+ status = NtQuerySecurityObject( hparent, info, parentsd, n1, &n2 );
|
||||
+ if (status == STATUS_SUCCESS)
|
||||
+ status = NtQuerySecurityObject( hparent, info, parentsd, n1, &n2 );
|
||||
+ if (hparent != INVALID_HANDLE_VALUE)
|
||||
+ NtClose( hparent );
|
||||
+ if (status != STATUS_SUCCESS) return NULL;
|
||||
+ status = RtlGetDaclSecurityDescriptor(parentsd, &present, &pDacl, &defaulted);
|
||||
+ if (status != STATUS_SUCCESS || !present) return NULL;
|
||||
+ status = RtlQueryInformationAcl(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
|
||||
+ if (status != STATUS_SUCCESS) return NULL;
|
||||
+
|
||||
+ for (i=acl_size.AceCount-1; i>=0; i--)
|
||||
+ {
|
||||
+ DWORD inheritance_mask = INHERIT_ONLY_ACE|OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE;
|
||||
+ ACE_HEADER *ace;
|
||||
+
|
||||
+ status = RtlGetAce(pDacl, i, (VOID **)&ace);
|
||||
+ if (status != STATUS_SUCCESS || !(ace->AceFlags & inheritance_mask))
|
||||
+ {
|
||||
+ RtlDeleteAce(pDacl, i);
|
||||
+ acl_size.AceCount--;
|
||||
+ }
|
||||
+ else
|
||||
+ ace->AceFlags = (ace->AceFlags & ~inheritance_mask) | INHERITED_ACE;
|
||||
+ }
|
||||
+
|
||||
+ if (!acl_size.AceCount)
|
||||
+ {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ return parentsd;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/**************************************************************************
|
||||
* FILE_CreateFile (internal)
|
||||
* Open a file.
|
||||
@@ -161,10 +236,18 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
|
||||
{
|
||||
struct security_descriptor *sd;
|
||||
struct object_attributes objattr;
|
||||
+ PSECURITY_DESCRIPTOR parentsd = NULL, psd;
|
||||
|
||||
objattr.rootdir = wine_server_obj_handle( attr->RootDirectory );
|
||||
objattr.name_len = 0;
|
||||
- io->u.Status = NTDLL_create_struct_sd( attr->SecurityDescriptor, &sd, &objattr.sd_len );
|
||||
+ psd = attr->SecurityDescriptor;
|
||||
+ if (!psd && (disposition == FILE_CREATE||disposition == FILE_OVERWRITE_IF))
|
||||
+ parentsd = FILE_get_parent_sd( attr->ObjectName );
|
||||
+ if (parentsd)
|
||||
+ psd = parentsd;
|
||||
+ io->u.Status = NTDLL_create_struct_sd( psd, &sd, &objattr.sd_len );
|
||||
+ if (parentsd)
|
||||
+ RtlFreeHeap( GetProcessHeap(), 0, parentsd );
|
||||
if (io->u.Status != STATUS_SUCCESS)
|
||||
{
|
||||
RtlFreeAnsiString( &unix_name );
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,141 @@
|
||||
From b83ae7cc77483519ed870ead3a167e83acbf1cff 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
|
||||
Subject: server: Unify the retrieval of security attributes for files and
|
||||
directories.
|
||||
|
||||
---
|
||||
server/change.c | 32 +++++---------------------------
|
||||
server/file.c | 34 ++++++++++++++++++++++------------
|
||||
server/file.h | 2 ++
|
||||
3 files changed, 29 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/server/change.c b/server/change.c
|
||||
index 76fc9f7..eb16923 100644
|
||||
--- a/server/change.c
|
||||
+++ b/server/change.c
|
||||
@@ -278,39 +278,17 @@ static struct fd *dir_get_fd( struct object *obj )
|
||||
return (struct fd *)grab_object( dir->fd );
|
||||
}
|
||||
|
||||
-static int get_dir_unix_fd( struct dir *dir )
|
||||
-{
|
||||
- return get_unix_fd( dir->fd );
|
||||
-}
|
||||
-
|
||||
static struct security_descriptor *dir_get_sd( struct object *obj )
|
||||
{
|
||||
struct dir *dir = (struct dir *)obj;
|
||||
- int unix_fd;
|
||||
- struct stat st;
|
||||
struct security_descriptor *sd;
|
||||
- assert( obj->ops == &dir_ops );
|
||||
-
|
||||
- unix_fd = get_dir_unix_fd( dir );
|
||||
-
|
||||
- if (unix_fd == -1 || fstat( unix_fd, &st ) == -1)
|
||||
- return obj->sd;
|
||||
-
|
||||
- /* mode and uid the same? if so, no need to re-generate security descriptor */
|
||||
- if (obj->sd &&
|
||||
- (st.st_mode & (S_IRWXU|S_IRWXO)) == (dir->mode & (S_IRWXU|S_IRWXO)) &&
|
||||
- (st.st_uid == dir->uid))
|
||||
- return obj->sd;
|
||||
+ struct fd *fd;
|
||||
|
||||
- sd = mode_to_sd( st.st_mode,
|
||||
- security_unix_uid_to_sid( st.st_uid ),
|
||||
- token_get_primary_group( current->process->token ));
|
||||
- if (!sd) return obj->sd;
|
||||
+ assert( obj->ops == &dir_ops );
|
||||
|
||||
- dir->mode = st.st_mode;
|
||||
- dir->uid = st.st_uid;
|
||||
- free( obj->sd );
|
||||
- obj->sd = sd;
|
||||
+ fd = dir_get_fd( obj );
|
||||
+ sd = file_get_acls( 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
|
||||
--- 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
|
||||
return sd;
|
||||
}
|
||||
|
||||
-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 file *file = (struct file *)obj;
|
||||
- struct stat st;
|
||||
- int unix_fd;
|
||||
+ int unix_fd = get_unix_fd( 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;
|
||||
|
||||
/* mode and uid the same? if so, no need to re-generate security descriptor */
|
||||
- if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXO)) == (file->mode & (S_IRWXU|S_IRWXO)) &&
|
||||
- (st.st_uid == file->uid))
|
||||
+ if (obj->sd && (st.st_mode & (S_IRWXU|S_IRWXO)) == (*mode & (S_IRWXU|S_IRWXO)) &&
|
||||
+ (st.st_uid == *uid))
|
||||
return obj->sd;
|
||||
|
||||
sd = mode_to_sd( st.st_mode,
|
||||
@@ -448,13 +444,27 @@ static struct security_descriptor *file_get_sd( struct object *obj )
|
||||
token_get_primary_group( current->process->token ));
|
||||
if (!sd) return obj->sd;
|
||||
|
||||
- file->mode = st.st_mode;
|
||||
- file->uid = st.st_uid;
|
||||
+ *mode = st.st_mode;
|
||||
+ *uid = st.st_uid;
|
||||
free( obj->sd );
|
||||
obj->sd = sd;
|
||||
return sd;
|
||||
}
|
||||
|
||||
+static struct security_descriptor *file_get_sd( struct object *obj )
|
||||
+{
|
||||
+ struct file *file = (struct file *)obj;
|
||||
+ struct security_descriptor *sd;
|
||||
+ struct fd *fd;
|
||||
+
|
||||
+ assert( obj->ops == &file_ops );
|
||||
+
|
||||
+ fd = file_get_fd( obj );
|
||||
+ sd = file_get_acls( obj, fd, &file->mode, &file->uid );
|
||||
+ release_object( fd );
|
||||
+ return sd;
|
||||
+}
|
||||
+
|
||||
static mode_t file_access_to_mode( unsigned int access )
|
||||
{
|
||||
mode_t mode = 0;
|
||||
diff --git a/server/file.h b/server/file.h
|
||||
index 11c3220..89b5888 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 );
|
||||
|
||||
/* file mapping functions */
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,150 @@
|
||||
From 96470b6ee4c0e91700ac197e77784feb42d9a961 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
|
||||
Subject: server: Store file security attributes with extended file
|
||||
attributes.
|
||||
|
||||
---
|
||||
configure.ac | 12 +++++++++++
|
||||
server/file.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 79 insertions(+)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 32730f3..96d796a 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
|
||||
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]),
|
||||
@@ -661,6 +662,17 @@ AC_CHECK_HEADERS([libprocstat.h],,,
|
||||
#include <sys/socket.h>
|
||||
#endif])
|
||||
|
||||
+if test "x$with_xattr" != "xno"
|
||||
+then
|
||||
+ AC_CHECK_HEADERS(attr/xattr.h,HAVE_XATTR=1)
|
||||
+fi
|
||||
+if test "x$with_xattr" == "xyes"
|
||||
+then
|
||||
+ WINE_ERROR_WITH(xattr,[test "x$HAVE_XATTR" = "x"],[xattr ${notice_platform}development files not \
|
||||
+found. Wine will be built without extended attribute support, which probably isn't what you want. \
|
||||
+You will need to install ${notice_platform}development packages of libacl at the very least.])
|
||||
+fi
|
||||
+
|
||||
dnl **** Check for working dll ****
|
||||
|
||||
AC_SUBST(dlldir,"\${libdir}/wine")
|
||||
diff --git a/server/file.c b/server/file.c
|
||||
index 8baa712..c375c72 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
|
||||
@@ -178,6 +182,66 @@ 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 )
|
||||
+{
|
||||
+#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
|
||||
+}
|
||||
+
|
||||
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
|
||||
/* 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 );
|
||||
|
||||
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
|
||||
mode = st.st_mode & (S_ISUID|S_ISGID|S_ISVTX);
|
||||
mode |= sd_to_mode( sd, owner );
|
||||
|
||||
+ set_xattr_acls( unix_fd, sd );
|
||||
+
|
||||
if (((st.st_mode ^ mode) & (S_IRWXU|S_IRWXG|S_IRWXO)) && fchmod( unix_fd, mode ) == -1)
|
||||
{
|
||||
file_set_error();
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,293 @@
|
||||
From 66583f9f848becaa12d84270a2ebe7a79ac34724 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
|
||||
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(-)
|
||||
|
||||
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
|
||||
index e2e9cd5..f107abc 100644
|
||||
--- a/dlls/advapi32/tests/security.c
|
||||
+++ b/dlls/advapi32/tests/security.c
|
||||
@@ -3105,24 +3105,24 @@ 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(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
||||
- ace->Mask);
|
||||
+ 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);
|
||||
+ todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
+ "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
}
|
||||
if (acl_size.AceCount > 1)
|
||||
{
|
||||
bret = pGetAce(pDacl, 1, (VOID **)&ace);
|
||||
ok(bret, "Failed to get Administators Group ACE.\n");
|
||||
bret = EqualSid(&ace->SidStart, admin_sid);
|
||||
- todo_wine ok(bret, "Administators Group ACE != Administators Group SID.\n");
|
||||
- todo_wine ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
|
||||
- "Administators Group ACE has unexpected flags (0x%x != 0x03)\n",
|
||||
- ((ACE_HEADER *)ace)->AceFlags);
|
||||
- ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
||||
- ace->Mask);
|
||||
+ 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);
|
||||
+ todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
+ "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -3294,23 +3294,22 @@ 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",
|
||||
- ace->Mask);
|
||||
+ todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
+ "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
}
|
||||
if (acl_size.AceCount > 1)
|
||||
{
|
||||
bret = pGetAce(pDacl, 1, (VOID **)&ace);
|
||||
ok(bret, "Failed to get Administators Group ACE.\n");
|
||||
bret = EqualSid(&ace->SidStart, admin_sid);
|
||||
- todo_wine ok(bret || 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 */,
|
||||
- "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
+ todo_wine 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);
|
||||
@@ -3960,22 +3959,22 @@ 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",
|
||||
- ace->Mask);
|
||||
+ todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
+ "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
}
|
||||
if (acl_size.AceCount > 1)
|
||||
{
|
||||
bret = pGetAce(pDacl, 1, (VOID **)&ace);
|
||||
ok(bret, "Failed to get Administators Group ACE.\n");
|
||||
bret = EqualSid(&ace->SidStart, admin_sid);
|
||||
- todo_wine ok(bret, "Administators Group ACE != Administators Group SID.\n");
|
||||
+ 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",
|
||||
- ace->Mask);
|
||||
+ todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
+ "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
}
|
||||
CloseHandle(obj);
|
||||
}
|
||||
diff --git a/server/file.c b/server/file.c
|
||||
index c375c72..b9135b9 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
|
||||
return sd;
|
||||
}
|
||||
|
||||
+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;
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ return sd;
|
||||
+#else
|
||||
+ return NULL;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
struct security_descriptor *file_get_acls( struct object *obj, struct fd *fd, mode_t *mode,
|
||||
uid_t *uid )
|
||||
{
|
||||
int unix_fd = get_unix_fd( fd );
|
||||
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
|
||||
(st.st_uid == *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_xattr_acls( unix_fd, user, group );
|
||||
+ if (!sd) sd = mode_to_sd( st.st_mode, user, group);
|
||||
if (!sd) return obj->sd;
|
||||
|
||||
*mode = st.st_mode;
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,124 @@
|
||||
From e1b3d93adab31966d145ea41a9246d8f498c09d6 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
|
||||
Subject: server: Convert return of file security masks with generic access
|
||||
mappings.
|
||||
|
||||
---
|
||||
dlls/advapi32/tests/security.c | 24 ++++++++++++------------
|
||||
server/file.c | 22 ++++++++++++++++++++++
|
||||
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
|
||||
--- a/dlls/advapi32/tests/security.c
|
||||
+++ b/dlls/advapi32/tests/security.c
|
||||
@@ -3109,8 +3109,8 @@ static void test_CreateDirectoryA(void)
|
||||
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);
|
||||
- todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
- "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
+ ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
||||
+ ace->Mask);
|
||||
}
|
||||
if (acl_size.AceCount > 1)
|
||||
{
|
||||
@@ -3121,8 +3121,8 @@ static void test_CreateDirectoryA(void)
|
||||
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);
|
||||
- todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
- "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
+ ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
||||
+ ace->Mask);
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -3297,8 +3297,8 @@ static void test_GetNamedSecurityInfoA(void)
|
||||
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);
|
||||
- todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
- "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
+ ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
||||
+ ace->Mask);
|
||||
}
|
||||
if (acl_size.AceCount > 1)
|
||||
{
|
||||
@@ -3308,8 +3308,8 @@ static void test_GetNamedSecurityInfoA(void)
|
||||
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);
|
||||
- todo_wine ok(ace->Mask == 0x1f01ff || broken(ace->Mask == GENERIC_ALL) /* win2k */,
|
||||
- "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
+ 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);
|
||||
@@ -3962,8 +3962,8 @@ static void test_GetSecurityInfo(void)
|
||||
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);
|
||||
- todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
- "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
+ ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
||||
+ ace->Mask);
|
||||
}
|
||||
if (acl_size.AceCount > 1)
|
||||
{
|
||||
@@ -3973,8 +3973,8 @@ static void test_GetSecurityInfo(void)
|
||||
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);
|
||||
- todo_wine ok(ace->Mask == 0x1f01ff,
|
||||
- "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
|
||||
+ ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
|
||||
+ ace->Mask);
|
||||
}
|
||||
CloseHandle(obj);
|
||||
}
|
||||
diff --git a/server/file.c b/server/file.c
|
||||
index b9135b9..0df2245 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 *
|
||||
#endif
|
||||
}
|
||||
|
||||
+/* Convert generic rights into standard access rights */
|
||||
+void convert_generic_sd( struct security_descriptor *sd )
|
||||
+{
|
||||
+ const ACL *dacl;
|
||||
+ int present;
|
||||
+
|
||||
+ dacl = sd_get_dacl( sd, &present );
|
||||
+ if (present && dacl)
|
||||
+ {
|
||||
+ const ACE_HEADER *ace = (const ACE_HEADER *)(dacl + 1);
|
||||
+ ULONG i;
|
||||
+
|
||||
+ for (i = 0; i < dacl->AceCount; i++, ace = ace_next( ace ))
|
||||
+ {
|
||||
+ DWORD *mask = (DWORD *)(ace + 1);
|
||||
+
|
||||
+ *mask = generic_file_map_access( *mask );
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
struct security_descriptor *file_get_acls( 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
|
||||
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) sd = mode_to_sd( st.st_mode, user, group);
|
||||
if (!sd) return obj->sd;
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -0,0 +1,300 @@
|
||||
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
|
||||
|
@@ -0,0 +1,323 @@
|
||||
From 9c6061a4e74991b1b02a1532d5c109600504d91e Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Tue, 11 Mar 2014 11:09:00 -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 | 125 +++++++++++++++++++++++++++++++++++++++-
|
||||
server/file.h | 1 +
|
||||
5 files changed, 206 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 f785d33..5151638 100644
|
||||
--- a/include/winnt.h
|
||||
+++ b/include/winnt.h
|
||||
@@ -5054,14 +5054,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 c115ff7..cb518f5 100644
|
||||
--- a/server/file.c
|
||||
+++ b/server/file.c
|
||||
@@ -324,6 +324,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, char *parent_name,
|
||||
int is_dir )
|
||||
{
|
||||
@@ -921,16 +1020,32 @@ mode_t sd_to_mode( const struct security_descriptor *sd, const SID *owner )
|
||||
return new_mode & ~denied_mode;
|
||||
}
|
||||
|
||||
-int file_set_acls( struct object *obj, struct fd *fd, const struct security_descriptor *sd,
|
||||
+int file_set_acls( 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;
|
||||
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, 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 );
|
||||
@@ -962,10 +1077,14 @@ int file_set_acls( struct object *obj, struct fd *fd, const struct security_desc
|
||||
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 0905fbb..8cbc4cb 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
|
||||
|
@@ -0,0 +1,132 @@
|
||||
From a71389d7b9a53ea66a8cafc19c89a2287ee9cda0 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Tue, 25 Feb 2014 10:44:36 -0700
|
||||
Subject: shell32: Set the default security attributes for user shell folders.
|
||||
|
||||
---
|
||||
dlls/shell32/shellpath.c | 87 +++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 86 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c
|
||||
index 875be38..947ef29 100644
|
||||
--- a/dlls/shell32/shellpath.c
|
||||
+++ b/dlls/shell32/shellpath.c
|
||||
@@ -2169,6 +2169,63 @@ cleanup:
|
||||
return hr;
|
||||
}
|
||||
|
||||
+PSECURITY_DESCRIPTOR _SHGetUserSecurityDescriptor( void )
|
||||
+{
|
||||
+ PSECURITY_DESCRIPTOR sd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH);
|
||||
+ PACL dacl = HeapAlloc(GetProcessHeap(), 0, 100);
|
||||
+ PSID admin_sid = NULL, user_sid;
|
||||
+ TOKEN_USER *user = NULL;
|
||||
+ BOOL ret = FALSE;
|
||||
+ DWORD sid_size;
|
||||
+ HANDLE token;
|
||||
+
|
||||
+ if(!sd || !dacl) goto cleanup;
|
||||
+
|
||||
+ /* find the user SID */
|
||||
+ if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
|
||||
+ {
|
||||
+ if (GetLastError() != ERROR_NO_TOKEN) goto cleanup;
|
||||
+ else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) goto cleanup;
|
||||
+ }
|
||||
+ sid_size = 0;
|
||||
+ GetTokenInformation(token, TokenUser, NULL, 0, &sid_size);
|
||||
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto cleanup;
|
||||
+ user = HeapAlloc(GetProcessHeap(), 0, sid_size);
|
||||
+ if (!user) goto cleanup;
|
||||
+ if (!GetTokenInformation(token, TokenUser, user, sid_size, &sid_size)) goto cleanup;
|
||||
+ CloseHandle(token);
|
||||
+ user_sid = user->User.Sid;
|
||||
+
|
||||
+ /* find the administrator group SID */
|
||||
+ sid_size = 0;
|
||||
+ CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, NULL, &sid_size);
|
||||
+ if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto cleanup;
|
||||
+ admin_sid = HeapAlloc(GetProcessHeap(), 0, sid_size);
|
||||
+ if(!admin_sid) goto cleanup;
|
||||
+ if(!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size)) goto cleanup;
|
||||
+
|
||||
+ /* build the DACL */
|
||||
+ if(!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) goto cleanup;
|
||||
+ if(!InitializeAcl(dacl, 100, ACL_REVISION)) goto cleanup;
|
||||
+ if(!AddAccessAllowedAceEx(dacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
|
||||
+ GENERIC_ALL, user_sid)) goto cleanup;
|
||||
+ if(!AddAccessAllowedAceEx(dacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
|
||||
+ GENERIC_ALL, admin_sid)) goto cleanup;
|
||||
+ if(!SetSecurityDescriptorDacl(sd, TRUE, dacl, FALSE)) goto cleanup;
|
||||
+ ret = TRUE;
|
||||
+
|
||||
+cleanup:
|
||||
+ HeapFree(GetProcessHeap(), 0, user);
|
||||
+ HeapFree(GetProcessHeap(), 0, admin_sid);
|
||||
+ if(!ret)
|
||||
+ {
|
||||
+ HeapFree(GetProcessHeap(), 0, dacl);
|
||||
+ HeapFree(GetProcessHeap(), 0, sd);
|
||||
+ sd = NULL;
|
||||
+ }
|
||||
+ return sd;
|
||||
+}
|
||||
+
|
||||
/*************************************************************************
|
||||
* SHGetFolderPathAndSubDirW [SHELL32.@]
|
||||
*/
|
||||
@@ -2180,6 +2237,8 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
|
||||
LPCWSTR pszSubPath,/* [I] sub directory of the specified folder */
|
||||
LPWSTR pszPath) /* [O] converted path */
|
||||
{
|
||||
+ SECURITY_ATTRIBUTES sa, *sec = NULL;
|
||||
+ PSECURITY_DESCRIPTOR sd = NULL;
|
||||
HRESULT hr;
|
||||
WCHAR szBuildPath[MAX_PATH], szTemp[MAX_PATH];
|
||||
DWORD folder = nFolder & CSIDL_FOLDER_MASK;
|
||||
@@ -2292,8 +2351,25 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
|
||||
goto end;
|
||||
}
|
||||
|
||||
+ /* build the appropriate security attributes for the directory */
|
||||
+ switch (type)
|
||||
+ {
|
||||
+ case CSIDL_Type_User:
|
||||
+ sd = _SHGetUserSecurityDescriptor();
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ if (sd)
|
||||
+ {
|
||||
+ sa.nLength = sizeof(sa);
|
||||
+ sa.lpSecurityDescriptor = sd;
|
||||
+ sa.bInheritHandle = TRUE;
|
||||
+ sec = &sa;
|
||||
+ }
|
||||
+
|
||||
/* create directory/directories */
|
||||
- ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, NULL);
|
||||
+ ret = SHCreateDirectoryExW(hwndOwner, szBuildPath, sec);
|
||||
if (ret && ret != ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
ERR("Failed to create directory %s.\n", debugstr_w(szBuildPath));
|
||||
@@ -2303,6 +2379,15 @@ HRESULT WINAPI SHGetFolderPathAndSubDirW(
|
||||
|
||||
TRACE("Created missing system directory %s\n", debugstr_w(szBuildPath));
|
||||
end:
|
||||
+ if (sd)
|
||||
+ {
|
||||
+ BOOL present, defaulted;
|
||||
+ PACL dacl = NULL;
|
||||
+
|
||||
+ GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted);
|
||||
+ HeapFree(GetProcessHeap(), 0, dacl);
|
||||
+ HeapFree(GetProcessHeap(), 0, sd);
|
||||
+ }
|
||||
TRACE("returning 0x%08x (final path is %s)\n", hr, debugstr_w(szBuildPath));
|
||||
return hr;
|
||||
}
|
||||
--
|
||||
1.7.9.5
|
||||
|
@@ -1,3 +1,3 @@
|
||||
Revision: 1
|
||||
Revision: 2
|
||||
Author: Erich E. Hoover
|
||||
Title: Store and return security attributes with extended file attributes.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user