📄 win32_service.c
字号:
/* $Id: win32_service.c,v 1.5 2003/03/14 08:28:55 chris_reid Exp $ *//*** Copyright (C) 2002 Chris Reid <chris.reid@codecraftconsulants.com>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//* * win32_service.c v1.0 - 20 February 2002 * * Purpose: Lets Snort register as a Win32 Service. This includes both * an installation an uninstallation aspect. * * Author: Chris Reid (chris.reid@codecraftconsulants.com) * * Notes: The Snort command-line arguments need to be * saved into the registry when the snort service is * being installed. They are stored in: * HKLM \ SOFTWARE \ Snort * * Usage: * snort.exe /SERVICE /INSTALL [regular command-line params] * * snort.exe /SERVICE /UNINSTALL * * snort.exe /SERVICE /SHOW * * References * Microsoft has full docs on programming Win32 Services in their * MSDN (Microsoft Developer Network) library. * http://msdn.microsoft.com/ */#ifdef ENABLE_WIN32_SERVICE/* * Enable the next line to automatically assign a description to the Service. * According to the Microsoft documentation, the call to ChangeServiceConfig2() * which sets the description is only available on Windows 2000 or newer. * * #define SET_SERVICE_DESCRIPTION */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <Windows.h>#include <Winsvc.h> /* for Service stuff */#include <stdio.h> /* for printf(), etc */#include <direct.h> /* for _getcwd() */#include <shlwapi.h> /* for Windows shell */#include "snort.h"#include "debug.h"#include "util.h"static LPTSTR g_lpszServiceName = "SnortSvc";static LPTSTR g_lpszServiceDisplayName = "Snort";static LPTSTR g_lpszServiceDescription = "The Open Source Network Intrusion Detection System";static LPTSTR g_lpszRegistryKey = "SOFTWARE\\Snort";static LPTSTR g_lpszRegistryCmdFormat = "CmdLineParam_%03d";static LPTSTR g_lpszRegistryCountFormat= "CmdLineParamCount";static SERVICE_STATUS g_SnortServiceStatus; static SERVICE_STATUS_HANDLE g_SnortServiceStatusHandle; #define MAX_REGISTRY_KEY_LENGTH 255#define MAX_REGISTRY_DATA_LENGTH 1000 static VOID SvcDebugOut(LPSTR String, DWORD Status);static VOID SvcFormatMessage(LPSTR szString, int iCount);static VOID ReadServiceCommandLineParams( int * piArgCounter, char** * pargvDynamic );static VOID WINAPI SnortServiceStart (DWORD argc, LPTSTR *argv); static VOID WINAPI SnortServiceCtrlHandler (DWORD opcode); static DWORD SnortServiceInitialization (DWORD argc, LPTSTR *argv, DWORD *specificError); static VOID InstallSnortService(int argc, char* argv[]);static VOID UninstallSnortService();static VOID ShowSnortServiceParams();/******************************************************************************* * (This documentation was taken from Microsoft's own doc's on how to create * a Win32 Service.) * * Writing a Service Program's main Function * ----------------------------------------------------------------------------- * * The main function of a service program calls the StartServiceCtrlDispatcher * function to connect to the SCM and start the control dispatcher thread. The * dispatcher thread loops, waiting for incoming control requests for the * services specified in the dispatch table. This thread does not return until * there is an error or all of the services in the process have terminated. When * all services in a process have terminated, the SCM sends a control request * to the dispatcher thread telling it to shut down. The thread can then return * from the StartServiceCtrlDispatcher call and the process can terminate. * * The following example is a service process that supports only one service. It * takes two parameters: a string that can contain one formatted output * character and a numeric value to be used as the formatted character. The * SvcDebugOut function prints informational messages and errors to the debugger. * For information on writing the SnortServiceStart and SnortServiceInitialization * functions, see Writing a ServiceMain Function. For information on writing the * SnortServiceCtrlHandler function, see Writing a Control Handler Function. *******************************************************************************//* this is the entry point which is called from main() */int SnortServiceMain(int argc, char* argv[]) { int i; SERVICE_TABLE_ENTRY steDispatchTable[] = { { g_lpszServiceName, SnortServiceStart }, { NULL, NULL } }; for( i=1; i<argc; i++ ) { if( _stricmp(argv[i],SERVICE_CMDLINE_PARAM) == 0) { /* ignore it, because we already know that this is a service * simply by the fact that we are already in this function */ } else if( _stricmp(argv[i],SERVICE_INSTALL_CMDLINE_PARAM) == 0) { DEBUG_WRAP(DebugMessage(DEBUG_INIT, "User wishes to install the Snort service\n");); InstallSnortService(argc, argv); exit(0); } else if( _stricmp(argv[i],SERVICE_UNINSTALL_CMDLINE_PARAM) == 0) { DEBUG_WRAP(DebugMessage(DEBUG_INIT, "User wishes to un-install the Snort service\n");); UninstallSnortService(); exit(0); } else if( _stricmp(argv[i],SERVICE_SHOW_CMDLINE_PARAM) == 0) { DEBUG_WRAP(DebugMessage(DEBUG_INIT, "User wishes to show the Snort service command-line parameters\n");); ShowSnortServiceParams(); exit(0); } else { break; /* out of for() */ /* FatalError("ABORTING, unknown option: '%s'\n", argv[i]); */ /* exit(0); */ } } /* If we got to this point, then it's time to start up the Win32 Service */ if (!StartServiceCtrlDispatcher(steDispatchTable)) { char szString[1024]; memset(szString, sizeof(szString), '\0'); SvcFormatMessage(szString, sizeof(szString)); SvcDebugOut(szString, 0); SvcDebugOut(" [SNORT_SERVICE] StartServiceCtrlDispatcher error = %d\n%s\n", GetLastError()); FatalError (" [SNORT_SERVICE] StartServiceCtrlDispatcher error = %d\n%s\n", GetLastError(), szString); } return(0);} VOID SvcDebugOut(LPSTR szString, DWORD dwStatus) { CHAR szBuffer[1024]; if (strlen(szString) < 1000) { sprintf(szBuffer, szString, dwStatus); OutputDebugStringA(szBuffer); } }/* Copy the system error message into the buffer provided. * The buffer length is indicated in iCount. */VOID SvcFormatMessage(LPSTR szString, int iCount){ LPVOID lpMsgBuf; if( szString!=NULL && iCount>0) { memset(szString, 0, iCount); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ (LPTSTR) &lpMsgBuf, 0, NULL ); strncpy(szString, (LPCTSTR) lpMsgBuf, iCount); /* Free the buffer. */ LocalFree( lpMsgBuf ); lpMsgBuf = NULL; }}VOID ReadServiceCommandLineParams( int * piArgCounter, char** * pargvDynamic ){ HKEY hkSnort = NULL; long lRegRC = 0; DWORD dwType; DWORD dwDataSize; BYTE byData[MAX_REGISTRY_DATA_LENGTH]; int i; /********** * Read the registry entries for Snort command line parameters **********/ lRegRC = RegOpenKeyEx( HKEY_LOCAL_MACHINE, /* handle to open key */ g_lpszRegistryKey, /* subkey name */ 0, /* reserved (must be zero) */ KEY_READ, /* desired security access */ &hkSnort /* key handle */ ); if( lRegRC != ERROR_SUCCESS ) { TCHAR szMsg[1000]; SvcFormatMessage(szMsg, sizeof(szMsg)); FatalError(" [SNORT_SERVICE] Unable to open Snort registry entry. " " Perhaps Snort has not been installed as a service." " %s", szMsg); } memset(byData, 0, sizeof(byData)); dwDataSize = sizeof(byData); lRegRC = RegQueryValueEx( hkSnort, /* handle to key */ g_lpszRegistryCountFormat, /* value name */ NULL, /* reserved */ &dwType, /* type buffer */ byData, /* data buffer */ &dwDataSize /* size of data buffer */ ); if( lRegRC != ERROR_SUCCESS ) { TCHAR szMsg[1000]; SvcFormatMessage(szMsg, sizeof(szMsg)); FatalError(" [SNORT_SERVICE] Unable to read Snort registry entry '%s'." " Perhaps Snort has not been installed as a service." " %s", g_lpszRegistryCountFormat, szMsg); } (*piArgCounter) = * ((int*)&byData); (*pargvDynamic) = calloc( (*piArgCounter)+2, sizeof(char*) ); (*pargvDynamic)[0] = _strdup(g_lpszServiceName); DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Preparing to use the following command-line arguments:\n");); for( i=1; i<=(*piArgCounter); i++ ) { TCHAR szName[MAX_REGISTRY_KEY_LENGTH]; sprintf(szName, g_lpszRegistryCmdFormat, i); memset(byData, 0, sizeof(byData)); dwDataSize = sizeof(byData); lRegRC = RegQueryValueEx( hkSnort, /* handle to key */ szName, /* value name */ NULL, /* reserved */ &dwType, /* type buffer */ byData, /* data buffer */ &dwDataSize /* size of data buffer */ ); if( lRegRC != ERROR_SUCCESS ) { TCHAR szMsg[1000]; SvcFormatMessage(szMsg, sizeof(szMsg)); FatalError(" [SNORT_SERVICE] Unable to read Snort registry entry '%s'." " Perhaps Snort has not been installed as a service." " %s", szName, szMsg); } (*pargvDynamic)[i] = _strdup( (char*) byData ); DEBUG_WRAP(DebugMessage(DEBUG_INIT, " %s\n", (*pargvDynamic)[i]);); } lRegRC = RegCloseKey( hkSnort ); if( lRegRC != ERROR_SUCCESS ) { TCHAR szMsg[1000]; SvcFormatMessage(szMsg, sizeof(szMsg)); FatalError(" [SNORT_SERVICE] Unable to close Snort registry entry." " Perhaps Snort has not been installed as a service." " %s", szMsg); } hkSnort = NULL;}/******************************************************************************* * (This documentation was taken from Microsoft's own doc's on how to create * a Win32 Service.) * * Writing a ServiceMain Function * ----------------------------------------------------------------------------- * * The SnortServiceStart function in the following example is the entry point for * the service. SnortServiceStart has access to the command-line arguments, in the * way that the main function of a console application does. The first parameter * contains the number of arguments being passed to the service. There will * always be at least one argument. The second parameter is a pointer to an * array of string pointers. The first item in the array always points to the * service name. * * The SnortServiceStart function first fills in the SERVICE_STATUS structure * including the control codes that it accepts. Although this service accepts * SERVICE_CONTROL_PAUSE and SERVICE_CONTROL_CONTINUE, it does nothing * significant when told to pause. The flags SERVICE_ACCEPT_PAUSE_CONTINUE was * included for illustration purposes only; if pausing does not add value to * your service, do not support it. * * The SnortServiceStart function then calls the RegisterServiceCtrlHandler * function to register SnortService as the service's Handler function and begin * initialization. The following sample initialization function, * SnortServiceInitialization, is included for illustration purposes; it does not * perform any initialization tasks such as creating additional threads. If * your service's initialization performs tasks that are expected to take longer * than one second, your code must call the SetServiceStatus function * periodically to send out wait hints and check points indicating that progress * is being made. * * When initialization has completed successfully, the example calls * SetServiceStatus with a status of SERVICE_RUNNING and the service continues
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -