ReactOS 0.4.15-dev-7788-g1ad9096
logon.c File Reference
#include <advapi32.h>
Include dependency graph for logon.c:

Go to the source code of this file.

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (advapi)
 
 C_ASSERT (sizeof(AdvapiTokenSourceName)==RTL_FIELD_SIZE(TOKEN_SOURCE, SourceName)+1)
 
static NTSTATUS OpenLogonLsaHandle (VOID)
 
NTSTATUS CloseLogonLsaHandle (VOID)
 
static BOOL CreateDefaultProcessSecurityCommon (_In_ HANDLE TokenHandle, _Out_ PSECURITY_DESCRIPTOR *Sd)
 Creates a default security descriptor that is going to be used by both the newly created process and thread by a call to CreateProcessAsUserA/W. This descriptor also serves for the newly duplicated token object that is going to be set for the token which acts as the main user.
 
static BOOL InsertProcessSecurityCommon (_In_ HANDLE ProcessHandle, _In_ HANDLE ThreadHandle, _In_ PSECURITY_DESCRIPTOR ProcessSecurity, _In_ PSECURITY_DESCRIPTOR ThreadSecurity)
 Changes the object security information of a process and thread that belongs to the process with new security data, basically by replacing the previous security descriptor with a new one.
 
static NTSTATUS InsertTokenToProcessCommon (_In_ BOOL ImpersonateAsSelf, _In_ HANDLE ProcessHandle, _In_ HANDLE ThreadHandle, _In_ HANDLE DuplicatedTokenHandle)
 Sets a primary token to the newly created process. The primary token that gets assigned to is a token whose security context is associated with the logged in user. For futher documentation information, see Remarks.
 
static BOOL CreateProcessAsUserCommon (_In_opt_ HANDLE hToken, _In_ DWORD dwCreationFlags, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _Inout_ LPPROCESS_INFORMATION lpProcessInformation)
 Internal function that serves as a helper for CreateProcessAsUserW/A routines on creating a process within the context of the logged in user.
 
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)
 
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)
 
BOOL WINAPI LogonUserA (_In_ LPSTR lpszUsername, _In_opt_ LPSTR lpszDomain, _In_opt_ LPSTR lpszPassword, _In_ DWORD dwLogonType, _In_ DWORD dwLogonProvider, _Out_opt_ PHANDLE phToken)
 
