From 5e2c4657ca10dea1154cb43f16ee6962999ac7a4 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Mon, 17 Sep 2018 16:34:48 +0200 Subject: [PATCH] [ADVAPI32][SERVICES] Add (dummy) password encryption/decryption functions to CreateServiceA/W and ChangeServiceConfigA/W in order to prepare to pass encrypted passwords to the service manager --- base/system/services/config.c | 24 ++++++ base/system/services/rpcserver.c | 49 +++++++++++- base/system/services/services.h | 7 ++ dll/win32/advapi32/service/scm.c | 123 +++++++++++++++++++++++++------ 4 files changed, 177 insertions(+), 26 deletions(-) diff --git a/base/system/services/config.c b/base/system/services/config.c index 2099d64214b..14af8e5b0f1 100644 --- a/base/system/services/config.c +++ b/base/system/services/config.c @@ -677,4 +677,28 @@ done: return dwError; } + +DWORD +ScmDecryptPassword( + _In_ PBYTE pPassword, + _In_ DWORD dwPasswordSize, + _Out_ PWSTR *pClearTextPassword) +{ + PWSTR pBuffer; + + /* Allocate a buffer for the decrypted password */ + pBuffer = HeapAlloc(GetProcessHeap(), 0, dwPasswordSize); + if (pBuffer == NULL) + return ERROR_OUTOFMEMORY; + + /* Decrypt the password */ + CopyMemory(pBuffer, + pPassword, + dwPasswordSize); + + *pClearTextPassword = pBuffer; + + return ERROR_SUCCESS; +} + /* EOF */ diff --git a/base/system/services/rpcserver.c b/base/system/services/rpcserver.c index aa64233350d..454181bb665 100644 --- a/base/system/services/rpcserver.c +++ b/base/system/services/rpcserver.c @@ -1934,6 +1934,7 @@ RChangeServiceConfigW( HKEY hServiceKey = NULL; LPWSTR lpDisplayNameW = NULL; LPWSTR lpImagePathW = NULL; + LPWSTR lpClearTextPassword = NULL; DPRINT("RChangeServiceConfigW() called\n"); DPRINT("dwServiceType = 0x%lx\n", dwServiceType); @@ -1941,6 +1942,9 @@ RChangeServiceConfigW( DPRINT("dwErrorControl = %lu\n", dwErrorControl); DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName); DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup); + DPRINT("lpServiceStartName = %S\n", lpServiceStartName); + DPRINT("lpPassword = %p\n", lpPassword); + DPRINT("dwPwSite = %lu\n", dwPwSize); DPRINT("lpDisplayName = %S\n", lpDisplayName); if (ScmShutdown) @@ -2199,13 +2203,25 @@ RChangeServiceConfigW( { if (*(LPWSTR)lpPassword != 0) { - /* FIXME: Decrypt the password */ + /* Decrypt the password */ + dwError = ScmDecryptPassword(lpPassword, + dwPwSize, + &lpClearTextPassword); + if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmDecryptPassword failed (Error %lu)\n", dwError); + goto done; + } + DPRINT1("Clear text password: %S\n", lpClearTextPassword); /* Write the password */ dwError = ScmSetServicePassword(lpService->szServiceName, - (LPCWSTR)lpPassword); + lpClearTextPassword); if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError); goto done; + } } else { @@ -2216,12 +2232,23 @@ RChangeServiceConfigW( dwError = ERROR_SUCCESS; if (dwError != ERROR_SUCCESS) + { + DPRINT1("ScmSetServicePassword failed (Error %lu)\n", dwError); goto done; + } } } } done: + if (lpClearTextPassword != NULL) + { + /* Wipe and release the password buffer */ + ZeroMemory(lpClearTextPassword, + (wcslen(lpClearTextPassword) + 1) * sizeof(WCHAR)); + HeapFree(GetProcessHeap(), 0, lpClearTextPassword); + } + if (hServiceKey != NULL) RegCloseKey(hServiceKey); @@ -2260,6 +2287,7 @@ RCreateServiceW( PSERVICE lpService = NULL; SC_HANDLE hServiceHandle = NULL; LPWSTR lpImagePath = NULL; + LPWSTR lpClearTextPassword = NULL; HKEY hServiceKey = NULL; LPWSTR lpObjectName; @@ -2576,11 +2604,16 @@ RCreateServiceW( if (lpPassword != NULL && *(LPWSTR)lpPassword != 0) { - /* FIXME: Decrypt the password */ + /* Decrypt the password */ + dwError = ScmDecryptPassword(lpPassword, + dwPwSize, + &lpClearTextPassword); + if (dwError != ERROR_SUCCESS) + goto done; /* Write the password */ dwError = ScmSetServicePassword(lpServiceName, - (LPCWSTR)lpPassword); + lpClearTextPassword); if (dwError != ERROR_SUCCESS) goto done; } @@ -2612,6 +2645,14 @@ done: if (hServiceKey != NULL) RegCloseKey(hServiceKey); + if (lpClearTextPassword != NULL) + { + /* Wipe and release the password buffer */ + ZeroMemory(lpClearTextPassword, + (wcslen(lpClearTextPassword) + 1) * sizeof(WCHAR)); + HeapFree(GetProcessHeap(), 0, lpClearTextPassword); + } + if (dwError == ERROR_SUCCESS) { DPRINT("hService %p\n", hServiceHandle); diff --git a/base/system/services/services.h b/base/system/services/services.h index b455bead0f6..ce1b46eafa4 100644 --- a/base/system/services/services.h +++ b/base/system/services/services.h @@ -150,6 +150,13 @@ ScmDeleteRegKey( _In_ HKEY hKey, _In_ PCWSTR pszSubKey); +DWORD +ScmDecryptPassword( + _In_ PBYTE pPassword, + _In_ DWORD dwPasswordSize, + _Out_ PWSTR *pDecryptedPassword); + + /* controlset.c */ BOOL ScmGetControlSetValues(VOID); diff --git a/dll/win32/advapi32/service/scm.c b/dll/win32/advapi32/service/scm.c index 92661c9581d..022864bba93 100644 --- a/dll/win32/advapi32/service/scm.c +++ b/dll/win32/advapi32/service/scm.c @@ -155,6 +155,33 @@ ScmRpcStatusToWinError(RPC_STATUS Status) } +static +DWORD +ScmEncryptPassword( + _In_ PCWSTR pClearTextPassword, + _Out_ PBYTE *pEncryptedPassword, + _Out_ PDWORD pEncryptedPasswordSize) +{ + DWORD dwSize; + PBYTE pBuffer; + + dwSize = (wcslen(pClearTextPassword) + 1) * sizeof(WCHAR); + + pBuffer = HeapAlloc(GetProcessHeap(), 0, dwSize); + if (pBuffer == NULL) + return ERROR_OUTOFMEMORY; + + CopyMemory(pBuffer, + pClearTextPassword, + dwSize); + + *pEncryptedPassword = pBuffer; + *pEncryptedPasswordSize = dwSize; + + return ERROR_SUCCESS; +} + + /********************************************************************** * ChangeServiceConfig2A * @@ -293,12 +320,12 @@ ChangeServiceConfigA(SC_HANDLE hService, DWORD dwDependenciesLength = 0; SIZE_T cchLength; LPCSTR lpStr; - DWORD dwPasswordLength = 0; + DWORD dwPasswordSize = 0; LPWSTR lpPasswordW = NULL; LPBYTE lpEncryptedPassword = NULL; TRACE("ChangeServiceConfigA(%p %lu %lu %lu %s %s %p %s %s %s %s)\n", - dwServiceType, dwStartType, dwErrorControl, debugstr_a(lpBinaryPathName), + hService, dwServiceType, dwStartType, dwErrorControl, debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup), lpdwTagId, debugstr_a(lpDependencies), debugstr_a(lpServiceStartName), debugstr_a(lpPassword), debugstr_a(lpDisplayName)); @@ -334,9 +361,12 @@ ChangeServiceConfigA(SC_HANDLE hService, lpPasswordW, (int)(strlen(lpPassword) + 1)); - /* FIXME: Encrypt the password */ - lpEncryptedPassword = (LPBYTE)lpPasswordW; - dwPasswordLength = (wcslen(lpPasswordW) + 1) * sizeof(WCHAR); + /* Encrypt the unicode password */ + dwError = ScmEncryptPassword(lpPasswordW, + &lpEncryptedPassword, + &dwPasswordSize); + if (dwError != ERROR_SUCCESS) + goto done; } RpcTryExcept @@ -352,7 +382,7 @@ ChangeServiceConfigA(SC_HANDLE hService, dwDependenciesLength, (LPSTR)lpServiceStartName, lpEncryptedPassword, - dwPasswordLength, + dwPasswordSize, (LPSTR)lpDisplayName); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) @@ -361,9 +391,20 @@ ChangeServiceConfigA(SC_HANDLE hService, } RpcEndExcept; +done: if (lpPasswordW != NULL) + { + /* Wipe and release the password buffers */ + ZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR)); HeapFree(GetProcessHeap(), 0, lpPasswordW); + if (lpEncryptedPassword != NULL) + { + ZeroMemory(lpEncryptedPassword, dwPasswordSize); + HeapFree(GetProcessHeap(), 0, lpEncryptedPassword); + } + } + if (dwError != ERROR_SUCCESS) { TRACE("RChangeServiceConfigA() failed (Error %lu)\n", dwError); @@ -397,11 +438,11 @@ ChangeServiceConfigW(SC_HANDLE hService, DWORD dwDependenciesLength = 0; SIZE_T cchLength; LPCWSTR lpStr; - DWORD dwPasswordLength = 0; + DWORD dwPasswordSize = 0; LPBYTE lpEncryptedPassword = NULL; TRACE("ChangeServiceConfigW(%p %lu %lu %lu %s %s %p %s %s %s %s)\n", - dwServiceType, dwStartType, dwErrorControl, debugstr_w(lpBinaryPathName), + hService, dwServiceType, dwStartType, dwErrorControl, debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup), lpdwTagId, debugstr_w(lpDependencies), debugstr_w(lpServiceStartName), debugstr_w(lpPassword), debugstr_w(lpDisplayName)); @@ -421,9 +462,14 @@ ChangeServiceConfigW(SC_HANDLE hService, if (lpPassword != NULL) { - /* FIXME: Encrypt the password */ - lpEncryptedPassword = (LPBYTE)lpPassword; - dwPasswordLength = (wcslen(lpPassword) + 1) * sizeof(WCHAR); + dwError = ScmEncryptPassword(lpPassword, + &lpEncryptedPassword, + &dwPasswordSize); + if (dwError != ERROR_SUCCESS) + { + ERR("ScmEncryptPassword failed (Error %lu)\n", dwError); + goto done; + } } RpcTryExcept @@ -439,7 +485,7 @@ ChangeServiceConfigW(SC_HANDLE hService, dwDependenciesLength, (LPWSTR)lpServiceStartName, lpEncryptedPassword, - dwPasswordLength, + dwPasswordSize, (LPWSTR)lpDisplayName); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) @@ -448,6 +494,14 @@ ChangeServiceConfigW(SC_HANDLE hService, } RpcEndExcept; +done: + if (lpEncryptedPassword != NULL) + { + /* Wipe and release the password buffer */ + ZeroMemory(lpEncryptedPassword, dwPasswordSize); + HeapFree(GetProcessHeap(), 0, lpEncryptedPassword); + } + if (dwError != ERROR_SUCCESS) { TRACE("RChangeServiceConfigW() failed (Error %lu)\n", dwError); @@ -584,7 +638,7 @@ CreateServiceA(SC_HANDLE hSCManager, DWORD dwError; SIZE_T cchLength; LPCSTR lpStr; - DWORD dwPasswordLength = 0; + DWORD dwPasswordSize = 0; LPWSTR lpPasswordW = NULL; LPBYTE lpEncryptedPassword = NULL; @@ -632,9 +686,12 @@ CreateServiceA(SC_HANDLE hSCManager, lpPasswordW, (int)(strlen(lpPassword) + 1)); - /* FIXME: Encrypt the password */ - lpEncryptedPassword = (LPBYTE)lpPasswordW; - dwPasswordLength = (wcslen(lpPasswordW) + 1) * sizeof(WCHAR); + /* Encrypt the password */ + dwError = ScmEncryptPassword(lpPasswordW, + &lpEncryptedPassword, + &dwPasswordSize); + if (dwError != ERROR_SUCCESS) + goto done; } RpcTryExcept @@ -653,7 +710,7 @@ CreateServiceA(SC_HANDLE hSCManager, dwDependenciesLength, (LPSTR)lpServiceStartName, lpEncryptedPassword, - dwPasswordLength, + dwPasswordSize, (SC_RPC_HANDLE *)&hService); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) @@ -662,9 +719,20 @@ CreateServiceA(SC_HANDLE hSCManager, } RpcEndExcept; +done: if (lpPasswordW != NULL) + { + /* Wipe and release the password buffers */ + ZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR)); HeapFree(GetProcessHeap(), 0, lpPasswordW); + if (lpEncryptedPassword != NULL) + { + ZeroMemory(lpEncryptedPassword, dwPasswordSize); + HeapFree(GetProcessHeap(), 0, lpEncryptedPassword); + } + } + SetLastError(dwError); if (dwError != ERROR_SUCCESS) { @@ -701,7 +769,7 @@ CreateServiceW(SC_HANDLE hSCManager, DWORD dwError; SIZE_T cchLength; LPCWSTR lpStr; - DWORD dwPasswordLength = 0; + DWORD dwPasswordSize = 0; LPBYTE lpEncryptedPassword = NULL; TRACE("CreateServiceW(%p %s %s %lx %lu %lu %lu %s %s %p %s %s %s)\n", @@ -732,9 +800,12 @@ CreateServiceW(SC_HANDLE hSCManager, if (lpPassword != NULL) { - /* FIXME: Encrypt the password */ - lpEncryptedPassword = (LPBYTE)lpPassword; - dwPasswordLength = (wcslen(lpPassword) + 1) * sizeof(WCHAR); + /* Encrypt the password */ + dwError = ScmEncryptPassword(lpPassword, + &lpEncryptedPassword, + &dwPasswordSize); + if (dwError != ERROR_SUCCESS) + goto done; } RpcTryExcept @@ -753,7 +824,7 @@ CreateServiceW(SC_HANDLE hSCManager, dwDependenciesLength, lpServiceStartName, lpEncryptedPassword, - dwPasswordLength, + dwPasswordSize, (SC_RPC_HANDLE *)&hService); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) @@ -762,6 +833,14 @@ CreateServiceW(SC_HANDLE hSCManager, } RpcEndExcept; +done: + if (lpEncryptedPassword != NULL) + { + /* Wipe and release the password buffers */ + ZeroMemory(lpEncryptedPassword, dwPasswordSize); + HeapFree(GetProcessHeap(), 0, lpEncryptedPassword); + } + SetLastError(dwError); if (dwError != ERROR_SUCCESS) {