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
This commit is contained in:
Eric Kohl 2014-02-02 21:52:27 +00:00
parent fbd003350e
commit d6031f2244
5 changed files with 260 additions and 16 deletions

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -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);

View file

@ -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;
}