BOOL WINAPI LogonUserExA (_In_ LPSTR lpszUsername, _In_opt_ LPSTR lpszDomain, _In_opt_ LPSTR lpszPassword, _In_ DWORD dwLogonType, _In_ DWORD dwLogonProvider, _Out_opt_ PHANDLE phToken, _Out_opt_ PSID *ppLogonSid, _Out_opt_ PVOID *ppProfileBuffer, _Out_opt_ LPDWORD pdwProfileLength, _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
 
BOOL WINAPI LogonUserW (_In_ LPWSTR lpszUsername, _In_opt_ LPWSTR lpszDomain, _In_opt_ LPWSTR lpszPassword, _In_ DWORD dwLogonType, _In_ DWORD dwLogonProvider, _Out_opt_ PHANDLE phToken)
 
BOOL WINAPI LogonUserExW (_In_ LPWSTR lpszUsername, _In_opt_ LPWSTR lpszDomain, _In_opt_ LPWSTR lpszPassword, _In_ DWORD dwLogonType, _In_ DWORD dwLogonProvider, _Out_opt_ PHANDLE phToken, _Out_opt_ PSID *ppLogonSid, _Out_opt_ PVOID *ppProfileBuffer, _Out_opt_ LPDWORD pdwProfileLength, _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
 

Variables

static const CHAR AdvapiTokenSourceName [] = "Advapi "
 
HANDLE LsaHandle = NULL
 
ULONG AuthenticationPackage = 0
 

Function Documentation

◆ C_ASSERT()

◆ CloseLogonLsaHandle()

NTSTATUS CloseLogonLsaHandle ( VOID  )

Definition at line 75 of file logon.c.

76{
78
79 if (LsaHandle != NULL)
80 {
82 if (!NT_SUCCESS(Status))
83 {
84 TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
85 }
86 }
87
88 return Status;
89}
LONG NTSTATUS
Definition: precomp.h:26
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
HANDLE LsaHandle
Definition: logon.c:17
Status
Definition: gdiplustypes.h:25
NTSTATUS NTAPI LsaDeregisterLogonProcess(HANDLE)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4

Referenced by DllMain().

◆ CreateDefaultProcessSecurityCommon()

static BOOL CreateDefaultProcessSecurityCommon ( _In_ HANDLE  TokenHandle,
_Out_ PSECURITY_DESCRIPTOR Sd 
)
static

Creates a default security descriptor that is going to be used by both the newly created process and thread by a call to CreateProcessAsUserA/W. This descriptor also serves for the newly duplicated token object that is going to be set for the token which acts as the main user.

Parameters
[in]TokenHandleA handle to a token. The function will use this token to query security details such as the owner and primary group associated with the security context of this token. The obtained information will then be assigned to the security descriptor.
[out]SdA pointer to an allocated security descriptor that is given to the caller.
Returns
Return TRUE if the security descriptor has been successfully created, FALSE otherwise.
Remarks
When a process is created on behald of the user's security context this user will be the owner and responsible for that process. Whatever objects created or stuff done within the process space is at the discretion of the user, that is, further objects created are in charge by the user himself as is the owner of the process.

!!!NOTE!!! – On Windows the security descriptor is created by using CreatePrivateObjectSecurity(Ex) API call. Whilst the way the security descriptor is created in our end is not wrong per se, this function serves a placeholder until CreatePrivateObjectSecurity is implemented.

Definition at line 129 of file logon.c.

132{
135 PACL Dacl;
136 PTOKEN_OWNER OwnerOfToken;
137 PTOKEN_PRIMARY_GROUP PrimaryGroupOfToken;
138 SECURITY_DESCRIPTOR AbsoluteSd;
139 ULONG DaclSize, TokenOwnerSize, PrimaryGroupSize, RelativeSDSize = 0;
140 PSID OwnerSid = NULL, SystemSid = NULL, PrimaryGroupSid = NULL;
141 PSECURITY_DESCRIPTOR RelativeSD = NULL;
143
144 /*
145 * Since we do not know how much space
146 * is needed to allocate the buffer to
147 * hold the token owner, first we must
148 * query the exact size.
149 */
152 NULL,
153 0,
154 &TokenOwnerSize);
156 {
157 ERR("CreateDefaultProcessSecurityCommon(): Unexpected status code returned, must be STATUS_BUFFER_TOO_SMALL (Status 0x%08lx)\n", Status);
158 return FALSE;
159 }
160
161 /* We have the required space size, allocate the buffer now */
162 OwnerOfToken = RtlAllocateHeap(RtlGetProcessHeap(),
164 TokenOwnerSize);
165 if (OwnerOfToken == NULL)
166 {
167 ERR("CreateDefaultProcessSecurityCommon(): Failed to allocate buffer for token owner!\n");
168 return FALSE;
169 }
170
171 /* Now query the token owner */
174 OwnerOfToken,
175 TokenOwnerSize,
176 &TokenOwnerSize);
177 if (!NT_SUCCESS(Status))
178 {
179 ERR("CreateDefaultProcessSecurityCommon(): Failed to query the token owner (Status 0x%08lx)\n", Status);
180 Success = FALSE;
181 goto Quit;
182 }
183
184 /* Do the same process but for the primary group now */
187 NULL,
188 0,
191 {
192 ERR("CreateDefaultProcessSecurityCommon(): Unexpected status code returned, must be STATUS_BUFFER_TOO_SMALL (Status 0x%08lx)\n", Status);
193 Success = FALSE;
194 goto Quit;
195 }
196
197 /* Allocate the buffer */
198 PrimaryGroupOfToken = RtlAllocateHeap(RtlGetProcessHeap(),
201 if (PrimaryGroupOfToken == NULL)
202 {
203 ERR("CreateDefaultProcessSecurityCommon(): Failed to allocate buffer for primary group token!\n");
204 Success = FALSE;
205 goto Quit;
206 }
207
208 /* Query the primary group now */
211 PrimaryGroupOfToken,
214 if (!NT_SUCCESS(Status))
215 {
216 ERR("CreateDefaultProcessSecurityCommon(): Failed to query the token owner (Status 0x%08lx)\n", Status);
217 Success = FALSE;
218 goto Quit;
219 }
220
221 /* Create the SYSTEM SID */
223 1,
225 0, 0, 0, 0, 0, 0, 0,
226 &SystemSid))
227 {
228 ERR("CreateDefaultProcessSecurityCommon(): Failed to create Local System SID (error code %d)\n", GetLastError());
229 Success = FALSE;
230 goto Quit;
231 }
232
233 /* Cache the token owner and primary group SID */
234 OwnerSid = OwnerOfToken->Owner;
235 PrimaryGroupSid = PrimaryGroupOfToken->PrimaryGroup;
236
237 /* Set up the DACL size */
238 DaclSize = sizeof(ACL) +
239 sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(OwnerSid) +
240 sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(SystemSid);
241
242 /* Allocate buffer for the DACL */
243 Dacl = RtlAllocateHeap(RtlGetProcessHeap(),
245 DaclSize);
246 if (Dacl == NULL)
247 {
248 ERR("CreateDefaultProcessSecurityCommon(): Failed to allocate buffer for DACL!\n");
249 Success = FALSE;
250 goto Quit;
251 }
252
253 /* Initialize the DACL */
255 {
256 ERR("CreateDefaultProcessSecurityCommon(): Failed to initialize DACL (error code %d)\n", GetLastError());
257 Success = FALSE;
258 goto Quit;
259 }
260
261 /* Give full powers to the owner */
265 OwnerSid))
266 {
267 ERR("CreateDefaultProcessSecurityCommon(): Failed to set up ACE for owner (error code %d)\n", GetLastError());
268 Success = FALSE;
269 goto Quit;
270 }
271
272 /* Give full powers to SYSTEM as well */
276 SystemSid))
277 {
278 ERR("CreateDefaultProcessSecurityCommon(): Failed to set up ACE for SYSTEM (error code %d)\n", GetLastError());
279 Success = FALSE;
280 goto Quit;
281 }
282
283 /* Initialize the descriptor in absolute format */
285 {
286 ERR("CreateDefaultProcessSecurityCommon(): Failed to initialize absolute security descriptor (error code %d)\n", GetLastError());
287 Success = FALSE;
288 goto Quit;
289 }
290
291 /* Set the DACL to the security descriptor */
292 if (!SetSecurityDescriptorDacl(&AbsoluteSd, TRUE, Dacl, FALSE))
293 {
294 ERR("CreateDefaultProcessSecurityCommon(): Failed to set up DACL to absolute security descriptor (error code %d)\n", GetLastError());
295 Success = FALSE;
296 goto Quit;
297 }
298
299 /* Set the owner for this descriptor */
300 if (!SetSecurityDescriptorOwner(&AbsoluteSd, OwnerSid, FALSE))
301 {
302 ERR("CreateDefaultProcessSecurityCommon(): Failed to set up owner to absolute security descriptor (error code %d)\n", GetLastError());
303 Success = FALSE;
304 goto Quit;
305 }
306
307 /* Set the primary group for this descriptor */
308 if (!SetSecurityDescriptorGroup(&AbsoluteSd, PrimaryGroupSid, FALSE))
309 {
310 ERR("CreateDefaultProcessSecurityCommon(): Failed to set up group to absolute security descriptor (error code %d)\n", GetLastError());
311 Success = FALSE;
312 goto Quit;
313 }
314
315 /*
316 * Determine the exact size space of the absolute
317 * descriptor so that we can allocate a buffer
318 * to hold the descriptor in a converted self
319 * relative format.
320 */
321 if (!MakeSelfRelativeSD(&AbsoluteSd, NULL, &RelativeSDSize) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
322 {
323 ERR("CreateDefaultProcessSecurityCommon(): Unexpected error code (error code %d -- must be ERROR_INSUFFICIENT_BUFFER)\n", GetLastError());
324 Success = FALSE;
325 goto Quit;
326 }
327
328 /* Allocate the buffer */
329 RelativeSD = RtlAllocateHeap(RtlGetProcessHeap(),
331 RelativeSDSize);
332 if (RelativeSD == NULL)
333 {
334 ERR("CreateDefaultProcessSecurityCommon(): Failed to allocate buffer for self relative descriptor!\n");
335 Success = FALSE;
336 goto Quit;
337 }
338
339 /* Convert to a self relative format now */
340 if (!MakeSelfRelativeSD(&AbsoluteSd, RelativeSD, &RelativeSDSize))
341 {
342 ERR("CreateDefaultProcessSecurityCommon(): Failed to allocate relative SD, buffer too smal (error code %d)\n", GetLastError());
343 Success = FALSE;
344 goto Quit;
345 }
346
347 /* Success, give the descriptor to the caller */
348 *Sd = RelativeSD;
349 Success = TRUE;
350
351Quit:
352 /* Free all the stuff we have allocated */
353 if (OwnerOfToken != NULL)
354 RtlFreeHeap(RtlGetProcessHeap(), 0, OwnerOfToken);
355
356 if (PrimaryGroupOfToken != NULL)
357 RtlFreeHeap(RtlGetProcessHeap(), 0, PrimaryGroupOfToken);
358
359 if (SystemSid != NULL)
360 FreeSid(SystemSid);
361
362 if (Dacl != NULL)
363 RtlFreeHeap(RtlGetProcessHeap(), 0, Dacl);
364
365 if (Success == FALSE)
366 {
367 if (RelativeSD != NULL)
368 {
369 RtlFreeHeap(RtlGetProcessHeap(), 0, RelativeSD);
370 }
371 }
372
373 return Success;
374}
static SID_IDENTIFIER_AUTHORITY NtAuthority
Definition: security.c:40
#define ERR(fmt,...)
Definition: debug.h:110
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount, DWORD nSubAuthority0, DWORD nSubAuthority1, DWORD nSubAuthority2, DWORD nSubAuthority3, DWORD nSubAuthority4, DWORD nSubAuthority5, DWORD nSubAuthority6, DWORD nSubAuthority7, PSID *pSid)
Definition: security.c:674
BOOL WINAPI InitializeAcl(PACL pAcl, DWORD nAclLength, DWORD dwAclRevision)
Definition: security.c:1006
BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision)
Definition: security.c:929
BOOL WINAPI AddAccessAllowedAce(PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid)
Definition: security.c:1039
DWORD WINAPI GetLengthSid(PSID pSid)
Definition: security.c:919
PVOID WINAPI FreeSid(PSID pSid)
Definition: security.c:698
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
@ Success
Definition: eventcreate.c:712
unsigned int BOOL
Definition: ntddk_ex.h:94
struct _ACL ACL
struct _ACCESS_ALLOWED_ACE ACCESS_ALLOWED_ACE
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:726
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL Dacl
Definition: rtlfuncs.h:1593
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ SaclSize PACL _Inout_ PULONG _Out_writes_bytes_to_opt_ OwnerSize PSID _Inout_ PULONG _Out_writes_bytes_to_opt_ PrimaryGroupSize PSID _Inout_ PULONG PrimaryGroupSize
Definition: rtlfuncs.h:1601
_Out_writes_bytes_to_opt_ AbsoluteSecurityDescriptorSize PSECURITY_DESCRIPTOR _Inout_ PULONG _Out_writes_bytes_to_opt_ DaclSize PACL _Inout_ PULONG DaclSize
Definition: rtlfuncs.h:1594
#define GENERIC_ALL
Definition: nt_native.h:92
BOOL WINAPI SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted)
Definition: sec.c:262
BOOL WINAPI SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, BOOL bOwnerDefaulted)
Definition: sec.c:312
BOOL WINAPI MakeSelfRelativeSD(PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, LPDWORD lpdwBufferLength)
Definition: sec.c:214
BOOL WINAPI SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pGroup, BOOL bGroupDefaulted)
Definition: sec.c:288
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
PSID Owner
Definition: setypes.h:1028
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtQueryInformationToken(_In_ HANDLE TokenHandle, _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, _Out_writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) PVOID TokenInformation, _In_ ULONG TokenInformationLength, _Out_ PULONG ReturnLength)
Queries a specific type of information in regard of an access token based upon the information class....
Definition: tokencls.c:473
uint32_t ULONG
Definition: typedefs.h:59
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define SECURITY_LOCAL_SYSTEM_RID
Definition: setypes.h:574
#define SECURITY_NT_AUTHORITY
Definition: setypes.h:554
@ TokenPrimaryGroup
Definition: setypes.h:970
@ TokenOwner
Definition: setypes.h:969
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
#define ACL_REVISION
Definition: setypes.h:39

