1 /* Copyright (C) 2009 Trend Micro Inc.
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
13 #include "client-agent/agentd.h"
14 #include "logcollector/logcollector.h"
16 #include "os_net/os_net.h"
17 #include "os_execd/execd.h"
18 #include "os_crypto/md5/md5_op.h"
21 #define ARGV0 "ossec-agent"
24 time_t __win32_curr_time = 0;
25 time_t __win32_shared_time = 0;
26 char *__win32_uname = NULL;
27 char *__win32_shared = NULL;
31 int Start_win32_Syscheck();
32 void send_win32_info(time_t curr_time);
38 printf("\n%s %s %s .\n", __ossec_name, ARGV0, __version);
39 printf("Available options:\n");
40 printf("\t/? This help message.\n");
41 printf("\t-h This help message.\n");
42 printf("\thelp This help message.\n");
43 printf("\tinstall-service Installs as a service\n");
44 printf("\tuninstall-service Uninstalls as a service\n");
45 printf("\tstart Manually starts (not from services)\n");
49 /* syscheck main thread */
52 verbose("%s: Starting syscheckd thread.", ARGV0);
54 Start_win32_Syscheck();
59 int main(int argc, char **argv)
62 char mypath[OS_MAXSTR + 1];
63 char myfinalpath[OS_MAXSTR + 1];
64 char myfile[OS_MAXSTR + 1];
69 /* Find where we are */
70 mypath[OS_MAXSTR] = '\0';
71 myfinalpath[OS_MAXSTR] = '\0';
72 myfile[OS_MAXSTR] = '\0';
74 /* mypath is going to be the whole path of the file */
75 strncpy(mypath, argv[0], OS_MAXSTR);
76 tmpstr = strrchr(mypath, '\\');
78 /* tmpstr is now the file name */
81 strncpy(myfile, tmpstr, OS_MAXSTR);
83 strncpy(myfile, argv[0], OS_MAXSTR);
88 getcwd(mypath, OS_MAXSTR - 1);
89 snprintf(myfinalpath, OS_MAXSTR, "\"%s\\%s\"", mypath, myfile);
92 if (strcmp(argv[1], "install-service") == 0) {
93 return (InstallService(myfinalpath));
94 } else if (strcmp(argv[1], "uninstall-service") == 0) {
95 return (UninstallService());
96 } else if (strcmp(argv[1], "start") == 0) {
97 return (local_start());
98 } else if (strcmp(argv[1], "/?") == 0) {
100 } else if (strcmp(argv[1], "-h") == 0) {
102 } else if (strcmp(argv[1], "help") == 0) {
105 merror("%s: Unknown option: %s", ARGV0, argv[1]);
111 if (!os_WinMain(argc, argv)) {
112 ErrorExit("%s: Unable to start WinMain.", ARGV0);
118 /* Locally start (after service/win init) */
122 int accept_manager_commands = 0;
123 char *cfg = DEFAULTCPATH;
129 agt = (agent *)calloc(1, sizeof(agent));
131 ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno));
133 agt->port = DEFAULT_SECURE;
135 /* Get debug level */
136 debug_level = getDefine_Int("windows", "debug", 0, 2);
137 while (debug_level != 0) {
141 accept_manager_commands = getDefine_Int("logcollector",
142 "remote_commands", 0, 1);
143 loop_timeout = getDefine_Int("logcollector", "loop_timeout", 1, 120);
144 open_file_attempts = getDefine_Int("logcollector", "open_attempts", 2, 998);
146 /* Configuration file not present */
147 if (File_DateofChange(cfg) < 0) {
148 ErrorExit("%s: Configuration file '%s' not found", ARGV0, cfg);
152 if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
153 ErrorExit("%s: WSAStartup() failed", ARGV0);
156 /* Read agent config */
157 debug1("%s: DEBUG: Reading agent configuration.", ARGV0);
158 if (ClientConf(cfg) < 0) {
159 ErrorExit(CLIENT_ERROR, ARGV0);
161 if (agt->notify_time == 0) {
162 agt->notify_time = NOTIFY_TIME;
164 if (agt->max_time_reconnect_try == 0 ) {
165 agt->max_time_reconnect_try = NOTIFY_TIME * 3;
167 if (agt->max_time_reconnect_try <= agt->notify_time) {
168 agt->max_time_reconnect_try = (agt->notify_time * 3);
169 verbose("%s: Max time to reconnect can't be less than notify_time(%d), using notify_time*3 (%d)", ARGV0, agt->notify_time, agt->max_time_reconnect_try);
171 verbose("%s: Using notify time: %d and max time to reconnect: %d", ARGV0, agt->notify_time, agt->max_time_reconnect_try);
173 /* Read logcollector config file */
174 debug1("%s: DEBUG: Reading logcollector configuration.", ARGV0);
175 if (LogCollectorConfig(cfg, accept_manager_commands) < 0) {
176 ErrorExit(CONFIG_ERROR, ARGV0, cfg);
179 /* Check auth keys */
180 if (!OS_CheckKeys()) {
181 ErrorExit(AG_NOKEYS_EXIT, ARGV0);
184 /* If there is no file to monitor, create a clean entry
185 * for the mark messages.
188 os_calloc(2, sizeof(logreader), logff);
189 logff[0].file = NULL;
190 logff[0].ffile = NULL;
191 logff[0].logformat = NULL;
193 logff[1].file = NULL;
194 logff[1].logformat = NULL;
196 merror(NO_FILE, ARGV0);
199 /* Read execd config */
200 if (!WinExecd_Start()) {
205 verbose(ENC_READ, ARGV0);
208 OS_StartCounter(&keys);
209 os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id, agt->profile);
211 /* Initialize random numbers */
215 /* Socket connection */
220 debug1("%s: DEBUG: Creating thread mutex.", ARGV0);
221 hMutex = CreateMutex(NULL, FALSE, NULL);
222 if (hMutex == NULL) {
223 ErrorExit("%s: Error creating mutex.", ARGV0);
226 /* Start syscheck thread */
227 if (CreateThread(NULL,
229 (LPTHREAD_START_ROUTINE)skthread,
232 (LPDWORD)&threadID) == NULL) {
233 merror(THREAD_ERROR, ARGV0);
236 /* Check if server is connected */
241 /* Send integrity message for agent configs */
242 intcheck_file(cfg, "");
243 intcheck_file(OSSEC_DEFINES, "");
245 /* Start receiver thread */
246 if (CreateThread(NULL,
248 (LPTHREAD_START_ROUTINE)receiver_thread,
251 (LPDWORD)&threadID2) == NULL) {
252 merror(THREAD_ERROR, ARGV0);
255 /* Send agent information message */
256 send_win32_info(time(0));
258 /* Start logcollector -- main process here */
265 /* SendMSG for Windows */
266 int SendMSG(__attribute__((unused)) int queue, const char *message, const char *locmsg, char loc)
271 char tmpstr[OS_MAXSTR + 2];
272 char crypt_msg[OS_MAXSTR + 2];
275 tmpstr[OS_MAXSTR + 1] = '\0';
276 crypt_msg[OS_MAXSTR + 1] = '\0';
278 debug2("%s: DEBUG: Attempting to send message to server.", ARGV0);
280 /* Using a mutex to synchronize the writes */
282 dwWaitResult = WaitForSingleObject(hMutex, 1000000L);
284 if (dwWaitResult != WAIT_OBJECT_0) {
285 switch (dwWaitResult) {
287 merror("%s: Error waiting mutex (timeout).", ARGV0);
291 merror("%s: Error waiting mutex (abandoned).", ARGV0);
294 merror("%s: Error waiting mutex.", ARGV0);
301 } /* end - while for mutex... */
305 #ifndef ONEWAY_ENABLED
306 /* Check if the server has responded */
307 if ((cu_time - available_server) > agt->notify_time) {
308 debug1("%s: DEBUG: Sending info to server (c1)...", ARGV0);
309 verbose("%s: More than %d seconds without server response...sending win32info", ARGV0, agt->notify_time);
310 send_win32_info(cu_time);
312 /* Attempt to send message again */
313 if ((cu_time - available_server) > agt->notify_time) {
316 send_win32_info(cu_time);
319 if ((cu_time - available_server) > agt->notify_time) {
320 send_win32_info(cu_time);
324 /* If we reached here, the server is unavailable for a while */
325 if ((cu_time - available_server) > agt->max_time_reconnect_try) {
327 verbose("%s: More than %d seconds without server response...is server alive? and Is there connection?", ARGV0, agt->max_time_reconnect_try);
329 /* Last attempt before going into reconnect mode */
330 debug1("%s: DEBUG: Sending info to server (c3)...", ARGV0);
332 send_win32_info(cu_time);
333 if ((cu_time - available_server) > agt->max_time_reconnect_try) {
335 send_win32_info(cu_time);
339 /* Check and generate log if unavailable */
341 if ((cu_time - available_server) > agt->max_time_reconnect_try) {
342 int global_sleep = 1;
345 /* If response is not available, set lock and wait for it */
346 verbose(SERVER_UNAV, ARGV0);
348 /* Go into reconnect mode */
349 while ((cu_time - available_server) > agt->max_time_reconnect_try) {
350 /* Send information to see if server replies */
351 if (agt->sock != -1) {
352 send_win32_info(cu_time);
364 /* If we have more than one server, try all */
365 if (wi > 12 && agt->rip[1]) {
366 int curr_rip = agt->rip_id;
367 merror("%s: INFO: Trying next server ip in "
370 agt->rip[agt->rip_id + 1] != NULL ?
371 agt->rip[agt->rip_id + 1] :
374 connect_server(agt->rip_id + 1);
376 if (agt->rip_id != curr_rip) {
379 } else if (global_sleep == 2 || ((global_sleep % mod_sleep) == 0) ||
381 connect_server(agt->rip_id + 1);
382 if (agt->sock == -1) {
383 sleep(wi + global_sleep);
388 if (global_sleep > 30) {
394 verbose(AG_CONNECTED, ARGV0, agt->rip[agt->rip_id],
396 verbose(SERVER_UP, ARGV0);
405 /* Send notification */
406 else if ((cu_time - __win32_curr_time) > (NOTIFY_TIME - 200)) {
407 debug1("%s: DEBUG: Sending info to server (ctime2)...", ARGV0);
408 send_win32_info(cu_time);
411 /* locmsg cannot have the C:, as we use it as delimiter */
412 pl = strchr(locmsg, ':');
414 /* Set pl after the ":" if it exists */
421 debug2("%s: DEBUG: Sending message to server: '%s'", ARGV0, message);
423 snprintf(tmpstr, OS_MAXSTR, "%c:%s:%s", loc, pl, message);
424 _ssize = CreateSecMSG(&keys, tmpstr, crypt_msg, 0);
426 /* Returns NULL if can't create encrypted message */
428 merror(SEC_ERROR, ARGV0);
429 if (!ReleaseMutex(hMutex)) {
430 merror("%s: Error releasing mutex.", ARGV0);
436 /* Send _ssize of crypt_msg */
437 if (OS_SendUDPbySize(agt->sock, _ssize, crypt_msg) < 0) {
438 merror(SEND_ERROR, ARGV0, "server");
442 if (!ReleaseMutex(hMutex)) {
443 merror("%s: Error releasing mutex.", ARGV0);
448 /* StartMQ for Windows */
449 int StartMQ(const char *path, short int type)
451 /* Connect to the server */
454 if ((path == NULL) && (type == 0)) {
461 /* Send win32 info to server */
462 void send_win32_info(time_t curr_time)
465 char tmp_msg[OS_MAXSTR + 2];
466 char crypt_msg[OS_MAXSTR + 2];
468 tmp_msg[OS_MAXSTR + 1] = '\0';
469 crypt_msg[OS_MAXSTR + 1] = '\0';
471 debug1("%s: DEBUG: Sending keep alive message.", ARGV0);
474 __win32_curr_time = curr_time;
477 if (!__win32_uname) {
478 __win32_uname = getuname();
479 if (!__win32_uname) {
480 merror("%s: Error generating system information.", ARGV0);
481 os_strdup("Microsoft Windows - Unknown (unable to get system info)", __win32_uname);
485 /* Get shared files list -- every 30 seconds only */
486 if ((__win32_curr_time - __win32_shared_time) > 30) {
487 if (__win32_shared) {
488 free(__win32_shared);
489 __win32_shared = NULL;
492 __win32_shared_time = __win32_curr_time;
495 /* Get shared files */
496 if (!__win32_shared) {
497 __win32_shared = getsharedfiles();
498 if (!__win32_shared) {
499 __win32_shared = strdup("\0");
500 if (!__win32_shared) {
501 merror(MEM_ERROR, ARGV0, errno, strerror(errno));
508 if (File_DateofChange(AGENTCONFIGINT) > 0) {
510 if (OS_MD5_File(AGENTCONFIGINT, md5sum, OS_TEXT) != 0) {
511 snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s", __win32_uname, __win32_shared);
513 snprintf(tmp_msg, OS_SIZE_1024, "#!-%s / %s\n%s", __win32_uname, md5sum, __win32_shared);
516 snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s", __win32_uname, __win32_shared);
520 debug1("%s: DEBUG: Sending keep alive: %s", ARGV0, tmp_msg);
522 msg_size = CreateSecMSG(&keys, tmp_msg, crypt_msg, 0);
525 merror(SEC_ERROR, ARGV0);
529 /* Send UDP message */
530 if (OS_SendUDPbySize(agt->sock, msg_size, crypt_msg) < 0) {
531 merror(SEND_ERROR, ARGV0, "server");