https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d4b4da5385b76a7c1c7a1…
commit d4b4da5385b76a7c1c7a1b0e2d52e6cf4a448c11
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sat Jun 23 00:17:05 2018 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Wed Jun 27 23:40:07 2018 +0200
[ADVAPI32] Additions for CreateProcessAsUserA/W().
- Use a common helper function used by both the ANSI and UNICODE functions
so that the large code block that deals with setting the new process token
becomes automatically common to both these functions, while the ANSI vs.
UNICODE conversions are handled directly via the CreateProcessA/W() calls.
- Duplicate the token and acquire the process primary token assignment
privilege before calling NtSetInformationProcess().
---
dll/win32/advapi32/advapi32.h | 2 +
dll/win32/advapi32/misc/logon.c | 272 ++++++++++++++++++++++++++--------------
2 files changed, 180 insertions(+), 94 deletions(-)
diff --git a/dll/win32/advapi32/advapi32.h b/dll/win32/advapi32/advapi32.h
index 5869e35d43..77312e7654 100644
--- a/dll/win32/advapi32/advapi32.h
+++ b/dll/win32/advapi32/advapi32.h
@@ -23,12 +23,14 @@
#define _WMI_SOURCE_
#include <aclapi.h>
#include <winsafer.h>
+
#define NTOS_MODE_USER
#include <ndk/iofuncs.h>
#include <ndk/obfuncs.h>
#include <ndk/psfuncs.h>
#include <ndk/rtlfuncs.h>
#include <ndk/sefuncs.h>
+#include <ndk/setypes.h>
/* this has to go after the NDK when being used with the NDK */
#include <ntsecapi.h>
diff --git a/dll/win32/advapi32/misc/logon.c b/dll/win32/advapi32/misc/logon.c
index 8b3b6b4a2c..88be6e5f39 100644
--- a/dll/win32/advapi32/misc/logon.c
+++ b/dll/win32/advapi32/misc/logon.c
@@ -86,58 +86,132 @@ CloseLogonLsaHandle(VOID)
}
-/*
- * @implemented
- */
-BOOL WINAPI DECLSPEC_HOTPATCH
-CreateProcessAsUserA(HANDLE hToken,
- LPCSTR lpApplicationName,
- LPSTR lpCommandLine,
- LPSECURITY_ATTRIBUTES lpProcessAttributes,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- BOOL bInheritHandles,
- DWORD dwCreationFlags,
- LPVOID lpEnvironment,
- LPCSTR lpCurrentDirectory,
- LPSTARTUPINFOA lpStartupInfo,
- LPPROCESS_INFORMATION lpProcessInformation)
+static
+BOOL
+CreateProcessAsUserCommon(
+ _In_ BOOL bUnicode,
+ _In_opt_ HANDLE hToken,
+ _In_opt_ LPCVOID lpApplicationName,
+ _Inout_opt_ LPVOID lpCommandLine,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ _In_ BOOL bInheritHandles,
+ _In_ DWORD dwCreationFlags,
+ _In_opt_ LPVOID lpEnvironment,
+ _In_opt_ LPCVOID lpCurrentDirectory,
+ _In_ LPVOID lpStartupInfo,
+ _Out_ LPPROCESS_INFORMATION lpProcessInformation)
{
- PROCESS_ACCESS_TOKEN AccessToken;
NTSTATUS Status;
-
- TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken,
debugstr_a(lpApplicationName),
- debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes,
bInheritHandles,
- dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo,
lpProcessInformation);
+ PROCESS_ACCESS_TOKEN AccessToken;
/* Create the process with a suspended main thread */
- if (!CreateProcessA(lpApplicationName,
- lpCommandLine,
- lpProcessAttributes,
- lpThreadAttributes,
- bInheritHandles,
- dwCreationFlags | CREATE_SUSPENDED,
- lpEnvironment,
- lpCurrentDirectory,
- lpStartupInfo,
- lpProcessInformation))
+ if (bUnicode)
{
- ERR("CreateProcessA failed! GLE: %d\n", GetLastError());
- return FALSE;
+ /* Call the UNICODE version */
+ if (!CreateProcessW((LPCWSTR)lpApplicationName,
+ (LPWSTR)lpCommandLine,
+ lpProcessAttributes,
+ lpThreadAttributes,
+ bInheritHandles,
+ dwCreationFlags | CREATE_SUSPENDED,
+ lpEnvironment,
+ (LPCWSTR)lpCurrentDirectory,
+ (LPSTARTUPINFOW)lpStartupInfo,
+ lpProcessInformation))
+ {
+ ERR("CreateProcessW failed, last error: %d\n", GetLastError());
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* Call the ANSI version */
+ if (!CreateProcessA((LPCSTR)lpApplicationName,
+ (LPSTR)lpCommandLine,
+ lpProcessAttributes,
+ lpThreadAttributes,
+ bInheritHandles,
+ dwCreationFlags | CREATE_SUSPENDED,
+ lpEnvironment,
+ (LPCSTR)lpCurrentDirectory,
+ (LPSTARTUPINFOA)lpStartupInfo,
+ lpProcessInformation))
+ {
+ ERR("CreateProcessA failed, last error: %d\n", GetLastError());
+ return FALSE;
+ }
}
if (hToken != NULL)
{
- AccessToken.Token = hToken;
- AccessToken.Thread = NULL;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE hTokenDup;
+ BOOLEAN PrivilegeSet = FALSE;
+
+ /* Duplicate the token for this new process */
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ NULL); // FIXME: Use a valid SecurityDescriptor!
+ Status = NtDuplicateToken(hToken,
+ 0,
+ &ObjectAttributes,
+ FALSE,
+ TokenPrimary,
+ &hTokenDup);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("NtDuplicateToken failed, Status 0x%08x\n", Status);
+ TerminateProcess(lpProcessInformation->hProcess, Status);
+ SetLastError(RtlNtStatusToDosError(Status));
+ return FALSE;
+ }
+
+ // FIXME: Do we always need SecurityImpersonation?
+ if (!ImpersonateSelf(SecurityImpersonation))
+ {
+ ERR("ImpersonateSelf(SecurityImpersonation) failed, last error:
%d\n", GetLastError());
+ NtClose(hTokenDup);
+ TerminateProcess(lpProcessInformation->hProcess, RtlGetLastNtStatus());
+ // SetLastError(RtlNtStatusToDosError(Status));
+ return FALSE;
+ }
+
+ /* Acquire the process primary token assignment privilege */
+ Status = RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, TRUE,
&PrivilegeSet);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE) failed, Status
0x%08lx\n", Status);
+ RevertToSelf();
+ NtClose(hTokenDup);
+ TerminateProcess(lpProcessInformation->hProcess, Status);
+ SetLastError(RtlNtStatusToDosError(Status));
+ return FALSE;
+ }
+
+ AccessToken.Token = hTokenDup;
+ AccessToken.Thread = lpProcessInformation->hThread;
/* Set the new process token */
Status = NtSetInformationProcess(lpProcessInformation->hProcess,
ProcessAccessToken,
(PVOID)&AccessToken,
sizeof(AccessToken));
- if (!NT_SUCCESS (Status))
+
+ /* Restore the privileges */
+ RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, PrivilegeSet, TRUE,
&PrivilegeSet);
+
+ RevertToSelf();
+
+ /* Close the duplicated token */
+ NtClose(hTokenDup);
+
+ /* Check whether NtSetInformationProcess() failed */
+ if (!NT_SUCCESS(Status))
{
- ERR("NtSetInformationProcess failed: 0x%08x\n", Status);
+ ERR("NtSetInformationProcess failed, Status 0x%08x\n", Status);
TerminateProcess(lpProcessInformation->hProcess, Status);
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
@@ -157,68 +231,78 @@ CreateProcessAsUserA(HANDLE hToken,
/*
* @implemented
*/
-BOOL WINAPI DECLSPEC_HOTPATCH
-CreateProcessAsUserW(HANDLE hToken,
- LPCWSTR lpApplicationName,
- LPWSTR lpCommandLine,
- LPSECURITY_ATTRIBUTES lpProcessAttributes,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- BOOL bInheritHandles,
- DWORD dwCreationFlags,
- LPVOID lpEnvironment,
- LPCWSTR lpCurrentDirectory,
- LPSTARTUPINFOW lpStartupInfo,
- LPPROCESS_INFORMATION lpProcessInformation)
+BOOL
+WINAPI
+DECLSPEC_HOTPATCH
+CreateProcessAsUserA(
+ _In_opt_ HANDLE hToken,
+ _In_opt_ LPCSTR lpApplicationName,
+ _Inout_opt_ LPSTR lpCommandLine,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ _In_ BOOL bInheritHandles,
+ _In_ DWORD dwCreationFlags,
+ _In_opt_ LPVOID lpEnvironment,
+ _In_opt_ LPCSTR lpCurrentDirectory,
+ _In_ LPSTARTUPINFOA lpStartupInfo,
+ _Out_ LPPROCESS_INFORMATION lpProcessInformation)
{
- PROCESS_ACCESS_TOKEN AccessToken;
- NTSTATUS Status;
+ TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken,
debugstr_a(lpApplicationName),
+ debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes,
bInheritHandles,
+ dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo,
lpProcessInformation);
+
+ /* Call the helper function */
+ return CreateProcessAsUserCommon(FALSE,
+ hToken,
+ lpApplicationName,
+ lpCommandLine,
+ lpProcessAttributes,
+ lpThreadAttributes,
+ bInheritHandles,
+ dwCreationFlags,
+ lpEnvironment,
+ lpCurrentDirectory,
+ lpStartupInfo,
+ lpProcessInformation);
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+DECLSPEC_HOTPATCH
+CreateProcessAsUserW(
+ _In_opt_ HANDLE hToken,
+ _In_opt_ LPCWSTR lpApplicationName,
+ _Inout_opt_ LPWSTR lpCommandLine,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ _In_ BOOL bInheritHandles,
+ _In_ DWORD dwCreationFlags,
+ _In_opt_ LPVOID lpEnvironment,
+ _In_opt_ LPCWSTR lpCurrentDirectory,
+ _In_ LPSTARTUPINFOW lpStartupInfo,
+ _Out_ LPPROCESS_INFORMATION lpProcessInformation)
+{
TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken,
debugstr_w(lpApplicationName),
debugstr_w(lpCommandLine), lpProcessAttributes, lpThreadAttributes,
bInheritHandles,
dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory), lpStartupInfo,
lpProcessInformation);
- /* Create the process with a suspended main thread */
- if (!CreateProcessW(lpApplicationName,
- lpCommandLine,
- lpProcessAttributes,
- lpThreadAttributes,
- bInheritHandles,
- dwCreationFlags | CREATE_SUSPENDED,
- lpEnvironment,
- lpCurrentDirectory,
- lpStartupInfo,
- lpProcessInformation))
- {
- ERR("CreateProcessW failed! GLE: %d\n", GetLastError());
- return FALSE;
- }
-
- if (hToken != NULL)
- {
- AccessToken.Token = hToken;
- AccessToken.Thread = NULL;
-
- /* Set the new process token */
- Status = NtSetInformationProcess(lpProcessInformation->hProcess,
- ProcessAccessToken,
- (PVOID)&AccessToken,
- sizeof(AccessToken));
- if (!NT_SUCCESS (Status))
- {
- ERR("NtSetInformationProcess failed: 0x%08x\n", Status);
- TerminateProcess(lpProcessInformation->hProcess, Status);
- SetLastError(RtlNtStatusToDosError(Status));
- return FALSE;
- }
- }
-
- /* Resume the main thread */
- if (!(dwCreationFlags & CREATE_SUSPENDED))
- {
- ResumeThread(lpProcessInformation->hThread);
- }
-
- return TRUE;
+ /* Call the helper function */
+ return CreateProcessAsUserCommon(TRUE,
+ hToken,
+ lpApplicationName,
+ lpCommandLine,
+ lpProcessAttributes,
+ lpThreadAttributes,
+ bInheritHandles,
+ dwCreationFlags,
+ lpEnvironment,
+ lpCurrentDirectory,
+ lpStartupInfo,
+ lpProcessInformation);
}
@@ -478,7 +562,7 @@ LogonUserExW(
Password.Buffer,
Password.MaximumLength);
- /* Create the Logon SID*/
+ /* Create the Logon SID */
AllocateLocallyUniqueId(&LogonId);
Status = RtlAllocateAndInitializeSid(&SystemAuthority,
SECURITY_LOGON_IDS_RID_COUNT,
@@ -494,7 +578,7 @@ LogonUserExW(
if (!NT_SUCCESS(Status))
goto done;
- /* Create the Local SID*/
+ /* Create the Local SID */
Status = RtlAllocateAndInitializeSid(&LocalAuthority,
1,
SECURITY_LOCAL_RID,