Referenced by CreateProcessAsUserCommon().

◆ CreateProcessAsUserA()

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 
)

Definition at line 945 of file logon.c.

957{
958 TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_a(lpApplicationName),
959 debugstr_a(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
960 dwCreationFlags, lpEnvironment, debugstr_a(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
961
962 /* Create the process with a suspended main thread */
963 if (!CreateProcessA(lpApplicationName,
964 lpCommandLine,
965 lpProcessAttributes,
966 lpThreadAttributes,
967 bInheritHandles,
968 dwCreationFlags | CREATE_SUSPENDED,
969 lpEnvironment,
970 lpCurrentDirectory,
971 lpStartupInfo,
972 lpProcessInformation))
973 {
974 ERR("CreateProcessA failed, last error: %d\n", GetLastError());
975 return FALSE;
976 }
977
978 /* Call the helper function */
979 return CreateProcessAsUserCommon(hToken,
980 dwCreationFlags,
981 lpProcessAttributes,
982 lpThreadAttributes,
983 lpProcessInformation);
984}
static BOOL CreateProcessAsUserCommon(_In_opt_ HANDLE hToken, _In_ DWORD dwCreationFlags, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _Inout_ LPPROCESS_INFORMATION lpProcessInformation)
Internal function that serves as a helper for CreateProcessAsUserW/A routines on creating a process w...
Definition: logon.c:645
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4741
#define debugstr_a
Definition: kernel32.h:31
#define CREATE_SUSPENDED
Definition: winbase.h:178

Referenced by test_token_security_descriptor().

◆ CreateProcessAsUserCommon()

static BOOL CreateProcessAsUserCommon ( _In_opt_ HANDLE  hToken,
_In_ DWORD  dwCreationFlags,
_In_opt_ LPSECURITY_ATTRIBUTES  lpProcessAttributes,
_In_opt_ LPSECURITY_ATTRIBUTES  lpThreadAttributes,
_Inout_ LPPROCESS_INFORMATION  lpProcessInformation 
)
static

Internal function that serves as a helper for CreateProcessAsUserW/A routines on creating a process within the context of the logged in user.

Parameters
[in]hTokenA handle to an access token that is associated with the logged in user. If the caller does not submit a token, the helper will immediately quit and return success, and the newly created process will be created upon using the default security context.
[in]dwCreationFlagsBit masks containing the creation process flags. The function uses this parameter to determine if the process wasn't created in a suspended way and if not the function will resume the main thread.
[in]lpProcessAttributesA pointer to process attributes. This function uses this parameter to gather the security descriptor, if ever present. If it is, this descriptor takes precedence over the default one when setting new security information to the process.
[in]lpThreadAttributesA pointer to thread attributes. This function uses this parameter to gather the security descriptor, if ever present. If it is, this descriptor takes precedence over the default one when setting new security information to the thread.
[in,out]lpProcessInformationA pointer to a structure that contains process creation information data. Such pointer contains the process and thread handles and whatnot.
Returns
Returns TRUE if the helper has successfully assigned the newly created process the user's security context to that process, otherwise FALSE is returned.
Remarks
In order for the helper function to assign the primary token to the process, it has to do a "rinse and repeat" approach. That is, the helper will stop the impersonation and attempt to assign the token to process by acting on behalf of the main process' security context. If that fails, the function will do a second attempt by doing this but with impersonation enabled instead.

Definition at line 645 of file logon.c.

651{
652 NTSTATUS Status = STATUS_SUCCESS, StatusOnExit;
657 PSECURITY_DESCRIPTOR DefaultSd = NULL, ProcessSd, ThreadSd;
658 HANDLE hTokenDup = NULL;
659 HANDLE OriginalImpersonationToken = NULL;
660 HANDLE NullToken = NULL;
661
662 if (hToken != NULL)
663 {
664 /* Check whether the user-provided token is a primary token */
665 // GetTokenInformation();
667 TokenType,
668 &Type,
669 sizeof(Type),
670 &ReturnLength);
671 if (!NT_SUCCESS(Status))
672 {
673 ERR("NtQueryInformationToken() failed, Status 0x%08x\n", Status);
674 Success = FALSE;
675 goto Quit;
676 }
677
678 if (Type != TokenPrimary)
679 {
680 ERR("Wrong token type for token 0x%p, expected TokenPrimary, got %ld\n", hToken, Type);
682 Success = FALSE;
683 goto Quit;
684 }
685
686 /*
687 * Open the original token of the calling thread
688 * and halt the impersonation for the moment
689 * being. The opened thread token will be cached
690 * so that we will restore it back when we're done.
691 */
694 TRUE,
695 &OriginalImpersonationToken);
696 if (!NT_SUCCESS(Status))
697 {
698 /* We failed? Does this thread have a token at least? */
699 OriginalImpersonationToken = NULL;
700 if (Status != STATUS_NO_TOKEN)
701 {
702 /*
703 * OK so this thread has a token but we
704 * could not open it for whatever reason.
705 * Bail out then.
706 */
707 ERR("Failed to open thread token with 0x%08lx\n", Status);
708 Success = FALSE;
709 goto Quit;
710 }
711 }
712 else
713 {
714 /* We succeeded, stop the impersonation for now */
717 &NullToken,
718 sizeof(NullToken));
719 if (!NT_SUCCESS(Status))
720 {
721 ERR("Failed to stop impersonation with 0x%08lx\n", Status);
722 Success = FALSE;
723 goto Quit;
724 }
725 }
726
727 /*
728 * Create a security descriptor that will be common for the
729 * newly created process on behalf of the context user.
730 */
731 if (!CreateDefaultProcessSecurityCommon(hToken, &DefaultSd))
732 {
733 ERR("Failed to create common security descriptor for the token for new process!\n");
734 Success = FALSE;
735 goto Quit;
736 }
737
738 /*
739 * Duplicate the token for this new process. This token
740 * object will get a default security descriptor that we
741 * have created ourselves in ADVAPI32.
742 */
744 NULL,
745 0,
746 NULL,
747 DefaultSd);
748 Status = NtDuplicateToken(hToken,
749 0,
751 FALSE,
753 &hTokenDup);
754 if (!NT_SUCCESS(Status))
755 {
756 ERR("NtDuplicateToken() failed, Status 0x%08x\n", Status);
757 Success = FALSE;
758 goto Quit;
759 }
760
761 /*
762 * Now it's time to set the primary token into
763 * the process. On the first try, do it by
764 * impersonating the security context of the
765 * calling process (impersonate as self).
766 */
768 lpProcessInformation->hProcess,
769 lpProcessInformation->hThread,
770 hTokenDup);
771 if (!NT_SUCCESS(Status))
772 {
773 /*
774 * OK, we failed. Our second (and last try) is to not
775 * impersonate as self but instead we will try by setting
776 * the original impersonation (thread) token and set the
777 * primary token to the process through this way. This is
778 * what we call -- the "rinse and repeat" approach.
779 */
782 &OriginalImpersonationToken,
783 sizeof(OriginalImpersonationToken));
784 if (!NT_SUCCESS(Status))
785 {
786 ERR("Failed to restore impersonation token for setting process token, Status 0x%08lx\n", Status);
787 NtClose(hTokenDup);
788 Success = FALSE;
789 goto Quit;
790 }
791
792 /* Retry again */
794 lpProcessInformation->hProcess,
795 lpProcessInformation->hThread,
796 hTokenDup);
797 if (!NT_SUCCESS(Status))
798 {
799 /* Even the second try failed, bail out... */
800 ERR("Failed to insert the primary token into process, Status 0x%08lx\n", Status);
801 NtClose(hTokenDup);
802 Success = FALSE;
803 goto Quit;
804 }
805
806 /* All good, now stop impersonation */
809 &NullToken,
810 sizeof(NullToken));
811 if (!NT_SUCCESS(Status))
812 {
813 ERR("Failed to unset impersonationg token after setting process token, Status 0x%08lx\n", Status);
814 NtClose(hTokenDup);
815 Success = FALSE;
816 goto Quit;
817 }
818 }
819
820 /*
821 * FIXME: As we have successfully set up a primary token to
822 * the newly created process, we must set up as well a definite
823 * limit of quota charges for this process on the context of
824 * this user.
825 */
826
827 /*
828 * As we have successfully set the token into the process now
829 * it is time that we set up new security information for both
830 * the process and its thread as well, that is, these securable
831 * objects will grant a security descriptor. The security descriptors
832 * provided by the caller take precedence so we should use theirs
833 * if possible in this case. Otherwise both the process and thread
834 * will receive the default security descriptor that we have created
835 * ourselves.
836 *
837 * BEAR IN MIND!!! AT THE MOMENT when these securable objects get new
838 * security information, the process (and the thread) can't be opened
839 * by the creator anymore as the new owner will take in charge of
840 * the process and future objects that are going to be created within
841 * the process. For further information in regard of the documentation
842 * see https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasuserw.
843 */
844 if (lpProcessAttributes && lpProcessAttributes->lpSecurityDescriptor)
845 {
846 ProcessSd = lpProcessAttributes->lpSecurityDescriptor;
847 }
848 else
849 {
850 ProcessSd = DefaultSd;
851 }
852
853 if (lpThreadAttributes && lpThreadAttributes->lpSecurityDescriptor)
854 {
855 ThreadSd = lpThreadAttributes->lpSecurityDescriptor;
856 }
857 else
858 {
859 ThreadSd = DefaultSd;
860 }
861
862 /* Set new security info to the process and thread now */
863 if (!InsertProcessSecurityCommon(lpProcessInformation->hProcess,
864 lpProcessInformation->hThread,
865 ProcessSd,
866 ThreadSd))
867 {
868 ERR("Failed to set new security information for process and thread!\n");
869 NtClose(hTokenDup);
870 Success = FALSE;
871 goto Quit;
872 }
873
874 /* Close the duplicated token */
875 NtClose(hTokenDup);
876 Success = TRUE;
877 }
878
879 /*
880 * If the caller did not supply a token then just declare
881 * ourselves as job done. The newly created process will use
882 * the default security context at this point anyway.
883 */
884 TRACE("No token supplied, the process will use default security context!\n");
885 Success = TRUE;
886
887Quit:
888 /*
889 * If we successfully opened the thread token before
890 * and stopped the impersonation then we have to assign
891 * its original token back and close that token we have
892 * referenced it.
893 */
894 if (OriginalImpersonationToken != NULL)
895 {
898 &OriginalImpersonationToken,
899 sizeof(OriginalImpersonationToken));
900
901 /*
902 * We really must assert ourselves that we successfully
903 * set the original token back, otherwise if we fail
904 * then something is seriously going wrong....
905 * The status code is cached in a separate status
906 * variable because we would not want to tamper
907 * with the original status code that could have been
908 * returned by someone else above in this function code.
909 */
910 ASSERT(NT_SUCCESS(StatusOnExit));
911
912 /* De-reference it */
913 NtClose(OriginalImpersonationToken);
914 }
915
916 /* Terminate the process and set the last error status */
917 if (!NT_SUCCESS(Status))
918 {
919 TerminateProcess(lpProcessInformation->hProcess, Status);
921 }
922
923 /* Resume the main thread */
924 if (!(dwCreationFlags & CREATE_SUSPENDED))
925 {
926 ResumeThread(lpProcessInformation->hThread);
927 }
928
929 /* Free the security descriptor from memory */
930 if (DefaultSd != NULL)
931 {
932 RtlFreeHeap(RtlGetProcessHeap(), 0, DefaultSd);
933 }
934
935 return Success;
936}
Type
Definition: Type.h:7
TOKEN_TYPE
Definition: asmpp.cpp:29
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
static NTSTATUS InsertTokenToProcessCommon(_In_ BOOL ImpersonateAsSelf, _In_ HANDLE ProcessHandle, _In_ HANDLE ThreadHandle, _In_ HANDLE DuplicatedTokenHandle)
Sets a primary token to the newly created process. The primary token that gets assigned to is a token...
Definition: logon.c:482
static BOOL CreateDefaultProcessSecurityCommon(_In_ HANDLE TokenHandle, _Out_ PSECURITY_DESCRIPTOR *Sd)
Creates a default security descriptor that is going to be used by both the newly created process and ...
Definition: logon.c:129
static BOOL InsertProcessSecurityCommon(_In_ HANDLE ProcessHandle, _In_ HANDLE ThreadHandle, _In_ PSECURITY_DESCRIPTOR ProcessSecurity, _In_ PSECURITY_DESCRIPTOR ThreadSecurity)
Changes the object security information of a process and thread that belongs to the process with new ...
Definition: logon.c:404
#define SetLastError(x)
Definition: compat.h:752
@ ThreadImpersonationToken
Definition: compat.h:940
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
DWORD WINAPI ResumeThread(IN HANDLE hThread)
Definition: thread.c:567
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:43
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define ASSERT(a)
Definition: mode.c:44
@ TokenPrimary
Definition: imports.h:273
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:411
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, IN PVOID ThreadInformation, IN ULONG ThreadInformationLength)
Definition: query.c:2018
NTSTATUS NTAPI NtOpenThreadToken(_In_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN OpenAsSelf, _Out_ PHANDLE TokenHandle)
Opens a token that is tied to a thread handle.
Definition: token.c:2474
#define STATUS_NO_TOKEN
Definition: ntstatus.h:360
#define STATUS_BAD_TOKEN_TYPE
Definition: ntstatus.h:404
_Must_inspect_result_ __kernel_entry NTSTATUS NTAPI NtDuplicateToken(_In_ HANDLE ExistingTokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, _In_ TOKEN_TYPE TokenType, _Out_ PHANDLE NewTokenHandle)
Duplicates a token.
Definition: tokenlif.c:1869
#define TOKEN_QUERY
Definition: setypes.h:928
#define TOKEN_IMPERSONATE
Definition: setypes.h:927
#define NtCurrentThread()

