?? win32_service.c
字號:
/* $Id$ *//*** 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 Version 2 as** published by the Free Software Foundation. You may not use, modify or** distribute this program under any other version of the GNU General** Public License.**** 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 "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 } }; */ SERVICE_TABLE_ENTRY steDispatchTable[2]; steDispatchTable[0].lpServiceName = g_lpszServiceName; steDispatchTable[0].lpServiceProc = SnortServiceStart; steDispatchTable[1].lpServiceName = NULL; steDispatchTable[1].lpServiceProc = NULL; for( i=1; i<argc; i++ ) { if( _stricmp(argv[i],SERVICE_CMDLINE_PARAM) == 0) { /* Ignore param, because we already know that this is a service * simply by the fact that we are already in this function. * However, perform a sanity check to ensure that the user * didn't just type "snort /SERVICE" without an indicator * following. */ if( (i+1) < argc && ( _stricmp(argv[(i+1)], SERVICE_INSTALL_CMDLINE_PARAM)!=0 || _stricmp(argv[(i+1)], SERVICE_UNINSTALL_CMDLINE_PARAM)!=0 || _stricmp(argv[(i+1)], SERVICE_SHOW_CMDLINE_PARAM)!=0 ) ) { /* user entered correct command-line parameters, keep looping */ continue; } } 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() */ } } /* 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", 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-1); szString[iCount-1]=0; /* 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) = SnortAlloc( ((*piArgCounter) + 2) * sizeof(char *) ); (*pargvDynamic)[0] = SnortStrdup(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
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -