From d6031f2244fdf9b8e52dbab08651daf26db87ef7 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 2 Feb 2014 21:52:27 +0000 Subject: [PATCH] [MSGINA] Use our own implementation of LogonUser instead of the one from advapi32 in order to use only one LSA connection. svn path=/trunk/; revision=61932 --- reactos/dll/win32/msgina/gui.c | 2 +- reactos/dll/win32/msgina/lsa.c | 219 ++++++++++++++++++++++++++++++ reactos/dll/win32/msgina/msgina.c | 29 ++-- reactos/dll/win32/msgina/msgina.h | 10 ++ reactos/dll/win32/msgina/tui.c | 16 ++- 5 files changed, 260 insertions(+), 16 deletions(-) diff --git a/reactos/dll/win32/msgina/gui.c b/reactos/dll/win32/msgina/gui.c index 4031557d32b..33abbd7d801 100644 --- a/reactos/dll/win32/msgina/gui.c +++ b/reactos/dll/win32/msgina/gui.c @@ -829,7 +829,7 @@ DoUnlock( else { /* Wrong user name */ - if (DoAdminUnlock(UserName, NULL, Password)) + if (DoAdminUnlock(pgContext, UserName, NULL, Password)) { *Action = WLX_SAS_ACTION_UNLOCK_WKSTA; res = TRUE; diff --git a/reactos/dll/win32/msgina/lsa.c b/reactos/dll/win32/msgina/lsa.c index 354f7f02975..126a55aa5c4 100644 --- a/reactos/dll/win32/msgina/lsa.c +++ b/reactos/dll/win32/msgina/lsa.c @@ -49,4 +49,223 @@ ConnectToLsa( return TRUE; } + +BOOL +MyLogonUser( + HANDLE LsaHandle, + ULONG AuthenticationPackage, + LPWSTR lpszUsername, + LPWSTR lpszDomain, + LPWSTR lpszPassword, + PHANDLE phToken) +{ + 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; + NTSTATUS SubStatus = STATUS_SUCCESS; + NTSTATUS Status; + + *phToken = NULL; + + RtlInitAnsiString((PANSI_STRING)&OriginName, + "MSGINA 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 */ + strcpy(TokenSource.SourceName, "LogonUser"); + AllocateLocallyUniqueId(&TokenSource.SourceIdentifier); + + Status = LsaLogonUser(LsaHandle, + &OriginName, + Interactive, + 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; + +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 */ diff --git a/reactos/dll/win32/msgina/msgina.c b/reactos/dll/win32/msgina/msgina.c index 2c7c1c18b46..167fb45c152 100644 --- a/reactos/dll/win32/msgina/msgina.c +++ b/reactos/dll/win32/msgina/msgina.c @@ -594,6 +594,7 @@ DuplicationString(PWSTR Str) BOOL DoAdminUnlock( + IN PGINA_CONTEXT pgContext, IN PWSTR UserName, IN PWSTR Domain, IN PWSTR Password) @@ -607,12 +608,15 @@ DoAdminUnlock( TRACE("(%S %S %S)\n", UserName, Domain, Password); - if (!LogonUserW(UserName, - Domain, - Password, - LOGON32_LOGON_INTERACTIVE, - LOGON32_PROVIDER_DEFAULT, - &hToken)) + if (!ConnectToLsa(pgContext)) + return FALSE; + + if (!MyLogonUser(pgContext->LsaHandle, + pgContext->AuthenticationPackage, + UserName, + Domain, + Password, + &pgContext->UserToken)) { WARN("LogonUserW() failed\n"); return FALSE; @@ -683,10 +687,15 @@ DoLoginTasks( DWORD dwLength; BOOL bResult; - if (!LogonUserW(UserName, Domain, Password, - LOGON32_LOGON_INTERACTIVE, - LOGON32_PROVIDER_DEFAULT, - &pgContext->UserToken)) + if (!ConnectToLsa(pgContext)) + return FALSE; + + if (!MyLogonUser(pgContext->LsaHandle, + pgContext->AuthenticationPackage, + UserName, + Domain, + Password, + &pgContext->UserToken)) { WARN("LogonUserW() failed\n"); goto cleanup; diff --git a/reactos/dll/win32/msgina/msgina.h b/reactos/dll/win32/msgina/msgina.h index a9c62a44f2c..f36450d47f7 100644 --- a/reactos/dll/win32/msgina/msgina.h +++ b/reactos/dll/win32/msgina/msgina.h @@ -90,10 +90,20 @@ BOOL ConnectToLsa( PGINA_CONTEXT pgContext); +BOOL +MyLogonUser( + HANDLE LsaHandle, + ULONG AuthenticationPackage, + LPWSTR lpszUsername, + LPWSTR lpszDomain, + LPWSTR lpszPassword, + PHANDLE phToken); + /* msgina.c */ BOOL DoAdminUnlock( + IN PGINA_CONTEXT pgContext, IN PWSTR UserName, IN PWSTR Domain, IN PWSTR Password); diff --git a/reactos/dll/win32/msgina/tui.c b/reactos/dll/win32/msgina/tui.c index d071fd2e316..3a99ea4e373 100644 --- a/reactos/dll/win32/msgina/tui.c +++ b/reactos/dll/win32/msgina/tui.c @@ -233,14 +233,20 @@ TUILockedSAS( if (!ReadString(IDS_ASKFORPASSWORD, Password, 256, FALSE)) return WLX_SAS_ACTION_NONE; - if (!LogonUserW(UserName, NULL, Password, - LOGON32_LOGON_UNLOCK, - LOGON32_PROVIDER_DEFAULT, - &hToken)) + if (!ConnectToLsa(pgContext)) + return WLX_SAS_ACTION_NONE; + + if (!MyLogonUser(pgContext->LsaHandle, + pgContext->AuthenticationPackage, + UserName, + NULL, + Password, + &hToken)) { - TRACE("LogonUserW() failed\n"); + WARN("LogonUserW() failed\n"); return WLX_SAS_ACTION_NONE; } + CloseHandle(hToken); return WLX_SAS_ACTION_UNLOCK_WKSTA; }