[MSV1_0] Check logon hours and workstation names on logon. Also return the machine name on logon and fix the LOGONSERVER environment variable.

This commit is contained in:
Eric Kohl 2019-03-04 17:25:11 +01:00
parent 0649f25b48
commit ac73ba7db6

View file

@ -94,7 +94,7 @@ static
NTSTATUS
BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
IN PSAMPR_USER_INFO_BUFFER UserInfo,
IN PUNICODE_STRING LogonServer,
IN PWSTR ComputerName,
OUT PMSV1_0_INTERACTIVE_PROFILE *ProfileBuffer,
OUT PULONG ProfileBufferLength)
{
@ -113,7 +113,7 @@ BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR) +
UserInfo->All.ScriptPath.Length + sizeof(WCHAR) +
UserInfo->All.ProfilePath.Length + sizeof(WCHAR) +
LogonServer->Length + sizeof(WCHAR);
((wcslen(ComputerName) + 3) * sizeof(WCHAR));
LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
if (LocalBuffer == NULL)
@ -204,12 +204,11 @@ BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectoryDrive.MaximumLength);
LocalBuffer->LogonServer.Length = LogonServer->Length;
LocalBuffer->LogonServer.MaximumLength = LogonServer->Length + sizeof(WCHAR);
LocalBuffer->LogonServer.Length = (wcslen(ComputerName) + 2) * sizeof(WCHAR);
LocalBuffer->LogonServer.MaximumLength = LocalBuffer->LogonServer.Length + sizeof(WCHAR);
LocalBuffer->LogonServer.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
memcpy(Ptr,
LogonServer->Buffer,
LogonServer->Length);
wcscpy(Ptr, L"\\");
wcscat(Ptr, ComputerName);
LocalBuffer->UserFlags = 0;
@ -844,6 +843,73 @@ done:
}
static
BOOL
MsvpCheckLogonHours(
_In_ PSAMPR_LOGON_HOURS LogonHours,
_In_ PLARGE_INTEGER LogonTime)
{
LARGE_INTEGER LocalLogonTime;
TIME_FIELDS TimeFields;
USHORT MinutesPerUnit, Offset;
TRACE("MsvpCheckLogonHours(%p %p)\n", LogonHours, LogonTime);
if (LogonHours->UnitsPerWeek == 0 || LogonHours->LogonHours == NULL)
return TRUE;
RtlSystemTimeToLocalTime(LogonTime, &LocalLogonTime);
RtlTimeToTimeFields(&LocalLogonTime, &TimeFields);
TRACE("UnitsPerWeek: %u\n", LogonHours->UnitsPerWeek);
MinutesPerUnit = 10080 / LogonHours->UnitsPerWeek;
Offset = ((TimeFields.Weekday * 24 + TimeFields.Hour) * 60 + TimeFields.Minute) / MinutesPerUnit;
return (BOOL)(LogonHours->LogonHours[Offset / 8] & (1 << (Offset % 8)));
}
static
BOOL
MsvpCheckWorkstations(
_In_ PRPC_UNICODE_STRING WorkStations,
_In_ PWSTR ComputerName)
{
PWSTR pStart, pEnd;
BOOL bFound = FALSE;
TRACE("MsvpCheckWorkstations(%wZ %S)\n", WorkStations, ComputerName);
if (WorkStations->Length == 0 || WorkStations->Buffer == NULL)
return TRUE;
pStart = WorkStations->Buffer;
for (;;)
{
pEnd = wcschr(pStart, L',');
if (pEnd != NULL)
*pEnd = UNICODE_NULL;
if (_wcsicmp(ComputerName, pStart) == 0)
{
bFound = TRUE;
if (pEnd != NULL)
*pEnd = L',';
break;
}
if (pEnd == NULL)
break;
*pEnd = L',';
pStart = pEnd + 1;
}
return bFound;
}
/*
* @unimplemented
*/
@ -944,7 +1010,7 @@ LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest,
/*
* @unimplemented
* @implemented
*/
NTSTATUS
NTAPI
@ -1008,7 +1074,7 @@ LsaApLogonTerminated(IN PLUID LogonId)
/*
* @unimplemented
* @implemented
*/
NTSTATUS
NTAPI
@ -1026,11 +1092,11 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
OUT PUNICODE_STRING *AccountName,
OUT PUNICODE_STRING *AuthenticatingAuthority,
OUT PUNICODE_STRING *MachineName,
OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,
OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials)
OUT PSECPKG_PRIMARY_CRED PrimaryCredentials, /* Not supported yet */
OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials) /* Not supported yet */
{
PMSV1_0_INTERACTIVE_LOGON LogonInfo;
WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
SAMPR_HANDLE ServerHandle = NULL;
SAMPR_HANDLE DomainHandle = NULL;
SAMPR_HANDLE UserHandle = NULL;
@ -1039,12 +1105,12 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
SAMPR_ULONG_ARRAY Use = {0, NULL};
PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
UNICODE_STRING LogonServer;
BOOLEAN SessionCreated = FALSE;
LARGE_INTEGER LogonTime;
LARGE_INTEGER AccountExpires;
LARGE_INTEGER PasswordMustChange;
LARGE_INTEGER PasswordLastSet;
DWORD ComputerNameSize;
BOOL SpecialAccount = FALSE;
NTSTATUS Status;
@ -1078,8 +1144,6 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
TRACE("User: %S\n", LogonInfo->UserName.Buffer);
TRACE("Password: %S\n", LogonInfo->Password.Buffer);
RtlInitUnicodeString(&LogonServer, L"Testserver");
}
else
{
@ -1090,6 +1154,10 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
/* Get the logon time */
NtQuerySystemTime(&LogonTime);
/* Get the computer name */
ComputerNameSize = MAX_COMPUTERNAME_LENGTH + 1;
GetComputerNameW(ComputerName, &ComputerNameSize);
/* Check for special accounts */
if (_wcsicmp(LogonInfo->LogonDomainName.Buffer, L"NT AUTHORITY") == 0)
{
@ -1291,9 +1359,23 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
goto done;
}
/* FIXME: more checks */
// STATUS_INVALID_LOGON_HOURS;
// STATUS_INVALID_WORKSTATION;
/* Check logon hours */
if (!MsvpCheckLogonHours(&UserInfo->All.LogonHours, &LogonTime))
{
ERR("Invalid logon hours!\n");
*SubStatus = STATUS_INVALID_LOGON_HOURS;
Status = STATUS_ACCOUNT_RESTRICTION;
goto done;
}
/* Check workstations */
if (!MsvpCheckWorkstations(&UserInfo->All.WorkStations, ComputerName))
{
ERR("Invalid workstation!\n");
*SubStatus = STATUS_INVALID_WORKSTATION;
Status = STATUS_ACCOUNT_RESTRICTION;
goto done;
}
}
}
@ -1320,7 +1402,7 @@ LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
/* Build and fill the interactive profile buffer */
Status = BuildInteractiveProfileBuffer(ClientRequest,
UserInfo,
&LogonServer,
ComputerName,
(PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
ProfileBufferSize);
if (!NT_SUCCESS(Status))
@ -1390,6 +1472,19 @@ done:
}
}
/* Return the machine name */
*MachineName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
if (*MachineName != NULL)
{
(*MachineName)->Buffer = DispatchTable.AllocateLsaHeap((ComputerNameSize + 1) * sizeof(WCHAR));
if ((*MachineName)->Buffer != NULL)
{
(*MachineName)->MaximumLength = (ComputerNameSize + 1) * sizeof(WCHAR);
(*MachineName)->Length = ComputerNameSize * sizeof(WCHAR);
RtlCopyMemory((*MachineName)->Buffer, ComputerName, (*MachineName)->MaximumLength);
}
}
if (!NT_SUCCESS(Status))
{
if (SessionCreated != FALSE)