Referenced by CreateProcessAsUserA(), and CreateProcessAsUserW().

◆ CreateProcessAsUserW()

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 
)

Definition at line 993 of file logon.c.

1005{
1006 TRACE("%p %s %s %p %p %d 0x%08x %p %s %p %p\n", hToken, debugstr_w(lpApplicationName),
1007 debugstr_w(lpCommandLine), lpProcessAttributes, lpThreadAttributes, bInheritHandles,
1008 dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory), lpStartupInfo, lpProcessInformation);
1009
1010 /* Create the process with a suspended main thread */
1011 if (!CreateProcessW(lpApplicationName,
1012 lpCommandLine,
1013 lpProcessAttributes,
1014 lpThreadAttributes,
1015 bInheritHandles,
1016 dwCreationFlags | CREATE_SUSPENDED,
1017 lpEnvironment,
1018 lpCurrentDirectory,
1019 lpStartupInfo,
1020 lpProcessInformation))
1021 {
1022 ERR("CreateProcessW failed, last error: %d\n", GetLastError());
1023 return FALSE;
1024 }
1025
1026 /* Call the helper function */
1027 return CreateProcessAsUserCommon(hToken,
1028 dwCreationFlags,
1029 lpProcessAttributes,
1030 lpThreadAttributes,
1031 lpProcessInformation);
1032}
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4592
#define debugstr_w
Definition: kernel32.h:32

