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