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