[MSV1_0] Extract the code for SamValidateUser function (3/5)

This is a part of the Partial Network Login Implementation PR.

- Extract code for SamValidateUser (sam.c) from LsaApLogonUserEx2.
- Make SamValidateNormalUser a local function for sam.c
- Move dependent function GetNtAuthorityDomainSid to sam.c
This commit is contained in:
Andreas Maier 2020-06-22 19:01:37 +02:00 committed by Victor Perevertkin
parent 045cd5d42f
commit 472b32d902
3 changed files with 181 additions and 136 deletions

View File

@ -20,28 +20,6 @@ LSA_DISPATCH_TABLE DispatchTable;
/* FUNCTIONS ***************************************************************/
static
NTSTATUS
GetNtAuthorityDomainSid(PRPC_SID *Sid)
{
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
ULONG Length = 0;
Length = RtlLengthRequiredSid(0);
*Sid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
if (*Sid == NULL)
{
ERR("Failed to allocate SID\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlInitializeSid(*Sid,&NtAuthority, 0);
return STATUS_SUCCESS;
}
static
NTSTATUS
BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
@ -953,15 +931,12 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
OUT PSECPKG_PRIMARY_CRED PrimaryCredentials, /* Not supported yet */
OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials) /* Not supported yet */
{
static const UNICODE_STRING NtAuthorityU = RTL_CONSTANT_STRING(L"NT AUTHORITY");
static const UNICODE_STRING LocalServiceU = RTL_CONSTANT_STRING(L"LocalService");
static const UNICODE_STRING NetworkServiceU = RTL_CONSTANT_STRING(L"NetworkService");
NTSTATUS Status;
PMSV1_0_INTERACTIVE_LOGON LogonInfo;
UNICODE_STRING ComputerName;
WCHAR ComputerNameData[MAX_COMPUTERNAME_LENGTH + 1];
PUNICODE_STRING LogonUserName = NULL;
LSA_SAM_PWD_DATA LogonPwdData = { FALSE, NULL };
PUNICODE_STRING LogonDomain = NULL;
SAMPR_HANDLE UserHandle = NULL;
PRPC_SID AccountDomainSid = NULL;
PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
@ -997,6 +972,7 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
LogonType == Batch ||
LogonType == Service)
{
PMSV1_0_INTERACTIVE_LOGON LogonInfo;
ULONG_PTR PtrOffset;
if (SubmitBufferSize < sizeof(MSV1_0_INTERACTIVE_LOGON))
@ -1092,8 +1068,11 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
if (!NT_SUCCESS(Status))
return STATUS_INVALID_PARAMETER;
LogonUserName = &LogonInfo->UserName;
LogonDomain = &LogonInfo->LogonDomainName;
LogonPwdData.IsNetwork = FALSE;
LogonPwdData.PlainPwd = &LogonInfo->Password;
LogonPwdData.ComputerName = &ComputerName;
TRACE("Domain: %wZ\n", &LogonInfo->LogonDomainName);
TRACE("User: %wZ\n", &LogonInfo->UserName);
@ -1108,80 +1087,18 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
}
// TODO: Add other LogonType validity checks.
/* Check for special accounts */
// FIXME: Windows does not do this that way!! (msv1_0 does not contain these hardcoded values)
if (RtlEqualUnicodeString(&LogonInfo->LogonDomainName, &NtAuthorityU, TRUE))
{
SpecialAccount = TRUE;
/* Get the authority domain SID */
Status = GetNtAuthorityDomainSid(&AccountDomainSid);
if (!NT_SUCCESS(Status))
{
ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status);
return Status;
}
if (RtlEqualUnicodeString(&LogonInfo->UserName, &LocalServiceU, TRUE))
{
TRACE("SpecialAccount: LocalService\n");
if (LogonType != Service)
return STATUS_LOGON_FAILURE;
UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SAMPR_USER_ALL_INFORMATION));
if (UserInfo == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
UserInfo->All.UserId = SECURITY_LOCAL_SERVICE_RID;
UserInfo->All.PrimaryGroupId = SECURITY_LOCAL_SERVICE_RID;
}
else if (RtlEqualUnicodeString(&LogonInfo->UserName, &NetworkServiceU, TRUE))
{
TRACE("SpecialAccount: NetworkService\n");
if (LogonType != Service)
return STATUS_LOGON_FAILURE;
UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SAMPR_USER_ALL_INFORMATION));
if (UserInfo == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
UserInfo->All.UserId = SECURITY_NETWORK_SERVICE_RID;
UserInfo->All.PrimaryGroupId = SECURITY_NETWORK_SERVICE_RID;
}
else
{
Status = STATUS_NO_SUCH_USER;
goto done;
}
}
else
{
TRACE("NormalAccount\n");
Status = SamValidateNormalUser(&LogonInfo->UserName,
&LogonPwdData,
&ComputerName,
&AccountDomainSid,
&UserHandle,
&UserInfo,
SubStatus);
if (!NT_SUCCESS(Status))
{
ERR("SamValidateNormalUser() failed (Status 0x%08lx)\n", Status);
return Status;
}
}
Status = SamValidateUser(LogonType,
LogonUserName,
LogonDomain,
&LogonPwdData,
&ComputerName,
&SpecialAccount,
&AccountDomainSid,
&UserHandle,
&UserInfo,
SubStatus);
if (!NT_SUCCESS(Status))
goto done;
/* Return logon information */
@ -1254,44 +1171,51 @@ done:
&InternalInfo);
}
/* Return the account name */
*AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
if (*AccountName != NULL)
if (NT_SUCCESS(Status))
{
(*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
sizeof(UNICODE_NULL));
if ((*AccountName)->Buffer != NULL)
/* Return the account name */
*AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
if ((LogonUserName != NULL) &&
(*AccountName != NULL))
{
(*AccountName)->MaximumLength = LogonInfo->UserName.Length +
sizeof(UNICODE_NULL);
RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
(*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonUserName->Length +
sizeof(UNICODE_NULL));
if ((*AccountName)->Buffer != NULL)
{
(*AccountName)->MaximumLength = LogonUserName->Length +
sizeof(UNICODE_NULL);
RtlCopyUnicodeString(*AccountName, LogonUserName);
}
}
}
/* Return the authenticating authority */
*AuthenticatingAuthority = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
if (*AuthenticatingAuthority != NULL)
{
(*AuthenticatingAuthority)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->LogonDomainName.Length +
sizeof(UNICODE_NULL));
if ((*AuthenticatingAuthority)->Buffer != NULL)
/* Return the authenticating authority */
*AuthenticatingAuthority = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
if ((LogonDomain != NULL) &&
(*AuthenticatingAuthority != NULL))
{
(*AuthenticatingAuthority)->MaximumLength = LogonInfo->LogonDomainName.Length +
sizeof(UNICODE_NULL);
RtlCopyUnicodeString(*AuthenticatingAuthority, &LogonInfo->LogonDomainName);
(*AuthenticatingAuthority)->Buffer = DispatchTable.AllocateLsaHeap(LogonDomain->Length +
sizeof(UNICODE_NULL));
if ((*AuthenticatingAuthority)->Buffer != NULL)
{
(*AuthenticatingAuthority)->MaximumLength = LogonDomain->Length +
sizeof(UNICODE_NULL);
RtlCopyUnicodeString(*AuthenticatingAuthority, LogonDomain);
}
}
}
/* Return the machine name */
*MachineName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
if (*MachineName != NULL)
{
(*MachineName)->Buffer = DispatchTable.AllocateLsaHeap(ComputerName.MaximumLength);
if ((*MachineName)->Buffer != NULL)
/* Return the machine name */
*MachineName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
if (*MachineName != NULL)
{
(*MachineName)->MaximumLength = ComputerName.MaximumLength;
(*MachineName)->Length = ComputerName.Length;
RtlCopyMemory((*MachineName)->Buffer, ComputerName.Buffer, ComputerName.MaximumLength);
(*MachineName)->Buffer = DispatchTable.AllocateLsaHeap(ComputerName.MaximumLength);
if ((*MachineName)->Buffer != NULL)
{
(*MachineName)->MaximumLength = ComputerName.MaximumLength;
(*MachineName)->Length = ComputerName.Length;
RtlCopyMemory((*MachineName)->Buffer,
ComputerName.Buffer,
ComputerName.MaximumLength);
}
}
}

