3 /* Copyright (C) 2009 Trend Micro Inc.
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
15 #include "localfile-config.h"
18 int Read_Localfile(XML_NODE node, void *d1, void *d2)
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";
38 logreader_config *log_config;
40 log_config = (logreader_config *)d1;
43 /* If config is not set, we need to create it */
44 if(!log_config->config)
46 os_calloc(2, sizeof(logreader), log_config->config);
47 logf = log_config->config;
49 logf[0].command = NULL;
51 logf[0].logformat = NULL;
53 logf[1].command = NULL;
55 logf[1].logformat = NULL;
59 logf = log_config->config;
60 while(logf[pl].file != NULL)
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;
75 logf[pl].command = NULL;
76 logf[pl].alias = NULL;
77 logf[pl].logformat = NULL;
79 logf[pl].ffile = NULL;
80 logf[pl].djb_program_name = NULL;
84 /* Searching for entries related to files */
90 merror(XML_ELEMNULL, ARGV0);
93 else if(!node[i]->content)
95 merror(XML_VALUENULL, ARGV0, node[i]->element);
98 else if(strcmp(node[i]->element,xml_localfile_command) == 0)
100 os_strdup(node[i]->content, logf[pl].file);
101 logf[pl].command = logf[pl].file;
103 else if(strcmp(node[i]->element,xml_localfile_frequency) == 0)
105 if(!OS_StrIsNum(node[i]->content))
107 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
111 logf[pl].ign = atoi(node[i]->content);
113 else if(strcmp(node[i]->element,xml_localfile_location) == 0)
116 /* Expand variables on Windows. */
117 if(strchr(node[i]->content, '%'))
119 int expandreturn = 0;
120 char newfile[OS_MAXSTR +1];
122 newfile[OS_MAXSTR] = '\0';
123 expandreturn = ExpandEnvironmentStrings(node[i]->content,
126 if((expandreturn > 0) && (expandreturn < OS_MAXSTR))
128 free(node[i]->content);
130 os_strdup(newfile, node[i]->content);
137 * We will call this file multiple times until
138 * there is no one else available.
140 #ifndef WIN32 /* No windows support for glob */
141 if(strchr(node[i]->content, '*') ||
142 strchr(node[i]->content, '?') ||
143 strchr(node[i]->content, '['))
147 /* Setting ot the first entry of the glob */
151 if(glob(node[i]->content, 0, NULL, &g) != 0)
153 merror(GLOB_ERROR, ARGV0, node[i]->content);
154 os_strdup(node[i]->content, logf[pl].file);
159 /* Checking for the last entry */
160 if((g.gl_pathv[glob_offset]) == NULL)
162 /* Checking when nothing is found. */
165 merror(GLOB_NFOUND, ARGV0, node[i]->content);
173 /* Checking for strftime on globs too. */
174 if(strchr(g.gl_pathv[glob_offset], '%'))
177 time_t l_time = time(0);
178 char lfile[OS_FLSIZE + 1];
181 p = localtime(&l_time);
183 lfile[OS_FLSIZE] = '\0';
184 ret = strftime(lfile, OS_FLSIZE, g.gl_pathv[glob_offset], p);
187 merror(PARSE_ERROR, ARGV0, g.gl_pathv[glob_offset]);
191 os_strdup(g.gl_pathv[glob_offset], logf[pl].ffile);
192 os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
196 os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
203 /* Now we need to create another file entry */
205 os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
206 logf = log_config->config;
208 logf[pl].file = NULL;
209 logf[pl].alias = NULL;
210 logf[pl].logformat = NULL;
212 logf[pl].ffile = NULL;
214 logf[pl +1].file = NULL;
215 logf[pl +1].alias = NULL;
216 logf[pl +1].logformat = NULL;
218 /* We can not increment the file count in here */
221 else if(strchr(node[i]->content, '%'))
223 if(strchr(node[i]->content, '%'))
226 /* We need the format file (based on date) */
229 time_t l_time = time(0);
230 char lfile[OS_FLSIZE + 1];
233 p = localtime(&l_time);
235 lfile[OS_FLSIZE] = '\0';
236 ret = strftime(lfile, OS_FLSIZE, node[i]->content, p);
239 merror(PARSE_ERROR, ARGV0, node[i]->content);
243 os_strdup(node[i]->content, logf[pl].ffile);
244 os_strdup(node[i]->content, logf[pl].file);
251 os_strdup(node[i]->content, logf[pl].file);
255 /* Getting log format */
256 else if(strcasecmp(node[i]->element,xml_localfile_logformat) == 0)
258 os_strdup(node[i]->content, logf[pl].logformat);
260 if(strcmp(logf[pl].logformat, "syslog") == 0)
263 else if(strcmp(logf[pl].logformat, "generic") == 0)
266 else if(strcmp(logf[pl].logformat, "snort-full") == 0)
269 else if(strcmp(logf[pl].logformat, "snort-fast") == 0)
272 else if(strcmp(logf[pl].logformat, "apache") == 0)
275 else if(strcmp(logf[pl].logformat, "iis") == 0)
278 else if(strcmp(logf[pl].logformat, "squid") == 0)
281 else if(strcmp(logf[pl].logformat, "nmapg") == 0)
284 else if(strcmp(logf[pl].logformat, "mysql_log") == 0)
287 else if(strcmp(logf[pl].logformat, "mssql_log") == 0)
290 else if(strcmp(logf[pl].logformat, "postgresql_log") == 0)
293 else if(strcmp(logf[pl].logformat, "djb-multilog") == 0)
296 else if(strcmp(logf[pl].logformat, "syslog-pipe") == 0)
299 else if(strcmp(logf[pl].logformat, "command") == 0)
302 else if(strcmp(logf[pl].logformat, "full_command") == 0)
305 else if(strncmp(logf[pl].logformat, "multi-line", 10) == 0)
308 logf[pl].logformat+=10;
310 while(logf[pl].logformat[0] == ' ')
311 logf[pl].logformat++;
313 if(logf[pl].logformat[0] != ':')
315 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
318 logf[pl].logformat++;
320 while(*logf[pl].logformat == ' ')
321 logf[pl].logformat++;
323 while(logf[pl].logformat[x] >= '0' && logf[pl].logformat[x] <= '9')
326 while(logf[pl].logformat[x] == ' ')
329 if(logf[pl].logformat[x] != '\0')
331 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
335 else if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
340 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
344 else if(strcasecmp(node[i]->element,xml_localfile_alias) == 0)
346 os_strdup(node[i]->content, logf[pl].alias);
350 merror(XML_INVELEM, ARGV0, node[i]->element);
358 /* Validating glob entries */
363 /* Getting log format */
364 if(logf[pl].logformat)
366 format = logf[pl].logformat;
368 else if(logf[glob_set -1].logformat)
370 format = logf[glob_set -1].logformat;
374 merror(MISS_LOG_FORMAT, ARGV0);
378 /* The last entry is always null on glob */
382 /* Setting format for all entries */
383 for(i = (glob_set -1); i<= pl; i++)
385 /* Every entry must be valid */
388 merror(MISS_FILE, ARGV0);
392 if(logf[i].logformat == NULL)
394 logf[i].logformat = format;
400 /* Missing log format */
401 if(!logf[pl].logformat)
403 merror(MISS_LOG_FORMAT, ARGV0);
410 merror(MISS_FILE, ARGV0);
414 /* Verifying a valid event log config */
415 if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
417 if((strcmp(logf[pl].file, "Application") != 0)&&
418 (strcmp(logf[pl].file, "System") != 0)&&
419 (strcmp(logf[pl].file, "Security") != 0))
421 /* Invalid event log */
422 merror(NSTD_EVTLOG, ARGV0, logf[pl].file);
427 if((strcmp(logf[pl].logformat, "command") == 0)||
428 (strcmp(logf[pl].logformat, "full_command") == 0))
430 if(!logf[pl].command)
432 merror("%s: ERROR: Missing 'command' argument. "
433 "This option will be ignored.", ARGV0);