Referenced by custom_start_server(), InstallDevice(), LaunchProcess(), ScmStartUserModeService(), SeclCreateProcessWithLogonW(), StartScreenSaver(), and WlxStartApplication().

◆ InsertProcessSecurityCommon()

static BOOL InsertProcessSecurityCommon ( _In_ HANDLE  ProcessHandle,
_In_ HANDLE  ThreadHandle,
_In_ PSECURITY_DESCRIPTOR  ProcessSecurity,
_In_ PSECURITY_DESCRIPTOR  ThreadSecurity 
)
static

Changes the object security information of a process and thread that belongs to the process with new security data, basically by replacing the previous security descriptor with a new one.

Parameters
[in]ProcessHandleA handle to a valid process of which security information is to be changed by setting up a new security descriptor.
[in]ThreadHandleA handle to a valid thread of which security information is to be changed by setting up a new security descriptor.
[in]ProcessSecurityA pointer to a security descriptor that is for the process.
[in]ThreadSecurityA pointer to a security descriptor that is for the thread.
Returns
Return TRUE if new security information has been set, FALSE otherwise.

Definition at line 404 of file logon.c.

409{
410 /* Set new security data for the process */
413 ProcessSecurity))
414 {
415 ERR("InsertProcessSecurityCommon(): Failed to set security for process (error code %d)\n", GetLastError());
416 return FALSE;
417 }
418
419 /* Set new security data for the thread */
420 if (!SetKernelObjectSecurity(ThreadHandle,
422 ThreadSecurity))
423 {
424 ERR("InsertProcessSecurityCommon(): Failed to set security for thread (error code %d)\n", GetLastError());
425 return FALSE;
426 }
427
428 return TRUE;
429}
BOOL WINAPI SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor)
Definition: security.c:1928
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
#define DACL_SECURITY_INFORMATION
Definition: setypes.h:125
#define OWNER_SECURITY_INFORMATION
Definition: setypes.h:123
#define GROUP_SECURITY_INFORMATION
Definition: setypes.h:124

Referenced by CreateProcessAsUserCommon().

◆ InsertTokenToProcessCommon()

static NTSTATUS InsertTokenToProcessCommon ( _In_ BOOL  ImpersonateAsSelf,
_In_ HANDLE  ProcessHandle,
_In_ HANDLE  ThreadHandle,
_In_ HANDLE  DuplicatedTokenHandle 
)
static

Sets a primary token to the newly created process. The primary token that gets assigned to is a token whose security context is associated with the logged in user. For futher documentation information, see Remarks.

Parameters
[in]ImpersonateAsSelfIf set to TRUE, the function will act on behalf of the calling process by impersonating its security context. Generally the caller will disable impersonation and attempt to act on behalf of the said main process as a first tentative to acquire the needed privilege in order to assign a token to the process. If set to FALSE, the function won't act on behalf of the calling process.
[in]ProcessHandleA handle to the newly created process. The function will use it as a mean to assign the primary token to this process.
[in]ThreadHandleA handle to the newly and primary created thread associated with the process.
[in]DuplicatedTokenHandleA handle to a duplicated access token. This token represents as a primary one, initially duplicated in form as a primary type from an impersonation type.
Returns
STATUS_SUCCESS is returned if token assignment to process succeeded, otherwise a failure NTSTATUS code is returned. A potential failure status code is STATUS_ACCESS_DENIED which means the caller doesn't have enough rights to grant access for primary token assignment to process.
Remarks
This function acts like an internal helper for CreateProcessAsUserCommon (and as such for CreateProcessAsUserW/A as well) as once a process is created, the function is tasked to assign the security context of the logged in user to that process. However, the rate of success of inserting the token into the process ultimately depends on the caller.

The caller will either succeed or fail at acquiring SE_ASSIGNPRIMARYTOKEN_PRIVILEGE privilege depending on the security context of the user. If it's allowed, the caller would generally acquire such privilege immediately but if not, the caller will attempt to do a second try.

Definition at line 482 of file logon.c.

