Imported Upstream version 2.3
[ossec-hids.git] / src / config / localfile-config.c
1 /* @(#) $Id: localfile-config.c,v 1.25 2009/11/03 21:07:32 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
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
35
36     logreader *logf;
37     logreader_config *log_config;
38
39     log_config = (logreader_config *)d1;
40
41
42     /* If config is not set, we need to create it */ 
43     if(!log_config->config)
44     {
45         os_calloc(2, sizeof(logreader), log_config->config);
46         logf = log_config->config;
47         logf[0].file = NULL;
48         logf[0].command = NULL;
49         logf[0].logformat = NULL;
50         logf[1].file = NULL;
51         logf[1].command = NULL;
52         logf[1].logformat = NULL;
53     }
54     else
55     {
56         logf = log_config->config;
57         while(logf[pl].file != NULL)
58         {
59             pl++;
60         }
61         
62         /* Allocating more memory */
63         os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
64         logf = log_config->config;
65         logf[pl +1].file = NULL;
66         logf[pl +1].command = NULL;
67         logf[pl +1].logformat = NULL;
68     }
69     
70     logf[pl].file = NULL;
71     logf[pl].command = NULL;
72     logf[pl].logformat = NULL;
73     logf[pl].fp = NULL;
74     logf[pl].ffile = NULL;
75     logf[pl].djb_program_name = NULL;
76     
77     
78     /* Searching for entries related to files */
79     i = 0;
80     while(node[i])
81     {
82         if(!node[i]->element)
83         {
84             merror(XML_ELEMNULL, ARGV0);
85             return(OS_INVALID);
86         }
87         else if(!node[i]->content)
88         {
89             merror(XML_VALUENULL, ARGV0, node[i]->element);
90             return(OS_INVALID);
91         }
92         else if(strcmp(node[i]->element,xml_localfile_command) == 0)
93         {
94             os_strdup(node[i]->content, logf[pl].file);
95             logf[pl].command = logf[pl].file;
96         }
97         else if(strcmp(node[i]->element,xml_localfile_location) == 0)
98         {
99             #ifdef WIN32
100             /* Expand variables on Windows. */
101             if(strchr(node[i]->content, '%'))
102             {
103                 int expandreturn = 0;   
104                 char newfile[OS_MAXSTR +1];
105
106                 newfile[OS_MAXSTR] = '\0';
107                 expandreturn = ExpandEnvironmentStrings(node[i]->content, 
108                                                         newfile, OS_MAXSTR);
109
110                 if((expandreturn > 0) && (expandreturn < OS_MAXSTR))
111                 {
112                     free(node[i]->content);
113
114                     os_strdup(newfile, node[i]->content);
115                 }
116             }   
117             #endif
118
119
120             /* This is a glob*.
121              * We will call this file multiple times until
122              * there is no one else available.
123              */
124             #ifndef WIN32 /* No windows support for glob */ 
125             if(strchr(node[i]->content, '*') ||
126                strchr(node[i]->content, '?') ||
127                strchr(node[i]->content, '['))
128             {
129                 glob_t g;
130                 
131                 /* Setting ot the first entry of the glob */
132                 if(glob_set == 0)
133                     glob_set = pl +1;
134                 
135                 if(glob(node[i]->content, 0, NULL, &g) != 0)
136                 {
137                     merror(GLOB_ERROR, ARGV0, node[i]->content);
138                     os_strdup(node[i]->content, logf[pl].file);
139                     i++;
140                     continue;
141                 }
142              
143                 /* Checking for the last entry */
144                 if((g.gl_pathv[glob_offset]) == NULL)
145                 {
146                     /* Checking when nothing is found. */
147                     if(glob_offset == 0)
148                     {
149                         merror(GLOB_NFOUND, ARGV0, node[i]->content);
150                         return(OS_INVALID);
151                     }
152                     i++;
153                     continue;
154                 }
155
156
157                 /* Checking for strftime on globs too. */
158                 if(strchr(g.gl_pathv[glob_offset], '%'))
159                 {
160                     struct tm *p;
161                     time_t l_time = time(0);
162                     char lfile[OS_FLSIZE + 1];
163                     size_t ret;
164
165                     p = localtime(&l_time);
166
167                     lfile[OS_FLSIZE] = '\0';
168                     ret = strftime(lfile, OS_FLSIZE, g.gl_pathv[glob_offset], p);
169                     if(ret == 0)
170                     {
171                         merror(PARSE_ERROR, ARGV0, g.gl_pathv[glob_offset]);
172                         return(OS_INVALID);
173                     }
174
175                     os_strdup(g.gl_pathv[glob_offset], logf[pl].ffile);
176                     os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
177                 }
178                 else
179                 {
180                     os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
181                 }
182
183                 
184                 glob_offset++;
185                 globfree(&g);
186
187                 /* Now we need to create another file entry */
188                 pl++;
189                 os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
190                 logf = log_config->config;
191                 
192                 logf[pl].file = NULL;
193                 logf[pl].logformat = NULL;
194                 logf[pl].fp = NULL;
195                 logf[pl].ffile = NULL;
196                             
197                 logf[pl +1].file = NULL;
198                 logf[pl +1].logformat = NULL;
199
200                 /* We can not increment the file count in here */
201                 continue;
202             }
203             else if(strchr(node[i]->content, '%'))
204             #else
205             if(strchr(node[i]->content, '%'))    
206             #endif /* WIN32 */
207
208             /* We need the format file (based on date) */
209             {
210                 struct tm *p;
211                 time_t l_time = time(0);
212                 char lfile[OS_FLSIZE + 1];
213                 size_t ret;
214
215                 p = localtime(&l_time);
216
217                 lfile[OS_FLSIZE] = '\0';
218                 ret = strftime(lfile, OS_FLSIZE, node[i]->content, p);
219                 if(ret == 0)
220                 {
221                     merror(PARSE_ERROR, ARGV0, node[i]->content);
222                     return(OS_INVALID);
223                 }
224
225                 os_strdup(node[i]->content, logf[pl].ffile);
226                 os_strdup(node[i]->content, logf[pl].file);
227             }
228             
229             
230             /* Normal file */
231             else
232             {
233                 os_strdup(node[i]->content, logf[pl].file);
234             }
235         }
236
237         /* Getting log format */
238         else if(strcasecmp(node[i]->element,xml_localfile_logformat) == 0)
239         {
240             os_strdup(node[i]->content, logf[pl].logformat);
241
242             if(strcmp(logf[pl].logformat, "syslog") == 0)
243             {
244             }
245             else if(strcmp(logf[pl].logformat, "snort-full") == 0)
246             {
247             }
248             else if(strcmp(logf[pl].logformat, "snort-fast") == 0)
249             {
250             }
251             else if(strcmp(logf[pl].logformat, "apache") == 0)
252             {
253             }
254             else if(strcmp(logf[pl].logformat, "iis") == 0)
255             {
256             }
257             else if(strcmp(logf[pl].logformat, "squid") == 0)
258             {
259             }
260             else if(strcmp(logf[pl].logformat, "nmapg") == 0)
261             {
262             }
263             else if(strcmp(logf[pl].logformat, "mysql_log") == 0)
264             {
265             }
266             else if(strcmp(logf[pl].logformat, "mssql_log") == 0)
267             {
268             }
269             else if(strcmp(logf[pl].logformat, "postgresql_log") == 0)
270             {
271             }
272             else if(strcmp(logf[pl].logformat, "djb-multilog") == 0)
273             {
274             }
275             else if(strcmp(logf[pl].logformat, "syslog-pipe") == 0)
276             {
277             }
278             else if(strcmp(logf[pl].logformat, "command") == 0)
279             {
280             }
281             else if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
282             {
283             }
284             else
285             {
286                 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
287                 return(OS_INVALID);
288             }
289         }
290         else
291         {
292             merror(XML_INVELEM, ARGV0, node[i]->element);
293             return(OS_INVALID);
294         }
295
296         i++;
297     }
298
299
300     /* Validating glob entries */
301     if(glob_set)
302     {
303         char *format;
304         
305         /* Getting log format */
306         if(logf[pl].logformat)
307         {
308             format = logf[pl].logformat;
309         }
310         else if(logf[glob_set -1].logformat)
311         {
312             format = logf[glob_set -1].logformat;
313         }
314         else
315         {
316             merror(MISS_LOG_FORMAT, ARGV0);
317             return(OS_INVALID);
318         }
319
320         /* The last entry is always null on glob */
321         pl--;
322
323
324         /* Setting format for all entries */
325         for(i = (glob_set -1); i<= pl; i++)
326         {
327             /* Every entry must be valid */
328             if(!logf[i].file)
329             {
330                 merror(MISS_FILE, ARGV0);
331                 return(OS_INVALID);
332             }
333             
334             if(logf[i].logformat == NULL)
335             {
336                 logf[i].logformat = format;
337             }
338
339         }
340     }
341
342     /* Missing log format */
343     if(!logf[pl].logformat)
344     {
345         merror(MISS_LOG_FORMAT, ARGV0);
346         return(OS_INVALID);
347     }
348
349     /* Missing file */
350     if(!logf[pl].file)
351     {
352         merror(MISS_FILE, ARGV0);
353         return(OS_INVALID);
354     }
355     
356     /* Verifying a valid event log config */
357     if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
358     {
359         if((strcmp(logf[pl].file, "Application") != 0)&&
360            (strcmp(logf[pl].file, "System") != 0)&&
361            (strcmp(logf[pl].file, "Security") != 0))
362          {
363              /* Invalid event log */
364              merror(NSTD_EVTLOG, ARGV0, logf[pl].file);
365              return(0);
366          }
367     }
368
369     if(strcmp(logf[pl].logformat, "command") == 0)
370     {
371         if(!logf[pl].command)
372         {
373             merror("%s: ERROR: Missing 'command' argument. "
374                    "This option will be ignored.", ARGV0);
375         }
376     }
377
378     return(0);
379 }
380
381 /* EOF */