/* FUNCTIONS *****************************************************************/
+static
+BOOL
+ScmIsSecurityService(
+ _In_ PSERVICE_IMAGE pServiceImage)
+{
+ return (wcsstr(pServiceImage->pszImagePath, L"\\system32\\lsass.exe") != NULL);
+}
+
+
static DWORD
-ScmCreateNewControlPipe(PSERVICE_IMAGE pServiceImage)
+ScmCreateNewControlPipe(
+ _In_ PSERVICE_IMAGE pServiceImage,
+ _In_ BOOL bSecurityServiceProcess)
{
WCHAR szControlPipeName[MAX_PATH + 1];
+ SECURITY_ATTRIBUTES SecurityAttributes;
HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
- DWORD ServiceCurrent = 0;
- DWORD KeyDisposition;
+ DWORD dwServiceCurrent = 1;
+ DWORD dwKeyDisposition;
DWORD dwKeySize;
DWORD dwError;
/* Get the service number */
- /* TODO: Create registry entry with correct write access */
- dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
- L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent", 0, NULL,
- REG_OPTION_VOLATILE,
- KEY_WRITE | KEY_READ,
- NULL,
- &hServiceCurrentKey,
- &KeyDisposition);
- if (dwError != ERROR_SUCCESS)
- {
- DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
- return dwError;
- }
-
- if (KeyDisposition == REG_OPENED_EXISTING_KEY)
+ if (bSecurityServiceProcess == FALSE)
{
- dwKeySize = sizeof(DWORD);
- dwError = RegQueryValueExW(hServiceCurrentKey,
- L"", 0, NULL, (BYTE*)&ServiceCurrent, &dwKeySize);
-
+ /* TODO: Create registry entry with correct write access */
+ dwError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Control\\ServiceCurrent",
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ KEY_WRITE | KEY_READ,
+ NULL,
+ &hServiceCurrentKey,
+ &dwKeyDisposition);
if (dwError != ERROR_SUCCESS)
{
- RegCloseKey(hServiceCurrentKey);
- DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError);
+ DPRINT1("RegCreateKeyEx() failed with error %lu\n", dwError);
return dwError;
}
- ServiceCurrent++;
- }
+ if (dwKeyDisposition == REG_OPENED_EXISTING_KEY)
+ {
+ dwKeySize = sizeof(DWORD);
+ dwError = RegQueryValueExW(hServiceCurrentKey,
+ L"",
+ 0,
+ NULL,
+ (BYTE*)&dwServiceCurrent,
+ &dwKeySize);
+ if (dwError != ERROR_SUCCESS)
+ {
+ RegCloseKey(hServiceCurrentKey);
+ DPRINT1("RegQueryValueEx() failed with error %lu\n", dwError);
+ return dwError;
+ }
- dwError = RegSetValueExW(hServiceCurrentKey, L"", 0, REG_DWORD, (BYTE*)&ServiceCurrent, sizeof(ServiceCurrent));
+ dwServiceCurrent++;
+ }
- RegCloseKey(hServiceCurrentKey);
+ dwError = RegSetValueExW(hServiceCurrentKey,
+ L"",
+ 0,
+ REG_DWORD,
+ (BYTE*)&dwServiceCurrent,
+ sizeof(dwServiceCurrent));
- if (dwError != ERROR_SUCCESS)
+ RegCloseKey(hServiceCurrentKey);
+
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
+ return dwError;
+ }
+ }
+ else
{
- DPRINT1("RegSetValueExW() failed (Error %lu)\n", dwError);
- return dwError;
+ dwServiceCurrent = 0;
}
/* Create '\\.\pipe\net\NtControlPipeXXX' instance */
StringCchPrintfW(szControlPipeName, ARRAYSIZE(szControlPipeName),
- L"\\\\.\\pipe\\net\\NtControlPipe%lu", ServiceCurrent);
+ L"\\\\.\\pipe\\net\\NtControlPipe%lu", dwServiceCurrent);
DPRINT("PipeName: %S\n", szControlPipeName);
+ SecurityAttributes.nLength = sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor = pPipeSD;
+ SecurityAttributes.bInheritHandle = FALSE;
+
pServiceImage->hControlPipe = CreateNamedPipeW(szControlPipeName,
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
8000,
4,
PipeTimeout,
- NULL);
+ &SecurityAttributes);
DPRINT("CreateNamedPipeW(%S) done\n", szControlPipeName);
if (pServiceImage->hControlPipe == INVALID_HANDLE_VALUE)
{
}
+static
+BOOL
+ScmEnableBackupRestorePrivileges(
+ _In_ HANDLE hToken,
+ _In_ BOOL bEnable)
+{
+ PTOKEN_PRIVILEGES pTokenPrivileges = NULL;
+ DWORD dwSize;
+ BOOL bRet = FALSE;
+
+ DPRINT("ScmEnableBackupRestorePrivileges(%p %d)\n", hToken, bEnable);
+
+ dwSize = sizeof(TOKEN_PRIVILEGES) + 2 * sizeof(LUID_AND_ATTRIBUTES);
+ pTokenPrivileges = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
+ if (pTokenPrivileges == NULL)
+ {
+ DPRINT1("Failed to allocate the privilege buffer!\n");
+ goto done;
+ }
+
+ pTokenPrivileges->PrivilegeCount = 2;
+ pTokenPrivileges->Privileges[0].Luid.LowPart = SE_BACKUP_PRIVILEGE;
+ pTokenPrivileges->Privileges[0].Luid.HighPart = 0;
+ pTokenPrivileges->Privileges[0].Attributes = (bEnable ? SE_PRIVILEGE_ENABLED : 0);
+ pTokenPrivileges->Privileges[1].Luid.LowPart = SE_RESTORE_PRIVILEGE;
+ pTokenPrivileges->Privileges[1].Luid.HighPart = 0;
+ pTokenPrivileges->Privileges[1].Attributes = (bEnable ? SE_PRIVILEGE_ENABLED : 0);
+
+ bRet = AdjustTokenPrivileges(hToken, FALSE, pTokenPrivileges, 0, NULL, NULL);
+ if (!bRet)
+ {
+ DPRINT1("AdjustTokenPrivileges() failed with error %lu\n", GetLastError());
+ }
+ else if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
+ {
+ DPRINT1("AdjustTokenPrivileges() succeeded, but with not all privileges assigned\n");
+ bRet = FALSE;
+ }
+
+done:
+ if (pTokenPrivileges != NULL)
+ HeapFree(GetProcessHeap(), 0, pTokenPrivileges);
+
+ return bRet;
+}
+
+
static
DWORD
ScmLogonService(
IN PSERVICE pService,
IN PSERVICE_IMAGE pImage)
{
- DWORD dwError = ERROR_SUCCESS;
PROFILEINFOW ProfileInfo;
PWSTR pszUserName = NULL;
PWSTR pszDomainName = NULL;
PWSTR pszPassword = NULL;
PWSTR ptr;
+ DWORD dwError = ERROR_SUCCESS;
DPRINT("ScmLogonService(%p %p)\n", pService, pImage);
DPRINT("Service %S\n", pService->lpServiceName);
// ProfileInfo.lpPolicyPath = NULL;
// ProfileInfo.hProfile = NULL;
+ ScmEnableBackupRestorePrivileges(pImage->hToken, TRUE);
if (!LoadUserProfileW(pImage->hToken, &ProfileInfo))
- {
dwError = GetLastError();
+ ScmEnableBackupRestorePrivileges(pImage->hToken, FALSE);
+
+ if (dwError != ERROR_SUCCESS)
+ {
DPRINT1("LoadUserProfileW() failed (Error %lu)\n", dwError);
goto done;
}
DWORD dwError = ERROR_SUCCESS;
DWORD dwRecordSize;
LPWSTR pString;
+ BOOL bSecurityService;
DPRINT("ScmCreateOrReferenceServiceImage(%p)\n", pService);
goto done;
}
+ bSecurityService = ScmIsSecurityService(pServiceImage);
+
/* Create the control pipe */
- dwError = ScmCreateNewControlPipe(pServiceImage);
+ dwError = ScmCreateNewControlPipe(pServiceImage,
+ bSecurityService);
if (dwError != ERROR_SUCCESS)
{
DPRINT1("ScmCreateNewControlPipe() failed (Error %lu)\n", dwError);
/* Unload the user profile */
if (pServiceImage->hProfile != NULL)
+ {
+ ScmEnableBackupRestorePrivileges(pServiceImage->hToken, TRUE);
UnloadUserProfile(pServiceImage->hToken, pServiceImage->hProfile);
+ ScmEnableBackupRestorePrivileges(pServiceImage->hToken, FALSE);
+ }
/* Close the logon token */
if (pServiceImage->hToken != NULL)
goto done;
}
+ if (bSecurityService)
+ {
+ SetSecurityServicesEvent();
+ }
+
/* FIXME: Add more initialization code here */
/* Unload the user profile */
if (pServiceImage->hProfile != NULL)
+ {
+ ScmEnableBackupRestorePrivileges(pServiceImage->hToken, TRUE);
UnloadUserProfile(pServiceImage->hToken, pServiceImage->hProfile);
+ ScmEnableBackupRestorePrivileges(pServiceImage->hToken, FALSE);
+ }
/* Close the logon token */
if (pServiceImage->hToken != NULL)
}
}
- if (dwProcessId != Service->lpImage->dwProcessId)
+ if ((ScmIsSecurityService(Service->lpImage) == FALSE)&&
+ (dwProcessId != Service->lpImage->dwProcessId))
{
#if 0
_ultow(Service->lpImage->dwProcessId, szBuffer1, 10);
StartupInfo.lpDesktop = L"WinSta0\\Default";
}
- Result = CreateProcessW(NULL,
- Service->lpImage->pszImagePath,
- NULL,
- NULL,
- FALSE,
- CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS | CREATE_SUSPENDED,
- lpEnvironment,
- NULL,
- &StartupInfo,
- &ProcessInformation);
- if (!Result)
- dwError = GetLastError();
+ if (!ScmIsSecurityService(Service->lpImage))
+ {
+ Result = CreateProcessW(NULL,
+ Service->lpImage->pszImagePath,
+ NULL,
+ NULL,
+ FALSE,
+ CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS | CREATE_SUSPENDED,
+ lpEnvironment,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation);
+ if (!Result)
+ dwError = GetLastError();
+ }
+ else
+ {
+ Result = TRUE;
+ dwError = ERROR_SUCCESS;
+ }
}
if (lpEnvironment)