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
139 Commits
v2.10-back
...
v2.15
Author | SHA1 | Date | |
---|---|---|---|
|
eb4587492e | ||
|
b6bab9758e | ||
|
bab383452b | ||
|
9fbebe7a46 | ||
|
14cfabe8ab | ||
|
5adb9710aa | ||
|
f09e1db3cc | ||
|
ea6cb58103 | ||
|
62f94a1ed2 | ||
|
41cf5ea976 | ||
|
be0aab1653 | ||
|
0e27dc7034 | ||
|
f6565eb6af | ||
|
2d92c18c9e | ||
|
96dd810f82 | ||
|
8ca3547a36 | ||
|
4938755f5f | ||
|
adb8deeaf2 | ||
|
716ea2cef3 | ||
|
6edf4d136c | ||
|
51d419bbeb | ||
|
6b40eb077f | ||
|
ae3f3b8bb7 | ||
|
ed87feaf71 | ||
|
081fbc2ef1 | ||
|
4455721443 | ||
|
5559653869 | ||
|
8f9cc5e01c | ||
|
d364296484 | ||
|
0892d6d89e | ||
|
aa23179c36 | ||
|
e28edf1951 | ||
|
5f7efc6b30 | ||
|
71f0cf0aef | ||
|
ea9d4a0fa1 | ||
|
3aabb941ae | ||
|
f64dc8457e | ||
|
ebc9ba4921 | ||
|
77a90f1dd0 | ||
|
c0a61524e1 | ||
|
9f5d2cab05 | ||
|
2e99d9e465 | ||
|
2c12e538dd | ||
|
d943e0bd51 | ||
|
67ebee7f44 | ||
|
91424695c4 | ||
|
7b07cb08f5 | ||
|
4d2afbf14b | ||
|
f47fa538c5 | ||
|
e866c7f3e1 | ||
|
b539f0f369 | ||
|
f5e96b9a37 | ||
|
7a242b50e4 | ||
|
9921dc7846 | ||
|
1a4ebb027f | ||
|
3bf7fe4763 | ||
|
eeb6529b09 | ||
|
2cb3198298 | ||
|
69e273a07f | ||
|
60870e076f | ||
|
c8a8ef48e5 | ||
|
be9feb4570 | ||
|
62ae507b36 | ||
|
5ec57827af | ||
|
d0dccc7b7e | ||
|
4e031ef171 | ||
|
60d4b6fe21 | ||
|
8706a334ad | ||
|
43f5b05fd5 | ||
|
a05970ca53 | ||
|
d9d149f369 | ||
|
e2dbf3ab7e | ||
|
fe97269c92 | ||
|
c99cdb85d7 | ||
|
020888539d | ||
|
b8ffc62855 | ||
|
dc531c457c | ||
|
08cd599f17 | ||
|
bfef128732 | ||
|
201e62615e | ||
|
c852826507 | ||
|
c1b18bc491 | ||
|
edcc6684ad | ||
|
96a77f3ae2 | ||
|
4c1a8684a0 | ||
|
3ebda6fa93 | ||
|
8d2edd8de8 | ||
|
e3b7fd770e | ||
|
e2a70628df | ||
|
a5daeb1e36 | ||
|
eed8160b22 | ||
|
996d9ab307 | ||
|
325f3758f8 | ||
|
ad2d0fdc3a | ||
|
5e62fbb2d0 | ||
|
0211a4935e | ||
|
a59a69804a | ||
|
55b5c61703 | ||
|
8b3a73a4df | ||
|
f9ad524910 | ||
|
68d0ea3a19 | ||
|
00969f9cd8 | ||
|
de4694c81b | ||
|
b888a45d12 | ||
|
46514b9952 | ||
|
de09d74c97 | ||
|
aa00b4044e | ||
|
9aabd07862 | ||
|
3dad3ddae9 | ||
|
8fb3cd2056 | ||
|
d78dc772d6 | ||
|
0e64c29e85 | ||
|
ff7e264839 | ||
|
8f35a7629b | ||
|
735a9982cc | ||
|
1b5a0095b8 | ||
|
12a893e94f | ||
|
dab61e7333 | ||
|
b1cb4553ec | ||
|
4d290efd99 | ||
|
c0c29e5a88 | ||
|
e179ddf842 | ||
|
83a65ef99b | ||
|
0a16521c7e | ||
|
866e79688c | ||
|
dbe0e706a4 | ||
|
907dc4eae6 | ||
|
e24fc5fec1 | ||
|
8ebf6f58e5 | ||
|
f254a73e66 | ||
|
463f2b02c9 | ||
|
e9daff5bc8 | ||
|
be0d43d2b1 | ||
|
2420bc89ed | ||
|
ecdf44fe29 | ||
|
e2b993408e | ||
|
4a13b7eac7 | ||
|
3a7c5ae711 | ||
|
3fab2fbed2 |
30
CONTRIBUTING.md
Normal file
30
CONTRIBUTING.md
Normal file
@@ -0,0 +1,30 @@
|
||||
Contributing to Wine Staging
|
||||
----------------------------
|
||||
|
||||
First of all, thank you for taking the time to contribute to this project.
|
||||
|
||||
### Reporting bugs
|
||||
|
||||
Since WineConf 2015 Wine Staging is an official part of WineHQ, which means you
|
||||
can report problems directly at [bugs.winehq.org](https://bugs.winehq.org/).
|
||||
Most of the time bugs found in Wine Staging also turn out to be present in the
|
||||
development branch, so its recommended to open your bug in the "Wine" product,
|
||||
unless you are sure its really "Wine Staging" specific. For bugs related to our
|
||||
binary packages, please open a bug report in the "Packaging" product.
|
||||
|
||||
### Submitting patches
|
||||
|
||||
**IMPORTANT:** Please use [dev.wine-staging.com](https://dev.wine-staging.com/patches)
|
||||
for patch submissions, we currently do not accept Pull requests on GitHub.
|
||||
|
||||
Wine Staging mainly concentrates on experimental features and patches which are
|
||||
difficult to get into the development branch. If you have a very simple bug fix
|
||||
including tests, there is usually no need to send it to Wine Staging. You can
|
||||
directly contribute it to the
|
||||
[development branch](http://wiki.winehq.org/SubmittingPatches). However, if you
|
||||
already tried that without success, or are working on such a complex area that
|
||||
you do not really think its ready for inclusion, you might want to submit it to
|
||||
our Staging tree. Please open a patch submission request on
|
||||
[dev.wine-staging.com](https://dev.wine-staging.com/patches) including the patch.
|
||||
More information is also available in our
|
||||
[Wiki](https://wiki.winehq.org/Wine-Staging_Patches).
|
23
README.md
23
README.md
@@ -24,16 +24,6 @@ other wine-specific programs like `winecfg`. To learn more about how to use
|
||||
Wine Staging, please take a look at the
|
||||
[usage instructions](https://github.com/wine-compholio/wine-staging/wiki/Usage).
|
||||
|
||||
Reporting bugs
|
||||
--------------
|
||||
|
||||
Since WineConf 2015 Wine Staging is an official part of WineHQ, which means you
|
||||
can report problems directly at https://bugs.winehq.org/. Most of the time bugs
|
||||
found in Wine Staging also turn out to be present in the development branch, so
|
||||
its recommended to open your bug in the "Wine" product, unless you are sure its
|
||||
really "Wine Staging" specific. For problems with our binary packages, please
|
||||
also open a bug report there.
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
@@ -88,14 +78,5 @@ in our [Wiki](https://github.com/wine-compholio/wine-staging/wiki/Packaging).
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Wine Staging mainly concentrates on experimental features and patches which are
|
||||
difficult to get into the development branch. If you have a very simple bug fix
|
||||
including tests, there is usually no need to send it to Wine Staging. You can
|
||||
directly contribute it to the
|
||||
[development branch](http://wiki.winehq.org/SubmittingPatches). However, if you
|
||||
already tried that without success, or are working on such a complex area that
|
||||
you do not really think its ready for inclusion, you might want to submit it to
|
||||
our Staging tree. Please open a patch submission request on
|
||||
[bugs.wine-staging.com](https://bugs.wine-staging.com/) including the patch.
|
||||
More information is also available in our
|
||||
[Wiki](https://github.com/wine-compholio/wine-staging/wiki/Contributing).
|
||||
Please see CONTRIBUTING.md for more information about contributing to Wine
|
||||
Staging.
|
||||
|
@@ -1,37 +0,0 @@
|
||||
From 9d0f651d9cb5c3ae68810e37dd6030373c7aeab6 Mon Sep 17 00:00:00 2001
|
||||
From: Nils Kuhnhenn <kuhnhenn.nils@gmail.com>
|
||||
Date: Wed, 24 Aug 2016 19:56:00 +0200
|
||||
Subject: oleaut32: Use variable with the correct type in LIST_FOR_EACH_ENTRY_SAFE macro.
|
||||
|
||||
---
|
||||
dlls/oleaut32/typelib.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
|
||||
index b9318fba423..5a6dad496ed 100644
|
||||
--- a/dlls/oleaut32/typelib.c
|
||||
+++ b/dlls/oleaut32/typelib.c
|
||||
@@ -4830,10 +4830,9 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
|
||||
if (!ref)
|
||||
{
|
||||
TLBImpLib *pImpLib, *pImpLibNext;
|
||||
- TLBRefType *ref_type;
|
||||
+ TLBRefType *ref_type, *ref_type_next;
|
||||
TLBString *tlbstr, *tlbstr_next;
|
||||
TLBGuid *tlbguid, *tlbguid_next;
|
||||
- void *cursor2;
|
||||
int i;
|
||||
|
||||
/* remove cache entry */
|
||||
@@ -4883,7 +4882,7 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
|
||||
heap_free(pImpLib);
|
||||
}
|
||||
|
||||
- LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
|
||||
+ LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
|
||||
{
|
||||
list_remove(&ref_type->entry);
|
||||
heap_free(ref_type);
|
||||
--
|
||||
2.13.1
|
||||
|
@@ -1,24 +0,0 @@
|
||||
From 380543910f8912374a13b9773738e018bd638341 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sun, 11 Jun 2017 02:42:47 +0200
|
||||
Subject: gdiplus: Initialize containers list in GdipCloneImage.
|
||||
|
||||
---
|
||||
dlls/gdiplus/image.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c
|
||||
index ce2194317ff..b28606e916c 100644
|
||||
--- a/dlls/gdiplus/image.c
|
||||
+++ b/dlls/gdiplus/image.c
|
||||
@@ -1339,6 +1339,7 @@ GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage)
|
||||
result->unit = metafile->unit;
|
||||
result->metafile_type = metafile->metafile_type;
|
||||
result->hemf = CopyEnhMetaFileW(metafile->hemf, NULL);
|
||||
+ list_init(&result->containers);
|
||||
|
||||
if (!result->hemf)
|
||||
{
|
||||
--
|
||||
2.13.1
|
||||
|
@@ -1,15 +1,14 @@
|
||||
From b6b1e5da04ed867251253410e37d412109a4cec2 Mon Sep 17 00:00:00 2001
|
||||
From cd34de81164087b3593d0ec9416e2f157a5df40d Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Fri, 8 Aug 2014 19:33:14 -0600
|
||||
Subject: Appease the blessed version of gcc (4.5) when -Werror is enabled.
|
||||
|
||||
---
|
||||
dlls/d3d9/tests/visual.c | 2 +-
|
||||
dlls/netapi32/netapi32.c | 2 +-
|
||||
dlls/winealsa.drv/mmdevdrv.c | 2 +-
|
||||
dlls/wined3d/glsl_shader.c | 2 +-
|
||||
tools/makedep.c | 2 +-
|
||||
5 files changed, 5 insertions(+), 5 deletions(-)
|
||||
dlls/d3d9/tests/visual.c | 2 +-
|
||||
dlls/netapi32/netapi32.c | 2 +-
|
||||
dlls/wined3d/glsl_shader.c | 2 +-
|
||||
tools/makedep.c | 2 +-
|
||||
4 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
|
||||
index c8a6a1fa5a8..0261d3708e6 100644
|
||||
@@ -37,24 +36,11 @@ index 278d4528b01..1c5f110b828 100644
|
||||
NET_API_STATUS status;
|
||||
|
||||
if (servername && !(server = strdup_unixcp( servername ))) return ERROR_OUTOFMEMORY;
|
||||
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
|
||||
index 2ecb111e218..b285705509c 100644
|
||||
--- a/dlls/winealsa.drv/mmdevdrv.c
|
||||
+++ b/dlls/winealsa.drv/mmdevdrv.c
|
||||
@@ -359,7 +359,7 @@ static WCHAR *construct_device_id(EDataFlow flow, const WCHAR *chunk1, const cha
|
||||
{
|
||||
WCHAR *ret;
|
||||
const WCHAR *prefix;
|
||||
- DWORD len_wchars = 0, chunk1_len, copied = 0, prefix_len;
|
||||
+ DWORD len_wchars = 0, chunk1_len = 0, copied = 0, prefix_len;
|
||||
|
||||
static const WCHAR dashW[] = {' ','-',' ',0};
|
||||
static const size_t dashW_len = (sizeof(dashW) / sizeof(*dashW)) - 1;
|
||||
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
|
||||
index ce960853362..f4275d8dd48 100644
|
||||
index f96f48d97d1..8fe3318cd78 100644
|
||||
--- a/dlls/wined3d/glsl_shader.c
|
||||
+++ b/dlls/wined3d/glsl_shader.c
|
||||
@@ -9316,7 +9316,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
|
||||
@@ -9721,7 +9721,7 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
|
||||
GLuint ds_id = 0;
|
||||
GLuint gs_id = 0;
|
||||
GLuint ps_id = 0;
|
||||
@@ -64,7 +50,7 @@ index ce960853362..f4275d8dd48 100644
|
||||
struct wined3d_string_buffer *tmp_name;
|
||||
|
||||
diff --git a/tools/makedep.c b/tools/makedep.c
|
||||
index add722f80a9..24b06bbfcb2 100644
|
||||
index 296356b0a57..5a2873b56f1 100644
|
||||
--- a/tools/makedep.c
|
||||
+++ b/tools/makedep.c
|
||||
@@ -1608,7 +1608,7 @@ static const char *get_make_variable( const struct makefile *make, const char *n
|
||||
@@ -77,5 +63,5 @@ index add722f80a9..24b06bbfcb2 100644
|
||||
var = get_make_variable( make, name );
|
||||
if (!var) return NULL;
|
||||
--
|
||||
2.12.2
|
||||
2.13.1
|
||||
|
||||
|
@@ -0,0 +1,25 @@
|
||||
From 814a4e7a4cad942e284a4828927dd0b67938af33 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sun, 2 Jul 2017 22:32:45 +0200
|
||||
Subject: wsdapi: Avoid implicit cast of interface pointer.
|
||||
|
||||
---
|
||||
dlls/wsdapi/msgparams.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/wsdapi/msgparams.c b/dlls/wsdapi/msgparams.c
|
||||
index a7a2f0a73b3..47a77138709 100644
|
||||
--- a/dlls/wsdapi/msgparams.c
|
||||
+++ b/dlls/wsdapi/msgparams.c
|
||||
@@ -45,7 +45,7 @@ static inline IWSDMessageParametersImpl *impl_from_IWSDMessageParameters(IWSDMes
|
||||
|
||||
static inline IWSDUdpMessageParametersImpl *impl_from_IWSDUdpMessageParameters(IWSDUdpMessageParameters *iface)
|
||||
{
|
||||
- return CONTAINING_RECORD(iface, IWSDUdpMessageParametersImpl, base.IWSDMessageParameters_iface);
|
||||
+ return CONTAINING_RECORD((IWSDMessageParameters *)iface, IWSDUdpMessageParametersImpl, base.IWSDMessageParameters_iface);
|
||||
}
|
||||
|
||||
/* IWSDMessageParameters implementation */
|
||||
--
|
||||
2.13.1
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From bee5e0baac722c66ad8c1034a65a2cecfe74716e Mon Sep 17 00:00:00 2001
|
||||
From fcefc5661656de44d02fed0431b4a61fa618b663 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sun, 5 Mar 2017 23:50:06 +0100
|
||||
Subject: advapi32: Implement LsaLookupPrivilegeName.
|
||||
@@ -6,13 +6,13 @@ Subject: advapi32: Implement LsaLookupPrivilegeName.
|
||||
---
|
||||
dlls/advapi32/advapi32.spec | 2 +-
|
||||
dlls/advapi32/advapi32_misc.h | 2 ++
|
||||
dlls/advapi32/lsa.c | 38 ++++++++++++++++++++++++++++++++++++++
|
||||
dlls/advapi32/lsa.c | 39 +++++++++++++++++++++++++++++++++++++++
|
||||
dlls/advapi32/security.c | 27 ++++++++++++++++++---------
|
||||
include/ntsecapi.h | 1 +
|
||||
5 files changed, 60 insertions(+), 10 deletions(-)
|
||||
5 files changed, 61 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec
|
||||
index 078bb8fc25..124f527282 100644
|
||||
index d5503490a0..709a385967 100644
|
||||
--- a/dlls/advapi32/advapi32.spec
|
||||
+++ b/dlls/advapi32/advapi32.spec
|
||||
@@ -469,7 +469,7 @@
|
||||
@@ -36,10 +36,10 @@ index d116ecb836..ecb07f635a 100644
|
||||
+
|
||||
#endif /* __WINE_ADVAPI32MISC_H */
|
||||
diff --git a/dlls/advapi32/lsa.c b/dlls/advapi32/lsa.c
|
||||
index 479201bfc1..ceb3b05c05 100644
|
||||
index 3da6d19b82..af5f9dd46d 100644
|
||||
--- a/dlls/advapi32/lsa.c
|
||||
+++ b/dlls/advapi32/lsa.c
|
||||
@@ -973,3 +973,41 @@ NTSTATUS WINAPI LsaUnregisterPolicyChangeNotification(
|
||||
@@ -973,3 +973,42 @@ NTSTATUS WINAPI LsaUnregisterPolicyChangeNotification(
|
||||
FIXME("(%d,%p) stub\n", class, event);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -67,7 +67,8 @@ index 479201bfc1..ceb3b05c05 100644
|
||||
+
|
||||
+ if (lpLuid->HighPart ||
|
||||
+ (lpLuid->LowPart < SE_MIN_WELL_KNOWN_PRIVILEGE ||
|
||||
+ lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE))
|
||||
+ lpLuid->LowPart > SE_MAX_WELL_KNOWN_PRIVILEGE ||
|
||||
+ !WellKnownPrivNames[lpLuid->LowPart]))
|
||||
+ return STATUS_NO_SUCH_PRIVILEGE;
|
||||
+
|
||||
+ priv_size = (strlenW(WellKnownPrivNames[lpLuid->LowPart]) + 1) * sizeof(WCHAR);
|
||||
@@ -158,5 +159,5 @@ index 2bb3d312e4..0bf0eca43e 100644
|
||||
ULONG WINAPI LsaNtStatusToWinError(NTSTATUS);
|
||||
NTSTATUS WINAPI LsaOpenPolicy(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBUTES,ACCESS_MASK,PLSA_HANDLE);
|
||||
--
|
||||
2.11.0
|
||||
2.13.1
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
Fixes: Add LsaLookupPrivilege[Display]Name stubs
|
||||
Fixes: [43316] Add LsaLookupPrivilege[Display]Name stubs
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 63082c3863d8be466ed14f532653ddf35e40328a Mon Sep 17 00:00:00 2001
|
||||
From 09d62cfc4fa999eacc89af2ad414810e22c910a9 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Fri, 5 May 2017 00:18:50 +0200
|
||||
Subject: advapi32/tests: Add basic tests for BuildSecurityDescriptor.
|
||||
@@ -8,11 +8,11 @@ Subject: advapi32/tests: Add basic tests for BuildSecurityDescriptor.
|
||||
1 file changed, 39 insertions(+)
|
||||
|
||||
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
|
||||
index d6ea3a19fad..c591f7b6e5f 100644
|
||||
index ca5edffae5..db5a0f934c 100644
|
||||
--- a/dlls/advapi32/tests/security.c
|
||||
+++ b/dlls/advapi32/tests/security.c
|
||||
@@ -7489,6 +7489,44 @@ static void test_child_token_sd(void)
|
||||
HeapFree(GetProcessHeap(), 0, sd);
|
||||
@@ -7217,6 +7217,44 @@ static void test_GetExplicitEntriesFromAclW(void)
|
||||
HeapFree(GetProcessHeap(), 0, old_acl);
|
||||
}
|
||||
|
||||
+static void test_BuildSecurityDescriptorW(void)
|
||||
@@ -56,14 +56,14 @@ index d6ea3a19fad..c591f7b6e5f 100644
|
||||
START_TEST(security)
|
||||
{
|
||||
init();
|
||||
@@ -7542,6 +7580,7 @@ START_TEST(security)
|
||||
test_pseudo_tokens();
|
||||
@@ -7271,6 +7309,7 @@ START_TEST(security)
|
||||
test_maximum_allowed();
|
||||
test_token_label();
|
||||
test_GetExplicitEntriesFromAclW();
|
||||
+ test_BuildSecurityDescriptorW();
|
||||
|
||||
/* must be the last test, modifies process token */
|
||||
/* Must be the last test, modifies process token */
|
||||
test_token_security_descriptor();
|
||||
--
|
||||
2.12.2
|
||||
2.13.1
|
||||
|
||||
|
@@ -1,2 +1,2 @@
|
||||
Fixes: Initial implementation of advapi32.BuildSecurityDescriptorW
|
||||
Depends: server-LABEL_SECURITY_INFORMATION
|
||||
Depends: advapi32-GetExplicitEntriesFromAclW
|
||||
|
@@ -0,0 +1,315 @@
|
||||
From 3f314cc8251f62f592013abe7b1c3b977de0699a Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Fri, 4 Aug 2017 02:33:14 +0200
|
||||
Subject: ntdll: Implement NtFilterToken.
|
||||
|
||||
---
|
||||
dlls/ntdll/nt.c | 59 ++++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/ntdll.spec | 2 +-
|
||||
include/winnt.h | 5 +++
|
||||
include/winternl.h | 1 +
|
||||
server/process.c | 2 +-
|
||||
server/protocol.def | 10 ++++++
|
||||
server/security.h | 4 ++-
|
||||
server/token.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||
8 files changed, 162 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
|
||||
index 93554e929be..5822dec9b15 100644
|
||||
--- a/dlls/ntdll/nt.c
|
||||
+++ b/dlls/ntdll/nt.c
|
||||
@@ -136,6 +136,65 @@ NTSTATUS WINAPI NtDuplicateToken(
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
+ * NtFilterToken [NTDLL.@]
|
||||
+ * ZwFilterToken [NTDLL.@]
|
||||
+ */
|
||||
+NTSTATUS WINAPI NtFilterToken( HANDLE token, ULONG flags, TOKEN_GROUPS *disable_sids,
|
||||
+ TOKEN_PRIVILEGES *privileges, TOKEN_GROUPS *restrict_sids,
|
||||
+ HANDLE *new_token )
|
||||
+{
|
||||
+ data_size_t privileges_len = 0;
|
||||
+ data_size_t sids_len = 0;
|
||||
+ SID *sids = NULL;
|
||||
+ NTSTATUS status;
|
||||
+
|
||||
+ TRACE( "(%p, 0x%08x, %p, %p, %p, %p)\n", token, flags, disable_sids, privileges,
|
||||
+ restrict_sids, new_token );
|
||||
+
|
||||
+ if (flags)
|
||||
+ FIXME( "flags %x unsupported\n", flags );
|
||||
+
|
||||
+ if (restrict_sids)
|
||||
+ FIXME( "support for restricting sids not yet implemented\n" );
|
||||
+
|
||||
+ if (privileges)
|
||||
+ privileges_len = privileges->PrivilegeCount * sizeof(LUID_AND_ATTRIBUTES);
|
||||
+
|
||||
+ if (disable_sids)
|
||||
+ {
|
||||
+ DWORD len, i;
|
||||
+ BYTE *tmp;
|
||||
+
|
||||
+ for (i = 0; i < disable_sids->GroupCount; i++)
|
||||
+ sids_len += RtlLengthSid( disable_sids->Groups[i].Sid );
|
||||
+
|
||||
+ sids = RtlAllocateHeap( GetProcessHeap(), 0, sids_len );
|
||||
+ if (!sids) return STATUS_NO_MEMORY;
|
||||
+
|
||||
+ for (i = 0, tmp = (BYTE *)sids; i < disable_sids->GroupCount; i++, tmp += len)
|
||||
+ {
|
||||
+ len = RtlLengthSid( disable_sids->Groups[i].Sid );
|
||||
+ memcpy( tmp, disable_sids->Groups[i].Sid, len );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ SERVER_START_REQ( filter_token )
|
||||
+ {
|
||||
+ req->handle = wine_server_obj_handle( token );
|
||||
+ req->flags = flags;
|
||||
+ req->privileges_size = privileges_len;
|
||||
+ wine_server_add_data( req, privileges->Privileges, privileges_len );
|
||||
+ wine_server_add_data( req, sids, sids_len );
|
||||
+ status = wine_server_call( req );
|
||||
+ if (!status) *new_token = wine_server_ptr_handle( reply->new_handle );
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+
|
||||
+ RtlFreeHeap( GetProcessHeap(), 0, sids );
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+/******************************************************************************
|
||||
* NtOpenProcessToken [NTDLL.@]
|
||||
* ZwOpenProcessToken [NTDLL.@]
|
||||
*/
|
||||
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
|
||||
index 4f7ee496437..275fda57970 100644
|
||||
--- a/dlls/ntdll/ntdll.spec
|
||||
+++ b/dlls/ntdll/ntdll.spec
|
||||
@@ -179,7 +179,7 @@
|
||||
# @ stub NtEnumerateSystemEnvironmentValuesEx
|
||||
@ stdcall NtEnumerateValueKey(long long long ptr long ptr)
|
||||
@ stub NtExtendSection
|
||||
-# @ stub NtFilterToken
|
||||
+@ stdcall NtFilterToken(long long ptr ptr ptr ptr)
|
||||
@ stdcall NtFindAtom(ptr long ptr)
|
||||
@ stdcall NtFlushBuffersFile(long ptr)
|
||||
@ stdcall NtFlushInstructionCache(long ptr long)
|
||||
diff --git a/include/winnt.h b/include/winnt.h
|
||||
index f91f81eb559..891c9b6d4bb 100644
|
||||
--- a/include/winnt.h
|
||||
+++ b/include/winnt.h
|
||||
@@ -3844,6 +3844,11 @@ typedef enum _TOKEN_INFORMATION_CLASS {
|
||||
TOKEN_ADJUST_SESSIONID | \
|
||||
TOKEN_ADJUST_DEFAULT )
|
||||
|
||||
+#define DISABLE_MAX_PRIVILEGE 0x1
|
||||
+#define SANDBOX_INERT 0x2
|
||||
+#define LUA_TOKEN 0x4
|
||||
+#define WRITE_RESTRICTED 0x8
|
||||
+
|
||||
#ifndef _SECURITY_DEFINED
|
||||
#define _SECURITY_DEFINED
|
||||
|
||||
diff --git a/include/winternl.h b/include/winternl.h
|
||||
index 140669b0105..899e8324d67 100644
|
||||
--- a/include/winternl.h
|
||||
+++ b/include/winternl.h
|
||||
@@ -2348,6 +2348,7 @@ NTSYSAPI NTSTATUS WINAPI NtDuplicateToken(HANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES
|
||||
NTSYSAPI NTSTATUS WINAPI NtEnumerateKey(HANDLE,ULONG,KEY_INFORMATION_CLASS,void *,DWORD,DWORD *);
|
||||
NTSYSAPI NTSTATUS WINAPI NtEnumerateValueKey(HANDLE,ULONG,KEY_VALUE_INFORMATION_CLASS,PVOID,ULONG,PULONG);
|
||||
NTSYSAPI NTSTATUS WINAPI NtExtendSection(HANDLE,PLARGE_INTEGER);
|
||||
+NTSYSAPI NTSTATUS WINAPI NtFilterToken(HANDLE,ULONG,TOKEN_GROUPS*,TOKEN_PRIVILEGES*,TOKEN_GROUPS*,HANDLE*);
|
||||
NTSYSAPI NTSTATUS WINAPI NtFindAtom(const WCHAR*,ULONG,RTL_ATOM*);
|
||||
NTSYSAPI NTSTATUS WINAPI NtFlushBuffersFile(HANDLE,IO_STATUS_BLOCK*);
|
||||
NTSYSAPI NTSTATUS WINAPI NtFlushInstructionCache(HANDLE,LPCVOID,SIZE_T);
|
||||
diff --git a/server/process.c b/server/process.c
|
||||
index cbe726afe81..f0f60edcd3f 100644
|
||||
--- a/server/process.c
|
||||
+++ b/server/process.c
|
||||
@@ -571,7 +571,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
|
||||
: alloc_handle_table( process, 0 );
|
||||
/* Note: for security reasons, starting a new process does not attempt
|
||||
* to use the current impersonation token for the new process */
|
||||
- process->token = token_duplicate( parent->token, TRUE, 0, NULL );
|
||||
+ process->token = token_duplicate( parent->token, TRUE, 0, NULL, NULL, 0, NULL, 0 );
|
||||
process->affinity = parent->affinity;
|
||||
}
|
||||
if (!process->handles || !process->token) goto error;
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index fc6e343af52..b3dce66eb9c 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -3391,6 +3391,16 @@ enum caret_state
|
||||
obj_handle_t new_handle; /* duplicated handle */
|
||||
@END
|
||||
|
||||
+@REQ(filter_token)
|
||||
+ obj_handle_t handle; /* handle to the token to duplicate */
|
||||
+ unsigned int flags; /* flags */
|
||||
+ data_size_t privileges_size; /* size of privileges */
|
||||
+ VARARG(privileges,LUID_AND_ATTRIBUTES,privileges_size); /* privileges to remove from new token */
|
||||
+ VARARG(disable_sids,SID); /* array of groups to remove from new token */
|
||||
+@REPLY
|
||||
+ obj_handle_t new_handle; /* filtered handle */
|
||||
+@END
|
||||
+
|
||||
@REQ(access_check)
|
||||
obj_handle_t handle; /* handle to the token */
|
||||
unsigned int desired_access; /* desired access to the object */
|
||||
diff --git a/server/security.h b/server/security.h
|
||||
index 606dbb2ab2c..6c337143c3d 100644
|
||||
--- a/server/security.h
|
||||
+++ b/server/security.h
|
||||
@@ -56,7 +56,9 @@ extern const PSID security_high_label_sid;
|
||||
extern struct token *token_create_admin(void);
|
||||
extern int token_assign_label( struct token *token, PSID label );
|
||||
extern struct token *token_duplicate( struct token *src_token, unsigned primary,
|
||||
- int impersonation_level, const struct security_descriptor *sd );
|
||||
+ int impersonation_level, const struct security_descriptor *sd,
|
||||
+ const LUID_AND_ATTRIBUTES *filter_privileges, unsigned int priv_count,
|
||||
+ const SID *filter_groups, unsigned int group_count );
|
||||
extern int token_check_privileges( struct token *token, int all_required,
|
||||
const LUID_AND_ATTRIBUTES *reqprivs,
|
||||
unsigned int count, LUID_AND_ATTRIBUTES *usedprivs);
|
||||
diff --git a/server/token.c b/server/token.c
|
||||
index 74db66e1e24..acd7a4dedb5 100644
|
||||
--- a/server/token.c
|
||||
+++ b/server/token.c
|
||||
@@ -299,6 +299,19 @@ static int acl_is_valid( const ACL *acl, data_size_t size )
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+static unsigned int get_sid_count( const SID *sid, data_size_t size )
|
||||
+{
|
||||
+ unsigned int count;
|
||||
+
|
||||
+ for (count = 0; size >= sizeof(SID) && security_sid_len( sid ) <= size; count++)
|
||||
+ {
|
||||
+ size -= security_sid_len( sid );
|
||||
+ sid = (const SID *)((char *)sid + security_sid_len( sid ));
|
||||
+ }
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
/* checks whether all members of a security descriptor fit inside the size
|
||||
* of memory specified */
|
||||
int sd_is_valid( const struct security_descriptor *sd, data_size_t size )
|
||||
@@ -639,8 +652,36 @@ static struct token *create_token( unsigned primary, const SID *user,
|
||||
return token;
|
||||
}
|
||||
|
||||
+static int filter_group( struct group *group, const SID *filter, unsigned int count )
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < count; i++)
|
||||
+ {
|
||||
+ if (security_equal_sid( &group->sid, filter )) return 1;
|
||||
+ filter = (const SID *)((char *)filter + security_sid_len( filter ));
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int filter_privilege( struct privilege *privilege, const LUID_AND_ATTRIBUTES *filter, unsigned int count )
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < count; i++)
|
||||
+ {
|
||||
+ if (!memcmp( &privilege->luid, &filter[i].Luid, sizeof(LUID) ))
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
struct token *token_duplicate( struct token *src_token, unsigned primary,
|
||||
- int impersonation_level, const struct security_descriptor *sd )
|
||||
+ int impersonation_level, const struct security_descriptor *sd,
|
||||
+ const LUID_AND_ATTRIBUTES *filter_privileges, unsigned int priv_count,
|
||||
+ const SID *filter_groups, unsigned int group_count)
|
||||
{
|
||||
const luid_t *modified_id =
|
||||
primary || (impersonation_level == src_token->impersonation_level) ?
|
||||
@@ -676,6 +717,12 @@ struct token *token_duplicate( struct token *src_token, unsigned primary,
|
||||
return NULL;
|
||||
}
|
||||
memcpy( newgroup, group, size );
|
||||
+ if (filter_group( group, filter_groups, group_count ))
|
||||
+ {
|
||||
+ newgroup->enabled = 0;
|
||||
+ newgroup->def = 0;
|
||||
+ newgroup->deny_only = 1;
|
||||
+ }
|
||||
list_add_tail( &token->groups, &newgroup->entry );
|
||||
if (src_token->primary_group == &group->sid)
|
||||
token->primary_group = &newgroup->sid;
|
||||
@@ -684,11 +731,14 @@ struct token *token_duplicate( struct token *src_token, unsigned primary,
|
||||
|
||||
/* copy privileges */
|
||||
LIST_FOR_EACH_ENTRY( privilege, &src_token->privileges, struct privilege, entry )
|
||||
+ {
|
||||
+ if (filter_privilege( privilege, filter_privileges, priv_count )) continue;
|
||||
if (!privilege_add( token, &privilege->luid, privilege->enabled ))
|
||||
{
|
||||
release_object( token );
|
||||
return NULL;
|
||||
}
|
||||
+ }
|
||||
|
||||
if (sd) default_set_sd( &token->obj, sd, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION );
|
||||
@@ -1322,7 +1372,7 @@ DECL_HANDLER(duplicate_token)
|
||||
TOKEN_DUPLICATE,
|
||||
&token_ops )))
|
||||
{
|
||||
- struct token *token = token_duplicate( src_token, req->primary, req->impersonation_level, sd );
|
||||
+ struct token *token = token_duplicate( src_token, req->primary, req->impersonation_level, sd, NULL, 0, NULL, 0 );
|
||||
if (token)
|
||||
{
|
||||
reply->new_handle = alloc_handle_no_access_check( current->process, token, req->access, objattr->attributes );
|
||||
@@ -1332,6 +1382,36 @@ DECL_HANDLER(duplicate_token)
|
||||
}
|
||||
}
|
||||
|
||||
+/* creates a restricted version of a token */
|
||||
+DECL_HANDLER(filter_token)
|
||||
+{
|
||||
+ struct token *src_token;
|
||||
+
|
||||
+ if ((src_token = (struct token *)get_handle_obj( current->process, req->handle,
|
||||
+ TOKEN_DUPLICATE,
|
||||
+ &token_ops )))
|
||||
+ {
|
||||
+ const LUID_AND_ATTRIBUTES *filter_privileges = get_req_data();
|
||||
+ unsigned int priv_count, group_count;
|
||||
+ const SID *filter_groups;
|
||||
+ struct token *token;
|
||||
+
|
||||
+ priv_count = min( req->privileges_size, get_req_data_size() ) / sizeof(LUID_AND_ATTRIBUTES);
|
||||
+ filter_groups = (const SID *)((char *)filter_privileges + priv_count * sizeof(LUID_AND_ATTRIBUTES));
|
||||
+ group_count = get_sid_count( filter_groups, get_req_data_size() - priv_count * sizeof(LUID_AND_ATTRIBUTES) );
|
||||
+
|
||||
+ token = token_duplicate( src_token, src_token->primary, src_token->impersonation_level, NULL,
|
||||
+ filter_privileges, priv_count, filter_groups, group_count );
|
||||
+ if (token)
|
||||
+ {
|
||||
+ unsigned int access = get_handle_access( current->process, req->handle );
|
||||
+ reply->new_handle = alloc_handle_no_access_check( current->process, token, access, 0 );
|
||||
+ release_object( token );
|
||||
+ }
|
||||
+ release_object( src_token );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* checks the specified privileges are held by the token */
|
||||
DECL_HANDLER(check_token_privileges)
|
||||
{
|
||||
--
|
||||
2.13.1
|
||||
|
@@ -0,0 +1,271 @@
|
||||
From 2a1064c5f90beac2bd709ab5d1c454c90a16189b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Fri, 4 Aug 2017 02:51:57 +0200
|
||||
Subject: advapi32: Implement CreateRestrictedToken.
|
||||
|
||||
---
|
||||
dlls/advapi32/security.c | 88 +++++++++++++++++++++++++++++++++++-------
|
||||
dlls/advapi32/tests/security.c | 88 +++++++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 157 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c
|
||||
index 82bb6689d43..c531e45c9a0 100644
|
||||
--- a/dlls/advapi32/security.c
|
||||
+++ b/dlls/advapi32/security.c
|
||||
@@ -840,6 +840,60 @@ BOOL WINAPI SetThreadToken(PHANDLE thread, HANDLE token)
|
||||
ThreadImpersonationToken, &token, sizeof token ));
|
||||
}
|
||||
|
||||
+static BOOL allocate_groups(TOKEN_GROUPS **groups_ret, SID_AND_ATTRIBUTES *sids, DWORD count)
|
||||
+{
|
||||
+ TOKEN_GROUPS *groups;
|
||||
+ DWORD i;
|
||||
+
|
||||
+ if (!count)
|
||||
+ {
|
||||
+ *groups_ret = NULL;
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+
|
||||
+ groups = (TOKEN_GROUPS *)heap_alloc(FIELD_OFFSET(TOKEN_GROUPS, Groups) +
|
||||
+ count * sizeof(SID_AND_ATTRIBUTES));
|
||||
+ if (!groups)
|
||||
+ {
|
||||
+ SetLastError(ERROR_OUTOFMEMORY);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ groups->GroupCount = count;
|
||||
+ for (i = 0; i < count; i++)
|
||||
+ groups->Groups[i] = sids[i];
|
||||
+
|
||||
+ *groups_ret = groups;
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+static BOOL allocate_privileges(TOKEN_PRIVILEGES **privileges_ret, LUID_AND_ATTRIBUTES *privs, DWORD count)
|
||||
+{
|
||||
+ TOKEN_PRIVILEGES *privileges;
|
||||
+ DWORD i;
|
||||
+
|
||||
+ if (!count)
|
||||
+ {
|
||||
+ *privileges_ret = NULL;
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+
|
||||
+ privileges = (TOKEN_PRIVILEGES *)heap_alloc(FIELD_OFFSET(TOKEN_PRIVILEGES, Privileges) +
|
||||
+ count * sizeof(LUID_AND_ATTRIBUTES));
|
||||
+ if (!privileges)
|
||||
+ {
|
||||
+ SetLastError(ERROR_OUTOFMEMORY);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ privileges->PrivilegeCount = count;
|
||||
+ for (i = 0; i < count; i++)
|
||||
+ privileges->Privileges[i] = privs[i];
|
||||
+
|
||||
+ *privileges_ret = privileges;
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
/*************************************************************************
|
||||
* CreateRestrictedToken [ADVAPI32.@]
|
||||
*
|
||||
@@ -871,25 +925,33 @@ BOOL WINAPI CreateRestrictedToken(
|
||||
PSID_AND_ATTRIBUTES restrictSids,
|
||||
PHANDLE newToken)
|
||||
{
|
||||
- TOKEN_TYPE type;
|
||||
- SECURITY_IMPERSONATION_LEVEL level = SecurityAnonymous;
|
||||
- DWORD size;
|
||||
+ TOKEN_PRIVILEGES *delete_privs = NULL;
|
||||
+ TOKEN_GROUPS *disable_groups = NULL;
|
||||
+ TOKEN_GROUPS *restrict_sids = NULL;
|
||||
+ BOOL ret = FALSE;
|
||||
|
||||
- FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n",
|
||||
+ TRACE("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p)\n",
|
||||
baseToken, flags, nDisableSids, disableSids,
|
||||
nDeletePrivs, deletePrivs,
|
||||
nRestrictSids, restrictSids,
|
||||
newToken);
|
||||
|
||||
- size = sizeof(type);
|
||||
- if (!GetTokenInformation( baseToken, TokenType, &type, size, &size )) return FALSE;
|
||||
- if (type == TokenImpersonation)
|
||||
- {
|
||||
- size = sizeof(level);
|
||||
- if (!GetTokenInformation( baseToken, TokenImpersonationLevel, &level, size, &size ))
|
||||
- return FALSE;
|
||||
- }
|
||||
- return DuplicateTokenEx( baseToken, MAXIMUM_ALLOWED, NULL, level, type, newToken );
|
||||
+ if (!allocate_groups(&disable_groups, disableSids, nDisableSids))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (!allocate_privileges(&delete_privs, deletePrivs, nDeletePrivs))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (!allocate_groups(&restrict_sids, restrictSids, nRestrictSids))
|
||||
+ goto done;
|
||||
+
|
||||
+ ret = set_ntstatus(NtFilterToken(baseToken, flags, disable_groups, delete_privs, restrict_sids, newToken));
|
||||
+
|
||||
+done:
|
||||
+ heap_free(disable_groups);
|
||||
+ heap_free(delete_privs);
|
||||
+ heap_free(restrict_sids);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
/* ##############################
|
||||
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
|
||||
index a1ecc409b73..0fd41fe82fa 100644
|
||||
--- a/dlls/advapi32/tests/security.c
|
||||
+++ b/dlls/advapi32/tests/security.c
|
||||
@@ -5292,10 +5292,13 @@ static void test_GetUserNameW(void)
|
||||
|
||||
static void test_CreateRestrictedToken(void)
|
||||
{
|
||||
+ TOKEN_PRIMARY_GROUP *primary_group, *primary_group2;
|
||||
HANDLE process_token, token, r_token;
|
||||
PTOKEN_GROUPS token_groups, groups2;
|
||||
SID_AND_ATTRIBUTES sattr;
|
||||
SECURITY_IMPERSONATION_LEVEL level;
|
||||
+ TOKEN_PRIVILEGES *privs;
|
||||
+ PRIVILEGE_SET privset;
|
||||
TOKEN_TYPE type;
|
||||
BOOL is_member;
|
||||
DWORD size;
|
||||
@@ -5311,7 +5314,7 @@ static void test_CreateRestrictedToken(void)
|
||||
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token);
|
||||
ok(ret, "got error %d\n", GetLastError());
|
||||
|
||||
- ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_QUERY,
|
||||
+ ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
|
||||
NULL, SecurityImpersonation, TokenImpersonation, &token);
|
||||
ok(ret, "got error %d\n", GetLastError());
|
||||
|
||||
@@ -5342,11 +5345,21 @@ static void test_CreateRestrictedToken(void)
|
||||
ok(ret, "got error %d\n", GetLastError());
|
||||
ok(is_member, "not a member\n");
|
||||
|
||||
- /* disable a SID in new token */
|
||||
+ privset.PrivilegeCount = 1;
|
||||
+ privset.Control = PRIVILEGE_SET_ALL_NECESSARY;
|
||||
+ ret = LookupPrivilegeValueA(NULL, "SeChangeNotifyPrivilege", &privset.Privilege[0].Luid);
|
||||
+ ok(ret, "got error %d\n", GetLastError());
|
||||
+
|
||||
+ is_member = FALSE;
|
||||
+ ret = PrivilegeCheck(token, &privset, &is_member);
|
||||
+ ok(ret, "got error %d\n", GetLastError());
|
||||
+ ok(is_member, "Expected SeChangeNotifyPrivilege to be enabled\n");
|
||||
+
|
||||
+ /* disable a SID and a privilege in new token */
|
||||
sattr.Sid = token_groups->Groups[i].Sid;
|
||||
sattr.Attributes = 0;
|
||||
r_token = NULL;
|
||||
- ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
|
||||
+ ret = pCreateRestrictedToken(token, 0, 1, &sattr, 1, &privset.Privilege[0], 0, NULL, &r_token);
|
||||
ok(ret, "got error %d\n", GetLastError());
|
||||
|
||||
if (ret)
|
||||
@@ -5355,7 +5368,7 @@ static void test_CreateRestrictedToken(void)
|
||||
is_member = TRUE;
|
||||
ret = pCheckTokenMembership(r_token, token_groups->Groups[i].Sid, &is_member);
|
||||
ok(ret, "got error %d\n", GetLastError());
|
||||
- todo_wine ok(!is_member, "not a member\n");
|
||||
+ ok(!is_member, "not a member\n");
|
||||
|
||||
ret = GetTokenInformation(r_token, TokenGroups, NULL, 0, &size);
|
||||
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
|
||||
@@ -5370,9 +5383,9 @@ static void test_CreateRestrictedToken(void)
|
||||
break;
|
||||
}
|
||||
|
||||
- todo_wine ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY,
|
||||
+ ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY,
|
||||
"got wrong attributes\n");
|
||||
- todo_wine ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0,
|
||||
+ ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0,
|
||||
"got wrong attributes\n");
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, groups2);
|
||||
@@ -5386,10 +5399,73 @@ static void test_CreateRestrictedToken(void)
|
||||
ret = GetTokenInformation(r_token, TokenImpersonationLevel, &level, size, &size);
|
||||
ok(ret, "got error %d\n", GetLastError());
|
||||
ok(level == SecurityImpersonation, "got level %u\n", type);
|
||||
+
|
||||
+ is_member = TRUE;
|
||||
+ ret = PrivilegeCheck(r_token, &privset, &is_member);
|
||||
+ ok(ret, "got error %d\n", GetLastError());
|
||||
+ ok(!is_member, "Expected SeChangeNotifyPrivilege not to be enabled\n");
|
||||
+
|
||||
+ ret = GetTokenInformation(r_token, TokenPrivileges, NULL, 0, &size);
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
|
||||
+ ret, GetLastError());
|
||||
+ privs = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
+ ret = GetTokenInformation(r_token, TokenPrivileges, privs, size, &size);
|
||||
+ ok(ret, "got error %d\n", GetLastError());
|
||||
+
|
||||
+ is_member = FALSE;
|
||||
+ for (j = 0; j < privs->PrivilegeCount; j++)
|
||||
+ {
|
||||
+ if (RtlEqualLuid(&privs->Privileges[j].Luid, &privset.Privilege[0].Luid))
|
||||
+ {
|
||||
+ is_member = TRUE;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ok(!is_member, "Expected not to find privilege\n");
|
||||
+ HeapFree(GetProcessHeap(), 0, privs);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, token_groups);
|
||||
CloseHandle(r_token);
|
||||
+
|
||||
+ ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &size);
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
|
||||
+ ret, GetLastError());
|
||||
+ primary_group = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
+ ret = GetTokenInformation(token, TokenPrimaryGroup, primary_group, size, &size);
|
||||
+ ok(ret, "got error %d\n", GetLastError());
|
||||
+
|
||||
+ /* disable primary group */
|
||||
+ sattr.Sid = primary_group->PrimaryGroup;
|
||||
+ sattr.Attributes = 0;
|
||||
+ r_token = NULL;
|
||||
+ ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
|
||||
+ ok(ret, "got error %d\n", GetLastError());
|
||||
+
|
||||
+ if (ret)
|
||||
+ {
|
||||
+ is_member = TRUE;
|
||||
+ ret = pCheckTokenMembership(r_token, primary_group->PrimaryGroup, &is_member);
|
||||
+ ok(ret, "got error %d\n", GetLastError());
|
||||
+ ok(!is_member, "not a member\n");
|
||||
+
|
||||
+ ret = GetTokenInformation(r_token, TokenPrimaryGroup, NULL, 0, &size);
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
|
||||
+ ret, GetLastError());
|
||||
+ primary_group2 = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
+ ret = GetTokenInformation(r_token, TokenPrimaryGroup, primary_group2, size, &size);
|
||||
+ ok(ret, "got error %d\n", GetLastError());
|
||||
+
|
||||
+ ok(EqualSid(primary_group2->PrimaryGroup, primary_group->PrimaryGroup),
|
||||
+ "Expected same primary group\n");
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, primary_group2);
|
||||
+ }
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, primary_group);
|
||||
+ CloseHandle(r_token);
|
||||
+
|
||||
CloseHandle(token);
|
||||
CloseHandle(process_token);
|
||||
}
|
||||
--
|
||||
2.13.1
|
||||
|
@@ -0,0 +1,36 @@
|
||||
From 22a49dfa50cda9b1f5a5c64eabed2d17b0033896 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Fri, 4 Aug 2017 02:52:50 +0200
|
||||
Subject: server: Correctly validate SID length in sd_is_valid.
|
||||
|
||||
---
|
||||
server/token.c | 6 ++----
|
||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/server/token.c b/server/token.c
|
||||
index acd7a4dedb5..7ab0f634c05 100644
|
||||
--- a/server/token.c
|
||||
+++ b/server/token.c
|
||||
@@ -332,8 +332,7 @@ int sd_is_valid( const struct security_descriptor *sd, data_size_t size )
|
||||
owner = sd_get_owner( sd );
|
||||
if (owner)
|
||||
{
|
||||
- size_t needed_size = security_sid_len( owner );
|
||||
- if ((sd->owner_len < sizeof(SID)) || (needed_size > sd->owner_len))
|
||||
+ if ((sd->owner_len < sizeof(SID)) || (security_sid_len( owner ) > sd->owner_len))
|
||||
return FALSE;
|
||||
}
|
||||
offset += sd->owner_len;
|
||||
@@ -344,8 +343,7 @@ int sd_is_valid( const struct security_descriptor *sd, data_size_t size )
|
||||
group = sd_get_group( sd );
|
||||
if (group)
|
||||
{
|
||||
- size_t needed_size = security_sid_len( group );
|
||||
- if ((sd->group_len < sizeof(SID)) || (needed_size > sd->group_len))
|
||||
+ if ((sd->group_len < sizeof(SID)) || (security_sid_len( group ) > sd->group_len))
|
||||
return FALSE;
|
||||
}
|
||||
offset += sd->group_len;
|
||||
--
|
||||
2.13.1
|
||||
|
1
patches/advapi32-CreateRestrictedToken/definition
Normal file
1
patches/advapi32-CreateRestrictedToken/definition
Normal file
@@ -0,0 +1 @@
|
||||
Fixes: Implement advapi32.CreateRestrictedToken
|
@@ -1,4 +1,4 @@
|
||||
From b4469d7a12637ef2b57df3f6aebbe65c9b52ef57 Mon Sep 17 00:00:00 2001
|
||||
From 510d9f43f441bc3a9723aabfd2c1cdc8737d6dcc Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sun, 28 Aug 2016 21:56:41 +0200
|
||||
Subject: advapi32: Implement GetExplicitEntriesFromAclW.
|
||||
@@ -9,10 +9,10 @@ Subject: advapi32: Implement GetExplicitEntriesFromAclW.
|
||||
2 files changed, 221 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c
|
||||
index 7e41c0a7361..ccd0bf64cab 100644
|
||||
index e36792cff4..b305947347 100644
|
||||
--- a/dlls/advapi32/security.c
|
||||
+++ b/dlls/advapi32/security.c
|
||||
@@ -4202,8 +4202,85 @@ DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntr
|
||||
@@ -4205,8 +4205,85 @@ DWORD WINAPI GetExplicitEntriesFromAclA( PACL pacl, PULONG pcCountOfExplicitEntr
|
||||
DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntries,
|
||||
PEXPLICIT_ACCESSW* pListOfExplicitEntries)
|
||||
{
|
||||
@@ -101,10 +101,10 @@ index 7e41c0a7361..ccd0bf64cab 100644
|
||||
|
||||
/******************************************************************************
|
||||
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
|
||||
index c31dfbeace3..23cbff58117 100644
|
||||
index 3c68205922..ca5edffae5 100644
|
||||
--- a/dlls/advapi32/tests/security.c
|
||||
+++ b/dlls/advapi32/tests/security.c
|
||||
@@ -133,6 +133,7 @@ static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*);
|
||||
@@ -134,6 +134,7 @@ static BOOL (WINAPI *pGetWindowsAccountDomainSid)(PSID,PSID,DWORD*);
|
||||
static void (WINAPI *pRtlInitAnsiString)(PANSI_STRING,PCSZ);
|
||||
static NTSTATUS (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
|
||||
static PSID_IDENTIFIER_AUTHORITY (WINAPI *pGetSidIdentifierAuthority)(PSID);
|
||||
@@ -112,16 +112,16 @@ index c31dfbeace3..23cbff58117 100644
|
||||
|
||||
static HMODULE hmod;
|
||||
static int myARGC;
|
||||
@@ -227,6 +228,7 @@ static void init(void)
|
||||
pGetAce = (void *)GetProcAddress(hmod, "GetAce");
|
||||
@@ -230,6 +231,7 @@ static void init(void)
|
||||
pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid");
|
||||
pGetSidIdentifierAuthority = (void *)GetProcAddress(hmod, "GetSidIdentifierAuthority");
|
||||
pDuplicateTokenEx = (void *)GetProcAddress(hmod, "DuplicateTokenEx");
|
||||
+ pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW");
|
||||
|
||||
myARGC = winetest_get_mainargs( &myARGV );
|
||||
}
|
||||
@@ -6451,6 +6453,145 @@ static void test_maximum_allowed(void)
|
||||
CloseHandle(handle);
|
||||
@@ -7076,6 +7078,145 @@ static void test_child_token_sd(void)
|
||||
HeapFree(GetProcessHeap(), 0, sd);
|
||||
}
|
||||
|
||||
+static void test_GetExplicitEntriesFromAclW(void)
|
||||
@@ -266,12 +266,14 @@ index c31dfbeace3..23cbff58117 100644
|
||||
START_TEST(security)
|
||||
{
|
||||
init();
|
||||
@@ -6499,4 +6640,5 @@ START_TEST(security)
|
||||
test_GetSidIdentifierAuthority();
|
||||
@@ -7129,6 +7270,7 @@ START_TEST(security)
|
||||
test_pseudo_tokens();
|
||||
test_maximum_allowed();
|
||||
test_token_label();
|
||||
+ test_GetExplicitEntriesFromAclW();
|
||||
}
|
||||
|
||||
/* Must be the last test, modifies process token */
|
||||
test_token_security_descriptor();
|
||||
--
|
||||
2.11.0
|
||||
2.13.1
|
||||
|
||||
|
@@ -0,0 +1,456 @@
|
||||
From ba50fc98ee4690e62899d48efc856c2bc910536c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Mon, 7 Aug 2017 01:25:02 +0200
|
||||
Subject: advapi32/tests: Extend security label / token integrity tests.
|
||||
|
||||
---
|
||||
dlls/advapi32/tests/Makefile.in | 2 +-
|
||||
dlls/advapi32/tests/security.c | 389 +++++++++++++++++++++++++++++++++++++++-
|
||||
2 files changed, 387 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/advapi32/tests/Makefile.in b/dlls/advapi32/tests/Makefile.in
|
||||
index 36ce031ef62..4437e6e5de7 100644
|
||||
--- a/dlls/advapi32/tests/Makefile.in
|
||||
+++ b/dlls/advapi32/tests/Makefile.in
|
||||
@@ -1,5 +1,5 @@
|
||||
TESTDLL = advapi32.dll
|
||||
-IMPORTS = ole32 advapi32
|
||||
+IMPORTS = ole32 user32 advapi32
|
||||
|
||||
C_SRCS = \
|
||||
cred.c \
|
||||
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
|
||||
index 0fd41fe82fa..4a03db27e69 100644
|
||||
--- a/dlls/advapi32/tests/security.c
|
||||
+++ b/dlls/advapi32/tests/security.c
|
||||
@@ -7191,13 +7191,19 @@ static void test_token_security_descriptor(void)
|
||||
{
|
||||
static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
|
||||
{SECURITY_MANDATORY_LOW_RID}};
|
||||
+ static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
|
||||
+ {SECURITY_MANDATORY_MEDIUM_RID}};
|
||||
+ static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
|
||||
+ {SECURITY_MANDATORY_HIGH_RID}};
|
||||
char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
|
||||
- SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2;
|
||||
+ SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2, *sd3;
|
||||
char buffer_acl[256], buffer[MAX_PATH];
|
||||
- ACL *acl = (ACL *)&buffer_acl, *acl2, *acl_child;
|
||||
+ ACL *acl = (ACL *)&buffer_acl, *acl2, *acl_child, *sacl;
|
||||
BOOL defaulted, present, ret, found;
|
||||
- HANDLE token, token2, token3;
|
||||
+ HANDLE token, token2, token3, token4, token5, token6;
|
||||
EXPLICIT_ACCESSW exp_access;
|
||||
+ TOKEN_MANDATORY_LABEL *tml;
|
||||
+ BYTE buffer_integrity[64];
|
||||
PROCESS_INFORMATION info;
|
||||
DWORD size, index, retd;
|
||||
ACCESS_ALLOWED_ACE *ace;
|
||||
@@ -7347,6 +7353,185 @@ static void test_token_security_descriptor(void)
|
||||
/* The security label is also not inherited */
|
||||
if (pAddMandatoryAce)
|
||||
{
|
||||
+ memset(buffer_integrity, 0, sizeof(buffer_integrity));
|
||||
+ ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
|
||||
+ ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
|
||||
+ tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
|
||||
+ ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
|
||||
+ "Expected medium or high integrity level\n");
|
||||
+
|
||||
+ if (EqualSid(tml->Label.Sid, &high_level))
|
||||
+ {
|
||||
+ DWORD process_id;
|
||||
+ HANDLE process;
|
||||
+ HWND shell;
|
||||
+
|
||||
+ /* This test tries to get a medium token and then impersonates this token. The
|
||||
+ * idea is to check whether the sd label of a newly created token depends on the
|
||||
+ * current active token or the integrity level of the newly created token. */
|
||||
+
|
||||
+ /* Steal process token of the explorer.exe process */
|
||||
+ shell = GetShellWindow();
|
||||
+ todo_wine ok(shell != NULL, "Failed to get shell window\n");
|
||||
+ if (!shell) shell = GetDesktopWindow(); /* FIXME: Workaround for Wine */
|
||||
+ ok(GetWindowThreadProcessId(shell, &process_id),
|
||||
+ "Failed to get process id of shell window: %u\n", GetLastError());
|
||||
+ process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_id);
|
||||
+ ok(process != NULL, "Failed to open process: %u\n", GetLastError());
|
||||
+ ok(OpenProcessToken(process, TOKEN_ALL_ACCESS, &token4),
|
||||
+ "Failed to open process token: %u\n", GetLastError());
|
||||
+ CloseHandle(process);
|
||||
+
|
||||
+ /* Check TokenIntegrityLevel and LABEL_SECURITY_INFORMATION of explorer.exe token */
|
||||
+ memset(buffer_integrity, 0, sizeof(buffer_integrity));
|
||||
+ ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
|
||||
+ ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
|
||||
+ tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
|
||||
+ todo_wine ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n");
|
||||
+
|
||||
+ size = 0;
|
||||
+ ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
+ "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
|
||||
+
|
||||
+ sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
+ ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
|
||||
+ ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ sacl = NULL;
|
||||
+ ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
|
||||
+ ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
+ ok(present, "No SACL in the security descriptor\n");
|
||||
+ ok(sacl != NULL, "NULL SACL in the security descriptor\n");
|
||||
+
|
||||
+ if (sacl)
|
||||
+ {
|
||||
+ ret = pGetAce(sacl, 0, (void **)&ace);
|
||||
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
|
||||
+ ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
|
||||
+ "Unexpected ACE type %#x\n", ace->Header.AceType);
|
||||
+ todo_wine ok(EqualSid(&ace->SidStart, &medium_level),
|
||||
+ "Expected medium integrity level\n");
|
||||
+ }
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, sd3);
|
||||
+
|
||||
+ /* Start child process with the explorer.exe token */
|
||||
+ memset(&startup, 0, sizeof(startup));
|
||||
+ startup.cb = sizeof(startup);
|
||||
+ startup.dwFlags = STARTF_USESHOWWINDOW;
|
||||
+ startup.wShowWindow = SW_SHOWNORMAL;
|
||||
+
|
||||
+ sprintf(buffer, "%s tests/security.c test_token_sd_medium", myARGV[0]);
|
||||
+ ret = CreateProcessAsUserA(token4, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
|
||||
+ ok(ret || GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
|
||||
+ "CreateProcess failed with error %u\n", GetLastError());
|
||||
+ if (ret)
|
||||
+ {
|
||||
+ winetest_wait_child_process(info.hProcess);
|
||||
+ CloseHandle(info.hProcess);
|
||||
+ CloseHandle(info.hThread);
|
||||
+ }
|
||||
+ else
|
||||
+ win_skip("Skipping test for creating process with medium level token\n");
|
||||
+
|
||||
+ ret = DuplicateTokenEx(token4, 0, NULL, SecurityImpersonation, TokenImpersonation, &token5);
|
||||
+ ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
|
||||
+ ret = SetThreadToken(NULL, token5);
|
||||
+ todo_wine ok(ret, "SetThreadToken failed with error %u\n", GetLastError());
|
||||
+ CloseHandle(token4);
|
||||
+
|
||||
+ /* Restrict current process token while impersonating a medium integrity token */
|
||||
+ ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token6);
|
||||
+ ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ memset(buffer_integrity, 0, sizeof(buffer_integrity));
|
||||
+ ret = GetTokenInformation(token6, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
|
||||
+ ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
|
||||
+ tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
|
||||
+ ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n");
|
||||
+
|
||||
+ size = 0;
|
||||
+ ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
+ "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
|
||||
+
|
||||
+ sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
+ ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size);
|
||||
+ ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ sacl = NULL;
|
||||
+ ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
|
||||
+ ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
+ todo_wine ok(present, "No SACL in the security descriptor\n");
|
||||
+ todo_wine ok(sacl != NULL, "NULL SACL in the security descriptor\n");
|
||||
+
|
||||
+ if (sacl)
|
||||
+ {
|
||||
+ ret = pGetAce(sacl, 0, (void **)&ace);
|
||||
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
|
||||
+ ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
|
||||
+ "Unexpected ACE type %#x\n", ace->Header.AceType);
|
||||
+ ok(EqualSid(&ace->SidStart, &medium_level),
|
||||
+ "Expected medium integrity level\n");
|
||||
+ }
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, sd3);
|
||||
+ RevertToSelf();
|
||||
+ CloseHandle(token5);
|
||||
+
|
||||
+ /* Start child process with the restricted token */
|
||||
+ sprintf(buffer, "%s tests/security.c test_token_sd_restricted", myARGV[0]);
|
||||
+ ret = CreateProcessAsUserA(token6, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
|
||||
+ ok(ret, "CreateProcess failed with error %u\n", GetLastError());
|
||||
+ winetest_wait_child_process(info.hProcess);
|
||||
+ CloseHandle(info.hProcess);
|
||||
+ CloseHandle(info.hThread);
|
||||
+ CloseHandle(token6);
|
||||
+
|
||||
+ /* DuplicateTokenEx should assign security label even when SA points to empty SD */
|
||||
+ memset(sd, 0, sizeof(buffer_sd));
|
||||
+ ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
|
||||
+ ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
+ sa.lpSecurityDescriptor = sd;
|
||||
+ sa.bInheritHandle = FALSE;
|
||||
+
|
||||
+ ret = DuplicateTokenEx(token, 0, &sa, 0, TokenPrimary, &token6);
|
||||
+ ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ size = 0;
|
||||
+ ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
|
||||
+ todo_wine ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
+ "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
|
||||
+
|
||||
+ sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
+ ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size);
|
||||
+ todo_wine ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ sacl = NULL;
|
||||
+ ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
|
||||
+ todo_wine ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
+ todo_wine ok(present, "No SACL in the security descriptor\n");
|
||||
+ todo_wine ok(sacl != NULL, "NULL SACL in the security descriptor\n");
|
||||
+
|
||||
+ if (sacl)
|
||||
+ {
|
||||
+ ret = pGetAce(sacl, 0, (void **)&ace);
|
||||
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
|
||||
+ ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
|
||||
+ "Unexpected ACE type %#x\n", ace->Header.AceType);
|
||||
+ ok(EqualSid(&ace->SidStart, &high_level),
|
||||
+ "Expected high integrity level\n");
|
||||
+ }
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, sd3);
|
||||
+ CloseHandle(token6);
|
||||
+ }
|
||||
+ else
|
||||
+ skip("Skipping test, running without admin rights\n");
|
||||
+
|
||||
ret = InitializeAcl(acl, 256, ACL_REVISION);
|
||||
ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
|
||||
|
||||
@@ -7362,6 +7547,90 @@ static void test_token_security_descriptor(void)
|
||||
|
||||
ret = SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd);
|
||||
ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ /* changing the label of the security descriptor does not change the integrity level of the token itself */
|
||||
+ memset(buffer_integrity, 0, sizeof(buffer_integrity));
|
||||
+ ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
|
||||
+ ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
|
||||
+ tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
|
||||
+ ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
|
||||
+ "Expected medium or high integrity level\n");
|
||||
+
|
||||
+ /* restricting / duplicating a token resets the mandatory sd label */
|
||||
+ ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token4);
|
||||
+ ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ memset(buffer_integrity, 0, sizeof(buffer_integrity));
|
||||
+ ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
|
||||
+ ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
|
||||
+ tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
|
||||
+ ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
|
||||
+ "Expected medium or high integrity level\n");
|
||||
+
|
||||
+ size = 0;
|
||||
+ ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
+ "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
|
||||
+
|
||||
+ sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
+ ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
|
||||
+ ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
|
||||
+ ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
+ todo_wine ok(present, "No SACL in the security descriptor\n");
|
||||
+ todo_wine ok(sacl != NULL, "NULL SACL in the security descriptor\n");
|
||||
+
|
||||
+ if (sacl)
|
||||
+ {
|
||||
+ ret = pGetAce(sacl, 0, (void **)&ace);
|
||||
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
|
||||
+ ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
|
||||
+ "Unexpected ACE type %#x\n", ace->Header.AceType);
|
||||
+ ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level),
|
||||
+ "Low integrity level should not have been inherited\n");
|
||||
+ }
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, sd3);
|
||||
+ CloseHandle(token4);
|
||||
+
|
||||
+ ret = DuplicateTokenEx(token, 0, NULL, 0, TokenPrimary, &token4);
|
||||
+ ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ memset(buffer_integrity, 0, sizeof(buffer_integrity));
|
||||
+ ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
|
||||
+ ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
|
||||
+ tml = (TOKEN_MANDATORY_LABEL*) buffer_integrity;
|
||||
+ ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
|
||||
+ "Expected medium or high integrity level\n");
|
||||
+
|
||||
+ size = 0;
|
||||
+ ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
|
||||
+ todo_wine ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
+ "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
|
||||
+
|
||||
+ sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
+ ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
|
||||
+ todo_wine ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ sacl = NULL;
|
||||
+ ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
|
||||
+ todo_wine ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
+ todo_wine ok(present, "No SACL in the security descriptor\n");
|
||||
+ todo_wine ok(sacl != NULL, "NULL SACL in the security descriptor\n");
|
||||
+
|
||||
+ if (sacl)
|
||||
+ {
|
||||
+ ret = pGetAce(sacl, 0, (void **)&ace);
|
||||
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
|
||||
+ ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
|
||||
+ "Unexpected ACE type %#x\n", ace->Header.AceType);
|
||||
+ ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level),
|
||||
+ "Low integrity level should not have been inherited\n");
|
||||
+ }
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, sd3);
|
||||
+ CloseHandle(token4);
|
||||
}
|
||||
else
|
||||
win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
|
||||
@@ -7467,6 +7736,116 @@ static void test_child_token_sd(void)
|
||||
HeapFree(GetProcessHeap(), 0, sd);
|
||||
}
|
||||
|
||||
+static void test_child_token_sd_restricted(void)
|
||||
+{
|
||||
+ static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
|
||||
+ {SECURITY_MANDATORY_HIGH_RID}};
|
||||
+ SYSTEM_MANDATORY_LABEL_ACE *ace_label;
|
||||
+ BOOL ret, present, defaulted;
|
||||
+ TOKEN_MANDATORY_LABEL *tml;
|
||||
+ BYTE buffer_integrity[64];
|
||||
+ SECURITY_DESCRIPTOR *sd;
|
||||
+ HANDLE token;
|
||||
+ DWORD size;
|
||||
+ ACL *acl;
|
||||
+
|
||||
+ if (!pAddMandatoryAce)
|
||||
+ {
|
||||
+ win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
|
||||
+ ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
+ "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
|
||||
+
|
||||
+ sd = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
+ ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
|
||||
+ ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ acl = NULL;
|
||||
+ present = FALSE;
|
||||
+ defaulted = TRUE;
|
||||
+ ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
|
||||
+ ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
+ ok(present, "SACL not present\n");
|
||||
+ ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
|
||||
+ ok(!defaulted, "SACL defaulted\n");
|
||||
+ ok(acl->AceCount == 1, "Expected exactly one ACE\n");
|
||||
+ ret = pGetAce(acl, 0, (void **)&ace_label);
|
||||
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
|
||||
+ ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
|
||||
+ "Unexpected ACE type %#x\n", ace_label->Header.AceType);
|
||||
+ ok(EqualSid(&ace_label->SidStart, &high_level),
|
||||
+ "Expected high integrity level\n");
|
||||
+
|
||||
+ memset(buffer_integrity, 0, sizeof(buffer_integrity));
|
||||
+ ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
|
||||
+ ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
|
||||
+ tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
|
||||
+ ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n");
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, sd);
|
||||
+}
|
||||
+
|
||||
+static void test_child_token_sd_medium(void)
|
||||
+{
|
||||
+ static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
|
||||
+ {SECURITY_MANDATORY_MEDIUM_RID}};
|
||||
+ SYSTEM_MANDATORY_LABEL_ACE *ace_label;
|
||||
+ BOOL ret, present, defaulted;
|
||||
+ TOKEN_MANDATORY_LABEL *tml;
|
||||
+ BYTE buffer_integrity[64];
|
||||
+ SECURITY_DESCRIPTOR *sd;
|
||||
+ HANDLE token;
|
||||
+ DWORD size;
|
||||
+ ACL *acl;
|
||||
+
|
||||
+ if (!pAddMandatoryAce)
|
||||
+ {
|
||||
+ win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
|
||||
+ ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
+ "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
|
||||
+
|
||||
+ sd = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
+ ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
|
||||
+ ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+
|
||||
+ acl = NULL;
|
||||
+ present = FALSE;
|
||||
+ defaulted = TRUE;
|
||||
+ ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
|
||||
+ ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
+ ok(present, "SACL not present\n");
|
||||
+ ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
|
||||
+ ok(!defaulted, "SACL defaulted\n");
|
||||
+ ok(acl->AceCount == 1, "Expected exactly one ACE\n");
|
||||
+ ret = pGetAce(acl, 0, (void **)&ace_label);
|
||||
+ ok(ret, "GetAce failed with error %u\n", GetLastError());
|
||||
+ ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
|
||||
+ "Unexpected ACE type %#x\n", ace_label->Header.AceType);
|
||||
+ todo_wine ok(EqualSid(&ace_label->SidStart, &medium_level),
|
||||
+ "Expected medium integrity level\n");
|
||||
+
|
||||
+ memset(buffer_integrity, 0, sizeof(buffer_integrity));
|
||||
+ ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
|
||||
+ ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
|
||||
+ tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
|
||||
+ todo_wine ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n");
|
||||
+
|
||||
+ HeapFree(GetProcessHeap(), 0, sd);
|
||||
+}
|
||||
+
|
||||
static void test_GetExplicitEntriesFromAclW(void)
|
||||
{
|
||||
static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
|
||||
@@ -7653,6 +8032,10 @@ START_TEST(security)
|
||||
{
|
||||
if (!strcmp(myARGV[2], "test_token_sd"))
|
||||
test_child_token_sd();
|
||||
+ else if (!strcmp(myARGV[2], "test_token_sd_restricted"))
|
||||
+ test_child_token_sd_restricted();
|
||||
+ else if (!strcmp(myARGV[2], "test_token_sd_medium"))
|
||||
+ test_child_token_sd_medium();
|
||||
else
|
||||
test_process_security_child();
|
||||
return;
|
||||
--
|
||||
2.13.1
|
||||
|
@@ -0,0 +1,136 @@
|
||||
From 4b428e09733605affb987d369f56ec09d2525858 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Sat, 5 Aug 2017 00:26:03 +0200
|
||||
Subject: server: Implement token elevation information.
|
||||
|
||||
---
|
||||
dlls/ntdll/nt.c | 16 ++++++++++++----
|
||||
server/protocol.def | 8 ++++++++
|
||||
server/token.c | 22 +++++++++++++++++++---
|
||||
3 files changed, 39 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
|
||||
index 5822dec9b15..dda6cabe1cf 100644
|
||||
--- a/dlls/ntdll/nt.c
|
||||
+++ b/dlls/ntdll/nt.c
|
||||
@@ -597,18 +597,26 @@ NTSTATUS WINAPI NtQueryInformationToken(
|
||||
SERVER_END_REQ;
|
||||
break;
|
||||
case TokenElevationType:
|
||||
+ SERVER_START_REQ( get_token_elevation_type )
|
||||
{
|
||||
TOKEN_ELEVATION_TYPE *elevation_type = tokeninfo;
|
||||
- FIXME("QueryInformationToken( ..., TokenElevationType, ...) semi-stub\n");
|
||||
- *elevation_type = TokenElevationTypeFull;
|
||||
+ req->handle = wine_server_obj_handle( token );
|
||||
+ status = wine_server_call( req );
|
||||
+ if (status == STATUS_SUCCESS)
|
||||
+ *elevation_type = reply->elevation;
|
||||
}
|
||||
+ SERVER_END_REQ;
|
||||
break;
|
||||
case TokenElevation:
|
||||
+ SERVER_START_REQ( get_token_elevation_type )
|
||||
{
|
||||
TOKEN_ELEVATION *elevation = tokeninfo;
|
||||
- FIXME("QueryInformationToken( ..., TokenElevation, ...) semi-stub\n");
|
||||
- elevation->TokenIsElevated = TRUE;
|
||||
+ req->handle = wine_server_obj_handle( token );
|
||||
+ status = wine_server_call( req );
|
||||
+ if (status == STATUS_SUCCESS)
|
||||
+ elevation->TokenIsElevated = (reply->elevation == TokenElevationTypeFull);
|
||||
}
|
||||
+ SERVER_END_REQ;
|
||||
break;
|
||||
case TokenSessionId:
|
||||
{
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index b3dce66eb9c..33f1d5f0ab8 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -3673,6 +3673,14 @@ struct handle_info
|
||||
@END
|
||||
|
||||
|
||||
+/* Get elevation level of token */
|
||||
+@REQ(get_token_elevation_type)
|
||||
+ obj_handle_t handle; /* handle to the object */
|
||||
+@REPLY
|
||||
+ unsigned int elevation; /* elevation level */
|
||||
+@END
|
||||
+
|
||||
+
|
||||
/* Create I/O completion port */
|
||||
@REQ(create_completion)
|
||||
unsigned int access; /* desired access to a port */
|
||||
diff --git a/server/token.c b/server/token.c
|
||||
index 7ab0f634c05..6a1085bae12 100644
|
||||
--- a/server/token.c
|
||||
+++ b/server/token.c
|
||||
@@ -126,6 +126,7 @@ struct token
|
||||
ACL *default_dacl; /* the default DACL to assign to objects created by this user */
|
||||
TOKEN_SOURCE source; /* source of the token */
|
||||
int impersonation_level; /* impersonation level this token is capable of if non-primary token */
|
||||
+ TOKEN_ELEVATION_TYPE elevation; /* elevation level */
|
||||
};
|
||||
|
||||
struct privilege
|
||||
@@ -566,7 +567,7 @@ static struct token *create_token( unsigned primary, const SID *user,
|
||||
const LUID_AND_ATTRIBUTES *privs, unsigned int priv_count,
|
||||
const ACL *default_dacl, TOKEN_SOURCE source,
|
||||
const luid_t *modified_id,
|
||||
- int impersonation_level )
|
||||
+ int impersonation_level, TOKEN_ELEVATION_TYPE elevation )
|
||||
{
|
||||
struct token *token = alloc_object( &token_ops );
|
||||
if (token)
|
||||
@@ -588,6 +589,7 @@ static struct token *create_token( unsigned primary, const SID *user,
|
||||
token->impersonation_level = impersonation_level;
|
||||
token->default_dacl = NULL;
|
||||
token->primary_group = NULL;
|
||||
+ token->elevation = elevation;
|
||||
|
||||
/* copy user */
|
||||
token->user = memdup( user, security_sid_len( user ));
|
||||
@@ -700,7 +702,8 @@ struct token *token_duplicate( struct token *src_token, unsigned primary,
|
||||
token = create_token( primary, src_token->user, NULL, 0,
|
||||
NULL, 0, src_token->default_dacl,
|
||||
src_token->source, modified_id,
|
||||
- impersonation_level );
|
||||
+ impersonation_level,
|
||||
+ src_token->elevation );
|
||||
if (!token) return token;
|
||||
|
||||
/* copy groups */
|
||||
@@ -904,7 +907,7 @@ struct token *token_create_admin( void )
|
||||
static const TOKEN_SOURCE admin_source = {"SeMgr", {0, 0}};
|
||||
token = create_token( TRUE, user_sid, admin_groups, sizeof(admin_groups)/sizeof(admin_groups[0]),
|
||||
admin_privs, sizeof(admin_privs)/sizeof(admin_privs[0]), default_dacl,
|
||||
- admin_source, NULL, -1 );
|
||||
+ admin_source, NULL, -1, TokenElevationTypeFull );
|
||||
/* we really need a primary group */
|
||||
assert( token->primary_group );
|
||||
}
|
||||
@@ -1652,6 +1655,19 @@ DECL_HANDLER(get_token_statistics)
|
||||
}
|
||||
}
|
||||
|
||||
+DECL_HANDLER(get_token_elevation_type)
|
||||
+{
|
||||
+ struct token *token;
|
||||
+
|
||||
+ if ((token = (struct token *)get_handle_obj( current->process, req->handle,
|
||||
+ TOKEN_QUERY,
|
||||
+ &token_ops )))
|
||||
+ {
|
||||
+ reply->elevation = token->elevation;
|
||||
+ release_object( token );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
DECL_HANDLER(get_token_default_dacl)
|
||||
{
|
||||
struct token *token;
|
||||
--
|
||||
2.13.1
|
||||
|
@@ -0,0 +1,81 @@
|
||||
From 7e73f449d158f0d6a6b6b421d073dbaf1741e1c7 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Mon, 7 Aug 2017 02:22:11 +0200
|
||||
Subject: server: Correctly treat zero access mask in duplicate_token
|
||||
wineserver call.
|
||||
|
||||
---
|
||||
dlls/advapi32/tests/security.c | 14 +++++++-------
|
||||
server/token.c | 3 ++-
|
||||
2 files changed, 9 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
|
||||
index 4a03db27e69..f1a64e29dea 100644
|
||||
--- a/dlls/advapi32/tests/security.c
|
||||
+++ b/dlls/advapi32/tests/security.c
|
||||
@@ -7438,7 +7438,7 @@ static void test_token_security_descriptor(void)
|
||||
ret = DuplicateTokenEx(token4, 0, NULL, SecurityImpersonation, TokenImpersonation, &token5);
|
||||
ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
|
||||
ret = SetThreadToken(NULL, token5);
|
||||
- todo_wine ok(ret, "SetThreadToken failed with error %u\n", GetLastError());
|
||||
+ ok(ret, "SetThreadToken failed with error %u\n", GetLastError());
|
||||
CloseHandle(token4);
|
||||
|
||||
/* Restrict current process token while impersonating a medium integrity token */
|
||||
@@ -7503,16 +7503,16 @@ static void test_token_security_descriptor(void)
|
||||
|
||||
size = 0;
|
||||
ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
|
||||
- todo_wine ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
"Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
|
||||
|
||||
sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size);
|
||||
- todo_wine ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+ ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
|
||||
sacl = NULL;
|
||||
ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
|
||||
- todo_wine ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
+ ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
todo_wine ok(present, "No SACL in the security descriptor\n");
|
||||
todo_wine ok(sacl != NULL, "NULL SACL in the security descriptor\n");
|
||||
|
||||
@@ -7606,16 +7606,16 @@ static void test_token_security_descriptor(void)
|
||||
|
||||
size = 0;
|
||||
ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
|
||||
- todo_wine ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
+ ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
"Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
|
||||
|
||||
sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
|
||||
- todo_wine ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
+ ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
|
||||
|
||||
sacl = NULL;
|
||||
ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
|
||||
- todo_wine ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
+ ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
|
||||
todo_wine ok(present, "No SACL in the security descriptor\n");
|
||||
todo_wine ok(sacl != NULL, "NULL SACL in the security descriptor\n");
|
||||
|
||||
diff --git a/server/token.c b/server/token.c
|
||||
index 6a1085bae12..292e1df80fd 100644
|
||||
--- a/server/token.c
|
||||
+++ b/server/token.c
|
||||
@@ -1376,7 +1376,8 @@ DECL_HANDLER(duplicate_token)
|
||||
struct token *token = token_duplicate( src_token, req->primary, req->impersonation_level, sd, NULL, 0, NULL, 0 );
|
||||
if (token)
|
||||
{
|
||||
- reply->new_handle = alloc_handle_no_access_check( current->process, token, req->access, objattr->attributes );
|
||||
+ unsigned int access = req->access ? req->access : get_handle_access( current->process, req->handle );
|
||||
+ reply->new_handle = alloc_handle_no_access_check( current->process, token, access, objattr->attributes );
|
||||
release_object( token );
|
||||
}
|
||||
release_object( src_token );
|
||||
--
|
||||
2.13.1
|
||||
|
@@ -0,0 +1,153 @@
|
||||
From 3092c9de3ac89e77a139db97a33b8b15f9a12eac Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
Date: Mon, 7 Aug 2017 02:28:35 +0200
|
||||
Subject: server: Implement token integrity level.
|
||||
|
||||
---
|
||||
dlls/ntdll/nt.c | 23 ++++++++++++++---------
|
||||
server/protocol.def | 7 +++++++
|
||||
server/token.c | 30 +++++++++++++++++++++++++++---
|
||||
3 files changed, 48 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
|
||||
index dda6cabe1cf..6f2b24e6ba4 100644
|
||||
--- a/dlls/ntdll/nt.c
|
||||
+++ b/dlls/ntdll/nt.c
|
||||
@@ -372,7 +372,7 @@ NTSTATUS WINAPI NtQueryInformationToken(
|
||||
0, /* TokenAccessInformation */
|
||||
0, /* TokenVirtualizationAllowed */
|
||||
0, /* TokenVirtualizationEnabled */
|
||||
- sizeof(TOKEN_MANDATORY_LABEL) + sizeof(SID), /* TokenIntegrityLevel [sizeof(SID) includes one SubAuthority] */
|
||||
+ 0, /* TokenIntegrityLevel */
|
||||
0, /* TokenUIAccess */
|
||||
0, /* TokenMandatoryPolicy */
|
||||
sizeof(TOKEN_GROUPS) + sizeof(logon_sid), /* TokenLogonSid */
|
||||
@@ -625,18 +625,23 @@ NTSTATUS WINAPI NtQueryInformationToken(
|
||||
}
|
||||
break;
|
||||
case TokenIntegrityLevel:
|
||||
+ SERVER_START_REQ( get_token_integrity )
|
||||
{
|
||||
- /* report always "S-1-16-12288" (high mandatory level) for now */
|
||||
- static const SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
|
||||
- {SECURITY_MANDATORY_HIGH_RID}};
|
||||
-
|
||||
TOKEN_MANDATORY_LABEL *tml = tokeninfo;
|
||||
- PSID psid = tml + 1;
|
||||
+ PSID sid = tml + 1;
|
||||
+ DWORD sid_len = tokeninfolength < sizeof(*tml) ? 0 : tokeninfolength - sizeof(*tml);
|
||||
|
||||
- tml->Label.Sid = psid;
|
||||
- tml->Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
|
||||
- memcpy(psid, &high_level, sizeof(SID));
|
||||
+ req->handle = wine_server_obj_handle( token );
|
||||
+ wine_server_set_reply( req, sid, sid_len );
|
||||
+ status = wine_server_call( req );
|
||||
+ if (retlen) *retlen = reply->sid_len + sizeof(*tml);
|
||||
+ if (status == STATUS_SUCCESS)
|
||||
+ {
|
||||
+ tml->Label.Sid = sid;
|
||||
+ tml->Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
|
||||
+ }
|
||||
}
|
||||
+ SERVER_END_REQ;
|
||||
break;
|
||||
case TokenAppContainerSid:
|
||||
{
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index 33f1d5f0ab8..ac2e2242511 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -3424,6 +3424,13 @@ enum caret_state
|
||||
VARARG(sid,SID); /* the sid specified by which_sid from the token */
|
||||
@END
|
||||
|
||||
+@REQ(get_token_integrity)
|
||||
+ obj_handle_t handle; /* handle to the token */
|
||||
+@REPLY
|
||||
+ data_size_t sid_len; /* length needed to store sid */
|
||||
+ VARARG(sid,SID); /* the integrity sid */
|
||||
+@END
|
||||
+
|
||||
@REQ(get_token_groups)
|
||||
obj_handle_t handle; /* handle to the token */
|
||||
@REPLY
|
||||
diff --git a/server/token.c b/server/token.c
|
||||
index 292e1df80fd..8d2de6ab58e 100644
|
||||
--- a/server/token.c
|
||||
+++ b/server/token.c
|
||||
@@ -127,6 +127,7 @@ struct token
|
||||
TOKEN_SOURCE source; /* source of the token */
|
||||
int impersonation_level; /* impersonation level this token is capable of if non-primary token */
|
||||
TOKEN_ELEVATION_TYPE elevation; /* elevation level */
|
||||
+ const SID *integrity; /* token integrity */
|
||||
};
|
||||
|
||||
struct privilege
|
||||
@@ -567,7 +568,8 @@ static struct token *create_token( unsigned primary, const SID *user,
|
||||
const LUID_AND_ATTRIBUTES *privs, unsigned int priv_count,
|
||||
const ACL *default_dacl, TOKEN_SOURCE source,
|
||||
const luid_t *modified_id,
|
||||
- int impersonation_level, TOKEN_ELEVATION_TYPE elevation )
|
||||
+ int impersonation_level, TOKEN_ELEVATION_TYPE elevation,
|
||||
+ const SID *integrity )
|
||||
{
|
||||
struct token *token = alloc_object( &token_ops );
|
||||
if (token)
|
||||
@@ -648,6 +650,7 @@ static struct token *create_token( unsigned primary, const SID *user,
|
||||
}
|
||||
|
||||
token->source = source;
|
||||
+ token->integrity = integrity;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
@@ -703,7 +706,8 @@ struct token *token_duplicate( struct token *src_token, unsigned primary,
|
||||
NULL, 0, src_token->default_dacl,
|
||||
src_token->source, modified_id,
|
||||
impersonation_level,
|
||||
- src_token->elevation );
|
||||
+ src_token->elevation,
|
||||
+ src_token->integrity );
|
||||
if (!token) return token;
|
||||
|
||||
/* copy groups */
|
||||
@@ -907,7 +911,7 @@ struct token *token_create_admin( void )
|
||||
static const TOKEN_SOURCE admin_source = {"SeMgr", {0, 0}};
|
||||
token = create_token( TRUE, user_sid, admin_groups, sizeof(admin_groups)/sizeof(admin_groups[0]),
|
||||
admin_privs, sizeof(admin_privs)/sizeof(admin_privs[0]), default_dacl,
|
||||
- admin_source, NULL, -1, TokenElevationTypeFull );
|
||||
+ admin_source, NULL, -1, TokenElevationTypeFull, &high_label_sid );
|
||||
/* we really need a primary group */
|
||||
assert( token->primary_group );
|
||||
}
|
||||
@@ -1550,6 +1554,26 @@ DECL_HANDLER(get_token_sid)
|
||||
}
|
||||
}
|
||||
|
||||
+/* retrieves the integrity sid */
|
||||
+DECL_HANDLER(get_token_integrity)
|
||||
+{
|
||||
+ struct token *token;
|
||||
+
|
||||
+ reply->sid_len = 0;
|
||||
+
|
||||
+ if ((token = (struct token *)get_handle_obj( current->process, req->handle,
|
||||
+ TOKEN_QUERY,
|
||||
+ &token_ops )))
|
||||
+ {
|
||||
+ reply->sid_len = security_sid_len( token->integrity );
|
||||
+ if (reply->sid_len <= get_reply_max_size())
|
||||
+ set_reply_data( token->integrity, reply->sid_len );
|
||||
+ else
|
||||
+ set_error( STATUS_BUFFER_TOO_SMALL );
|
||||
+ release_object( token );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* retrieves the groups that the user represented by the token belongs to */
|
||||
DECL_HANDLER(get_token_groups)
|
||||
{
|
||||
--
|
||||
2.13.1
|
||||
|
@@ -0,0 +1,46 @@
|
||||
From 77c9e6c6f408a2b59a79f3773a379a43b6994f2c Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sun, 6 Aug 2017 15:16:33 +0200
|
||||
Subject: server: Use all group attributes in create_token.
|
||||
|
||||
---
|
||||
server/token.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/server/token.c b/server/token.c
|
||||
index 8d2de6ab58e..e61fe97bfa0 100644
|
||||
--- a/server/token.c
|
||||
+++ b/server/token.c
|
||||
@@ -613,13 +613,13 @@ static struct token *create_token( unsigned primary, const SID *user,
|
||||
return NULL;
|
||||
}
|
||||
memcpy( &group->sid, groups[i].Sid, security_sid_len( groups[i].Sid ));
|
||||
- group->enabled = TRUE;
|
||||
- group->def = TRUE;
|
||||
- group->logon = (groups[i].Attributes & SE_GROUP_LOGON_ID) != 0;
|
||||
group->mandatory = (groups[i].Attributes & SE_GROUP_MANDATORY) != 0;
|
||||
- group->owner = (groups[i].Attributes & SE_GROUP_OWNER) != 0;
|
||||
- group->resource = FALSE;
|
||||
- group->deny_only = FALSE;
|
||||
+ group->def = (groups[i].Attributes & SE_GROUP_ENABLED_BY_DEFAULT) != 0;
|
||||
+ group->enabled = (groups[i].Attributes & SE_GROUP_ENABLED) != 0;
|
||||
+ group->owner = (groups[i].Attributes & SE_GROUP_OWNER) != 0;
|
||||
+ group->deny_only = (groups[i].Attributes & SE_GROUP_USE_FOR_DENY_ONLY) != 0;
|
||||
+ group->logon = (groups[i].Attributes & SE_GROUP_LOGON_ID) != 0;
|
||||
+ group->resource = (groups[i].Attributes & SE_GROUP_RESOURCE) != 0;
|
||||
list_add_tail( &token->groups, &group->entry );
|
||||
/* Use first owner capable group as an owner */
|
||||
if (!token->primary_group && group->owner)
|
||||
@@ -1628,8 +1628,8 @@ DECL_HANDLER(get_token_groups)
|
||||
if (group->enabled) *attr_ptr |= SE_GROUP_ENABLED;
|
||||
if (group->owner) *attr_ptr |= SE_GROUP_OWNER;
|
||||
if (group->deny_only) *attr_ptr |= SE_GROUP_USE_FOR_DENY_ONLY;
|
||||
- if (group->resource) *attr_ptr |= SE_GROUP_RESOURCE;
|
||||
if (group->logon) *attr_ptr |= SE_GROUP_LOGON_ID;
|
||||
+ if (group->resource) *attr_ptr |= SE_GROUP_RESOURCE;
|
||||
|
||||
memcpy(sid_ptr, &group->sid, security_sid_len( &group->sid ));
|
||||
|
||||
--
|
||||
2.13.1
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user