From 5c3e60a8b17d8069bdb8420d6a2a647a76c76f1d Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Mon, 10 Feb 2014 20:08:29 +0000 Subject: [PATCH] [MSV1_0] - Encrypt the old and new passwords before changing the password. [MSGINA] - Store the new password after a successful password change in order to be able to unlock a locked computer with the new password. svn path=/trunk/; revision=62110 --- reactos/dll/win32/msgina/gui.c | 25 +++--- reactos/dll/win32/msgina/msgina.c | 7 +- reactos/dll/win32/msgina/msgina.h | 2 +- reactos/dll/win32/msv1_0/msv1_0.c | 142 +++++++++++++++++++++++++++--- reactos/dll/win32/msv1_0/msv1_0.h | 20 +++++ 5 files changed, 168 insertions(+), 28 deletions(-) diff --git a/reactos/dll/win32/msgina/gui.c b/reactos/dll/win32/msgina/gui.c index d51aaa3837b..804c98dc375 100644 --- a/reactos/dll/win32/msgina/gui.c +++ b/reactos/dll/win32/msgina/gui.c @@ -283,7 +283,7 @@ DoChangePassword( IN HWND hwndDlg) { WCHAR UserName[256]; - WCHAR DomainName[256]; + WCHAR Domain[256]; WCHAR OldPassword[256]; WCHAR NewPassword1[256]; WCHAR NewPassword2[256]; @@ -297,7 +297,7 @@ DoChangePassword( NTSTATUS Status; GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_USERNAME, UserName, 256); - GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_DOMAIN, DomainName, 256); + GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_DOMAIN, Domain, 256); GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_OLDPWD, OldPassword, 256); GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD1, NewPassword1, 256); GetDlgItemTextW(hwndDlg, IDC_CHANGEPWD_NEWPWD2, NewPassword2, 256); @@ -315,7 +315,7 @@ DoChangePassword( /* Calculate the request buffer size */ RequestBufferSize = sizeof(MSV1_0_CHANGEPASSWORD_REQUEST) + - ((wcslen(DomainName) + 1) * sizeof(WCHAR)) + + ((wcslen(Domain) + 1) * sizeof(WCHAR)) + ((wcslen(UserName) + 1) * sizeof(WCHAR)) + ((wcslen(OldPassword) + 1) * sizeof(WCHAR)) + ((wcslen(NewPassword1) + 1) * sizeof(WCHAR)); @@ -337,12 +337,12 @@ DoChangePassword( Ptr = (LPWSTR)((ULONG_PTR)RequestBuffer + sizeof(MSV1_0_CHANGEPASSWORD_REQUEST)); /* Pack the domain name */ - RequestBuffer->DomainName.Length = wcslen(DomainName) * sizeof(WCHAR); + RequestBuffer->DomainName.Length = wcslen(Domain) * sizeof(WCHAR); RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length + sizeof(WCHAR); RequestBuffer->DomainName.Buffer = Ptr; RtlCopyMemory(RequestBuffer->DomainName.Buffer, - DomainName, + Domain, RequestBuffer->DomainName.MaximumLength); Ptr = (LPWSTR)((ULONG_PTR)Ptr + RequestBuffer->DomainName.MaximumLength); @@ -413,6 +413,14 @@ DoChangePassword( IDS_CHANGEPWDTITLE, IDS_PASSWORDCHANGED); + if ((wcscmp(UserName, pgContext->UserName) == 0) && + (wcscmp(Domain, pgContext->Domain) == 0) && + (wcscmp(OldPassword, pgContext->Password) == 0)) + { + ZeroMemory(pgContext->Password, 256 * sizeof(WCHAR)); + wcscpy(pgContext->Password, NewPassword1); + } + done: if (RequestBuffer != NULL) HeapFree(GetProcessHeap(), 0, RequestBuffer); @@ -755,11 +763,8 @@ LoggedOutWindowProc( if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) && DoLoginTasks(pgContext, UserName, Domain, Password)) { - pgContext->Password = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - (wcslen(Password) + 1) * sizeof(WCHAR)); - if (pgContext->Password != NULL) - wcscpy(pgContext->Password, Password); + ZeroMemory(pgContext->Password, 256 * sizeof(WCHAR)); + wcscpy(pgContext->Password, Password); result = WLX_SAS_ACTION_LOGON; } diff --git a/reactos/dll/win32/msgina/msgina.c b/reactos/dll/win32/msgina/msgina.c index f00cdc8ced2..6086023c78d 100644 --- a/reactos/dll/win32/msgina/msgina.c +++ b/reactos/dll/win32/msgina/msgina.c @@ -871,11 +871,8 @@ DoAutoLogon( if (result == TRUE) { - pgContext->Password = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - (wcslen(Password) + 1) * sizeof(WCHAR)); - if (pgContext->Password != NULL) - wcscpy(pgContext->Password, Password); + ZeroMemory(pgContext->Password, 256 * sizeof(WCHAR)); + wcscpy(pgContext->Password, Password); NotifyBootConfigStatus(TRUE); } diff --git a/reactos/dll/win32/msgina/msgina.h b/reactos/dll/win32/msgina/msgina.h index 7709e75eb50..ed478d18a6c 100644 --- a/reactos/dll/win32/msgina/msgina.h +++ b/reactos/dll/win32/msgina/msgina.h @@ -42,7 +42,7 @@ typedef struct /* Information to be filled during logon */ WCHAR UserName[256]; WCHAR Domain[256]; - LPWSTR Password; + WCHAR Password[256]; SYSTEMTIME LogonTime; HANDLE UserToken; PLUID pAuthenticationId; diff --git a/reactos/dll/win32/msv1_0/msv1_0.c b/reactos/dll/win32/msv1_0/msv1_0.c index 13eed474cf7..5581d78a2e8 100644 --- a/reactos/dll/win32/msv1_0/msv1_0.c +++ b/reactos/dll/win32/msv1_0/msv1_0.c @@ -437,6 +437,22 @@ MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest, SAMPR_ULONG_ARRAY Use = {0, NULL}; NTSTATUS Status; + ENCRYPTED_NT_OWF_PASSWORD OldNtPassword; + ENCRYPTED_NT_OWF_PASSWORD NewNtPassword; + ENCRYPTED_LM_OWF_PASSWORD OldLmPassword; + ENCRYPTED_LM_OWF_PASSWORD NewLmPassword; + OEM_STRING LmPwdString; + CHAR LmPwdBuffer[15]; + BOOLEAN OldLmPasswordPresent = FALSE; + BOOLEAN NewLmPasswordPresent = FALSE; + + ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm; + ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm; + ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt; + ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt; + PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL; + PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL; + TRACE("()\n"); RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer; @@ -523,26 +539,128 @@ MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest, } + /* Calculate the NT hash for the old password */ + Status = SystemFunction007(&RequestBuffer->OldPassword, + (LPBYTE)&OldNtPassword); + if (!NT_SUCCESS(Status)) + { + TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Calculate the NT hash for the new password */ + Status = SystemFunction007(&RequestBuffer->NewPassword, + (LPBYTE)&NewNtPassword); + if (!NT_SUCCESS(Status)) + { + TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Calculate the LM password and hash for the old password */ + LmPwdString.Length = 15; + LmPwdString.MaximumLength = 15; + LmPwdString.Buffer = LmPwdBuffer; + ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength); + + Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString, + &RequestBuffer->OldPassword, + FALSE); + if (NT_SUCCESS(Status)) + { + /* Calculate the LM hash value of the password */ + Status = SystemFunction006(LmPwdString.Buffer, + (LPSTR)&OldLmPassword); + if (NT_SUCCESS(Status)) + { + OldLmPasswordPresent = TRUE; + } + } + + /* Calculate the LM password and hash for the new password */ + LmPwdString.Length = 15; + LmPwdString.MaximumLength = 15; + LmPwdString.Buffer = LmPwdBuffer; + ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength); + + Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString, + &RequestBuffer->NewPassword, + FALSE); + if (NT_SUCCESS(Status)) + { + /* Calculate the LM hash value of the password */ + Status = SystemFunction006(LmPwdString.Buffer, + (LPSTR)&NewLmPassword); + if (NT_SUCCESS(Status)) + { + NewLmPasswordPresent = TRUE; + } + } + + /* Encrypt the old and new LM passwords, if they exist */ + if (OldLmPasswordPresent && NewLmPasswordPresent) + { + /* Encrypt the old LM password */ + Status = SystemFunction012((const BYTE *)&OldLmPassword, + (const BYTE *)&NewLmPassword, + (LPBYTE)&OldLmEncryptedWithNewLm); + if (!NT_SUCCESS(Status)) + { + TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Encrypt the new LM password */ + Status = SystemFunction012((const BYTE *)&NewLmPassword, + (const BYTE *)&OldLmPassword, + (LPBYTE)&NewLmEncryptedWithOldLm); + if (!NT_SUCCESS(Status)) + { + TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status); + goto done; + } + + pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm; + pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm; + } + + /* Encrypt the old NT password */ + Status = SystemFunction012((const BYTE *)&OldNtPassword, + (const BYTE *)&NewNtPassword, + (LPBYTE)&OldNtEncryptedWithNewNt); + if (!NT_SUCCESS(Status)) + { + TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status); + goto done; + } + + /* Encrypt the new NT password */ + Status = SystemFunction012((const BYTE *)&NewNtPassword, + (const BYTE *)&OldNtPassword, + (LPBYTE)&NewNtEncryptedWithOldNt); + if (!NT_SUCCESS(Status)) + { + TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status); + goto done; + } -#if 0 /* Change the password */ Status = SamrChangePasswordUser(UserHandle, - IN unsigned char LmPresent, - IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm, - IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm, - IN unsigned char NtPresent, - IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt, - IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt, - IN unsigned char NtCrossEncryptionPresent, - IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm, - IN unsigned char LmCrossEncryptionPresent, - IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt) + OldLmPasswordPresent && NewLmPasswordPresent, + pOldLmEncryptedWithNewLm, + pNewLmEncryptedWithOldLm, + TRUE, + &OldNtEncryptedWithNewNt, + &NewNtEncryptedWithOldNt, + FALSE, + NULL, + FALSE, + NULL); if (!NT_SUCCESS(Status)) { TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status); goto done; } -#endif done: if (UserHandle != NULL) diff --git a/reactos/dll/win32/msv1_0/msv1_0.h b/reactos/dll/win32/msv1_0/msv1_0.h index 643c21151a0..efbc90a0f3e 100644 --- a/reactos/dll/win32/msv1_0/msv1_0.h +++ b/reactos/dll/win32/msv1_0/msv1_0.h @@ -184,6 +184,20 @@ NTAPI SamIFree_SAMPR_USER_INFO_BUFFER(PSAMPR_USER_INFO_BUFFER Ptr, USER_INFORMATION_CLASS InformationClass); +NTSTATUS +NTAPI +SamrChangePasswordUser(IN SAMPR_HANDLE UserHandle, + IN unsigned char LmPresent, + IN PENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm, + IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm, + IN unsigned char NtPresent, + IN PENCRYPTED_NT_OWF_PASSWORD OldNtEncryptedWithNewNt, + IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithOldNt, + IN unsigned char NtCrossEncryptionPresent, + IN PENCRYPTED_NT_OWF_PASSWORD NewNtEncryptedWithNewLm, + IN unsigned char LmCrossEncryptionPresent, + IN PENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithNewNt); + NTSTATUS NTAPI SamrCloseHandle(IN OUT SAMPR_HANDLE *SamHandle); @@ -317,4 +331,10 @@ WINAPI SystemFunction007(PUNICODE_STRING string, LPBYTE hash); +NTSTATUS +WINAPI +SystemFunction012(const BYTE *in, + const BYTE *key, + LPBYTE out); + /* EOF */ -- 2.17.1