reactos/dll/win32/advapi32/misc/logon.c

609 lines
18 KiB
C
Raw Normal View History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/advapi32/misc/logon.c
* PURPOSE: Logon functions
* PROGRAMMER: Eric Kohl
*/
#include <advapi32.h>
WINE_DEFAULT_DEBUG_CHANNEL(advapi);
/* GLOBALS *****************************************************************/
HANDLE LsaHandle = NULL;
ULONG AuthenticationPackage = 0;
/* FUNCTIONS ***************************************************************/
static
NTSTATUS
OpenLogonLsaHandle(VOID)
{
LSA_STRING LogonProcessName;
LSA_STRING PackageName;
LSA_OPERATIONAL_MODE SecurityMode = 0;
NTSTATUS Status;
RtlInitAnsiString((PANSI_STRING)&LogonProcessName,
"User32LogonProcess");
Status = LsaRegisterLogonProcess(&LogonProcessName,
&LsaHandle,
&SecurityMode);
if (!NT_SUCCESS(Status))
{
TRACE("LsaRegisterLogonProcess failed (Status 0x%08lx)\n", Status);
goto done;
}
RtlInitAnsiString((PANSI_STRING)&PackageName,
MSV1_0_PACKAGE_NAME);
Status = LsaLookupAuthenticationPackage(LsaHandle,
&PackageName,
&AuthenticationPackage);
if (!NT_SUCCESS(Status))
{
TRACE("LsaLookupAuthenticationPackage failed (Status 0x%08lx)\n", Status);
goto done;
}
TRACE("AuthenticationPackage: 0x%08lx\n", AuthenticationPackage);
done:
if (!NT_SUCCESS(Status))
{
if (LsaHandle != NULL)
{
Status = LsaDeregisterLogonProcess(LsaHandle);
if (!NT_SUCCESS(Status))
{
TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
}
}
}
return Status;
}
NTSTATUS
CloseLogonLsaHandle(VOID)
{
NTSTATUS Status = STATUS_SUCCESS;
if (LsaHandle != NULL)
{
Status = LsaDeregisterLogonProcess(LsaHandle);
if (!NT_SUCCESS(Status))
{
TRACE("LsaDeregisterLogonProcess failed (Status 0x%08lx)\n", Status);
}
}
return Status;
}
/*
* @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)
{
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);
/* Create the process with a suspended main thread */
if (!CreateProcessA(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags | CREATE_SUSPENDED,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation))
{
ERR("CreateProcessA 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;
}
/*
* @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)
{
PROCESS_ACCESS_TOKEN AccessToken;
NTSTATUS Status;
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;
}
/*
* @implemented
*/
BOOL
WINAPI
LogonUserA(
_In_ LPSTR lpszUsername,
_In_opt_ LPSTR lpszDomain,
_In_opt_ LPSTR lpszPassword,
_In_ DWORD dwLogonType,
_In_ DWORD dwLogonProvider,
_Out_opt_ PHANDLE phToken)
{
return LogonUserExA(lpszUsername,
lpszDomain,
lpszPassword,
dwLogonType,
dwLogonProvider,
phToken,
NULL,
NULL,
NULL,
NULL);
}
/*
* @implemented
*/
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)
{
UNICODE_STRING UserName;
UNICODE_STRING Domain;
UNICODE_STRING Password;
BOOL ret = FALSE;
UserName.Buffer = NULL;
Domain.Buffer = NULL;
Password.Buffer = NULL;
if (!RtlCreateUnicodeStringFromAsciiz(&UserName, lpszUsername))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto UsernameDone;
}
if (!RtlCreateUnicodeStringFromAsciiz(&Domain, lpszDomain))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto DomainDone;
}
if (!RtlCreateUnicodeStringFromAsciiz(&Password, lpszPassword))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto PasswordDone;
}
ret = LogonUserExW(UserName.Buffer,
Domain.Buffer,
Password.Buffer,
dwLogonType,
dwLogonProvider,
phToken,
ppLogonSid,
ppProfileBuffer,
pdwProfileLength,
pQuotaLimits);
if (Password.Buffer != NULL)
RtlFreeUnicodeString(&Password);
PasswordDone:
if (Domain.Buffer != NULL)
RtlFreeUnicodeString(&Domain);
DomainDone:
if (UserName.Buffer != NULL)
RtlFreeUnicodeString(&UserName);
UsernameDone:
return ret;
}
/*
* @implemented
*/
BOOL
WINAPI
LogonUserW(
_In_ LPWSTR lpszUsername,
_In_opt_ LPWSTR lpszDomain,
_In_opt_ LPWSTR lpszPassword,
_In_ DWORD dwLogonType,
_In_ DWORD dwLogonProvider,
_Out_opt_ PHANDLE phToken)
{
return LogonUserExW(lpszUsername,
lpszDomain,
lpszPassword,
dwLogonType,
dwLogonProvider,
phToken,
NULL,
NULL,
NULL,
NULL);
}
/*
* @implemented
*/
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)
{
SID_IDENTIFIER_AUTHORITY LocalAuthority = {SECURITY_LOCAL_SID_AUTHORITY};
SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
PSID LogonSid = NULL;
PSID LocalSid = NULL;
LSA_STRING OriginName;
UNICODE_STRING DomainName;
UNICODE_STRING UserName;
UNICODE_STRING Password;
PMSV1_0_INTERACTIVE_LOGON AuthInfo = NULL;
ULONG AuthInfoLength;
ULONG_PTR Ptr;
TOKEN_SOURCE TokenSource;
PTOKEN_GROUPS TokenGroups = NULL;
PMSV1_0_INTERACTIVE_PROFILE ProfileBuffer = NULL;
ULONG ProfileBufferLength = 0;
LUID Luid = {0, 0};
LUID LogonId = {0, 0};
HANDLE TokenHandle = NULL;
QUOTA_LIMITS QuotaLimits;
SECURITY_LOGON_TYPE LogonType;
NTSTATUS SubStatus = STATUS_SUCCESS;
NTSTATUS Status;
*phToken = NULL;
switch (dwLogonType)
{
case LOGON32_LOGON_INTERACTIVE:
LogonType = Interactive;
break;
case LOGON32_LOGON_NETWORK:
LogonType = Network;
break;
case LOGON32_LOGON_BATCH:
LogonType = Batch;
break;
case LOGON32_LOGON_SERVICE:
LogonType = Service;
break;
default:
ERR("Invalid logon type: %ul\n", dwLogonType);
Status = STATUS_INVALID_PARAMETER;
goto done;
}
if (LsaHandle == NULL)
{
Status = OpenLogonLsaHandle();
if (!NT_SUCCESS(Status))
goto done;
}
RtlInitAnsiString((PANSI_STRING)&OriginName,
"Advapi32 Logon");
RtlInitUnicodeString(&DomainName,
lpszDomain);
RtlInitUnicodeString(&UserName,
lpszUsername);
RtlInitUnicodeString(&Password,
lpszPassword);
AuthInfoLength = sizeof(MSV1_0_INTERACTIVE_LOGON)+
DomainName.MaximumLength +
UserName.MaximumLength +
Password.MaximumLength;
AuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
AuthInfoLength);
if (AuthInfo == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
AuthInfo->MessageType = MsV1_0InteractiveLogon;
Ptr = (ULONG_PTR)AuthInfo + sizeof(MSV1_0_INTERACTIVE_LOGON);
AuthInfo->LogonDomainName.Length = DomainName.Length;
AuthInfo->LogonDomainName.MaximumLength = DomainName.MaximumLength;
AuthInfo->LogonDomainName.Buffer = (DomainName.Buffer == NULL) ? NULL : (PWCHAR)Ptr;
if (DomainName.MaximumLength > 0)
{
RtlCopyMemory(AuthInfo->LogonDomainName.Buffer,
DomainName.Buffer,
DomainName.MaximumLength);
Ptr += DomainName.MaximumLength;
}
AuthInfo->UserName.Length = UserName.Length;
AuthInfo->UserName.MaximumLength = UserName.MaximumLength;
AuthInfo->UserName.Buffer = (PWCHAR)Ptr;
if (UserName.MaximumLength > 0)
RtlCopyMemory(AuthInfo->UserName.Buffer,
UserName.Buffer,
UserName.MaximumLength);
Ptr += UserName.MaximumLength;
AuthInfo->Password.Length = Password.Length;
AuthInfo->Password.MaximumLength = Password.MaximumLength;
AuthInfo->Password.Buffer = (PWCHAR)Ptr;
if (Password.MaximumLength > 0)
RtlCopyMemory(AuthInfo->Password.Buffer,
Password.Buffer,
Password.MaximumLength);
/* Create the Logon SID*/
AllocateLocallyUniqueId(&LogonId);
Status = RtlAllocateAndInitializeSid(&SystemAuthority,
SECURITY_LOGON_IDS_RID_COUNT,
SECURITY_LOGON_IDS_RID,
LogonId.HighPart,
LogonId.LowPart,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
&LogonSid);
if (!NT_SUCCESS(Status))
goto done;
/* Create the Local SID*/
Status = RtlAllocateAndInitializeSid(&LocalAuthority,
1,
SECURITY_LOCAL_RID,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
SECURITY_NULL_RID,
&LocalSid);
if (!NT_SUCCESS(Status))
goto done;
/* Allocate and set the token groups */
TokenGroups = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(TOKEN_GROUPS) + ((2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES)));
if (TokenGroups == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
TokenGroups->GroupCount = 2;
TokenGroups->Groups[0].Sid = LogonSid;
TokenGroups->Groups[0].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_LOGON_ID;
TokenGroups->Groups[1].Sid = LocalSid;
TokenGroups->Groups[1].Attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED |
SE_GROUP_ENABLED_BY_DEFAULT;
/* Set the token source */
strncpy(TokenSource.SourceName, "Advapi ", sizeof(TokenSource.SourceName));
AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);
Status = LsaLogonUser(LsaHandle,
&OriginName,
LogonType,
AuthenticationPackage,
(PVOID)AuthInfo,
AuthInfoLength,
TokenGroups,
&TokenSource,
(PVOID*)&ProfileBuffer,
&ProfileBufferLength,
&Luid,
&TokenHandle,
&QuotaLimits,
&SubStatus);
if (!NT_SUCCESS(Status))
{
ERR("LsaLogonUser failed (Status 0x%08lx)\n", Status);
goto done;
}
if (ProfileBuffer != NULL)
{
TRACE("ProfileBuffer: %p\n", ProfileBuffer);
TRACE("MessageType: %u\n", ProfileBuffer->MessageType);
TRACE("FullName: %p\n", ProfileBuffer->FullName.Buffer);
TRACE("FullName: %S\n", ProfileBuffer->FullName.Buffer);
TRACE("LogonServer: %p\n", ProfileBuffer->LogonServer.Buffer);
TRACE("LogonServer: %S\n", ProfileBuffer->LogonServer.Buffer);
}
TRACE("Luid: 0x%08lx%08lx\n", Luid.HighPart, Luid.LowPart);
if (TokenHandle != NULL)
{
TRACE("TokenHandle: %p\n", TokenHandle);
}
*phToken = TokenHandle;
/* FIXME: return ppLogonSid, ppProfileBuffer, pdwProfileLength and pQuotaLimits */
done:
if (ProfileBuffer != NULL)
LsaFreeReturnBuffer(ProfileBuffer);
if (!NT_SUCCESS(Status))
{
if (TokenHandle != NULL)
CloseHandle(TokenHandle);
}
if (TokenGroups != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, TokenGroups);
if (LocalSid != NULL)
RtlFreeSid(LocalSid);
if (LogonSid != NULL)
RtlFreeSid(LogonSid);
if (AuthInfo != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, AuthInfo);
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
return TRUE;
}
/* EOF */