487{
489 PROCESS_ACCESS_TOKEN AccessToken;
490 BOOLEAN PrivilegeSet;
491 BOOLEAN HavePrivilege;
492
493 /*
494 * Assume the SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
495 * privilege hasn't been set.
496 */
497 PrivilegeSet = FALSE;
498
499 /*
500 * The caller asked that we must impersonate as
501 * ourselves, that is, we'll be going to impersonate
502 * the security context of the calling process. If
503 * self impersonation fails then the caller has
504 * to do a "rinse and repeat" approach.
505 */
506 if (ImpersonateAsSelf)
507 {
509 if (!NT_SUCCESS(Status))
510 {
511 ERR("RtlImpersonateSelf(SecurityImpersonation) failed, Status 0x%08x\n", Status);
512 return Status;
513 }
514 }
515
516 /*
517 * Attempt to acquire the process primary token assignment privilege
518 * in case we actually need it.
519 * The call will either succeed or fail when the caller has (or has not)
520 * enough rights.
521 * The last situation may not be dramatic for us. Indeed it may happen
522 * that the user-provided token is a restricted version of the caller's
523 * primary token (aka. a "child" token), or both tokens inherit (i.e. are
524 * children, and are together "siblings") from a common parent token.
525 * In this case the NT kernel allows us to assign the token to the child
526 * process without the need for the assignment privilege, which is fine.
527 * On the contrary, if the user-provided token is completely arbitrary,
528 * then the NT kernel will enforce the presence of the assignment privilege:
529 * because we failed (by assumption) to assign the privilege, the process
530 * token assignment will fail as required. It is then the job of the
531 * caller to manually acquire the necessary privileges.
532 */
534 TRUE, TRUE, &PrivilegeSet);
535 HavePrivilege = NT_SUCCESS(Status);
536 if (!HavePrivilege)
537 {
538 ERR("RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE) failed, Status 0x%08lx, "
539 "attempting to continue without it...\n", Status);
540 }
541
542 /*
543 * Assign the duplicated token and thread
544 * handle to the structure so that we'll
545 * use it to assign the primary token
546 * to process.
547 */
548 AccessToken.Token = DuplicatedTokenHandle;
549 AccessToken.Thread = ThreadHandle;
550
551 /* Set the new process token */
554 (PVOID)&AccessToken,
555 sizeof(AccessToken));
556
557 /* Restore the privilege */
558 if (HavePrivilege)
559 {
561 PrivilegeSet, TRUE, &PrivilegeSet);
562 }
563
564 /*
565 * Check again if the caller wanted to impersonate
566 * as self. If that is the case we must revert this
567 * impersonation back.
568 */
569 if (ImpersonateAsSelf)
570 {
571 RevertToSelf();
572 }
573
574 /*
575 * Finally, check if we actually succeeded on assigning
576 * a primary token to the process. If we failed, oh well,
577 * asta la vista baby e arrivederci. The caller has to do
578 * a rinse and repeat approach.
579 */
580 if (!NT_SUCCESS(Status))
581 {
582 ERR("Failed to assign primary token to the process (Status 0x%08lx)\n", Status);
583 return Status;
584 }
585
586 return STATUS_SUCCESS;
587}
unsigned char BOOLEAN
@ ProcessAccessToken
Definition: winternl.h:865
@ SecurityImpersonation
Definition: lsa.idl:57
#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
Definition: security.c:657
NTSYSAPI NTSTATUS NTAPI RtlImpersonateSelf(IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
Definition: priv.c:45
NTSYSAPI NTSTATUS NTAPI RtlAdjustPrivilege(_In_ ULONG Privilege, _In_ BOOLEAN NewValue, _In_ BOOLEAN ForThread, _Out_ PBOOLEAN OldValue)
NTSTATUS NTAPI NtSetInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, IN PVOID ProcessInformation, IN ULONG ProcessInformationLength)
Definition: query.c:1105
BOOL WINAPI RevertToSelf(void)
Definition: security.c:1608

Referenced by CreateProcessAsUserCommon().

◆ LogonUserA()

BOOL WINAPI LogonUserA ( _In_ LPSTR  lpszUsername,
_In_opt_ LPSTR  lpszDomain,
_In_opt_ LPSTR  lpszPassword,
_In_ DWORD  dwLogonType,
_In_ DWORD  dwLogonProvider,
_Out_opt_ PHANDLE  phToken 
)

Definition at line 1040 of file logon.c.

1047{
1048 return LogonUserExA(lpszUsername,
1049 lpszDomain,
1053 phToken,
1054 NULL,
1055 NULL,
1056 NULL,
1057 NULL);
1058}
BOOL WINAPI LogonUserExA(_In_ LPSTR lpszUsername, _In_opt_ LPSTR lpszDomain, _In_opt_ LPSTR lpszPassword, _In_ DWORD dwLogonType, _In_ DWORD dwLogonProvider, _Out_opt_ PHANDLE phToken, _Out_opt_ PSID *ppLogonSid, _Out_opt_ PVOID *ppProfileBuffer, _Out_opt_ LPDWORD pdwProfileLength, _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
Definition: logon.c:1066
_In_opt_ LPSTR _In_opt_ LPSTR _In_ DWORD dwLogonType
Definition: winbase.h:2713
_In_opt_ LPSTR _In_opt_ LPSTR _In_ DWORD _In_ DWORD _Out_opt_ PHANDLE phToken
Definition: winbase.h:2715
_In_opt_ LPSTR _In_opt_ LPSTR _In_ DWORD _In_ DWORD dwLogonProvider
Definition: winbase.h:2714
_In_opt_ LPSTR _In_opt_ LPSTR lpszPassword
Definition: winbase.h:2712
_In_opt_ LPSTR lpszDomain
Definition: winbase.h:2711

◆ LogonUserExA()

BOOL WINAPI LogonUserExA ( _In_ LPSTR  lpszUsername,
_In_opt_ LPSTR  lpszDomain,
_In_opt_ LPSTR  lpszPassword,
_In_ DWORD  dwLogonType,
_In_ DWORD  dwLogonProvider,
_Out_opt_ PHANDLE  phToken,
_Out_opt_ PSID ppLogonSid,
_Out_opt_ PVOID ppProfileBuffer,
_Out_opt_ LPDWORD  pdwProfileLength,
_Out_opt_ PQUOTA_LIMITS  pQuotaLimits 
)

Definition at line 1066 of file logon.c.

1077{
1078 UNICODE_STRING UserName;
1079 UNICODE_STRING Domain;
1081 BOOL ret = FALSE;
1082
1083 UserName.Buffer = NULL;
1084 Domain.Buffer = NULL;
1085 Password.Buffer = NULL;
1086
1087 if (!RtlCreateUnicodeStringFromAsciiz(&UserName, lpszUsername))
1088 {
1090 goto UsernameDone;
1091 }
1092
1094 {
1096 goto DomainDone;
1097 }
1098
1100 {
1102 goto PasswordDone;
1103 }
1104
1105 ret = LogonUserExW(UserName.Buffer,
1106 Domain.Buffer,
1107 Password.Buffer,
1110 phToken,
1111 ppLogonSid,
1114 pQuotaLimits);
1115
1116 if (Password.Buffer != NULL)
1118
1119PasswordDone:
1120 if (Domain.Buffer != NULL)
1121 RtlFreeUnicodeString(&Domain);
1122
1123DomainDone:
1124 if (UserName.Buffer != NULL)
1125 RtlFreeUnicodeString(&UserName);
1126
1127UsernameDone:
1128 return ret;
1129}
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
BOOL WINAPI LogonUserExW(_In_ LPWSTR lpszUsername, _In_opt_ LPWSTR lpszDomain, _In_opt_ LPWSTR lpszPassword, _In_ DWORD dwLogonType, _In_ DWORD dwLogonProvider, _Out_opt_ PHANDLE phToken, _Out_opt_ PSID *ppLogonSid, _Out_opt_ PVOID *ppProfileBuffer, _Out_opt_ LPDWORD pdwProfileLength, _Out_opt_ PQUOTA_LIMITS pQuotaLimits)
Definition: logon.c:1163
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
@ Password
Definition: telnetd.h:65
int ret
_In_opt_ LPSTR _In_opt_ LPSTR _In_ DWORD _In_ DWORD _Out_opt_ PHANDLE _Out_opt_ PSID _Out_opt_ PVOID * ppProfileBuffer
Definition: winbase.h:2717
_In_opt_ LPSTR _In_opt_ LPSTR _In_ DWORD _In_ DWORD _Out_opt_ PHANDLE _Out_opt_ PSID * ppLogonSid
Definition: winbase.h:2716
_In_opt_ LPSTR _In_opt_ LPSTR _In_ DWORD _In_ DWORD _Out_opt_ PHANDLE _Out_opt_ PSID _Out_opt_ PVOID _Out_opt_ LPDWORD pdwProfileLength
Definition: winbase.h:2718
_In_opt_ LPSTR _In_opt_ LPSTR _In_ DWORD _In_ DWORD _Out_opt_ PHANDLE _Out_opt_ PSID _Out_opt_ PVOID _Out_opt_ LPDWORD _Out_opt_ PQUOTA_LIMITS pQuotaLimits
Definition: winbase.h:2719

Referenced by LogonUserA().

◆ LogonUserExW()

BOOL WINAPI LogonUserExW ( _In_ LPWSTR  lpszUsername,
_In_opt_ LPWSTR  lpszDomain,
_In_opt_ LPWSTR  lpszPassword,
_In_ DWORD  dwLogonType,
_In_ DWORD  dwLogonProvider,
_Out_opt_ PHANDLE  phToken,
_Out_opt_ PSID ppLogonSid,
_Out_opt_ PVOID ppProfileBuffer,
_Out_opt_ LPDWORD  pdwProfileLength,
_Out_opt_ PQUOTA_LIMITS  pQuotaLimits 
)

Definition at line 1163 of file logon.c.

1174{
1177 PSID LogonSid = NULL;
1178 PSID LocalSid = NULL;
1180 UNICODE_STRING DomainName;
1181 UNICODE_STRING UserName;
1184 ULONG AuthInfoLength;
1185 ULONG_PTR Ptr;
1190 LUID Luid = {0, 0};
1191 LUID LogonId = {0, 0};
1193 QUOTA_LIMITS QuotaLimits;
1197
1198 if ((ppProfileBuffer != NULL && pdwProfileLength == NULL) ||
1200 {
1202 return FALSE;
1203 }
1204
1206 {
1208 *pdwProfileLength = 0;
1209 }
1210
1211 if (phToken != NULL)
1212 *phToken = NULL;
1213
1214 switch (dwLogonType)
1215 {
1218 break;
1219
1222 break;
1223
1225 LogonType = Batch;
1226 break;
1227
1230 break;
1231
1232 default:
1233 ERR("Invalid logon type: %ul\n", dwLogonType);
1235 goto done;
1236 }
1237
1238 if (LsaHandle == NULL)
1239 {
1241 if (!NT_SUCCESS(Status))
1242 goto done;
1243 }
1244
1246 "Advapi32 Logon");
1247
1248 RtlInitUnicodeString(&DomainName,
1249 lpszDomain);
1250
1251 RtlInitUnicodeString(&UserName,
1252 lpszUsername);
1253
1255 lpszPassword);
1256
1257 AuthInfoLength = sizeof(MSV1_0_INTERACTIVE_LOGON)+
1258 DomainName.MaximumLength +
1259 UserName.MaximumLength +
1260 Password.MaximumLength;
1261
1262 AuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1264 AuthInfoLength);
1265 if (AuthInfo == NULL)
1266 {
1268 goto done;
1269 }
1270
1272
1273 Ptr = (ULONG_PTR)AuthInfo + sizeof(MSV1_0_INTERACTIVE_LOGON);
1274
1275 AuthInfo->LogonDomainName.Length = DomainName.Length;
1276 AuthInfo->LogonDomainName.MaximumLength = DomainName.MaximumLength;
1277 AuthInfo->LogonDomainName.Buffer = (DomainName.Buffer == NULL) ? NULL : (PWCHAR)Ptr;
1278 if (DomainName.MaximumLength > 0)
1279 {
1281 DomainName.Buffer,
1282 DomainName.MaximumLength);
1283
1284 Ptr += DomainName.MaximumLength;
1285 }
1286
1287 AuthInfo->UserName.Length = UserName.Length;
1288 AuthInfo->UserName.MaximumLength = UserName.MaximumLength;
1289 AuthInfo->UserName.Buffer = (PWCHAR)Ptr;
1290 if (UserName.MaximumLength > 0)
1291 RtlCopyMemory(AuthInfo->UserName.Buffer,
1292 UserName.Buffer,
1293 UserName.MaximumLength);
1294
1295 Ptr += UserName.MaximumLength;
1296
1297 AuthInfo->Password.Length = Password.Length;
1298 AuthInfo->Password.MaximumLength = Password.MaximumLength;
1299 AuthInfo->Password.Buffer = (PWCHAR)Ptr;
1300 if (Password.MaximumLength > 0)
1301 RtlCopyMemory(AuthInfo->Password.Buffer,
1302 Password.Buffer,
1303 Password.MaximumLength);
1304
1305 /* Create the Logon SID */
1310 LogonId.HighPart,
1311 LogonId.LowPart,
1317 &LogonSid);
1318 if (!NT_SUCCESS(Status))
1319 goto done;
1320
1321 /* Create the Local SID */
1322 Status = RtlAllocateAndInitializeSid(&LocalAuthority,
1323 1,
1332 &LocalSid);
1333 if (!NT_SUCCESS(Status))
1334 goto done;
1335
1336 /* Allocate and set the token groups */
1337 TokenGroups = RtlAllocateHeap(RtlGetProcessHeap(),
1339 sizeof(TOKEN_GROUPS) + ((2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES)));
1340 if (TokenGroups == NULL)
1341 {
1343 goto done;
1344 }
1345
1346 TokenGroups->GroupCount = 2;
1347 TokenGroups->Groups[0].Sid = LogonSid;
1348 TokenGroups->Groups[0].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
1350 TokenGroups->Groups[1].Sid = LocalSid;
1351 TokenGroups->Groups[1].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
1353
1354 /* Set the token source */
1355 RtlCopyMemory(TokenSource.SourceName,
1357 sizeof(TokenSource.SourceName));
1358 AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);
1359
1361 &OriginName,
1362 LogonType,
1364 (PVOID)AuthInfo,
1365 AuthInfoLength,
1367 &TokenSource,
1370 &Luid,
1371 &TokenHandle,
1372 &QuotaLimits,
1373 &SubStatus);
1374 if (!NT_SUCCESS(Status))
1375 {
1376 ERR("LsaLogonUser failed (Status 0x%08lx)\n", Status);
1377 goto done;
1378 }
1379
1380 if (ProfileBuffer != NULL)
1381 {
1382 TRACE("ProfileBuffer: %p\n", ProfileBuffer);
1383 TRACE("MessageType: %u\n", ProfileBuffer->MessageType);
1384
1385 TRACE("FullName: %p\n", ProfileBuffer->FullName.Buffer);
1386 TRACE("FullName: %S\n", ProfileBuffer->FullName.Buffer);
1387
1388 TRACE("LogonServer: %p\n", ProfileBuffer->LogonServer.Buffer);
1389 TRACE("LogonServer: %S\n", ProfileBuffer->LogonServer.Buffer);
1390 }
1391
1392 TRACE("Luid: 0x%08lx%08lx\n", Luid.HighPart, Luid.LowPart);
1393
1394 if (TokenHandle != NULL)
1395 {
1396 TRACE("TokenHandle: %p\n", TokenHandle);
1397 }
1398
1399 if (phToken != NULL)
1401
1402 /* FIXME: return ppLogonSid and pQuotaLimits */
1403
1404done:
1405 if (ProfileBuffer != NULL)
1407
1408 if (!NT_SUCCESS(Status))
1409 {
1410 if (TokenHandle != NULL)
1412 }
1413
1414 if (TokenGroups != NULL)
1415 RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroups);
1416
1417 if (LocalSid != NULL)
1419
1420 if (LogonSid != NULL)
1421 RtlFreeSid(LogonSid);
1422
1423 if (AuthInfo != NULL)
1424 RtlFreeHeap(RtlGetProcessHeap(), 0, AuthInfo);
1425
1426 if (!NT_SUCCESS(Status))
1427 {
1429 return FALSE;
1430 }
1431
1432 return TRUE;
1433}
PSID LocalSid
Definition: globals.c:15
@ Network
static const CHAR AdvapiTokenSourceName[]
Definition: logon.c:14
static NTSTATUS OpenLogonLsaHandle(VOID)
Definition: logon.c:24
ULONG AuthenticationPackage
Definition: logon.c:18
BOOL WINAPI AllocateLocallyUniqueId(PLUID Luid)
Definition: security.c:1218
#define CloseHandle
Definition: compat.h:739
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ULONG_PTR
Definition: config.h:101
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
static SID_IDENTIFIER_AUTHORITY SystemAuthority
Definition: msgina.c:38
NTSYSAPI PVOID NTAPI RtlFreeSid(_In_ _Post_invalid_ PSID Sid)
#define SE_GROUP_LOGON_ID
Definition: setypes.h:98
#define SE_GROUP_MANDATORY
Definition: setypes.h:90
#define SE_GROUP_ENABLED_BY_DEFAULT
Definition: setypes.h:91
#define SE_GROUP_ENABLED
Definition: setypes.h:92
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE LogonType
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID _Out_ PHANDLE _Out_ PQUOTA_LIMITS _Out_ PNTSTATUS SubStatus
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID * ProfileBuffer
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG ProfileBufferLength
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID LogonId
_IRQL_requires_same_ _In_ PLSA_STRING OriginName
NTSYSAPI NTSTATUS NTAPI RtlAllocateAndInitializeSid(IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount, IN ULONG SubAuthority0, IN ULONG SubAuthority1, IN ULONG SubAuthority2, IN ULONG SubAuthority3, IN ULONG SubAuthority4, IN ULONG SubAuthority5, IN ULONG SubAuthority6, IN ULONG SubAuthority7, OUT PSID *Sid)
Definition: sid.c:290
NTSTATUS NTAPI LsaLogonUser(HANDLE, PLSA_STRING, SECURITY_LOGON_TYPE, ULONG, PVOID, ULONG, PTOKEN_GROUPS, PTOKEN_SOURCE, PVOID *, PULONG, PLUID, PHANDLE, PQUOTA_LIMITS, PNTSTATUS)
@ Interactive
Definition: ntsecapi.h:289
@ Service
Definition: ntsecapi.h:292
@ Batch
Definition: ntsecapi.h:291
enum _SECURITY_LOGON_TYPE SECURITY_LOGON_TYPE
NTSTATUS NTAPI LsaFreeReturnBuffer(PVOID)
struct _MSV1_0_INTERACTIVE_LOGON MSV1_0_INTERACTIVE_LOGON
@ MsV1_0InteractiveLogon
Definition: ntsecapi.h:199
PCHAR Buffer
Definition: ntsecapi.h:174
LONG HighPart
DWORD LowPart
UNICODE_STRING Password
Definition: ntsecapi.h:437
UNICODE_STRING UserName
Definition: ntsecapi.h:436
MSV1_0_LOGON_SUBMIT_TYPE MessageType
Definition: ntsecapi.h:434
UNICODE_STRING LogonDomainName
Definition: ntsecapi.h:435
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define ANYSIZE_ARRAY
Definition: typedefs.h:46
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint16_t * PWCHAR
Definition: typedefs.h:56
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define LOGON32_LOGON_NETWORK
Definition: winbase.h:392
#define LOGON32_LOGON_BATCH
Definition: winbase.h:393
#define LOGON32_LOGON_INTERACTIVE
Definition: winbase.h:391
#define LOGON32_LOGON_SERVICE
Definition: winbase.h:394
#define SECURITY_LOGON_IDS_RID
Definition: setypes.h:560
#define SECURITY_LOCAL_SID_AUTHORITY
Definition: setypes.h:530
#define SECURITY_LOCAL_RID
Definition: setypes.h:542
#define SECURITY_NULL_RID
Definition: setypes.h:540
@ TokenSource
Definition: setypes.h:972
@ TokenGroups
Definition: setypes.h:967
#define SECURITY_LOGON_IDS_RID_COUNT
Definition: setypes.h:561

Referenced by LogonUserExA(), and LogonUserW().

◆ LogonUserW()

BOOL WINAPI LogonUserW ( _In_ LPWSTR  lpszUsername,
_In_opt_ LPWSTR  lpszDomain,
_In_opt_ LPWSTR  lpszPassword,
_In_ DWORD  dwLogonType,
_In_ DWORD  dwLogonProvider,
_Out_opt_ PHANDLE  phToken 
)

Definition at line 1137 of file logon.c.

1144{
1145 return LogonUserExW(lpszUsername,
1146 lpszDomain,
1150 phToken,
1151 NULL,
1152 NULL,
1153 NULL,
1154 NULL);
1155}

Referenced by ScmLogonService().

◆ OpenLogonLsaHandle()

static NTSTATUS OpenLogonLsaHandle ( VOID  )
static

Definition at line 24 of file logon.c.

25{
26 LSA_STRING LogonProcessName;
27 LSA_STRING PackageName;
30
31 RtlInitAnsiString((PANSI_STRING)&LogonProcessName,
32 "User32LogonProcess");
33
34 Status = LsaRegisterLogonProcess(&LogonProcessName,
35 &LsaHandle,
37 if (!NT_SUCCESS(Status))
38 {
39 TRACE("LsaRegisterLogonProcess failed (Status 0x%08lx)\n", Status);
40 goto done;
41 }
42
43 RtlInitAnsiString((PANSI_STRING)&PackageName,
45
47 &PackageName,
49 if (!NT_SUCCESS(Status))
50 {
51 TRACE("LsaLookupAuthenticationPackage failed (Status 0x%08lx)\n", Status);
52 goto done;
53 }
54
55 TRACE("AuthenticationPackage: 0x%08lx\n", AuthenticationPackage);
56
57done:
58 if (!NT_SUCCESS(Status))
59 {
60 if (LsaHandle != NULL)
61 {
63 if (!NT_SUCCESS(Status))
64 {
65 TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
66 }
67 }
68 }
69
70 return Status;
71}
_IRQL_requires_same_ _Out_ PHANDLE _Out_ PLSA_OPERATIONAL_MODE SecurityMode
NTSTATUS NTAPI LsaLookupAuthenticationPackage(HANDLE, PLSA_STRING, PULONG)
#define MSV1_0_PACKAGE_NAME
Definition: ntsecapi.h:42
ULONG LSA_OPERATIONAL_MODE
Definition: ntsecapi.h:367
NTSTATUS NTAPI LsaRegisterLogonProcess(PLSA_STRING, PHANDLE, PLSA_OPERATIONAL_MODE)

Referenced by LogonUserExW().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( advapi  )

Variable Documentation

◆ AdvapiTokenSourceName

const CHAR AdvapiTokenSourceName[] = "Advapi "
static

Definition at line 14 of file logon.c.

Referenced by LogonUserExW().

◆ AuthenticationPackage

◆ LsaHandle

HANDLE LsaHandle = NULL

Definition at line 17 of file logon.c.

Referenced by CloseLogonLsaHandle(), LogonUserExW(), and OpenLogonLsaHandle().