/// Prelude actions to start up the service, e.g. to set any global variables from the settings or perform /// any system specific actions. E.g. the Windows implementation registers with the service control manager /// and can optionally set the security descriptor on the process to allow clients to kill/restart it. /// /// @param[in] nReason how the startup is occuring (e.g. SERVICE_RUN_INLINE) - different actions may be /// required depending on whether the code is running direct from main() or through another mechansim static void _ServiceStartup (int nReason) { CSettings oSettings; #ifdef _WIN32 if (nReason == SERVICE_RUN_SCM) { g_hServiceStatus = RegisterServiceCtrlHandler (oSettings.GetServiceName (), ServiceHandler); } PCTSTR pszSDDL = oSettings.GetServiceSDDL (); if (pszSDDL) { LOGDEBUG (TEXT ("Setting security descriptor ") << pszSDDL); PSECURITY_DESCRIPTOR psdRelative; if (ConvertStringSecurityDescriptorToSecurityDescriptor (pszSDDL, SDDL_REVISION_1, &psdRelative, NULL)) { DWORD cbAbsolute = 1024; PSECURITY_DESCRIPTOR psdAbsolute = (PSECURITY_DESCRIPTOR)malloc (cbAbsolute); DWORD cbD = 1024; PACL paclD = (PACL)malloc (cbD); DWORD cbS = 1024; PACL paclS = (PACL)malloc (cbS); DWORD cbOwner = 1024; PSID psidOwner = (PSID)malloc (cbOwner); DWORD cbPGroup = 1024; PSID psidPGroup = (PSID)malloc (cbPGroup); if (MakeAbsoluteSD (psdRelative, psdAbsolute, &cbAbsolute, paclD, &cbD, paclS, &cbS, psidOwner, &cbOwner, psidPGroup, &cbPGroup)) { DWORD dwError = SetSecurityInfo (GetCurrentProcess (), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, paclD, NULL); if (dwError == ERROR_SUCCESS) { LOGINFO (TEXT ("Security descriptor set on process handle")); } else { LOGWARN (TEXT ("Couldn't set security descriptor on process handle, error ") << GetLastError ()); } } else { LOGWARN (TEXT ("Couldn't create absolute security description, error ") << GetLastError ()); } free (psdAbsolute); free (paclD); free (paclS); free (psidOwner); free (psidPGroup); LocalFree (psdRelative); } else { LOGWARN (TEXT ("Couldn't parse SDDL ") << pszSDDL << TEXT (", error ") << GetLastError ()); } } else { LOGDEBUG (TEXT ("No security descriptor specified")); } #endif /* ifdef _WIN32 */ g_lBusyTimeout = oSettings.GetBusyTimeout (); _ReportStateStarting (); }
/// Run the service, returning when it has stopped. /// /// @param[in] nReason how the service is running, e.g. SERVICE_RUN_INLINE, in case actions are different depending /// on how it was started. void ServiceRun (int nReason) { _ServiceStartup (nReason); g_poJVM = CJVM::Create (); if (!g_poJVM) { LOGERROR (TEXT ("Couldn't create JVM")); _ReportStateErrored (); return; } g_poJVM->Start (); g_poPipe = CConnectionPipe::Create (); if (!g_poPipe) { LOGERROR (TEXT ("Couldn't create IPC pipe")); } while (g_poJVM->IsBusy (g_lBusyTimeout)) { _ReportStateStarting (); } if (g_poPipe && g_poJVM->IsRunning ()) { _ReportStateRunning (); do { LOGDEBUG (TEXT ("Waiting for user connection")); ClientConnect *pcc = g_poPipe->ReadMessage (); if (pcc) { LOGINFO (TEXT ("Connection received from ") << pcc->_userName); LOGDEBUG (TEXT ("C++ -> Java = ") << pcc->_CPPToJavaPipe); LOGDEBUG (TEXT ("Java -> C++ = ") << pcc->_JavaToCPPPipe); // TODO [PLAT-1117] Use challenge/response to verify the user name g_poJVM->UserConnection (pcc->_userName, pcc->_CPPToJavaPipe, pcc->_JavaToCPPPipe, pcc->_languageID); ClientConnect_free (pcc); if (!g_poJVM->IsStopped ()) { g_poPipe->CancelLazyClose (); if (g_poJVM->IsStopped ()) { // Stop might have occurred between the check and the cancel, so restore the cancel ServiceStop (false); } } g_oMutex.Enter (); if (g_poPipe->IsClosed ()) { LOGINFO (TEXT ("Pipe closed with pending connection - reopening")); delete g_poPipe; g_poPipe = CConnectionPipe::Create (); if (g_poPipe) { _ReportStateRunning (); } else { LOGERROR (TEXT ("Couldn't create IPC pipe - shutting down JVM")); g_poJVM->Stop (); } } g_oMutex.Leave (); } else { LOGERROR (TEXT ("Shutting down JVM after failing to read from pipe")); g_poJVM->Stop (); } } while (!g_poJVM->IsBusy (g_lBusyTimeout) && g_poJVM->IsRunning ()); _ReportStateStopping (); while (g_poJVM->IsBusy (g_lBusyTimeout)) { _ReportStateStopping (); } _ReportStateStopped (); } else { _ReportStateErrored (); } if (g_poPipe) { delete g_poPipe; g_poPipe = NULL; } delete g_poJVM; g_poJVM = NULL; }
/// Prelude actions to start up the service, e.g. to set any global variables from the settings or perform /// any system specific actions. E.g. the Windows implementation registers with the service control manager /// and can optionally set the security descriptor on the process to allow clients to kill/restart it. /// /// @param[in] nReason how the startup is occuring (e.g. SERVICE_RUN_INLINE) - different actions may be /// required depending on whether the code is running direct from main() or through another mechansim static void _ServiceStartup (int nReason) { CSettings oSettings; #ifdef _WIN32 if (nReason == SERVICE_RUN_SCM) { g_hServiceStatus = RegisterServiceCtrlHandler (oSettings.GetServiceName (), ServiceHandler); } PCTSTR pszSDDL = oSettings.GetServiceSDDL (); if (pszSDDL) { LOGDEBUG (TEXT ("Setting security descriptor ") << pszSDDL); PSECURITY_DESCRIPTOR psdRelative; if (ConvertStringSecurityDescriptorToSecurityDescriptor (pszSDDL, SDDL_REVISION_1, &psdRelative, NULL)) { DWORD cbAbsolute = 1024; PSECURITY_DESCRIPTOR psdAbsolute = (PSECURITY_DESCRIPTOR)malloc (cbAbsolute); DWORD cbD = 1024; PACL paclD = (PACL)malloc (cbD); DWORD cbS = 1024; PACL paclS = (PACL)malloc (cbS); DWORD cbOwner = 1024; PSID psidOwner = (PSID)malloc (cbOwner); DWORD cbPGroup = 1024; PSID psidPGroup = (PSID)malloc (cbPGroup); if (MakeAbsoluteSD (psdRelative, psdAbsolute, &cbAbsolute, paclD, &cbD, paclS, &cbS, psidOwner, &cbOwner, psidPGroup, &cbPGroup)) { DWORD dwError = SetSecurityInfo (GetCurrentProcess (), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, paclD, NULL); if (dwError == ERROR_SUCCESS) { LOGINFO (TEXT ("Security descriptor set on process handle")); } else { LOGWARN (TEXT ("Couldn't set security descriptor on process handle, error ") << GetLastError ()); } if (nReason == SERVICE_RUN_SCM) { SC_HANDLE hSCM = OpenSCManager (NULL, NULL, GENERIC_READ); if (hSCM) { SC_HANDLE hService = OpenService (hSCM, oSettings.GetServiceName (), GENERIC_WRITE | WRITE_DAC); if (hService) { dwError = SetSecurityInfo (hService, SE_SERVICE, DACL_SECURITY_INFORMATION, NULL, NULL, paclD, NULL); if (dwError == ERROR_SUCCESS) { LOGINFO (TEXT ("Security descriptor set on service")); } else { LOGWARN (TEXT ("Couldn't set security descriptor on service, error ") << GetLastError ()); } CloseServiceHandle (hService); } else { LOGWARN (TEXT ("Couldn't open service, error ") << GetLastError ()); } CloseServiceHandle (hSCM); } else { LOGWARN (TEXT ("Couldn't open SCM, error ") << GetLastError ()); } } } else { LOGWARN (TEXT ("Couldn't create absolute security description, error ") << GetLastError ()); } free (psdAbsolute); free (paclD); free (paclS); free (psidOwner); free (psidPGroup); LocalFree (psdRelative); } else { LOGWARN (TEXT ("Couldn't parse SDDL ") << pszSDDL << TEXT (", error ") << GetLastError ()); } } else { LOGDEBUG (TEXT ("No security descriptor specified")); } #else /* ifdef _WIN32 */ if (nReason == SERVICE_RUN_DAEMON) { const TCHAR *pszPID = oSettings.GetPidFile (); if (pszPID) { LOGINFO (TEXT ("Creating PID file ") << pszPID); FILE *f = fopen (pszPID, "wt"); if (f) { fprintf (f, "%d", getpid ()); fclose (f); } else { LOGWARN (TEXT ("Couldn't write to PID file ") << pszPID << TEXT (", error ") << GetLastError ()); } } else { LOGWARN (TEXT ("No PID file")); } } #endif /* ifdef _WIN32 */ g_lBusyTimeout = oSettings.GetBusyTimeout (); _ReportStateStarting (); }