d17d7b8a0f1d3c40e328ca1e327bf2746ab2d0d5
[ossec-hids.git] / src / win32 / win_service.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All rights reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software
9  * Foundation.
10  *
11  * License details at the LICENSE file included with OSSEC or 
12  * online at: http://www.ossec.net/en/licensing.html
13  */
14
15
16 #ifdef WIN32
17
18 #include "shared.h"
19 #include "os_win.h"
20 #include <winsvc.h>
21
22 #ifndef ARGV0
23 #define ARGV0 "ossec-agent"
24 #endif
25
26 static LPTSTR g_lpszServiceName        = "OssecSvc";
27 static LPTSTR g_lpszServiceDisplayName = "OSSEC Hids";
28 static LPTSTR g_lpszServiceDescription = "OSSEC Hids Windows Agent";
29
30 static SERVICE_STATUS          ossecServiceStatus;
31 static SERVICE_STATUS_HANDLE   ossecServiceStatusHandle;
32
33 /* ServiceStart */
34 void WINAPI OssecServiceStart (DWORD argc, LPTSTR *argv);
35
36
37
38 /* os_start_service: Starts ossec service */
39 int os_start_service()
40 {
41     int rc = 0;
42     SC_HANDLE schSCManager, schService;
43
44
45     /* Removing from the services database */
46     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
47     if (schSCManager)
48     {
49         schService = OpenService(schSCManager,g_lpszServiceName,
50                                  SC_MANAGER_ALL_ACCESS);
51         if(schService)
52         {
53
54             if(StartService(schService, 0, NULL))
55             {
56                 rc = 1;
57             }
58             else
59             {
60                 if(GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
61                 {
62                     rc = -1;
63                 }
64             }
65             
66             CloseServiceHandle(schService);
67         }
68
69         CloseServiceHandle(schSCManager);
70     }
71
72     return(rc);
73 }
74
75
76 /* os_start_service: Starts ossec service */
77 int os_stop_service()
78 {
79     int rc = 0;
80     SC_HANDLE schSCManager, schService;
81
82
83     /* Removing from the services database */
84     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
85     if (schSCManager)
86     {
87         schService = OpenService(schSCManager,g_lpszServiceName,
88                                  SC_MANAGER_ALL_ACCESS);
89         if(schService)
90         {
91             SERVICE_STATUS lpServiceStatus;
92             
93             if(ControlService(schService, 
94                               SERVICE_CONTROL_STOP, &lpServiceStatus))
95             {
96                 rc = 1;
97             }
98             
99             CloseServiceHandle(schService);
100         }
101
102         CloseServiceHandle(schSCManager);
103     }
104
105     return(rc);
106 }
107
108
109 /* int QueryService(): Checks if service is running. */
110 int CheckServiceRunning()
111 {
112     int rc = 0;
113     SC_HANDLE schSCManager, schService;
114
115
116     /* Removing from the services database */
117     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
118     if (schSCManager)
119     {
120         schService = OpenService(schSCManager,g_lpszServiceName,
121                                  SC_MANAGER_ALL_ACCESS);
122         if(schService)
123         {
124             /* Checking status */
125             SERVICE_STATUS lpServiceStatus;
126             
127             if(QueryServiceStatus(schService, &lpServiceStatus))
128             {
129                 if(lpServiceStatus.dwCurrentState == SERVICE_RUNNING)
130                 {
131                     rc = 1;
132                 }
133             }
134             CloseServiceHandle(schService);
135         }
136         
137         CloseServiceHandle(schSCManager);
138     }
139
140     return(rc);
141 }
142
143                     
144 /* int InstallService()
145  * Install the OSSEC HIDS agent service.
146  */
147 int InstallService(char *path)
148 {
149     char buffer[MAX_PATH+1];
150
151     SC_HANDLE schSCManager, schService;
152     LPCTSTR lpszBinaryPathName = NULL;
153     SERVICE_DESCRIPTION sdBuf;
154     
155
156     /* Cleaning up some variables */
157     buffer[MAX_PATH] = '\0';
158     
159     
160     /* Executable path -- it must be called with the
161      * full path
162      */
163     lpszBinaryPathName = path;
164  
165     /* Opening the services database */
166     schSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
167
168     if (schSCManager == NULL)
169     {
170         goto install_error;
171     }
172
173     /* Creating the service */
174     schService = CreateService(schSCManager, 
175                                g_lpszServiceName,
176                                g_lpszServiceDisplayName,
177                                SERVICE_ALL_ACCESS,
178                                SERVICE_WIN32_OWN_PROCESS,
179                                SERVICE_AUTO_START,
180                                SERVICE_ERROR_NORMAL,
181                                lpszBinaryPathName,
182                                NULL, NULL, NULL, NULL, NULL);
183     
184     if (schService == NULL)
185     {
186         goto install_error;
187     }
188
189     /* Setting description */
190     sdBuf.lpDescription = g_lpszServiceDescription;
191     if(!ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &sdBuf))
192     {
193         goto install_error;
194     }
195     
196     CloseServiceHandle(schService);
197     CloseServiceHandle(schSCManager);
198
199     printf(" [%s] Successfully added to the Services database.\n", ARGV0);
200     return(1);
201
202
203     install_error:
204     {
205         char local_msg[1025];
206         LPVOID lpMsgBuf;
207         
208         memset(local_msg, 0, 1025);
209
210         FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
211                        FORMAT_MESSAGE_FROM_SYSTEM |
212                        FORMAT_MESSAGE_IGNORE_INSERTS,
213                        NULL,
214                        GetLastError(),
215                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
216                        (LPTSTR) &lpMsgBuf,
217                        0,
218                        NULL);
219
220         merror(local_msg, 1024, "[%s] Unable to create registry "
221                                   "entry: %s", ARGV0,(LPCTSTR)lpMsgBuf);
222         return(0);
223     }
224 }
225
226
227 /* int UninstallService()
228  * Uninstall the OSSEC HIDS agent service.
229  */
230 int UninstallService() 
231 {
232     SC_HANDLE schSCManager, schService;
233
234     
235     /* Removing from the services database */
236     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
237     if (schSCManager)
238     {
239         schService = OpenService(schSCManager,g_lpszServiceName,DELETE);
240         if(schService)
241         {
242             if (DeleteService(schService))
243
244             {
245                 CloseServiceHandle(schService);
246                 CloseServiceHandle(schSCManager);
247
248                 printf(" [%s] Successfully removed from "
249                        "the Services database.\n", ARGV0);
250                 return(1);
251             }
252             CloseServiceHandle(schService);
253         }
254         CloseServiceHandle(schSCManager);
255     }
256
257     fprintf(stderr, " [%s] Error removing from "
258                     "the Services database.\n", ARGV0);
259     
260     return(0);
261 }
262
263
264
265 /** VOID WINAPI OssecServiceCtrlHandler (DWORD dwOpcode)
266  * "Signal" handler
267  */
268 VOID WINAPI OssecServiceCtrlHandler(DWORD dwOpcode)
269 {
270     switch(dwOpcode)
271     {
272         case SERVICE_CONTROL_STOP:
273             ossecServiceStatus.dwCurrentState           = SERVICE_STOPPED;
274             ossecServiceStatus.dwWin32ExitCode          = 0;
275             ossecServiceStatus.dwCheckPoint             = 0;
276             ossecServiceStatus.dwWaitHint               = 0;
277
278             verbose("%s: Received exit signal.", ARGV0);
279             SetServiceStatus (ossecServiceStatusHandle, &ossecServiceStatus);
280             verbose("%s: Exiting...", ARGV0);
281             return;
282         default:
283             break;
284     }
285     return;
286 }
287  
288
289 /** void WinSetError()
290  * Sets the error code in the services
291  */
292 void WinSetError()
293 {
294     OssecServiceCtrlHandler(SERVICE_CONTROL_STOP);
295 }
296
297  
298 /** int os_WinMain(int argc, char **argv)
299  * Initializes OSSEC dispatcher
300  */
301 int os_WinMain(int argc, char **argv) 
302 {
303     SERVICE_TABLE_ENTRY   steDispatchTable[] =
304     {
305         { g_lpszServiceName, OssecServiceStart },
306         { NULL,       NULL                     }
307     };
308
309     if(!StartServiceCtrlDispatcher(steDispatchTable))
310     {
311         merror("%s: Unable to set service information.", ARGV0);
312         return(1);
313     }
314
315     return(1);
316 }
317
318
319 /** void WINAPI OssecServiceStart (DWORD argc, LPTSTR *argv)
320  * Starts OSSEC service
321  */
322 void WINAPI OssecServiceStart (DWORD argc, LPTSTR *argv)
323 {
324     ossecServiceStatus.dwServiceType            = SERVICE_WIN32;
325     ossecServiceStatus.dwCurrentState           = SERVICE_START_PENDING;
326     ossecServiceStatus.dwControlsAccepted       = SERVICE_ACCEPT_STOP;
327     ossecServiceStatus.dwWin32ExitCode          = 0;
328     ossecServiceStatus.dwServiceSpecificExitCode= 0;
329     ossecServiceStatus.dwCheckPoint             = 0;
330     ossecServiceStatus.dwWaitHint               = 0;
331
332     ossecServiceStatusHandle = 
333         RegisterServiceCtrlHandler(g_lpszServiceName, 
334                                    OssecServiceCtrlHandler);
335
336     if (ossecServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
337     {
338         merror("%s: RegisterServiceCtrlHandler failed.", ARGV0);
339         return;
340     }
341
342     ossecServiceStatus.dwCurrentState = SERVICE_RUNNING;
343     ossecServiceStatus.dwCheckPoint = 0;
344     ossecServiceStatus.dwWaitHint = 0;
345
346     if (!SetServiceStatus(ossecServiceStatusHandle, &ossecServiceStatus))
347     {
348         merror("%s: SetServiceStatus error.", ARGV0);
349         return;
350     }
351
352
353     #ifdef OSSECHIDS
354     /* Starting process */
355     local_start();
356     #endif
357 }
358
359
360 #endif
361 /* EOF */