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