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