View File

@ -238,6 +238,7 @@ MsvpCheckWorkstations(
}
static
NTSTATUS
SamValidateNormalUser(
_In_ PUNICODE_STRING UserName,
@ -431,3 +432,118 @@ done:
return Status;
}
static
NTSTATUS
GetNtAuthorityDomainSid(
_In_ PRPC_SID *Sid)
{
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
ULONG Length = 0;
Length = RtlLengthRequiredSid(0);
*Sid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
if (*Sid == NULL)
{
ERR("Failed to allocate SID\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlInitializeSid(*Sid,&NtAuthority, 0);
return STATUS_SUCCESS;
}
NTSTATUS
SamValidateUser(
_In_ SECURITY_LOGON_TYPE LogonType,
_In_ PUNICODE_STRING LogonUserName,
_In_ PUNICODE_STRING LogonDomain,
_In_ PLSA_SAM_PWD_DATA LogonPwdData,
_In_ PUNICODE_STRING ComputerName,
_Out_ PBOOL SpecialAccount,
_Out_ PRPC_SID* AccountDomainSidPtr,
_Out_ SAMPR_HANDLE* UserHandlePtr,
_Out_ PSAMPR_USER_INFO_BUFFER* UserInfoPtr,
_Out_ PNTSTATUS SubStatus)
{
static const UNICODE_STRING NtAuthorityU = RTL_CONSTANT_STRING(L"NT AUTHORITY");
static const UNICODE_STRING LocalServiceU = RTL_CONSTANT_STRING(L"LocalService");
static const UNICODE_STRING NetworkServiceU = RTL_CONSTANT_STRING(L"NetworkService");
NTSTATUS Status = STATUS_SUCCESS;
*SpecialAccount = FALSE;
/* Check for special accounts */
// FIXME: Windows does not do this that way!! (msv1_0 does not contain these hardcoded values)
if (RtlEqualUnicodeString(LogonDomain, &NtAuthorityU, TRUE))
{
*SpecialAccount = TRUE;
/* Get the authority domain SID */
Status = GetNtAuthorityDomainSid(AccountDomainSidPtr);
if (!NT_SUCCESS(Status))
{
ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status);
return Status;
}
if (RtlEqualUnicodeString(LogonUserName, &LocalServiceU, TRUE))
{
TRACE("SpecialAccount: LocalService\n");
if (LogonType != Service)
return STATUS_LOGON_FAILURE;
*UserInfoPtr = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SAMPR_USER_ALL_INFORMATION));
if (*UserInfoPtr == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
(*UserInfoPtr)->All.UserId = SECURITY_LOCAL_SERVICE_RID;
(*UserInfoPtr)->All.PrimaryGroupId = SECURITY_LOCAL_SERVICE_RID;
}
else if (RtlEqualUnicodeString(LogonUserName, &NetworkServiceU, TRUE))
{
TRACE("SpecialAccount: NetworkService\n");
if (LogonType != Service)
return STATUS_LOGON_FAILURE;
*UserInfoPtr = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SAMPR_USER_ALL_INFORMATION));
if (*UserInfoPtr == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
(*UserInfoPtr)->All.UserId = SECURITY_NETWORK_SERVICE_RID;
(*UserInfoPtr)->All.PrimaryGroupId = SECURITY_NETWORK_SERVICE_RID;
}
else
{
return STATUS_NO_SUCH_USER;
}
}
else
{
TRACE("NormalAccount\n");
Status = SamValidateNormalUser(LogonUserName,
LogonPwdData,
ComputerName,
AccountDomainSidPtr,
UserHandlePtr,
UserInfoPtr,
SubStatus);
if (!NT_SUCCESS(Status))
{
ERR("SamValidateNormalUser() failed (Status 0x%08lx)\n", Status);
return Status;
}
}
return Status;
}

