Imported Upstream version 2.7
[ossec-hids.git] / src / win32 / win_agent.c
1 /* @(#) $Id: ./src/win32/win_agent.c, 2011/11/01 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 "agentd.h"
21 #include "logcollector.h"
22 #include "os_win.h"
23 #include "os_net/os_net.h"
24 #include "os_execd/execd.h"
25 #include "os_crypto/md5/md5_op.h"
26
27 #ifndef ARGV0
28 #define ARGV0 "ossec-agent"
29 #endif
30
31 time_t __win32_curr_time = 0;
32 time_t __win32_shared_time = 0;
33 char *__win32_uname = NULL;
34 char *__win32_shared = NULL;
35 HANDLE hMutex;
36
37
38 /** Prototypes **/
39 int Start_win32_Syscheck();
40 void send_win32_info(time_t curr_time);
41
42
43 /* Help message */
44 void agent_help()
45 {
46     printf("\nOSSEC HIDS %s %s .\n", ARGV0, __version);
47     printf("Available options:\n");
48     printf("\t-h                This help message.\n");
49     printf("\thelp              This help message.\n");
50     printf("\tinstall-service   Installs as a service\n");
51     printf("\tuninstall-service Uninstalls as a service\n");
52     printf("\tstart             Manually starts (not from services)\n");
53     exit(1);
54 }
55
56 /* syscheck main thread */
57 void *skthread()
58 {
59     verbose("%s: Starting syscheckd thread.", ARGV0);
60
61     Start_win32_Syscheck();
62
63     return (NULL);
64 }
65
66
67 /** main(int argc, char **argv)
68  * ..
69  */
70 int main(int argc, char **argv)
71 {
72     char *tmpstr;
73     char mypath[OS_MAXSTR +1];
74     char myfile[OS_MAXSTR +1];
75
76     /* Setting the name */
77     OS_SetName(ARGV0);
78
79
80     /* Find where I'm */
81     mypath[OS_MAXSTR] = '\0';
82     myfile[OS_MAXSTR] = '\0';
83
84
85     /* mypath is going to be the whole path of the file */
86     strncpy(mypath, argv[0], OS_MAXSTR);
87     tmpstr = strrchr(mypath, '\\');
88     if(tmpstr)
89     {
90         /* tmpstr is now the file name */
91         *tmpstr = '\0';
92         tmpstr++;
93         strncpy(myfile, tmpstr, OS_MAXSTR);
94     }
95     else
96     {
97         strncpy(myfile, argv[0], OS_MAXSTR);
98         mypath[0] = '.';
99         mypath[1] = '\0';
100     }
101     chdir(mypath);
102     getcwd(mypath, OS_MAXSTR -1);
103     strncat(mypath, "\\", OS_MAXSTR - (strlen(mypath) + 2));
104     strncat(mypath, myfile, OS_MAXSTR - (strlen(mypath) + 2));
105
106
107     if(argc > 1)
108     {
109         if(strcmp(argv[1], "install-service") == 0)
110         {
111             return(InstallService(mypath));
112         }
113         else if(strcmp(argv[1], "uninstall-service") == 0)
114         {
115             return(UninstallService());
116         }
117         else if(strcmp(argv[1], "start") == 0)
118         {
119             return(local_start());
120         }
121         else if(strcmp(argv[1], "-h") == 0)
122         {
123             agent_help();
124         }
125         else if(strcmp(argv[1], "help") == 0)
126         {
127             agent_help();
128         }
129         else
130         {
131             merror("%s: Unknown option: %s", ARGV0, argv[1]);
132             exit(1);
133         }
134     }
135
136
137     /* Start it */
138     if(!os_WinMain(argc, argv))
139     {
140         ErrorExit("%s: Unable to start WinMain.", ARGV0);
141     }
142
143     return(0);
144 }
145
146
147 /* Locally starts (after service/win init) */
148 int local_start()
149 {
150     int debug_level;
151     int accept_manager_commands = 0;
152     char *cfg = DEFAULTCPATH;
153     WSADATA wsaData;
154     DWORD  threadID;
155     DWORD  threadID2;
156
157
158     /* Starting logr */
159     logr = (agent *)calloc(1, sizeof(agent));
160     if(!logr)
161     {
162         ErrorExit(MEM_ERROR, ARGV0);
163     }
164     logr->port = DEFAULT_SECURE;
165
166
167     /* Getting debug level */
168     debug_level = getDefine_Int("windows","debug", 0, 2);
169     while(debug_level != 0)
170     {
171         nowDebug();
172         debug_level--;
173     }
174     accept_manager_commands = getDefine_Int("logcollector",
175                               "remote_commands", 0, 1);
176
177
178
179
180     /* Configuration file not present */
181     if(File_DateofChange(cfg) < 0)
182         ErrorExit("%s: Configuration file '%s' not found",ARGV0,cfg);
183
184
185     /* Starting Winsock */
186     if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
187     {
188         ErrorExit("%s: WSAStartup() failed", ARGV0);
189     }
190
191
192     /* Read agent config */
193     debug1("%s: DEBUG: Reading agent configuration.", ARGV0);
194     if(ClientConf(cfg) < 0)
195     {
196         ErrorExit(CLIENT_ERROR,ARGV0);
197     }
198
199
200     /* Reading logcollector config file */
201     debug1("%s: DEBUG: Reading logcollector configuration.", ARGV0);
202     if(LogCollectorConfig(cfg, accept_manager_commands) < 0)
203     {
204         ErrorExit(CONFIG_ERROR, ARGV0, cfg);
205     }
206
207
208     /* Checking auth keys */
209     if(!OS_CheckKeys())
210     {
211         ErrorExit(AG_NOKEYS_EXIT, ARGV0);
212     }
213
214
215
216     /* If there is not file to monitor, create a clean entry
217      * for the mark messages.
218      */
219     if(logff == NULL)
220     {
221         os_calloc(2, sizeof(logreader), logff);
222         logff[0].file = NULL;
223         logff[0].ffile = NULL;
224         logff[0].logformat = NULL;
225         logff[0].fp = NULL;
226         logff[1].file = NULL;
227         logff[1].logformat = NULL;
228
229         merror(NO_FILE, ARGV0);
230     }
231
232
233     /* Reading execd config. */
234     if(!WinExecd_Start())
235     {
236         logr->execdq = -1;
237     }
238
239
240     /* Reading keys */
241     verbose(ENC_READ, ARGV0);
242
243     OS_ReadKeys(&keys);
244     OS_StartCounter(&keys);
245     os_write_agent_info(keys.keyentries[0]->name, NULL, keys.keyentries[0]->id, NULL);
246
247
248     /* Initial random numbers */
249     srandom(time(0));
250     random();
251
252
253     /* Socket connection */
254     logr->sock = -1;
255     StartMQ(NULL, 0);
256
257
258     /* Starting mutex */
259     debug1("%s: DEBUG: Creating thread mutex.", ARGV0);
260     hMutex = CreateMutex(NULL, FALSE, NULL);
261     if(hMutex == NULL)
262     {
263         ErrorExit("%s: Error creating mutex.", ARGV0);
264     }
265
266
267
268     /* Starting syscheck thread */
269     if(CreateThread(NULL,
270                     0,
271                     (LPTHREAD_START_ROUTINE)skthread,
272                     NULL,
273                     0,
274                     (LPDWORD)&threadID) == NULL)
275     {
276         merror(THREAD_ERROR, ARGV0);
277     }
278
279
280
281     /* Checking if server is connected */
282     os_setwait();
283
284     start_agent(1);
285
286     os_delwait();
287
288
289     /* Sending integrity message for agent configs */
290     intcheck_file(cfg, "");
291     intcheck_file(OSSEC_DEFINES, "");
292
293
294     /* Starting receiver thread */
295     if(CreateThread(NULL,
296                     0,
297                     (LPTHREAD_START_ROUTINE)receiver_thread,
298                     NULL,
299                     0,
300                     (LPDWORD)&threadID2) == NULL)
301     {
302         merror(THREAD_ERROR, ARGV0);
303     }
304
305
306     /* Sending agent information message */
307     send_win32_info(time(0));
308
309
310     /* Startting logcollector -- main process here */
311     LogCollectorStart();
312
313     WSACleanup();
314     return(0);
315 }
316
317
318 /* SendMSG for windows */
319 int SendMSG(int queue, char *message, char *locmsg, char loc)
320 {
321     int _ssize;
322
323     time_t cu_time;
324
325     char *pl;
326     char tmpstr[OS_MAXSTR+2];
327     char crypt_msg[OS_MAXSTR +2];
328
329     DWORD dwWaitResult;
330
331     tmpstr[OS_MAXSTR +1] = '\0';
332     crypt_msg[OS_MAXSTR +1] = '\0';
333
334
335     debug2("%s: DEBUG: Attempting to send message to server.", ARGV0);
336
337     /* Using a mutex to synchronize the writes */
338     while(1)
339     {
340         dwWaitResult = WaitForSingleObject(hMutex, 1000000L);
341
342         if(dwWaitResult != WAIT_OBJECT_0)
343         {
344             switch(dwWaitResult)
345             {
346                 case WAIT_TIMEOUT:
347                     merror("%s: Error waiting mutex (timeout).", ARGV0);
348                     sleep(5);
349                     continue;
350                 case WAIT_ABANDONED:
351                     merror("%s: Error waiting mutex (abandoned).", ARGV0);
352                     return(0);
353                 default:
354                     merror("%s: Error waiting mutex.", ARGV0);
355                     return(0);
356             }
357         }
358         else
359         {
360             /* Lock acquired */
361             break;
362         }
363     }
364
365
366     cu_time = time(0);
367
368
369     #ifndef ONEWAY
370     /* Check if the server has responded */
371     if((cu_time - available_server) > (NOTIFY_TIME - 180))
372     {
373         debug1("%s: DEBUG: Sending info to server (c1)...", ARGV0);
374         send_win32_info(cu_time);
375
376
377         /* Attempting to send message again. */
378         if((cu_time - available_server) > NOTIFY_TIME)
379         {
380             sleep(1);
381             send_win32_info(cu_time);
382             sleep(1);
383
384             if((cu_time - available_server) > NOTIFY_TIME)
385             {
386                 send_win32_info(cu_time);
387             }
388         }
389
390
391         /* If we reached here, the server is unavailable for a while. */
392         if((cu_time - available_server) > ((3 * NOTIFY_TIME) - 180))
393         {
394             int wi = 1;
395
396
397             /* Last attempt before going into reconnect mode. */
398             debug1("%s: DEBUG: Sending info to server (c3)...", ARGV0);
399             sleep(1);
400             send_win32_info(cu_time);
401             if((cu_time - available_server) > ((3 * NOTIFY_TIME) - 180))
402             {
403                 sleep(1);
404                 send_win32_info(cu_time);
405                 sleep(1);
406             }
407
408
409             /* Checking and generating log if unavailable. */
410             cu_time = time(0);
411             if((cu_time - available_server) > ((3 * NOTIFY_TIME) - 180))
412             {
413                 int global_sleep = 1;
414                 int mod_sleep = 12;
415
416                 /* If response is not available, set lock and
417                  * wait for it.
418                  */
419                 verbose(SERVER_UNAV, ARGV0);
420
421
422                 /* Going into reconnect mode. */
423                 while((cu_time - available_server) > ((3*NOTIFY_TIME) - 180))
424                 {
425                     /* Sending information to see if server replies */
426                     if(logr->sock != -1)
427                     {
428                         send_win32_info(cu_time);
429                     }
430
431                     sleep(wi);
432                     cu_time = time(0);
433
434                     if(wi < 20)
435                     {
436                         wi++;
437                     }
438                     else
439                     {
440                         global_sleep++;
441                     }
442
443
444                     /* If we have more than one server, try all. */
445                     if(wi > 12 && logr->rip[1])
446                     {
447                         int curr_rip = logr->rip_id;
448                         merror("%s: INFO: Trying next server ip in "
449                                "line: '%s'.",
450                                ARGV0,
451                                logr->rip[logr->rip_id + 1] != NULL?
452                                logr->rip[logr->rip_id + 1]:
453                                logr->rip[0]);
454
455                         connect_server(logr->rip_id +1);
456
457                         if(logr->rip_id != curr_rip)
458                         {
459                             wi = 1;
460                         }
461                     }
462                     else if(global_sleep == 2 || ((global_sleep % mod_sleep) == 0) ||
463                             (logr->sock == -1))
464                     {
465                         connect_server(logr->rip_id +1);
466                         if(logr->sock == -1)
467                         {
468                             sleep(wi + global_sleep);
469                         }
470                         else
471                         {
472                             sleep(global_sleep);
473                         }
474
475                         if(global_sleep > 30)
476                         {
477                             mod_sleep = 50;
478                         }
479                     }
480                 }
481
482                 verbose(AG_CONNECTED, ARGV0, logr->rip[logr->rip_id],
483                                              logr->port);
484                 verbose(SERVER_UP, ARGV0);
485             }
486         }
487     }
488     #else
489     if(0)
490     {
491     }
492     #endif
493
494
495     /* Send notification */
496     else if((cu_time - __win32_curr_time) > (NOTIFY_TIME - 200))
497     {
498         debug1("%s: DEBUG: Sending info to server (ctime2)...", ARGV0);
499         send_win32_info(cu_time);
500     }
501
502
503
504     /* locmsg cannot have the C:, as we use it as delimiter */
505     pl = strchr(locmsg, ':');
506     if(pl)
507     {
508         /* Setting pl after the ":" if it exists. */
509         pl++;
510     }
511     else
512     {
513         pl = locmsg;
514     }
515
516
517     debug2("%s: DEBUG: Sending message to server: '%s'", ARGV0, message);
518
519     snprintf(tmpstr,OS_MAXSTR,"%c:%s:%s", loc, pl, message);
520
521     _ssize = CreateSecMSG(&keys, tmpstr, crypt_msg, 0);
522
523
524     /* Returns NULL if can't create encrypted message */
525     if(_ssize == 0)
526     {
527         merror(SEC_ERROR,ARGV0);
528         if(!ReleaseMutex(hMutex))
529         {
530             merror("%s: Error releasing mutex.", ARGV0);
531         }
532
533         return(-1);
534     }
535
536     /* Send _ssize of crypt_msg */
537     if(OS_SendUDPbySize(logr->sock, _ssize, crypt_msg) < 0)
538     {
539         merror(SEND_ERROR,ARGV0, "server");
540         sleep(1);
541     }
542
543     if(!ReleaseMutex(hMutex))
544     {
545         merror("%s: Error releasing mutex.", ARGV0);
546     }
547     return(0);
548 }
549
550
551 /* StartMQ for windows */
552 int StartMQ(char * path, short int type)
553 {
554     /* Connecting to the server. */
555     connect_server(0);
556
557     if((path == NULL) && (type == 0))
558     {
559         return(0);
560     }
561
562     return(0);
563 }
564
565
566 /* Send win32 info to server */
567 void send_win32_info(time_t curr_time)
568 {
569     int msg_size;
570     char tmp_msg[OS_MAXSTR +2];
571     char crypt_msg[OS_MAXSTR +2];
572
573     tmp_msg[OS_MAXSTR +1] = '\0';
574     crypt_msg[OS_MAXSTR +1] = '\0';
575
576
577     debug1("%s: DEBUG: Sending keep alive message.", ARGV0);
578
579
580     /* fixing time */
581     __win32_curr_time = curr_time;
582
583
584     /* Getting uname. */
585     if(!__win32_uname)
586     {
587         __win32_uname = getuname();
588         if(!__win32_uname)
589         {
590             merror("%s: Error generating system information.", ARGV0);
591             os_strdup("Microsoft Windows - Unknown (unable to get system info)", __win32_uname);
592         }
593     }
594
595
596     /* Getting shared files list -- every 30 seconds only. */
597     if((__win32_curr_time - __win32_shared_time) > 30)
598     {
599         if(__win32_shared)
600         {
601             free(__win32_shared);
602             __win32_shared = NULL;
603         }
604
605         __win32_shared_time = __win32_curr_time;
606     }
607
608
609     /* get shared files */
610     if(!__win32_shared)
611     {
612         __win32_shared = getsharedfiles();
613         if(!__win32_shared)
614         {
615             __win32_shared = strdup("\0");
616             if(!__win32_shared)
617             {
618                 merror(MEM_ERROR, ARGV0);
619                 return;
620             }
621         }
622     }
623
624
625
626     /* creating message */
627     if(File_DateofChange(AGENTCONFIGINT) > 0)
628     {
629         os_md5 md5sum;
630         if(OS_MD5_File(AGENTCONFIGINT, md5sum) != 0)
631         {
632             snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s", __win32_uname, __win32_shared);
633         }
634         else
635         {
636             snprintf(tmp_msg, OS_SIZE_1024, "#!-%s / %s\n%s", __win32_uname, md5sum, __win32_shared);
637         }
638     }
639     else
640     {
641         snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s", __win32_uname, __win32_shared);
642     }
643
644
645     /* creating message */
646     debug1("%s: DEBUG: Sending keep alive: %s", ARGV0, tmp_msg);
647
648     msg_size = CreateSecMSG(&keys, tmp_msg, crypt_msg, 0);
649
650     if(msg_size == 0)
651     {
652         merror(SEC_ERROR, ARGV0);
653         return;
654     }
655
656     /* Sending UDP message */
657     if(OS_SendUDPbySize(logr->sock, msg_size, crypt_msg) < 0)
658     {
659         merror(SEND_ERROR, ARGV0, "server");
660         sleep(1);
661     }
662
663     return;
664 }
665
666 #endif
667 /* EOF */