From e5fcda922b0ad049f22815a6ea1258205fa17927 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Tue, 18 Sep 2018 21:33:29 +0200 Subject: [PATCH] [ADVAPI32][SERVICES] Pass encrypted passwords to the service manager. - Encrypt passwords before passing them to the service manager. Right now, we are using a fixed encryption key. This will be fixed later. - Replace the calls to ZeroMemory which are used to wipe the password buffers by calls to SecureZeroMemory. --- base/system/services/config.c | 58 ++++++++++++++++++++++++--- dll/win32/advapi32/service/scm.c | 67 +++++++++++++++++++++++++------- 2 files changed, 106 insertions(+), 19 deletions(-) diff --git a/base/system/services/config.c b/base/system/services/config.c index 14af8e5b0f1..4d1f2471c66 100644 --- a/base/system/services/config.c +++ b/base/system/services/config.c @@ -15,6 +15,20 @@ #define NDEBUG #include +struct ustring +{ + DWORD Length; + DWORD MaximumLength; + unsigned char *Buffer; +}; + +NTSTATUS +WINAPI +SystemFunction005( + const struct ustring *in, + const struct ustring *key, + struct ustring *out); + /* FUNCTIONS *****************************************************************/ @@ -684,17 +698,51 @@ ScmDecryptPassword( _In_ DWORD dwPasswordSize, _Out_ PWSTR *pClearTextPassword) { + struct ustring inData, keyData, outData; + PCHAR pszKey = "TestEncryptionKey"; PWSTR pBuffer; + NTSTATUS Status; - /* Allocate a buffer for the decrypted password */ - pBuffer = HeapAlloc(GetProcessHeap(), 0, dwPasswordSize); + inData.Length = dwPasswordSize; + inData.MaximumLength = inData.Length; + inData.Buffer = pPassword; + + keyData.Length = strlen(pszKey); + keyData.MaximumLength = keyData.Length; + keyData.Buffer = (unsigned char *)pszKey; + + outData.Length = 0; + outData.MaximumLength = 0; + outData.Buffer = NULL; + + /* Get the required buffer size */ + Status = SystemFunction005(&inData, + &keyData, + &outData); + if (Status != STATUS_BUFFER_TOO_SMALL) + { + DPRINT1("SystemFunction005 failed (Status 0x%08lx)\n", Status); + return RtlNtStatusToDosError(Status); + } + + /* Allocate a buffer for the clear text password */ + pBuffer = HeapAlloc(GetProcessHeap(), 0, outData.Length); if (pBuffer == NULL) return ERROR_OUTOFMEMORY; + outData.MaximumLength = outData.Length; + outData.Buffer = (unsigned char *)pBuffer; + /* Decrypt the password */ - CopyMemory(pBuffer, - pPassword, - dwPasswordSize); + Status = SystemFunction005(&inData, + &keyData, + &outData); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SystemFunction005 failed (Status 0x%08lx)\n", Status); + HeapFree(GetProcessHeap(), 0, pBuffer); + return RtlNtStatusToDosError(Status); + } *pClearTextPassword = pBuffer; diff --git a/dll/win32/advapi32/service/scm.c b/dll/win32/advapi32/service/scm.c index 022864bba93..efa19f2b354 100644 --- a/dll/win32/advapi32/service/scm.c +++ b/dll/win32/advapi32/service/scm.c @@ -12,6 +12,12 @@ #include WINE_DEFAULT_DEBUG_CHANNEL(advapi); +NTSTATUS +WINAPI +SystemFunction004( + const struct ustring *in, + const struct ustring *key, + struct ustring *out); /* FUNCTIONS *****************************************************************/ @@ -162,21 +168,54 @@ ScmEncryptPassword( _Out_ PBYTE *pEncryptedPassword, _Out_ PDWORD pEncryptedPasswordSize) { - DWORD dwSize; + struct ustring inData, keyData, outData; + PCHAR pszKey = "TestEncryptionKey"; PBYTE pBuffer; + NTSTATUS Status; - dwSize = (wcslen(pClearTextPassword) + 1) * sizeof(WCHAR); + inData.Length = (wcslen(pClearTextPassword) + 1) * sizeof(WCHAR); + inData.MaximumLength = inData.Length; + inData.Buffer = (unsigned char *)pClearTextPassword; - pBuffer = HeapAlloc(GetProcessHeap(), 0, dwSize); + keyData.Length = strlen(pszKey); + keyData.MaximumLength = keyData.Length; + keyData.Buffer = (unsigned char *)pszKey; + + outData.Length = 0; + outData.MaximumLength = 0; + outData.Buffer = NULL; + + /* Get the required buffer size */ + Status = SystemFunction004(&inData, + &keyData, + &outData); + if (Status != STATUS_BUFFER_TOO_SMALL) + { + ERR("SystemFunction004 failed (Status 0x%08lx)\n", Status); + return RtlNtStatusToDosError(Status); + } + + /* Allocate a buffer for the encrypted password */ + pBuffer = HeapAlloc(GetProcessHeap(), 0, outData.Length); if (pBuffer == NULL) return ERROR_OUTOFMEMORY; - CopyMemory(pBuffer, - pClearTextPassword, - dwSize); + outData.MaximumLength = outData.Length; + outData.Buffer = pBuffer; - *pEncryptedPassword = pBuffer; - *pEncryptedPasswordSize = dwSize; + /* Encrypt the password */ + Status = SystemFunction004(&inData, + &keyData, + &outData); + if (!NT_SUCCESS(Status)) + { + ERR("SystemFunction004 failed (Status 0x%08lx)\n", Status); + HeapFree(GetProcessHeap(), 0, pBuffer); + return RtlNtStatusToDosError(Status); + } + + *pEncryptedPassword = outData.Buffer; + *pEncryptedPasswordSize = outData.Length; return ERROR_SUCCESS; } @@ -395,12 +434,12 @@ done: if (lpPasswordW != NULL) { /* Wipe and release the password buffers */ - ZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR)); + SecureZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR)); HeapFree(GetProcessHeap(), 0, lpPasswordW); if (lpEncryptedPassword != NULL) { - ZeroMemory(lpEncryptedPassword, dwPasswordSize); + SecureZeroMemory(lpEncryptedPassword, dwPasswordSize); HeapFree(GetProcessHeap(), 0, lpEncryptedPassword); } } @@ -498,7 +537,7 @@ done: if (lpEncryptedPassword != NULL) { /* Wipe and release the password buffer */ - ZeroMemory(lpEncryptedPassword, dwPasswordSize); + SecureZeroMemory(lpEncryptedPassword, dwPasswordSize); HeapFree(GetProcessHeap(), 0, lpEncryptedPassword); } @@ -723,12 +762,12 @@ done: if (lpPasswordW != NULL) { /* Wipe and release the password buffers */ - ZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR)); + SecureZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR)); HeapFree(GetProcessHeap(), 0, lpPasswordW); if (lpEncryptedPassword != NULL) { - ZeroMemory(lpEncryptedPassword, dwPasswordSize); + SecureZeroMemory(lpEncryptedPassword, dwPasswordSize); HeapFree(GetProcessHeap(), 0, lpEncryptedPassword); } } @@ -837,7 +876,7 @@ done: if (lpEncryptedPassword != NULL) { /* Wipe and release the password buffers */ - ZeroMemory(lpEncryptedPassword, dwPasswordSize); + SecureZeroMemory(lpEncryptedPassword, dwPasswordSize); HeapFree(GetProcessHeap(), 0, lpEncryptedPassword); }