View File

@ -14,17 +14,22 @@ typedef struct _LSA_SAM_PWD_DATA
BOOL IsNetwork;
PUNICODE_STRING PlainPwd;
/* Input (IsNetwork = TRUE) */
PUNICODE_STRING ComputerName;
} LSA_SAM_PWD_DATA, *PLSA_SAM_PWD_DATA;
/**
* @brief Validates a normal user by checking if it exists in the sam database.
* Further some other checks are done.
* @brief Validates a user by checking if it exists in the sam database.
* Some other checks are done further.
*/
NTSTATUS
SamValidateNormalUser(
_In_ PUNICODE_STRING UserName,
_In_ PLSA_SAM_PWD_DATA PwdData,
SamValidateUser(
_In_ SECURITY_LOGON_TYPE LogonType,
_In_ PUNICODE_STRING LogonUserName,
_In_ PUNICODE_STRING LogonDomain,
_In_ PLSA_SAM_PWD_DATA LogonPwdData,
_In_ PUNICODE_STRING ComputerName,
_Out_ PBOOL SpecialAccount,
_Out_ PRPC_SID* AccountDomainSidPtr,
_Out_ SAMPR_HANDLE* UserHandlePtr,
_Out_ PSAMPR_USER_INFO_BUFFER* UserInfoPtr,