new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / win32 / win_service.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All rights reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation.
8  */
9
10 #ifdef WIN32
11
12 #include "shared.h"
13 #include "os_win.h"
14 #include <winsvc.h>
15
16 #ifndef ARGV0
17 #define ARGV0 "ossec-agent"
18 #endif
19
20 static LPTSTR g_lpszServiceName        = "OssecSvc";
21 static LPTSTR g_lpszServiceDisplayName = "OSSEC HIDS";
22 static LPTSTR g_lpszServiceDescription = "OSSEC HIDS Windows Agent";
23
24 static SERVICE_STATUS          ossecServiceStatus;
25 static SERVICE_STATUS_HANDLE   ossecServiceStatusHandle;
26
27 void WINAPI OssecServiceStart (DWORD argc, LPTSTR *argv);
28
29
30 /* Start OSSEC-HIDS service */
31 int os_start_service()
32 {
33     int rc = 0;
34     SC_HANDLE schSCManager, schService;
35
36     /* Start the database */
37     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
38     if (schSCManager) {
39         schService = OpenService(schSCManager, g_lpszServiceName,
40                                  SC_MANAGER_ALL_ACCESS);
41         if (schService) {
42             if (StartService(schService, 0, NULL)) {
43                 rc = 1;
44             } else {
45                 if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) {
46                     rc = -1;
47                 }
48             }
49
50             CloseServiceHandle(schService);
51         }
52
53         CloseServiceHandle(schSCManager);
54     }
55
56     return (rc);
57 }
58
59 /* Stop OSSEC-HIDS service */
60 int os_stop_service()
61 {
62     int rc = 0;
63     SC_HANDLE schSCManager, schService;
64
65     /* Stop the service database */
66     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
67     if (schSCManager) {
68         schService = OpenService(schSCManager, g_lpszServiceName,
69                                  SC_MANAGER_ALL_ACCESS);
70         if (schService) {
71             SERVICE_STATUS lpServiceStatus;
72
73             if (ControlService(schService, SERVICE_CONTROL_STOP, &lpServiceStatus)) {
74                 rc = 1;
75             }
76
77             CloseServiceHandle(schService);
78         }
79
80         CloseServiceHandle(schSCManager);
81     }
82
83     return (rc);
84 }
85
86 /* Check if the OSSEC-HIDS agent service is running
87  * Returns 1 on success (running) or 0 if not running
88  */
89 int CheckServiceRunning()
90 {
91     int rc = 0;
92     SC_HANDLE schSCManager, schService;
93
94     /* Check service status */
95     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
96     if (schSCManager) {
97         schService = OpenService(schSCManager, g_lpszServiceName,
98                                  SC_MANAGER_ALL_ACCESS);
99         if (schService) {
100             /* Check status */
101             SERVICE_STATUS lpServiceStatus;
102
103             if (QueryServiceStatus(schService, &lpServiceStatus)) {
104                 if (lpServiceStatus.dwCurrentState == SERVICE_RUNNING) {
105                     rc = 1;
106                 }
107             }
108             CloseServiceHandle(schService);
109         }
110
111         CloseServiceHandle(schSCManager);
112     }
113
114     return (rc);
115 }
116
117 /* Install the OSSEC-HIDS agent service */
118 int InstallService(char *path)
119 {
120     int ret;
121     SC_HANDLE schSCManager, schService;
122     LPCTSTR lpszBinaryPathName = NULL;
123     SERVICE_DESCRIPTION sdBuf;
124
125     /* Uninstall service (if it exists) */
126     if (!UninstallService()) {
127         verbose("%s: ERROR: Failure running UninstallService().", ARGV0);
128         return (0);
129     }
130
131     /* Executable path -- it must be called with the full path */
132     lpszBinaryPathName = path;
133
134     /* Opening the service database */
135     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
136
137     if (schSCManager == NULL) {
138         goto install_error;
139     }
140
141     /* Create the service */
142     schService = CreateService(schSCManager,
143                                g_lpszServiceName,
144                                g_lpszServiceDisplayName,
145                                SERVICE_ALL_ACCESS,
146                                SERVICE_WIN32_OWN_PROCESS,
147                                SERVICE_AUTO_START,
148                                SERVICE_ERROR_NORMAL,
149                                lpszBinaryPathName,
150                                NULL, NULL, NULL, NULL, NULL);
151
152     if (schService == NULL) {
153         CloseServiceHandle(schSCManager);
154         goto install_error;
155     }
156
157     /* Set description */
158     sdBuf.lpDescription = g_lpszServiceDescription;
159     ret = ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &sdBuf);
160
161     CloseServiceHandle(schService);
162     CloseServiceHandle(schSCManager);
163
164     /* Check for errors */
165     if (!ret) {
166         goto install_error;
167     }
168
169     verbose("%s: INFO: Successfully added to the service database.", ARGV0);
170     return (1);
171
172 install_error: {
173         char local_msg[1025];
174         LPVOID lpMsgBuf;
175
176         memset(local_msg, 0, 1025);
177
178         FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
179                        FORMAT_MESSAGE_FROM_SYSTEM |
180                        FORMAT_MESSAGE_IGNORE_INSERTS,
181                        NULL,
182                        GetLastError(),
183                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
184                        (LPTSTR) &lpMsgBuf,
185                        0,
186                        NULL);
187
188         verbose("%s: ERROR: Unable to create service entry: %s", ARGV0, (LPCTSTR)lpMsgBuf);
189         return (0);
190     }
191 }
192
193 /* Uninstall the OSSEC-HIDS agent service */
194 int UninstallService()
195 {
196     int ret;
197     int rc = 0;
198     SC_HANDLE schSCManager, schService;
199     SERVICE_STATUS lpServiceStatus;
200
201     /* Remove from the service database */
202     schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
203     if (schSCManager) {
204         schService = OpenService(schSCManager, g_lpszServiceName, SERVICE_STOP | DELETE);
205         if (schService) {
206             if (CheckServiceRunning()) {
207                 verbose("%s: INFO: Found (%s) service is running going to try and stop it.", ARGV0, g_lpszServiceName);
208                 ret = ControlService(schService, SERVICE_CONTROL_STOP, &lpServiceStatus);
209                 if (!ret) {
210                     verbose("%s: ERROR: Failure stopping service (%s) before removing it (%ld).", ARGV0, g_lpszServiceName, GetLastError());
211                 } else {
212                     verbose("%s: INFO: Successfully stopped (%s).", ARGV0, g_lpszServiceName);
213                 }
214             } else {
215                 verbose("%s: INFO: Found (%s) service is not running.", ARGV0, g_lpszServiceName);
216                 ret = 1;
217             }
218
219             if (ret && DeleteService(schService)) {
220                 verbose("%s: INFO: Successfully removed (%s) from the service database.", ARGV0, g_lpszServiceName);
221                 rc = 1;
222             }
223             CloseServiceHandle(schService);
224         } else {
225             verbose("%s: INFO: Service does not exist (%s) nothing to remove.", ARGV0, g_lpszServiceName);
226             rc = 1;
227         }
228         CloseServiceHandle(schSCManager);
229     }
230
231     if (!rc) {
232         verbose("%s: ERROR: Failure removing (%s) from the service database.", ARGV0, g_lpszServiceName);
233     }
234
235     return (rc);
236 }
237
238 /* "Signal" handler */
239 VOID WINAPI OssecServiceCtrlHandler(DWORD dwOpcode)
240 {
241     switch (dwOpcode) {
242         case SERVICE_CONTROL_STOP:
243             ossecServiceStatus.dwCurrentState           = SERVICE_STOPPED;
244             ossecServiceStatus.dwWin32ExitCode          = 0;
245             ossecServiceStatus.dwCheckPoint             = 0;
246             ossecServiceStatus.dwWaitHint               = 0;
247
248             verbose("%s: INFO: Received exit signal.", ARGV0);
249             SetServiceStatus (ossecServiceStatusHandle, &ossecServiceStatus);
250             verbose("%s: INFO: Exiting...", ARGV0);
251             return;
252         default:
253             break;
254     }
255     return;
256 }
257
258 /* Set the error code in the service */
259 void WinSetError()
260 {
261     OssecServiceCtrlHandler(SERVICE_CONTROL_STOP);
262 }
263
264 /* Initialize OSSEC-HIDS dispatcher */
265 int os_WinMain(__attribute__((unused)) int argc, __attribute__((unused)) char **argv)
266 {
267     SERVICE_TABLE_ENTRY   steDispatchTable[] = {
268         { g_lpszServiceName, OssecServiceStart },
269         { NULL,       NULL                     }
270     };
271
272     if (!StartServiceCtrlDispatcher(steDispatchTable)) {
273         verbose("%s: INFO: Unable to set service information.", ARGV0);
274         return (1);
275     }
276
277     return (1);
278 }
279
280 /* Start OSSEC service */
281 void WINAPI OssecServiceStart (__attribute__((unused)) DWORD argc, __attribute__((unused)) LPTSTR *argv)
282 {
283     ossecServiceStatus.dwServiceType            = SERVICE_WIN32;
284     ossecServiceStatus.dwCurrentState           = SERVICE_START_PENDING;
285     ossecServiceStatus.dwControlsAccepted       = SERVICE_ACCEPT_STOP;
286     ossecServiceStatus.dwWin32ExitCode          = 0;
287     ossecServiceStatus.dwServiceSpecificExitCode = 0;
288     ossecServiceStatus.dwCheckPoint             = 0;
289     ossecServiceStatus.dwWaitHint               = 0;
290
291     ossecServiceStatusHandle =
292         RegisterServiceCtrlHandler(g_lpszServiceName,
293                                    OssecServiceCtrlHandler);
294
295     if (ossecServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) {
296         verbose("%s: INFO: RegisterServiceCtrlHandler failed.", ARGV0);
297         return;
298     }
299
300     ossecServiceStatus.dwCurrentState = SERVICE_RUNNING;
301     ossecServiceStatus.dwCheckPoint = 0;
302     ossecServiceStatus.dwWaitHint = 0;
303
304     if (!SetServiceStatus(ossecServiceStatusHandle, &ossecServiceStatus)) {
305         verbose("%s: INFO: SetServiceStatus error.", ARGV0);
306         return;
307     }
308
309 #ifdef OSSECHIDS
310     /* Start process */
311     local_start();
312 #endif
313 }
314
315 #endif /* WIN32 */