PENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
PENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
PENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
+ BOOLEAN StoredLmPresent = FALSE;
+ BOOLEAN StoredNtPresent = FALSE;
+ BOOLEAN StoredLmEmpty = TRUE;
+ BOOLEAN StoredNtEmpty = TRUE;
PSAM_DB_OBJECT UserObject;
ULONG Length;
+ SAM_USER_FIXED_DATA UserFixedData;
+ SAM_DOMAIN_FIXED_DATA DomainFixedData;
+ LARGE_INTEGER SystemTime;
NTSTATUS Status;
TRACE("(%p %u %p %p %u %p %p %u %p %u %p)\n",
return Status;
}
+ /* Get the current time */
+ Status = NtQuerySystemTime(&SystemTime);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("NtQuerySystemTime failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
/* Retrieve the LM password */
Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
Status = SampGetObjectAttribute(UserObject,
NULL,
&StoredLmPassword,
&Length);
- if (!NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
{
-
+ if (Length == sizeof(ENCRYPTED_LM_OWF_PASSWORD))
+ {
+ StoredLmPresent = TRUE;
+ if (!RtlEqualMemory(&StoredLmPassword,
+ &EmptyLmHash,
+ sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
+ StoredLmEmpty = FALSE;
+ }
}
/* Retrieve the NT password */
NULL,
&StoredNtPassword,
&Length);
+ if (NT_SUCCESS(Status))
+ {
+ if (Length == sizeof(ENCRYPTED_NT_OWF_PASSWORD))
+ {
+ StoredNtPresent = TRUE;
+ if (!RtlEqualMemory(&StoredNtPassword,
+ &EmptyNtHash,
+ sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
+ StoredNtEmpty = FALSE;
+ }
+ }
+
+ /* Retrieve the fixed size user data */
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject,
+ L"F",
+ NULL,
+ &UserFixedData,
+ &Length);
if (!NT_SUCCESS(Status))
{
+ TRACE("SampGetObjectAttribute failed to retrieve the fixed user data (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+ /* Check if we can change the password at this time */
+ if ((StoredNtEmpty == FALSE) || (StoredNtEmpty == FALSE))
+ {
+ /* Get fixed domain data */
+ Length = sizeof(SAM_DOMAIN_FIXED_DATA);
+ Status = SampGetObjectAttribute(UserObject->ParentObject,
+ L"F",
+ NULL,
+ &DomainFixedData,
+ &Length);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("SampGetObjectAttribute failed to retrieve the fixed domain data (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ if (DomainFixedData.MinPasswordAge.QuadPart > 0)
+ {
+ if (SystemTime.QuadPart < (UserFixedData.PasswordLastSet.QuadPart + DomainFixedData.MinPasswordAge.QuadPart))
+ return STATUS_ACCOUNT_RESTRICTION;
+ }
}
/* FIXME: Decrypt passwords */
}
}
- /* Store the new LM password */
+ /* Store the new password hashes */
if (NT_SUCCESS(Status))
{
- if (LmPresent)
+ Status = SampSetUserPassword(UserObject,
+ NewNtPassword,
+ NtPresent,
+ NewLmPassword,
+ LmPresent);
+ if (NT_SUCCESS(Status))
{
- Length = sizeof(ENCRYPTED_LM_OWF_PASSWORD);
- Status = SampSetObjectAttribute(UserObject,
- L"LMPwd",
- REG_BINARY,
- NewLmPassword,
- Length);
- if (!NT_SUCCESS(Status))
- {
- goto done;
- }
- }
+ /* Update PasswordLastSet */
+ UserFixedData.PasswordLastSet.QuadPart = SystemTime.QuadPart;
- /* Store the new NT password */
- if (NtPresent)
- {
- Length = sizeof(ENCRYPTED_NT_OWF_PASSWORD);
+ /* Set the fixed size user data */
+ Length = sizeof(SAM_USER_FIXED_DATA);
Status = SampSetObjectAttribute(UserObject,
- L"NTPwd",
+ L"F",
REG_BINARY,
- NewNtPassword,
+ &UserFixedData,
Length);
- if (!NT_SUCCESS(Status))
- {
- goto done;
- }
}
}
+ if (Status == STATUS_WRONG_PASSWORD)
+ {
+ /* Update BadPasswordCount and LastBadPasswordTime */
+ UserFixedData.BadPasswordCount++;
+ UserFixedData.LastBadPasswordTime.QuadPart = SystemTime.QuadPart;
+
+ /* Set the fixed size user data */
+ Length = sizeof(SAM_USER_FIXED_DATA);
+ Status = SampSetObjectAttribute(UserObject,
+ L"F",
+ REG_BINARY,
+ &UserFixedData,
+ Length);
+ }
-done:
return Status;
}