37e8bd4175d37dc5f3c93308e5a03395a6d7f5f9
[ossec-hids.git] / src / shared / read-agents.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All right 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
12 #include "shared.h"
13 #include "read-agents.h"
14 #include "os_net/os_net.h"
15
16
17 /* Free the agent list in memory
18  */
19 void free_agents(char **agent_list)
20 {
21     int i;
22     if(!agent_list)
23         return;
24         
25     for(i = 0;;i++)
26     {
27         if(agent_list[i] == NULL)
28             break;
29
30         free(agent_list[i]);
31         agent_list[i] = NULL;
32     }
33
34     free(agent_list);
35     agent_list = NULL;
36 }
37
38
39 #ifndef WIN32
40
41 /* Print syscheck attributes. */
42 #define sk_strchr(x,y,z) z = strchr(x, y); if(z == NULL) return(0); else { *z = '\0'; z++; } 
43 int _do_print_attrs_syscheck(char *prev_attrs, char *attrs, int csv_output, 
44                              int is_win, int number_of_changes)
45 {
46     char *p_size, *p_perm, *p_uid, *p_gid, *p_md5, *p_sha1;
47     char *size, *perm, *uid, *gid, *md5, *sha1;
48     int perm_int;
49     char perm_str[36];
50
51
52     /* Setting each value. */
53     size = attrs;
54     sk_strchr(size, ':', perm);
55     sk_strchr(perm, ':', uid);
56     sk_strchr(uid, ':', gid);
57     sk_strchr(gid, ':', md5);
58     sk_strchr(md5, ':', sha1);
59     
60     if(strcmp(attrs, "-1") == 0)
61     {
62         printf("File deleted. ");
63         return(0);
64     }
65     else if(prev_attrs && (strcmp(prev_attrs, "-1") == 0))
66     {
67         printf("File restored. ");
68     }
69     else if(prev_attrs)
70     {
71         printf("File changed. ");
72         p_size = prev_attrs;
73         sk_strchr(p_size, ':', p_perm);
74         sk_strchr(p_perm, ':', p_uid);
75         sk_strchr(p_uid, ':', p_gid);
76         sk_strchr(p_gid, ':', p_md5);
77         sk_strchr(p_md5, ':', p_sha1);
78     }
79     else
80     {
81         p_size = size;
82         p_perm = perm;
83         p_uid = uid;
84         p_gid = gid;
85         p_md5 = md5;
86         p_sha1 = sha1;
87         printf("File added to the database. ");
88     }
89
90
91     /* Fixing number of changes. */
92     if(prev_attrs && !number_of_changes)
93     {
94         number_of_changes = 1;
95     }
96
97
98     if(number_of_changes)
99     {
100         switch(number_of_changes)
101         {
102             case 1:
103                 printf("- 1st time modified.\n");
104                 break;
105             case 2:    
106                 printf("- 2nd time modified.\n");
107                 break;
108             case 3:    
109                 printf("- 3rd time modified.\n");
110                 break;
111             default:
112                 printf("- Being ignored (3 or more changes).\n");       
113         }
114     }
115     else
116     {
117         printf("\n");
118     }
119
120
121     perm_str[35] = '\0';
122     perm_int = atoi(perm);
123     snprintf(perm_str, 35, 
124              "%c%c%c%c%c%c%c%c%c",
125              (perm_int & S_IRUSR)? 'r' : '-',
126              (perm_int & S_IWUSR)? 'w' : '-',
127              
128              (perm_int & S_ISUID)? 's' :
129              (perm_int & S_IXUSR)? 'x' : '-',
130
131              
132              (perm_int & S_IRGRP)? 'r' : '-',
133              (perm_int & S_IWGRP)? 'w' : '-',
134              
135              (perm_int & S_ISGID)? 's' :
136              (perm_int & S_IXGRP)? 'x' : '-',
137              
138              
139              (perm_int & S_IROTH)? 'r' : '-',
140              (perm_int & S_IWOTH)? 'w' : '-',
141              (perm_int & S_ISVTX)? 't' :
142              (perm_int & S_IXOTH)? 'x' : '-');
143
144
145     printf("Integrity checking values:\n");
146     printf("   Size:%s%s\n", (strcmp(size,p_size) == 0)? " ": " >", size);
147     if(!is_win)
148     {
149       printf("   Perm:%s%s\n", (strcmp(perm,p_perm) == 0)? " ": " >", perm_str);
150       printf("   Uid: %s%s\n", (strcmp(uid,p_uid) == 0)? " ": " >", uid);
151       printf("   Gid: %s%s\n", (strcmp(gid,p_gid) == 0)? " ": " >", gid);
152     }
153     printf("   Md5: %s%s\n", (strcmp(md5,p_md5) == 0)? " ": " >", md5);
154     printf("   Sha1:%s%s\n", (strcmp(sha1,p_sha1) == 0)? " ": " >", sha1);
155     
156
157     /* Fixing entries. */
158     perm[-1] = ':';
159     uid[-1] = ':';
160     gid[-1] = ':';
161     md5[-1] = ':';
162     sha1[-1] = ':';
163
164     return(0);
165 }
166
167
168
169 /* Print information about a specific file. */
170 int _do_print_file_syscheck(FILE *fp, char *fname, 
171                             int update_counter, int csv_output)
172 {
173     int f_found = 0;
174     struct tm *tm_time;
175     
176     char read_day[24 +1];
177     char buf[OS_MAXSTR + 1];
178
179     OSMatch reg;
180     OSStore *files_list;
181
182     fpos_t init_pos;
183     
184     buf[OS_MAXSTR] = '\0';
185     read_day[24] = '\0';
186
187
188     /* If the compilation failed, we don't need to free anything */
189     if(!OSMatch_Compile(fname, &reg, 0))
190     {
191         printf("\n** ERROR: Invalid file name: '%s'\n", fname);
192         return(0);
193     }
194
195
196     /* Creating list with files. */
197     files_list = OSStore_Create();
198     if(!files_list)
199     {
200         OSMatch_FreePattern(&reg);
201         return(0);
202     }
203
204
205     /* Getting initial position. */
206     if(fgetpos(fp, &init_pos) != 0)
207     {
208         printf("\n** ERROR: fgetpos failed.\n");
209         return(0);
210     }
211                                                     
212     
213     while(fgets(buf, OS_MAXSTR, fp) != NULL)
214     {
215         if(buf[0] == '!' || buf[0] == '#')
216         {
217             int number_changes = 0;
218             time_t change_time = 0;
219             char *changed_file_name;
220             char *changed_attrs;
221             char *prev_attrs;
222
223             
224             if(strlen(buf) < 16)
225             {
226                 fgetpos(fp, &init_pos);
227                 continue;
228             }
229                 
230             /* Removing new line. */    
231             buf[strlen(buf) -1] = '\0';    
232
233
234             /* with update counter, we only modify the last entry. */
235             if(update_counter && buf[0] == '#')
236             {
237                 fgetpos(fp, &init_pos);
238                 continue;
239             }
240
241
242             /* Checking number of changes. */
243             if(buf[1] == '!')
244             {
245                 number_changes = 2;
246                 if(buf[2] == '!')
247                 {
248                     number_changes = 3;
249                 }
250                 else if(buf[2] == '?')
251                 {
252                     number_changes = 4;
253                 }
254             }
255
256             changed_attrs = buf + 3;
257
258             
259             changed_file_name = strchr(changed_attrs, '!');
260             if(!changed_file_name)
261             {
262                 fgetpos(fp, &init_pos);
263                 continue;
264             }
265             
266             
267             /* Getting time of change. */
268             changed_file_name[-1] = '\0';
269             changed_file_name++;
270             change_time = (time_t)atoi(changed_file_name);
271             
272             changed_file_name = strchr(changed_file_name, ' ');
273             changed_file_name++; 
274     
275
276             /* Checking if the name should be printed. */
277             if(!OSMatch_Execute(changed_file_name, strlen(changed_file_name), 
278                                 &reg))
279             {
280                 fgetpos(fp, &init_pos);
281                 continue;
282             }
283
284
285             f_found = 1;
286             
287             
288             /* Reset the values. */
289             if(update_counter)
290             {
291                 if(fsetpos(fp, &init_pos) != 0)
292                 {
293                     printf("\n** ERROR: fsetpos failed (unable to update "
294                            "counter).\n");
295                     return(0);
296                 }
297
298                 if(update_counter == 2)
299                 {
300                     if(fprintf(fp, "!!?") <= 0)
301                     {
302                         printf("\n** ERROR: fputs failed (unable to update "
303                                 "counter).\n");
304                         return(0);
305                     }
306                 }
307
308                 else
309                 {
310                     if(fprintf(fp, "!++") <= 0)
311                     {
312                         printf("\n** ERROR: fputs failed (unable to update "
313                                 "counter).\n");
314                         return(0);
315                     }
316                 }
317
318                 printf("\n**Counter updated for file '%s'\n\n", 
319                        changed_file_name);
320                 return(0);
321             }
322
323             
324             tm_time = localtime(&change_time);
325             strftime(read_day, 23, "%Y %h %d %T", tm_time);
326             
327             if(!csv_output)           
328                 printf("\n%s,%d - %s\n", read_day, number_changes, 
329                                        changed_file_name);
330             else    
331                 printf("%s,%s,%d\n", read_day, changed_file_name, 
332                                      number_changes);
333             
334            
335             prev_attrs = OSStore_Get(files_list, changed_file_name);
336             if(prev_attrs)
337             {
338                 char *new_attrs;
339                 os_strdup(changed_attrs, new_attrs);
340                 _do_print_attrs_syscheck(prev_attrs, changed_attrs, 
341                                          csv_output, 
342                                          changed_file_name[0] == '/'?0:1,
343                                          number_changes);
344                 
345                 free(files_list->cur_node->data);
346                 files_list->cur_node->data = new_attrs;    
347             }
348             else
349             {
350                 char *new_name;
351                 char *new_attrs;
352                 
353                 os_strdup(changed_attrs, new_attrs);
354                 os_strdup(changed_file_name, new_name);
355                 OSStore_Put(files_list, new_name, new_attrs);
356                 _do_print_attrs_syscheck(NULL, 
357                                          changed_attrs, csv_output,
358                                          changed_file_name[0] == '/'?0:1,
359                                          number_changes);
360             }
361
362             fgetpos(fp, &init_pos);
363         }
364     }
365
366     if(!f_found)
367     {
368         printf("\n** No entries found.\n");
369     }
370     OSMatch_FreePattern(&reg);
371     
372     return(0);
373 }
374
375
376
377 /* Print syscheck db (of modified files. */
378 int _do_print_syscheck(FILE *fp, int all_files, int csv_output)
379 {
380     int f_found = 0;
381     struct tm *tm_time;
382     
383     char read_day[24 +1];
384     char saved_read_day[24 +1];
385     char buf[OS_MAXSTR + 1];
386     
387     buf[OS_MAXSTR] = '\0';
388     read_day[24] = '\0';
389     saved_read_day[0] = '\0';
390     saved_read_day[24] = '\0';
391     
392     while(fgets(buf, OS_MAXSTR, fp) != NULL)
393     {
394         if(buf[0] == '!' || buf[0] == '#')
395         {
396             int number_changes = 0;
397             time_t change_time = 0;
398             char *changed_file_name;
399
400             
401             if(strlen(buf) < 16)
402                 continue;
403                 
404             /* Removing new line. */    
405             buf[strlen(buf) -1] = '\0';    
406                 
407
408             /* Checking number of changes. */
409             if(buf[1] == '!')
410             {
411                 number_changes = 2;
412                 if(buf[2] == '!')
413                 {
414                     number_changes = 3;
415                 }
416                 else if(buf[2] == '?')
417                 {
418                     number_changes = 4;
419                 }
420             }
421             
422
423             changed_file_name = strchr(buf +3, '!');
424             if(!changed_file_name)
425                 continue;
426     
427     
428             f_found = 1;
429                     
430             
431             /* Getting time of change. */
432             changed_file_name++;
433             change_time = atoi(changed_file_name);
434             
435             changed_file_name = strchr(changed_file_name, ' ');
436             changed_file_name++; 
437     
438             tm_time = localtime(&change_time);
439             strftime(read_day, 23, "%Y %h %d", tm_time);
440             if(strcmp(read_day, saved_read_day) != 0)
441             {
442                 if(!csv_output)
443                     printf("\nChanges for %s:\n", read_day);
444                 strncpy(saved_read_day, read_day, 23);
445             }
446             strftime(read_day, 23, "%Y %h %d %T", tm_time);
447             
448             if(!csv_output)           
449                 printf("%s,%d - %s\n", read_day, number_changes, 
450                                        changed_file_name);
451             else    
452                 printf("%s,%s,%d\n", read_day, changed_file_name, 
453                                      number_changes);
454         }
455     }
456
457     if(!f_found && !csv_output)
458     {
459         printf("\n** No entries found.\n");
460     }
461                             
462     return(0);
463 }
464
465
466 /* Print syscheck db (of modified files. */
467 int print_syscheck(char *sk_name, char *sk_ip, char *fname, int print_registry, 
468                    int all_files, int csv_output, int update_counter)
469 {
470     FILE *fp;
471     char tmp_file[513];
472
473     tmp_file[512] = '\0';
474
475
476     if(sk_name == NULL)
477     {
478         /* Printing database */
479         snprintf(tmp_file, 512, "%s/syscheck",
480                 SYSCHECK_DIR);
481
482         fp = fopen(tmp_file, "r+");
483     }
484
485     else if(sk_ip == NULL)
486     {
487         /* Printing database */
488         snprintf(tmp_file, 512, "%s/%s->syscheck",SYSCHECK_DIR, sk_name);
489
490         fp = fopen(tmp_file, "r+");
491     }
492     
493     else if(!print_registry)
494     {
495         /* Printing database */
496         snprintf(tmp_file, 512, "%s/(%s) %s->syscheck",
497                 SYSCHECK_DIR,
498                 sk_name,
499                 sk_ip);
500
501         fp = fopen(tmp_file, "r+");
502     }
503
504     else
505     {
506         /* Printing database for the windows registry. */
507         snprintf(tmp_file, 512, "%s/(%s) %s->syscheck-registry",
508                 SYSCHECK_DIR,
509                 sk_name,
510                 sk_ip);
511
512         fp = fopen(tmp_file, "r+");
513     }
514
515
516     if(fp)
517     {
518         if(!fname)
519         {
520             _do_print_syscheck(fp, all_files, csv_output);
521         }
522         else
523         {
524             _do_print_file_syscheck(fp, fname, update_counter, csv_output);
525         }
526         fclose(fp);
527     }
528
529     return(0);
530 }
531
532
533
534 int _do_get_rootcheckscan(FILE *fp)
535 {
536     char *tmp_str;
537     char buf[OS_MAXSTR + 1];
538
539     while(fgets(buf, OS_MAXSTR, fp) != NULL)
540     {
541         tmp_str = strstr(buf, "Starting rootcheck scan");
542         if(tmp_str)
543         {
544             time_t s_time = 0;
545             tmp_str = buf + 1;
546
547             s_time = (time_t)atoi(tmp_str);
548
549             return((int)s_time);
550         }
551     }
552
553     return((int)time(NULL));
554 }
555
556
557
558 /* Print syscheck db (of modified files. */
559 int _do_print_rootcheck(FILE *fp, int resolved, int time_last_scan, 
560                         int csv_output, int show_last)
561 {
562     int i = 0;
563     int f_found = 0;
564     
565     /* Current time. */
566     time_t c_time;
567
568     /* Time from the message. */
569     time_t s_time = 0;
570     time_t i_time = 0;
571     struct tm *tm_time;
572     
573     char old_day[24 +1];
574     char read_day[24 +1];
575     char buf[OS_MAXSTR + 1];
576     char *tmp_str;
577
578
579     char *(ig_events[]) = {"Starting rootcheck scan",
580                            "Ending rootcheck scan",
581                            "Starting syscheck scan",
582                            "Ending syscheck scan",
583                            NULL};
584
585     char *(ns_events[]) = {"Application Found:",
586                            "Windows Audit:",
587                            "Windows Malware:",
588                            NULL}; 
589                            
590
591     buf[OS_MAXSTR] = '\0';
592     old_day[24] = '\0';
593     read_day[24] = '\0';
594
595     
596     c_time = time(0);
597     fseek(fp, 0, SEEK_SET);
598
599
600     if(!csv_output)
601     {
602         if(show_last)
603         {
604             tm_time = localtime((time_t *)&time_last_scan);
605             strftime(read_day, 23, "%Y %h %d %T", tm_time);
606                     
607             printf("\nLast scan: %s\n\n", read_day);
608         }
609         else if(resolved)
610             printf("\nResolved events: \n\n");
611         else
612             printf("\nOutstanding events: \n\n");    
613     }
614
615
616     while(fgets(buf, OS_MAXSTR, fp) != NULL)
617     {
618         /* Removing first ! */
619         tmp_str = buf + 1;
620         s_time = (time_t)atoi(tmp_str);
621
622
623         /* Removing new line. */
624         tmp_str = strchr(buf, '\n');
625         if(tmp_str)
626             *tmp_str = '\0';
627
628         
629         /* Getting initial time. */
630         tmp_str = strchr(buf + 1, '!');
631         if(!tmp_str)
632             continue;
633         tmp_str++;
634
635         i_time = (time_t)atoi(tmp_str);
636
637
638         /* Getting the actual message. */
639         tmp_str = strchr(tmp_str, ' ');
640         if(!tmp_str)
641             continue;
642         tmp_str++;    
643                 
644
645        
646         /* Checking for resolved. */
647         if(time_last_scan > (s_time + 86400))
648         {
649             if(!resolved)
650             {
651                 continue;
652             }
653         }
654         else
655         {
656             if(resolved)
657             {
658                 continue;
659             }
660         }
661
662
663         /* Checking events to ignore. */
664         i = 0;
665         while(ig_events[i])
666         {
667             if(strncmp(tmp_str, ig_events[i], strlen(ig_events[i]) -1) == 0)
668                 break;
669             i++;        
670         }
671         if(ig_events[i])
672             continue;
673
674         
675         /* Checking events that are not system audit. */
676         i = 0;
677         while(ns_events[i])
678         {
679             if(strncmp(tmp_str, ns_events[i], strlen(ns_events[i]) -1) == 0)
680                 break;
681             i++;
682         }
683         
684
685         tm_time = localtime((time_t *)&s_time);
686         strftime(read_day, 23, "%Y %h %d %T", tm_time);
687         tm_time = localtime((time_t *)&i_time);
688         strftime(old_day, 23, "%Y %h %d %T", tm_time);
689         
690
691         if(!csv_output)
692         {
693             if(!show_last)
694                 printf("%s (first time detected: %s)\n", read_day, old_day);
695
696             if(ns_events[i])
697             {
698                 printf("%s\n\n", tmp_str);
699             }
700             else
701             {
702                 printf("System Audit: %s\n\n", tmp_str);
703             }
704         }
705         else
706         {
707             printf("%s,%s,%s,%s%s\n", resolved == 0?"outstanding":"resolved",
708                                        read_day, old_day,
709                                        ns_events[i] != NULL?"":"System Audit: ",
710                                        tmp_str); 
711         }
712         
713         
714         
715         f_found++;
716     }
717
718     if(!f_found && !csv_output)
719     {
720         printf("** No entries found.\n");
721     }
722                             
723     return(0);
724 }
725
726
727
728 /* Print rootcheck db */
729 int print_rootcheck(char *sk_name, char *sk_ip, char *fname, int resolved, 
730                     int csv_output, int show_last)
731 {
732     int ltime = 0;
733     FILE *fp;
734     char tmp_file[513];
735
736     tmp_file[512] = '\0';
737
738
739     if(sk_name == NULL)
740     {
741         /* Printing database */
742         snprintf(tmp_file, 512, "%s/rootcheck",
743                 ROOTCHECK_DIR);
744
745         fp = fopen(tmp_file, "r+");
746     }
747     
748     else
749     {
750         /* Printing database */
751         snprintf(tmp_file, 512, "%s/(%s) %s->rootcheck",
752                 ROOTCHECK_DIR,
753                 sk_name,
754                 sk_ip);
755
756         fp = fopen(tmp_file, "r+");
757     }
758
759
760     if(fp)
761     {
762         /* Getting last time of scan. */
763         ltime = _do_get_rootcheckscan(fp);
764         if(!fname)
765         {
766             if(resolved == 1)
767             {
768                 _do_print_rootcheck(fp, 1, ltime, csv_output, 0);
769             }
770             else if(resolved == 2)
771             {
772                 _do_print_rootcheck(fp, 0, ltime, csv_output, show_last);
773             }
774             else
775             {
776                 _do_print_rootcheck(fp, 1, ltime, csv_output, 0);
777                 _do_print_rootcheck(fp, 0, ltime, csv_output, show_last);
778             }
779         }
780         else
781         {
782         }
783         fclose(fp);
784     }
785
786     return(0);
787 }
788
789 #endif
790
791
792 /* Delete syscheck db */ 
793 int delete_syscheck(char *sk_name, char *sk_ip, int full_delete)
794 {
795     FILE *fp;
796     char tmp_file[513];
797
798     tmp_file[512] = '\0';
799     
800     /* Deleting related files */
801     snprintf(tmp_file, 512, "%s/(%s) %s->syscheck",
802             SYSCHECK_DIR,
803             sk_name,
804             sk_ip);
805
806     fp = fopen(tmp_file, "w");
807     if(fp)
808         fclose(fp);
809
810     if(full_delete)    
811         unlink(tmp_file);
812
813
814     /* Deleting cpt files */
815     snprintf(tmp_file, 512, "%s/.(%s) %s->syscheck.cpt",
816             SYSCHECK_DIR,
817             sk_name,
818             sk_ip);
819
820     fp = fopen(tmp_file, "w");
821     if(fp)
822         fclose(fp);
823     unlink(tmp_file);
824
825
826     /* Deleting registry entries */
827     snprintf(tmp_file, 512, "%s/(%s) %s->syscheck-registry",
828             SYSCHECK_DIR,
829             sk_name,
830             sk_ip);
831
832     fp = fopen(tmp_file, "w");
833     if(fp)
834         fclose(fp);
835     if(full_delete)
836         unlink(tmp_file);
837
838
839     /* Deleting cpt files */
840     snprintf(tmp_file, 512, "%s/.(%s) %s->syscheck-registry.cpt",
841             SYSCHECK_DIR,
842             sk_name,
843             sk_ip);
844
845     fp = fopen(tmp_file, "w");
846     if(fp)
847         fclose(fp);
848     unlink(tmp_file);
849
850     return(1);
851 }
852
853
854
855 /* Delete rootcheck db */ 
856 int delete_rootcheck(char *sk_name, char *sk_ip, int full_delete)
857 {
858     FILE *fp;
859     char tmp_file[513];
860
861     tmp_file[512] = '\0';
862     
863     /* Deleting related files */
864     snprintf(tmp_file, 512, "%s/(%s) %s->rootcheck",
865             ROOTCHECK_DIR,
866             sk_name,
867             sk_ip);
868
869     fp = fopen(tmp_file, "w");
870     if(fp)
871         fclose(fp);
872
873     if(full_delete)    
874         unlink(tmp_file);
875
876
877     return(1);
878 }
879
880
881
882 /* Delete agent.
883  */
884 int delete_agentinfo(char *name)
885 {
886     char *sk_name;
887     char *sk_ip;
888     char tmp_file[513];
889
890     tmp_file[512] = '\0';
891
892
893     /* Deleting agent info */
894     snprintf(tmp_file, 512, "%s/%s", AGENTINFO_DIR, name);
895     unlink(tmp_file);
896
897
898     /* Deleting syscheck */
899     sk_name = name;
900     sk_ip = strrchr(name, '-');
901     if(!sk_ip)
902         return(0);
903
904     *sk_ip = '\0';
905     sk_ip++;
906
907
908     /* Deleting syscheck */
909     delete_syscheck(sk_name, sk_ip, 1);
910     
911     return(1);
912 }
913
914  
915
916 /** char *print_agent_status(int status)
917  * Prints the text representation of the agent status.
918  */
919 char *print_agent_status(int status)
920 {
921     char *status_str = "Never connected";
922
923     if(status == GA_STATUS_ACTIVE)
924     {
925         status_str = "Active";
926     }
927     else if(status == GA_STATUS_NACTIVE)
928     {
929         status_str = "Disconnected";
930     }
931
932     return(status_str);
933 }
934
935
936 /* non-windows functions from now on. */
937 #ifndef WIN32
938
939
940 /** int send_msg_to_agent(int socket, char *msg)
941  * Sends a message to an agent.
942  * returns -1 on error.
943  */
944 int send_msg_to_agent(int msocket, char *msg, char *agt_id, char *exec)
945 {
946     int rc;
947     char agt_msg[OS_SIZE_1024 +1];
948
949     agt_msg[OS_SIZE_1024] = '\0';
950     
951
952     if(!exec)
953     {
954         snprintf(agt_msg, OS_SIZE_1024,
955                 "%s %c%c%c %s %s",
956                 "(msg_to_agent) []",
957                 (agt_id == NULL)?ALL_AGENTS_C:NONE_C,
958                 NO_AR_C,
959                 (agt_id != NULL)?SPECIFIC_AGENT_C:NONE_C,
960                 agt_id != NULL? agt_id: "(null)",
961                 msg);
962     }
963     else
964     {
965         snprintf(agt_msg, OS_SIZE_1024,
966                 "%s %c%c%c %s %s - %s (from_the_server) (no_rule_id)",
967                 "(msg_to_agent) []",
968                 (agt_id == NULL)?ALL_AGENTS_C:NONE_C,
969                 NONE_C,
970                 (agt_id != NULL)?SPECIFIC_AGENT_C:NONE_C,
971                 agt_id != NULL? agt_id: "(null)",
972                 msg, exec);
973
974     }
975
976     
977     if((rc = OS_SendUnix(msocket, agt_msg, 0)) < 0)
978     {
979         if(rc == OS_SOCKBUSY)
980         {
981             merror("%s: ERROR: Remoted socket busy.", __local_name);
982         }
983         else
984         {
985             merror("%s: ERROR: Remoted socket error.", __local_name);
986         }
987         merror("%s: Error communicating with remoted queue (%d).",
988                __local_name, rc);
989
990         return(-1);
991     }
992
993     return(0);
994 }
995
996
997
998 /** int connect_to_remoted()
999  * Connects to remoted to be able to send messages to the agents.
1000  * Returns the socket on success or -1 on failure.
1001  */
1002 int connect_to_remoted()
1003 {
1004     int arq = -1;
1005     
1006     if((arq = StartMQ(ARQUEUE, WRITE)) < 0)
1007     {
1008         merror(ARQ_ERROR, __local_name);
1009         return(-1);
1010     }
1011
1012     return(arq);
1013 }
1014
1015
1016 #endif
1017
1018
1019 /* Internal funtion. Extract last time of scan from rootcheck/syscheck. */
1020 int _get_time_rkscan(char *agent_name, char *agent_ip, agent_info *agt_info)
1021 {
1022     FILE *fp;
1023     char buf[1024 +1];
1024
1025
1026     /* Agent name of null, means it is the server info. */
1027     if(agent_name == NULL)
1028     {
1029         snprintf(buf, 1024, "%s/rootcheck", 
1030                       ROOTCHECK_DIR);
1031     }
1032     else
1033     {
1034         snprintf(buf, 1024, "%s/(%s) %s->rootcheck", 
1035                       ROOTCHECK_DIR, agent_name, agent_ip);
1036     }
1037     
1038
1039     /* If file is not there, set to unknown. */
1040     fp = fopen(buf, "r");
1041     if(!fp)
1042     {
1043         os_strdup("Unknown", agt_info->rootcheck_time);
1044         os_strdup("Unknown", agt_info->rootcheck_endtime);
1045         os_strdup("Unknown", agt_info->syscheck_time);
1046         os_strdup("Unknown", agt_info->syscheck_endtime);
1047         return(0);
1048     }
1049     
1050
1051     while(fgets(buf, 1024, fp) != NULL)
1052     {
1053         char *tmp_str = NULL;
1054
1055         /* Removing new line. */
1056         tmp_str = strchr(buf, '\n');
1057         if(tmp_str)
1058             *tmp_str = '\0';
1059
1060
1061         tmp_str = strstr(buf, "Starting syscheck scan");
1062         if(tmp_str)
1063         {
1064             time_t s_time = 0;
1065             tmp_str = buf + 1;
1066
1067             s_time = (time_t)atoi(tmp_str);
1068
1069             os_strdup(ctime(&s_time), agt_info->syscheck_time);
1070
1071             /* Removing new line. */
1072             tmp_str = strchr(agt_info->syscheck_time, '\n');
1073             if(tmp_str)
1074                 *tmp_str = '\0';
1075                 
1076             continue;
1077         }
1078
1079         tmp_str = strstr(buf, "Ending syscheck scan");
1080         if(tmp_str)
1081         {
1082             time_t s_time = 0;
1083             tmp_str = buf + 1;
1084
1085             s_time = (time_t)atoi(tmp_str);
1086
1087             os_strdup(ctime(&s_time), agt_info->syscheck_endtime);
1088
1089             /* Removing new line. */
1090             tmp_str = strchr(agt_info->syscheck_endtime, '\n');
1091             if(tmp_str)
1092                 *tmp_str = '\0';
1093                 
1094             continue;
1095         }
1096         
1097
1098         tmp_str = strstr(buf, "Starting rootcheck scan");
1099         if(tmp_str)
1100         {
1101             time_t s_time = 0;
1102             tmp_str = buf + 1;
1103
1104             s_time = (time_t)atoi(tmp_str);
1105
1106             os_strdup(ctime(&s_time), agt_info->rootcheck_time);
1107
1108             /* Removing new line. */
1109             tmp_str = strchr(agt_info->rootcheck_time, '\n');
1110             if(tmp_str)
1111                 *tmp_str = '\0';
1112
1113             continue;
1114         }
1115
1116         tmp_str = strstr(buf, "Ending rootcheck scan");
1117         if(tmp_str)
1118         {
1119             time_t s_time = 0;
1120             tmp_str = buf + 1;
1121
1122             s_time = (time_t)atoi(tmp_str);
1123
1124             os_strdup(ctime(&s_time), agt_info->rootcheck_endtime);
1125
1126             /* Removing new line. */
1127             tmp_str = strchr(agt_info->rootcheck_endtime, '\n');
1128             if(tmp_str)
1129                 *tmp_str = '\0';
1130
1131             continue;
1132         }
1133     }
1134
1135
1136     /* Setting unknown values. */
1137     if(!agt_info->rootcheck_time)
1138         os_strdup("Unknown", agt_info->rootcheck_time);
1139     if(!agt_info->rootcheck_endtime)
1140         os_strdup("Unknown", agt_info->rootcheck_endtime);
1141     if(!agt_info->syscheck_time)
1142         os_strdup("Unknown", agt_info->syscheck_time);
1143     if(!agt_info->syscheck_endtime)
1144         os_strdup("Unknown", agt_info->syscheck_endtime);
1145             
1146     fclose(fp);
1147     return(0);
1148 }
1149
1150
1151
1152 /* Internal funtion. Extract last time of scan from rootcheck/syscheck. */
1153 char *_get_agent_keepalive(char *agent_name, char *agent_ip)
1154 {
1155     char buf[1024 +1];
1156     struct stat file_status;
1157
1158
1159     /* No keep alive for the server. */
1160     if(!agent_name)
1161     {
1162         return(strdup("Not available"));
1163     }
1164     
1165     snprintf(buf, 1024, "%s/%s-%s", AGENTINFO_DIR, agent_name, agent_ip);
1166     if(stat(buf, &file_status) < 0)
1167     {
1168         return(strdup("Unknown"));
1169     }
1170
1171
1172     return(strdup(ctime(&file_status.st_mtime)));
1173 }
1174
1175
1176
1177 /* Internal funtion. Extracts operating system. */
1178 int _get_agent_os(char *agent_name, char *agent_ip, agent_info *agt_info)
1179 {
1180     FILE *fp;
1181     char buf[1024 +1];
1182
1183     
1184     /* Getting server info. */
1185     if(!agent_name)
1186     {
1187         char *ossec_version = NULL;
1188         agt_info->os = getuname();
1189         os_strdup(__name " " __version, agt_info->version);
1190
1191
1192         /* Removing new line. */
1193         ossec_version = strchr(agt_info->os, '\n');
1194         if(ossec_version)
1195             *ossec_version = '\0';
1196
1197
1198         ossec_version = strstr(agt_info->os, " - ");
1199         if(ossec_version)
1200         {
1201             *ossec_version = '\0';
1202         }
1203
1204
1205         if(strlen(agt_info->os) > 55)
1206         {
1207             agt_info->os[52] = '.';
1208             agt_info->os[53] = '.';
1209             agt_info->os[54] = '\0';
1210         }
1211
1212
1213         return(0);
1214     }
1215
1216     
1217     snprintf(buf, 1024, "%s/%s-%s", AGENTINFO_DIR, agent_name, agent_ip);
1218     fp = fopen(buf, "r");
1219     if(!fp)
1220     {
1221         os_strdup("Unknown", agt_info->os);
1222         os_strdup("Unknown", agt_info->version);
1223         return(0);
1224     }
1225     
1226     
1227     if(fgets(buf, 1024, fp))
1228     {
1229         char *ossec_version = NULL;
1230
1231         /* Removing new line. */
1232         ossec_version = strchr(buf, '\n');
1233         if(ossec_version)
1234             *ossec_version = '\0';
1235         
1236         
1237         ossec_version = strstr(buf, " - ");
1238         if(ossec_version)
1239         {
1240             *ossec_version = '\0';
1241             ossec_version += 3;
1242
1243             os_calloc(1024 +1, sizeof(char), agt_info->version);
1244             strncpy(agt_info->version, ossec_version, 1024);
1245         }
1246
1247
1248         if(strlen(buf) > 55)
1249         {
1250             buf[52] = '.';
1251             buf[53] = '.';
1252             buf[54] = '\0';
1253         }
1254
1255         os_strdup(buf, agt_info->os);
1256         fclose(fp);
1257
1258         return(1);
1259     }
1260
1261     fclose(fp);
1262     
1263     os_strdup("Unknown", agt_info->os);
1264     os_strdup("Unknown", agt_info->version);
1265     
1266     return(0);
1267 }
1268
1269
1270
1271 /** agent_info *get_agent_info(char *agent_name, char *agent_ip)
1272  * Get information from an agent.
1273  */
1274 agent_info *get_agent_info(char *agent_name, char *agent_ip)
1275 {
1276     char tmp_file[513];
1277     char *agent_ip_pt = NULL;
1278     char *tmp_str = NULL;
1279     
1280     agent_info *agt_info = NULL;
1281
1282     tmp_file[512] = '\0';
1283
1284
1285     /* Removing the  "/", since it is not present on the file. */
1286     if((agent_ip_pt = strchr(agent_ip, '/')))
1287     {
1288         *agent_ip_pt = '\0';
1289     }
1290
1291
1292     /* Allocating memory for the info structure. */
1293     agt_info = calloc(1, sizeof(agent_info));
1294
1295
1296     /* Zeroing the values. */
1297     agt_info->rootcheck_time = NULL;
1298     agt_info->rootcheck_endtime = NULL;
1299     agt_info->syscheck_time = NULL;
1300     agt_info->syscheck_endtime = NULL;
1301     agt_info->os = NULL;
1302     agt_info->version = NULL;
1303     agt_info->last_keepalive = NULL;
1304
1305
1306     /* Getting information about the OS. */
1307     _get_agent_os(agent_name, agent_ip, agt_info);
1308     _get_time_rkscan(agent_name, agent_ip, agt_info);
1309     agt_info->last_keepalive = _get_agent_keepalive(agent_name, agent_ip);
1310
1311
1312     /* Removing new line from keep alive. */
1313     tmp_str = strchr(agt_info->last_keepalive, '\n');
1314     if(tmp_str)
1315         *tmp_str = '\0';
1316
1317         
1318
1319     /* Setting back the ip address. */
1320     if(agent_ip_pt)
1321     {
1322         *agent_ip_pt = '/';
1323     }
1324
1325
1326     return(agt_info);
1327 }
1328
1329
1330
1331 /** int get_agent_status(char *agent_name, char *agent_ip)
1332  * Gets the status of an agent, based on the name/ip.
1333  */
1334 int get_agent_status(char *agent_name, char *agent_ip)
1335 {
1336     char tmp_file[513];
1337     char *agent_ip_pt = NULL;
1338     
1339     struct stat file_status;
1340
1341     tmp_file[512] = '\0';
1342
1343
1344     /* Server info. */
1345     if(agent_name == NULL)
1346     {
1347         return(GA_STATUS_ACTIVE);     
1348     }
1349     
1350
1351     /* Removing the  "/", since it is not present on the file. */
1352     if((agent_ip_pt = strchr(agent_ip, '/')))
1353     {
1354         *agent_ip_pt = '\0';
1355     }
1356
1357     snprintf(tmp_file, 512, "%s/%s-%s", AGENTINFO_DIR, agent_name, agent_ip);
1358
1359
1360     /* Setting back the ip address. */
1361     if(agent_ip_pt)
1362     {
1363         *agent_ip_pt = '/';
1364     }
1365
1366
1367     if(stat(tmp_file, &file_status) < 0)
1368     {
1369         return(GA_STATUS_INV);
1370     }
1371     
1372
1373     if(file_status.st_mtime > (time(0) - (3*NOTIFY_TIME + 30)))
1374     {
1375         return(GA_STATUS_ACTIVE);
1376     }
1377
1378     return(GA_STATUS_NACTIVE);
1379 }
1380
1381
1382  
1383 /* List available agents.
1384  */
1385 char **get_agents(int flag)
1386 {
1387     int f_size = 0;
1388     
1389     char **f_files = NULL;
1390     DIR *dp;
1391
1392     struct dirent *entry;
1393     
1394     /* Opening the directory given */
1395     dp = opendir(AGENTINFO_DIR);
1396     if(!dp) 
1397     {
1398         merror("%s: Error opening directory: '%s': %s ",
1399                 __local_name,
1400                 AGENTINFO_DIR,
1401                 strerror(errno));
1402         return(NULL);
1403     }   
1404
1405
1406     /* Reading directory */
1407     while((entry = readdir(dp)) != NULL)
1408     {
1409         int status = 0;
1410         char tmp_file[513];
1411         tmp_file[512] = '\0';
1412         
1413         /* Just ignore . and ..  */
1414         if((strcmp(entry->d_name,".") == 0) ||
1415            (strcmp(entry->d_name,"..") == 0))
1416             continue;
1417
1418         snprintf(tmp_file, 512, "%s/%s", AGENTINFO_DIR, entry->d_name);
1419
1420
1421         if(flag != GA_ALL)
1422         {
1423             struct stat file_status;
1424
1425             if(stat(tmp_file, &file_status) < 0)
1426                 continue;
1427             
1428             if(file_status.st_mtime > (time(0) - (3*NOTIFY_TIME + 30)))
1429             {
1430                 status = 1;
1431                 if(flag == GA_NOTACTIVE)
1432                     continue;
1433             }
1434             else
1435             {
1436                 if(flag == GA_ACTIVE)
1437                     continue;
1438             }
1439         }
1440         
1441         f_files = (char **)realloc(f_files, (f_size +2) * sizeof(char *));
1442         if(!f_files)
1443         {
1444             ErrorExit(MEM_ERROR, __local_name);
1445         }
1446
1447
1448         /* Adding agent entry */
1449         if(flag == GA_ALL_WSTATUS)
1450         {
1451            char agt_stat[512];
1452            
1453            snprintf(agt_stat, sizeof(agt_stat) -1, "%s %s",
1454                     entry->d_name, status == 1?"active":"disconnected"); 
1455
1456            os_strdup(agt_stat, f_files[f_size]);
1457         }
1458         else
1459         {
1460             os_strdup(entry->d_name, f_files[f_size]);
1461         }
1462         
1463         f_files[f_size +1] = NULL;
1464         
1465         f_size++;
1466     }
1467     
1468     closedir(dp);
1469     return(f_files);
1470 }
1471
1472  
1473 /* EOF */