Imported Upstream version 2.5.1
[ossec-hids.git] / src / config / localfile-config.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All right reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software
9  * Foundation
10  */
11
12  
13
14 #include "shared.h" 
15 #include "localfile-config.h"
16
17
18 int Read_Localfile(XML_NODE node, void *d1, void *d2)
19 {
20     int pl = 0;
21     int i = 0;
22     
23     int glob_set = 0; 
24     
25     #ifndef WIN32
26     int glob_offset = 0;
27     #endif
28
29
30     /* XML Definitions */
31     char *xml_localfile_location = "location";
32     char *xml_localfile_command = "command";
33     char *xml_localfile_logformat = "log_format";
34     char *xml_localfile_frequency = "frequency";
35     char *xml_localfile_alias = "alias";
36
37     logreader *logf;
38     logreader_config *log_config;
39
40     log_config = (logreader_config *)d1;
41
42
43     /* If config is not set, we need to create it */ 
44     if(!log_config->config)
45     {
46         os_calloc(2, sizeof(logreader), log_config->config);
47         logf = log_config->config;
48         logf[0].file = NULL;
49         logf[0].command = NULL;
50         logf[0].alias = NULL;
51         logf[0].logformat = NULL;
52         logf[1].file = NULL;
53         logf[1].command = NULL;
54         logf[1].alias = NULL;
55         logf[1].logformat = NULL;
56     }
57     else
58     {
59         logf = log_config->config;
60         while(logf[pl].file != NULL)
61         {
62             pl++;
63         }
64         
65         /* Allocating more memory */
66         os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
67         logf = log_config->config;
68         logf[pl +1].file = NULL;
69         logf[pl +1].command = NULL;
70         logf[pl +1].alias = NULL;
71         logf[pl +1].logformat = NULL;
72     }
73     
74     logf[pl].file = NULL;
75     logf[pl].command = NULL;
76     logf[pl].alias = NULL;
77     logf[pl].logformat = NULL;
78     logf[pl].fp = NULL;
79     logf[pl].ffile = NULL;
80     logf[pl].djb_program_name = NULL;
81     logf[pl].ign = 360;
82
83     
84     /* Searching for entries related to files */
85     i = 0;
86     while(node[i])
87     {
88         if(!node[i]->element)
89         {
90             merror(XML_ELEMNULL, ARGV0);
91             return(OS_INVALID);
92         }
93         else if(!node[i]->content)
94         {
95             merror(XML_VALUENULL, ARGV0, node[i]->element);
96             return(OS_INVALID);
97         }
98         else if(strcmp(node[i]->element,xml_localfile_command) == 0)
99         {
100             os_strdup(node[i]->content, logf[pl].file);
101             logf[pl].command = logf[pl].file;
102         }
103         else if(strcmp(node[i]->element,xml_localfile_frequency) == 0)
104         {
105             if(!OS_StrIsNum(node[i]->content))
106             {
107                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
108                 return(OS_INVALID);
109             }
110
111             logf[pl].ign = atoi(node[i]->content);
112         }
113         else if(strcmp(node[i]->element,xml_localfile_location) == 0)
114         {
115             #ifdef WIN32
116             /* Expand variables on Windows. */
117             if(strchr(node[i]->content, '%'))
118             {
119                 int expandreturn = 0;   
120                 char newfile[OS_MAXSTR +1];
121
122                 newfile[OS_MAXSTR] = '\0';
123                 expandreturn = ExpandEnvironmentStrings(node[i]->content, 
124                                                         newfile, OS_MAXSTR);
125
126                 if((expandreturn > 0) && (expandreturn < OS_MAXSTR))
127                 {
128                     free(node[i]->content);
129
130                     os_strdup(newfile, node[i]->content);
131                 }
132             }   
133             #endif
134
135
136             /* This is a glob*.
137              * We will call this file multiple times until
138              * there is no one else available.
139              */
140             #ifndef WIN32 /* No windows support for glob */ 
141             if(strchr(node[i]->content, '*') ||
142                strchr(node[i]->content, '?') ||
143                strchr(node[i]->content, '['))
144             {
145                 glob_t g;
146                 
147                 /* Setting ot the first entry of the glob */
148                 if(glob_set == 0)
149                     glob_set = pl +1;
150                 
151                 if(glob(node[i]->content, 0, NULL, &g) != 0)
152                 {
153                     merror(GLOB_ERROR, ARGV0, node[i]->content);
154                     os_strdup(node[i]->content, logf[pl].file);
155                     i++;
156                     continue;
157                 }
158              
159                 /* Checking for the last entry */
160                 if((g.gl_pathv[glob_offset]) == NULL)
161                 {
162                     /* Checking when nothing is found. */
163                     if(glob_offset == 0)
164                     {
165                         merror(GLOB_NFOUND, ARGV0, node[i]->content);
166                         return(OS_INVALID);
167                     }
168                     i++;
169                     continue;
170                 }
171
172
173                 /* Checking for strftime on globs too. */
174                 if(strchr(g.gl_pathv[glob_offset], '%'))
175                 {
176                     struct tm *p;
177                     time_t l_time = time(0);
178                     char lfile[OS_FLSIZE + 1];
179                     size_t ret;
180
181                     p = localtime(&l_time);
182
183                     lfile[OS_FLSIZE] = '\0';
184                     ret = strftime(lfile, OS_FLSIZE, g.gl_pathv[glob_offset], p);
185                     if(ret == 0)
186                     {
187                         merror(PARSE_ERROR, ARGV0, g.gl_pathv[glob_offset]);
188                         return(OS_INVALID);
189                     }
190
191                     os_strdup(g.gl_pathv[glob_offset], logf[pl].ffile);
192                     os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
193                 }
194                 else
195                 {
196                     os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
197                 }
198
199                 
200                 glob_offset++;
201                 globfree(&g);
202
203                 /* Now we need to create another file entry */
204                 pl++;
205                 os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
206                 logf = log_config->config;
207                 
208                 logf[pl].file = NULL;
209                 logf[pl].alias = NULL;
210                 logf[pl].logformat = NULL;
211                 logf[pl].fp = NULL;
212                 logf[pl].ffile = NULL;
213                             
214                 logf[pl +1].file = NULL;
215                 logf[pl +1].alias = NULL;
216                 logf[pl +1].logformat = NULL;
217
218                 /* We can not increment the file count in here */
219                 continue;
220             }
221             else if(strchr(node[i]->content, '%'))
222             #else
223             if(strchr(node[i]->content, '%'))    
224             #endif /* WIN32 */
225
226             /* We need the format file (based on date) */
227             {
228                 struct tm *p;
229                 time_t l_time = time(0);
230                 char lfile[OS_FLSIZE + 1];
231                 size_t ret;
232
233                 p = localtime(&l_time);
234
235                 lfile[OS_FLSIZE] = '\0';
236                 ret = strftime(lfile, OS_FLSIZE, node[i]->content, p);
237                 if(ret == 0)
238                 {
239                     merror(PARSE_ERROR, ARGV0, node[i]->content);
240                     return(OS_INVALID);
241                 }
242
243                 os_strdup(node[i]->content, logf[pl].ffile);
244                 os_strdup(node[i]->content, logf[pl].file);
245             }
246             
247             
248             /* Normal file */
249             else
250             {
251                 os_strdup(node[i]->content, logf[pl].file);
252             }
253         }
254
255         /* Getting log format */
256         else if(strcasecmp(node[i]->element,xml_localfile_logformat) == 0)
257         {
258             os_strdup(node[i]->content, logf[pl].logformat);
259
260             if(strcmp(logf[pl].logformat, "syslog") == 0)
261             {
262             }
263             else if(strcmp(logf[pl].logformat, "generic") == 0)
264             {
265             }
266             else if(strcmp(logf[pl].logformat, "snort-full") == 0)
267             {
268             }
269             else if(strcmp(logf[pl].logformat, "snort-fast") == 0)
270             {
271             }
272             else if(strcmp(logf[pl].logformat, "apache") == 0)
273             {
274             }
275             else if(strcmp(logf[pl].logformat, "iis") == 0)
276             {
277             }
278             else if(strcmp(logf[pl].logformat, "squid") == 0)
279             {
280             }
281             else if(strcmp(logf[pl].logformat, "nmapg") == 0)
282             {
283             }
284             else if(strcmp(logf[pl].logformat, "mysql_log") == 0)
285             {
286             }
287             else if(strcmp(logf[pl].logformat, "mssql_log") == 0)
288             {
289             }
290             else if(strcmp(logf[pl].logformat, "postgresql_log") == 0)
291             {
292             }
293             else if(strcmp(logf[pl].logformat, "djb-multilog") == 0)
294             {
295             }
296             else if(strcmp(logf[pl].logformat, "syslog-pipe") == 0)
297             {
298             }
299             else if(strcmp(logf[pl].logformat, "command") == 0)
300             {
301             }
302             else if(strcmp(logf[pl].logformat, "full_command") == 0)
303             {
304             }
305             else if(strncmp(logf[pl].logformat, "multi-line", 10) == 0)
306             {
307                 int x = 0;
308                 logf[pl].logformat+=10;
309
310                 while(logf[pl].logformat[0] == ' ')
311                     logf[pl].logformat++;
312                 
313                 if(logf[pl].logformat[0] != ':')
314                 {
315                     merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
316                     return(OS_INVALID);
317                 }
318                 logf[pl].logformat++;
319
320                 while(*logf[pl].logformat == ' ')
321                     logf[pl].logformat++;
322                 
323                 while(logf[pl].logformat[x] >= '0' && logf[pl].logformat[x] <= '9')    
324                     x++;
325
326                 while(logf[pl].logformat[x] == ' ')
327                     x++;
328
329                 if(logf[pl].logformat[x] != '\0')
330                 {
331                     merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
332                     return(OS_INVALID);
333                 }
334             }
335             else if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
336             {
337             }
338             else
339             {
340                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
341                 return(OS_INVALID);
342             }
343         }
344         else if(strcasecmp(node[i]->element,xml_localfile_alias) == 0)
345         {
346             os_strdup(node[i]->content, logf[pl].alias);
347         }
348         else
349         {
350             merror(XML_INVELEM, ARGV0, node[i]->element);
351             return(OS_INVALID);
352         }
353
354         i++;
355     }
356
357
358     /* Validating glob entries */
359     if(glob_set)
360     {
361         char *format;
362         
363         /* Getting log format */
364         if(logf[pl].logformat)
365         {
366             format = logf[pl].logformat;
367         }
368         else if(logf[glob_set -1].logformat)
369         {
370             format = logf[glob_set -1].logformat;
371         }
372         else
373         {
374             merror(MISS_LOG_FORMAT, ARGV0);
375             return(OS_INVALID);
376         }
377
378         /* The last entry is always null on glob */
379         pl--;
380
381
382         /* Setting format for all entries */
383         for(i = (glob_set -1); i<= pl; i++)
384         {
385             /* Every entry must be valid */
386             if(!logf[i].file)
387             {
388                 merror(MISS_FILE, ARGV0);
389                 return(OS_INVALID);
390             }
391             
392             if(logf[i].logformat == NULL)
393             {
394                 logf[i].logformat = format;
395             }
396
397         }
398     }
399
400     /* Missing log format */
401     if(!logf[pl].logformat)
402     {
403         merror(MISS_LOG_FORMAT, ARGV0);
404         return(OS_INVALID);
405     }
406
407     /* Missing file */
408     if(!logf[pl].file)
409     {
410         merror(MISS_FILE, ARGV0);
411         return(OS_INVALID);
412     }
413     
414     /* Verifying a valid event log config */
415     if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
416     {
417         if((strcmp(logf[pl].file, "Application") != 0)&&
418            (strcmp(logf[pl].file, "System") != 0)&&
419            (strcmp(logf[pl].file, "Security") != 0))
420          {
421              /* Invalid event log */
422              merror(NSTD_EVTLOG, ARGV0, logf[pl].file);
423              return(0);
424          }
425     }
426
427     if((strcmp(logf[pl].logformat, "command") == 0)||
428        (strcmp(logf[pl].logformat, "full_command") == 0)) 
429     {
430         if(!logf[pl].command)
431         {
432             merror("%s: ERROR: Missing 'command' argument. "
433                    "This option will be ignored.", ARGV0);
434         }
435     }
436
437     return(0);
438 }
439
440 /* EOF */