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