Imported Upstream version 2.3
[ossec-hids.git] / src / config / syscheck-config.c
1 /* @(#) $Id: syscheck-config.c,v 1.25 2009/11/04 15:18:59 dcid Exp $ */
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 3) as published by the FSF - Free Software
9  * Foundation
10  */
11
12
13 #include "shared.h"
14
15 #include "syscheck-config.h"
16
17
18
19 int dump_syscheck_entry(config *syscheck, char *entry, int vals, int reg)
20 {
21     int pl = 0;
22     
23     if(reg == 1)
24     {
25         #ifdef WIN32
26         if(syscheck->registry == NULL)
27         {
28             os_calloc(2, sizeof(char *), syscheck->registry);
29             syscheck->registry[pl + 1] = NULL;
30             os_strdup(entry, syscheck->registry[pl]);        
31         }
32         else
33         {
34             while(syscheck->registry[pl] != NULL)
35             {
36                 pl++;
37             }
38             os_realloc(syscheck->registry, (pl +2) * sizeof(char *), 
39                         syscheck->registry);
40             syscheck->registry[pl + 1] = NULL;
41             os_strdup(entry, syscheck->registry[pl]);
42         }
43         #endif
44         
45     }
46
47     
48     else
49     {
50         if(syscheck->dir == NULL)
51         {
52             os_calloc(2, sizeof(char *), syscheck->dir);
53             syscheck->dir[pl + 1] = NULL;
54             os_strdup(entry, syscheck->dir[pl]);
55
56             os_calloc(2, sizeof(int), syscheck->opts);
57             syscheck->opts[pl + 1] = 0;
58             syscheck->opts[pl] = vals;         
59         }
60         else
61         {
62             while(syscheck->dir[pl] != NULL)
63             {
64                 pl++;
65             }
66             os_realloc(syscheck->dir, (pl +2) * sizeof(char *), 
67                        syscheck->dir);
68             syscheck->dir[pl + 1] = NULL;
69             os_strdup(entry, syscheck->dir[pl]);
70
71             os_realloc(syscheck->opts, (pl +2) * sizeof(int), 
72                        syscheck->opts);
73             syscheck->opts[pl + 1] = 0;
74             syscheck->opts[pl] = vals;         
75         }
76     }
77
78     return(1);
79 }
80
81
82
83 /* Read Windows registry configuration */
84 #ifdef WIN32
85 int read_reg(config *syscheck, char *entries)
86 {
87     int i;
88     char **entry;
89     char *tmp_str;
90
91     
92     /* Getting each entry separately */
93     entry = OS_StrBreak(',', entries, MAX_DIR_SIZE); /* Max number */
94
95
96     /* entry can not be null */
97     if(entry == NULL)
98     {
99         return(0);
100     }
101
102
103     /* Doing it for each Entry */
104     while(*entry)
105     {
106         char *tmp_entry;
107
108         tmp_entry = *entry;
109
110         /* Removing spaces at the beginning */
111         while(*tmp_entry == ' ')
112         {
113             tmp_entry++;
114         }
115
116         /* Removing spaces at the end */
117         tmp_str = strchr(tmp_entry, ' ');
118         if(tmp_str)
119         {
120             tmp_str++;
121
122             /* Checking if it is really at the end */
123             if((*tmp_str == '\0') || (*tmp_str == ' '))
124             {
125                 tmp_str--;
126                 *tmp_str = '\0';
127             }
128         }
129
130
131         /* Adding entries - looking for the last available */
132         i = 0;
133         while(syscheck->registry && syscheck->registry[i])
134         {
135             int str_len_i;
136             int str_len_dir;
137             
138             str_len_dir = strlen(tmp_entry);
139             str_len_i = strlen(syscheck->registry[i]);
140             
141             if(str_len_dir > str_len_i)
142             {
143                 str_len_dir = str_len_i;
144             }
145
146             /* Duplicated entry */
147             if(strcmp(syscheck->registry[i], tmp_entry) == 0)
148             {
149                 merror(SK_DUP, ARGV0, tmp_entry);
150                 return(1);
151             }
152             i++;
153         }
154         
155         /* Adding new entry */
156         dump_syscheck_entry(syscheck, tmp_entry, 0, 1);
157         
158         
159         /* Next entry */
160         entry++;    
161     }
162     
163     return(1);
164 }
165 #endif /* For read_reg */
166
167
168
169
170 /* Read directories attributes */            
171 int read_attr(config *syscheck, char *dirs, char **g_attrs, char **g_values)
172 {
173     char *xml_check_all = "check_all";
174     char *xml_check_sum = "check_sum";
175     char *xml_check_sha1sum = "check_sha1sum";
176     char *xml_check_md5sum = "check_md5sum";
177     char *xml_check_size = "check_size";
178     char *xml_check_owner = "check_owner";
179     char *xml_check_group = "check_group";
180     char *xml_check_perm = "check_perm";
181     char *xml_real_time = "realtime";
182
183     char **dir;
184     char *tmp_str;
185     dir = OS_StrBreak(',', dirs, MAX_DIR_SIZE); /* Max number */
186
187     /* Dir can not be null */
188     if(dir == NULL)
189     {
190         return(0);
191     }
192
193
194     /* Doing it for each directory */
195     while(*dir)
196     {
197         int i = 0;
198         int opts = 0;
199         char *tmp_dir;
200
201         char **attrs = NULL;
202         char **values = NULL;
203         
204         tmp_dir = *dir;
205
206         /* Removing spaces at the beginning */
207         while(*tmp_dir == ' ')
208         {
209             tmp_dir++;
210         }
211
212         /* Removing spaces at the end */
213         tmp_str = strchr(tmp_dir, ' ');
214         if(tmp_str)
215         {
216             tmp_str++;
217
218             /* Checking if it is really at the end */
219             if((*tmp_str == '\0') || (*tmp_str == ' '))
220             {
221                 tmp_str--;
222                 *tmp_str = '\0';
223             }
224         }
225
226
227         /* Getting the options */
228         if(!g_attrs || !g_values)
229         {
230             merror(SYSCHECK_NO_OPT, ARGV0, dirs);
231             return(0);
232         }
233
234         attrs = g_attrs;
235         values = g_values;
236
237         while(*attrs && *values)
238         {
239             /* Checking all */
240             if(strcmp(*attrs, xml_check_all) == 0)
241             {
242                 if(strcmp(*values, "yes") == 0)
243                 {
244                     opts|=CHECK_MD5SUM;
245                     opts|=CHECK_SHA1SUM;
246                     opts|=CHECK_PERM;
247                     opts|=CHECK_SIZE;
248                     opts|=CHECK_OWNER;
249                     opts|=CHECK_GROUP;
250                 }
251                 else if(strcmp(*values, "no") == 0)
252                 {
253                 }
254                 else
255                 {
256                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
257                     return(0);
258                 }
259             }
260             /* Checking sum */
261             else if(strcmp(*attrs, xml_check_sum) == 0)
262             {
263                 if(strcmp(*values, "yes") == 0)
264                 {
265                     opts|=CHECK_MD5SUM;
266                     opts|=CHECK_SHA1SUM;
267                 }
268                 else if(strcmp(*values, "no") == 0)
269                 {
270                 }
271                 else
272                 {
273                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
274                     return(0);
275                 }
276             }
277             /* Checking md5sum */
278             else if(strcmp(*attrs, xml_check_md5sum) == 0)
279             {
280                 if(strcmp(*values, "yes") == 0)
281                 {
282                     opts|=CHECK_MD5SUM;
283                 }
284                 else if(strcmp(*values, "no") == 0)
285                 {
286                 }
287                 else
288                 {
289                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
290                     return(0);
291                 }
292             }
293             /* Checking sha1sum */
294             else if(strcmp(*attrs, xml_check_sha1sum) == 0)
295             {
296                 if(strcmp(*values, "yes") == 0)
297                 {
298                     opts|=CHECK_SHA1SUM;
299                 }
300                 else if(strcmp(*values, "no") == 0)
301                 {
302                 }
303                 else
304                 {
305                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
306                     return(0);
307                 }
308             }
309             /* Checking permission */
310             else if(strcmp(*attrs, xml_check_perm) == 0)
311             {
312                 if(strcmp(*values, "yes") == 0)
313                 {
314                     opts|=CHECK_PERM;
315                 }
316                 else if(strcmp(*values, "no") == 0)
317                 {
318                 }
319                 else
320                 {
321                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
322                     return(0);
323                 }
324             }
325             /* Checking size */
326             else if(strcmp(*attrs, xml_check_size) == 0)
327             {
328                 if(strcmp(*values, "yes") == 0)
329                 {
330                     opts|=CHECK_SIZE;
331                 }
332                 else if(strcmp(*values, "no") == 0)
333                 {
334                 }
335                 else
336                 {
337                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
338                     return(0);
339                 }
340             }
341             /* Checking owner */
342             else if(strcmp(*attrs, xml_check_owner) == 0)
343             {
344                 if(strcmp(*values, "yes") == 0)
345                 {
346                     opts|=CHECK_OWNER;
347                 }
348                 else if(strcmp(*values, "no") == 0)
349                 {
350                 }
351                 else
352                 {
353                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
354                     return(0);
355                 }
356             }
357             /* Checking group */
358             else if(strcmp(*attrs, xml_check_group) == 0)
359             {
360                 if(strcmp(*values, "yes") == 0)
361                 {
362                     opts|=CHECK_GROUP;
363                 }
364                 else if(strcmp(*values, "no") == 0)
365                 {
366                 }
367                 else
368                 {
369                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
370                     return(0);
371                 }
372             }
373             else if(strcmp(*attrs, xml_real_time) == 0)
374             {
375                 if(strcmp(*values, "yes") == 0)
376                 {
377                     opts|=CHECK_REALTIME;
378                 }
379                 else if(strcmp(*values, "no") == 0)
380                 {
381                 }
382                 else
383                 {
384                     merror(SK_INV_OPT, ARGV0, *values, *attrs);
385                     return(0);
386                 }
387             }
388             else
389             {
390                 merror(SK_INV_ATTR, ARGV0, *attrs);
391                 return(0);
392             }
393             attrs++; values++;
394         }
395
396
397         /* You must have something set */
398         if(opts == 0)
399         {
400             merror(SYSCHECK_NO_OPT, ARGV0, dirs);
401             return(0);
402         }
403         
404         
405         /* Adding directory - looking for the last available */
406         i = 0;
407         while(syscheck->dir && syscheck->dir[i])
408         {
409             int str_len_i;
410             int str_len_dir;
411             
412             str_len_dir = strlen(tmp_dir);
413             str_len_i = strlen(syscheck->dir[i]);
414             
415             if(str_len_dir > str_len_i)
416             {
417                 str_len_dir = str_len_i;
418             }
419
420             /* Duplicate entry */
421             if(strcmp(syscheck->dir[i], tmp_dir) == 0)
422             {
423                 merror(SK_DUP, ARGV0, tmp_dir);
424                 return(1);
425             }
426
427             i++;
428         }
429
430
431         /* Checking for glob. */
432         #ifndef WIN32
433         if(strchr(tmp_dir, '*') ||
434            strchr(tmp_dir, '?') ||
435            strchr(tmp_dir, '['))
436         {
437             int gindex = 0;
438             glob_t g;
439
440             if(glob(tmp_dir, 0, NULL, &g) != 0)
441             {
442                 merror(GLOB_ERROR, ARGV0, tmp_dir);
443                 return(1);
444             }
445
446             if(g.gl_pathv[0] == NULL)
447             {
448                 merror(GLOB_NFOUND, ARGV0, tmp_dir);
449                 return(1);
450             }
451             
452             while(g.gl_pathv[gindex])
453             {
454                 dump_syscheck_entry(syscheck, g.gl_pathv[gindex], opts, 0);
455                 gindex++;
456             }
457             
458             globfree(&g);
459         }
460
461         else
462         {
463             dump_syscheck_entry(syscheck, tmp_dir, opts, 0);
464         }
465         #else
466         dump_syscheck_entry(syscheck, tmp_dir, opts, 0);
467         #endif
468         
469         
470         /* Next entry */
471         dir++;    
472     }
473     
474     return(1);
475 }
476
477
478
479 int Read_Syscheck(XML_NODE node, void *configp, void *mailp)
480 {
481     int i = 0;
482
483     /* XML Definitions */
484     char *xml_directories = "directories";
485     char *xml_registry = "windows_registry";
486     char *xml_time = "frequency";
487     char *xml_scanday = "scan_day";
488     char *xml_scantime = "scan_time";
489     char *xml_ignore = "ignore";
490     char *xml_registry_ignore = "registry_ignore";
491     char *xml_auto_ignore = "auto_ignore";
492     char *xml_alert_new_files = "alert_new_files";
493     char *xml_disabled = "disabled";
494     char *xml_scan_on_start = "scan_on_start";
495
496     /* Configuration example 
497     <directories check_all="yes">/etc,/usr/bin</directories>
498     <directories check_owner="yes" check_group="yes" check_perm="yes" 
499     check_sum="yes">/var/log</directories>
500     */
501
502     config *syscheck;
503
504     syscheck = (config *)configp;
505     
506     
507     while(node[i])
508     {
509         if(!node[i]->element)
510         {
511             merror(XML_ELEMNULL, ARGV0);
512             return(OS_INVALID);
513         }
514         else if(!node[i]->content)
515         {
516             merror(XML_VALUENULL, ARGV0, node[i]->element);
517             return(OS_INVALID);
518         }
519
520         /* Getting directories */
521         else if(strcmp(node[i]->element,xml_directories) == 0)
522         {
523             char dirs[OS_MAXSTR];
524             
525             #ifdef WIN32
526             ExpandEnvironmentStrings(node[i]->content, dirs, sizeof(dirs) -1);
527             #else
528             strncpy(dirs, node[i]->content, sizeof(dirs) -1);
529             #endif
530             
531             if(!read_attr(syscheck,
532                         dirs, 
533                         node[i]->attributes, 
534                         node[i]->values))
535             {
536                 return(OS_INVALID);
537             }
538         }
539         /* Getting windows registry */
540         else if(strcmp(node[i]->element,xml_registry) == 0)
541         {
542             #ifdef WIN32
543             if(!read_reg(syscheck, node[i]->content))
544             {
545                 return(OS_INVALID);
546             }
547             #endif
548         }
549         /* Getting frequency */
550         else if(strcmp(node[i]->element,xml_time) == 0)
551         {        
552             if(!OS_StrIsNum(node[i]->content))
553             {
554                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
555                 return(OS_INVALID);
556             }
557
558             syscheck->time = atoi(node[i]->content);
559         }
560         /* Getting scan time */
561         else if(strcmp(node[i]->element,xml_scantime) == 0)
562         {
563             syscheck->scan_time = OS_IsValidUniqueTime(node[i]->content);
564             if(!syscheck->scan_time)
565             {
566                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
567                 return(OS_INVALID);
568             }
569         }
570
571         /* Getting scan day */
572         else if(strcmp(node[i]->element,xml_scanday) == 0)
573         {
574             syscheck->scan_day = OS_IsValidDay(node[i]->content);
575             if(!syscheck->scan_day)
576             {
577                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
578                 return(OS_INVALID);
579             }
580         }
581     
582         /* Getting if xml_scan_on_start. */
583         else if(strcmp(node[i]->element, xml_scan_on_start) == 0)
584         {
585             if(strcmp(node[i]->content, "yes") == 0)
586                 syscheck->scan_on_start = 1;
587             else if(strcmp(node[i]->content, "no") == 0)
588                 syscheck->scan_on_start = 0;
589             else
590             {
591                 merror(XML_VALUEERR,ARGV0, node[i]->element, node[i]->content);
592                 return(OS_INVALID);
593             }
594         }
595         
596         /* Getting if disabled. */
597         else if(strcmp(node[i]->element,xml_disabled) == 0)
598         {
599             if(strcmp(node[i]->content, "yes") == 0)
600                 syscheck->disabled = 1;
601             else if(strcmp(node[i]->content, "no") == 0)
602                 syscheck->disabled = 0;
603             else
604             {
605                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
606                 return(OS_INVALID);
607             }
608         }
609         
610         /* Getting file/dir ignore */
611         else if(strcmp(node[i]->element,xml_ignore) == 0)
612         {
613             int ign_size = 0;
614
615             /* For Windows, we attempt to expand environment variables. */
616             #ifdef WIN32
617             char *new_ig = NULL;
618             os_calloc(2048, sizeof(char), new_ig);
619             
620             ExpandEnvironmentStrings(node[i]->content, new_ig, 2047);        
621
622             free(node[i]->content);
623             node[i]->content = new_ig;
624             #endif
625             
626             /* Adding if regex */
627             if(node[i]->attributes && node[i]->values)
628             {
629                 if(node[i]->attributes[0] && node[i]->values[0] &&
630                    (strcmp(node[i]->attributes[0], "type") == 0) && 
631                    (strcmp(node[i]->values[0], "sregex") == 0))
632                 {
633                     OSMatch *mt_pt;
634                     
635                     if(!syscheck->ignore_regex)
636                     {
637                         os_calloc(2, sizeof(OSMatch *),syscheck->ignore_regex);
638                         syscheck->ignore_regex[0] = NULL;
639                         syscheck->ignore_regex[1] = NULL;
640                     }
641                     else
642                     {
643                         while(syscheck->ignore_regex[ign_size] != NULL)
644                             ign_size++;
645
646                         os_realloc(syscheck->ignore_regex,
647                                 sizeof(OSMatch *)*(ign_size +2),
648                                 syscheck->ignore_regex);
649                         syscheck->ignore_regex[ign_size +1] = NULL;
650                     }
651                     os_calloc(1, sizeof(OSMatch), 
652                             syscheck->ignore_regex[ign_size]);
653
654                     if(!OSMatch_Compile(node[i]->content,
655                                         syscheck->ignore_regex[ign_size], 0))
656                     {
657                         mt_pt = (OSMatch *)syscheck->ignore_regex[ign_size];
658                         merror(REGEX_COMPILE, ARGV0, node[i]->content,
659                               mt_pt->error);
660                         return(0);
661                     }
662                 }
663                 else
664                 {
665                     merror(SK_INV_ATTR, ARGV0, node[i]->attributes[0]);
666                     return(OS_INVALID);
667                 }
668             }
669
670             /* Adding if simple entry -- checking for duplicates */
671             else if(!os_IsStrOnArray(node[i]->content, syscheck->ignore))
672             {
673                 if(!syscheck->ignore)
674                 {
675                     os_calloc(2, sizeof(char *), syscheck->ignore);
676                     syscheck->ignore[0] = NULL;
677                     syscheck->ignore[1] = NULL;
678                 }
679                 else
680                 {
681                     while(syscheck->ignore[ign_size] != NULL)
682                         ign_size++;
683
684                     os_realloc(syscheck->ignore, 
685                             sizeof(char *)*(ign_size +2),
686                             syscheck->ignore);
687                     syscheck->ignore[ign_size +1] = NULL;
688                 }
689                 os_strdup(node[i]->content,syscheck->ignore[ign_size]);
690             }
691         }
692
693         /* Getting registry ignore list */
694         else if(strcmp(node[i]->element,xml_registry_ignore) == 0)
695         {
696             #ifdef WIN32
697             int ign_size = 0;
698
699             /* Adding if regex */
700             if(node[i]->attributes && node[i]->values)
701             {
702                 if(node[i]->attributes[0] && node[i]->values[0] &&
703                    (strcmp(node[i]->attributes[0], "type") == 0) &&
704                    (strcmp(node[i]->values[0], "sregex") == 0))
705                 {
706                     OSMatch *mt_pt;
707
708                     if(!syscheck->registry_ignore_regex)
709                     {
710                         os_calloc(2, sizeof(OSMatch *),
711                                      syscheck->registry_ignore_regex);
712                         syscheck->registry_ignore_regex[0] = NULL;
713                         syscheck->registry_ignore_regex[1] = NULL;
714                     }
715                     else
716                     {
717                         while(syscheck->registry_ignore_regex[ign_size] !=NULL)
718                             ign_size++;
719
720                         os_realloc(syscheck->registry_ignore_regex,
721                                 sizeof(OSMatch *)*(ign_size +2),
722                                 syscheck->registry_ignore_regex);
723                         syscheck->registry_ignore_regex[ign_size +1] = NULL;
724                     }
725                     
726                     os_calloc(1, sizeof(OSMatch),
727                             syscheck->registry_ignore_regex[ign_size]);
728
729                     if(!OSMatch_Compile(node[i]->content,
730                                 syscheck->registry_ignore_regex[ign_size], 0))
731                     {
732                         mt_pt = (OSMatch *)
733                                 syscheck->registry_ignore_regex[ign_size];
734                         merror(REGEX_COMPILE, ARGV0, node[i]->content,
735                              mt_pt->error);
736                         return(0);
737                     }
738                 }
739                 else
740                 {
741                     merror(SK_INV_ATTR, ARGV0, node[i]->attributes[0]);
742                     return(OS_INVALID);
743                 }
744             }
745             /* We do not add duplicated entries */
746             else if(!os_IsStrOnArray(node[i]->content, 
747                      syscheck->registry_ignore))
748             {
749                 if(!syscheck->registry_ignore)
750                 {
751                     os_calloc(2, sizeof(char *), syscheck->registry_ignore);
752                     syscheck->registry_ignore[0] = NULL;
753                     syscheck->registry_ignore[1] = NULL;
754                 }
755                 else
756                 {
757                     while(syscheck->registry_ignore[ign_size] != NULL)
758                         ign_size++;
759
760                     os_realloc(syscheck->registry_ignore,
761                             sizeof(char *)*(ign_size +2),
762                             syscheck->registry_ignore);
763                     syscheck->registry_ignore[ign_size +1] = NULL;
764                 }
765                 os_strdup(node[i]->content,syscheck->registry_ignore[ign_size]);
766             }
767             #endif
768         }
769         else if(strcmp(node[i]->element,xml_auto_ignore) == 0)
770         {
771             /* auto_ignore is not read here. */
772         }
773         else if(strcmp(node[i]->element,xml_alert_new_files) == 0)
774         {
775             /* alert_new_files option is not read here. */
776         }
777         else
778         {
779             merror(XML_INVELEM, ARGV0, node[i]->element);
780             return(OS_INVALID);
781         }
782         i++;
783     } 
784     
785     return(0);
786 }