1 /* @(#) $Id: ./src/config/localfile-config.c, 2012/03/28 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
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
16 #include "localfile-config.h"
19 int Read_Localfile(XML_NODE node, void *d1, void *d2)
32 char *xml_localfile_location = "location";
33 char *xml_localfile_command = "command";
34 char *xml_localfile_logformat = "log_format";
35 char *xml_localfile_frequency = "frequency";
36 char *xml_localfile_alias = "alias";
39 logreader_config *log_config;
41 log_config = (logreader_config *)d1;
44 /* If config is not set, we need to create it */
45 if(!log_config->config)
47 os_calloc(2, sizeof(logreader), log_config->config);
48 logf = log_config->config;
50 logf[0].command = NULL;
52 logf[0].logformat = NULL;
54 logf[1].command = NULL;
56 logf[1].logformat = NULL;
60 logf = log_config->config;
61 while(logf[pl].file != NULL)
66 /* Allocating more memory */
67 os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
68 logf = log_config->config;
69 logf[pl +1].file = NULL;
70 logf[pl +1].command = NULL;
71 logf[pl +1].alias = NULL;
72 logf[pl +1].logformat = NULL;
76 logf[pl].command = NULL;
77 logf[pl].alias = NULL;
78 logf[pl].logformat = NULL;
80 logf[pl].ffile = NULL;
81 logf[pl].djb_program_name = NULL;
85 /* Searching for entries related to files */
91 merror(XML_ELEMNULL, ARGV0);
94 else if(!node[i]->content)
96 merror(XML_VALUENULL, ARGV0, node[i]->element);
99 else if(strcmp(node[i]->element,xml_localfile_command) == 0)
101 /* We don't accept remote commands from the manager - just in case. */
102 if(log_config->agent_cfg == 1 && log_config->accept_remote == 0)
104 merror("%s: Remote commands are not accepted from the manager. "
105 "Ignoring it on the agent.conf", ARGV0);
107 logf[pl].file = NULL;
108 logf[pl].ffile = NULL;
109 logf[pl].command = NULL;
110 logf[pl].alias = NULL;
111 logf[pl].logformat = NULL;
116 os_strdup(node[i]->content, logf[pl].file);
117 logf[pl].command = logf[pl].file;
119 else if(strcmp(node[i]->element,xml_localfile_frequency) == 0)
121 if(!OS_StrIsNum(node[i]->content))
123 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
127 logf[pl].ign = atoi(node[i]->content);
129 else if(strcmp(node[i]->element,xml_localfile_location) == 0)
132 /* Expand variables on Windows. */
133 if(strchr(node[i]->content, '%'))
135 int expandreturn = 0;
136 char newfile[OS_MAXSTR +1];
138 newfile[OS_MAXSTR] = '\0';
139 expandreturn = ExpandEnvironmentStrings(node[i]->content,
142 if((expandreturn > 0) && (expandreturn < OS_MAXSTR))
144 free(node[i]->content);
146 os_strdup(newfile, node[i]->content);
153 * We will call this file multiple times until
154 * there is no one else available.
156 #ifndef WIN32 /* No windows support for glob */
157 if(strchr(node[i]->content, '*') ||
158 strchr(node[i]->content, '?') ||
159 strchr(node[i]->content, '['))
163 /* Setting ot the first entry of the glob */
167 if(glob(node[i]->content, 0, NULL, &g) != 0)
169 merror(GLOB_ERROR, ARGV0, node[i]->content);
170 os_strdup(node[i]->content, logf[pl].file);
175 /* Checking for the last entry */
176 if((g.gl_pathv[glob_offset]) == NULL)
178 /* Checking when nothing is found. */
181 merror(GLOB_NFOUND, ARGV0, node[i]->content);
189 /* Checking for strftime on globs too. */
190 if(strchr(g.gl_pathv[glob_offset], '%'))
193 time_t l_time = time(0);
194 char lfile[OS_FLSIZE + 1];
197 p = localtime(&l_time);
199 lfile[OS_FLSIZE] = '\0';
200 ret = strftime(lfile, OS_FLSIZE, g.gl_pathv[glob_offset], p);
203 merror(PARSE_ERROR, ARGV0, g.gl_pathv[glob_offset]);
207 os_strdup(g.gl_pathv[glob_offset], logf[pl].ffile);
208 os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
212 os_strdup(g.gl_pathv[glob_offset], logf[pl].file);
219 /* Now we need to create another file entry */
221 os_realloc(logf, (pl +2)*sizeof(logreader), log_config->config);
222 logf = log_config->config;
224 logf[pl].file = NULL;
225 logf[pl].alias = NULL;
226 logf[pl].logformat = NULL;
228 logf[pl].ffile = NULL;
230 logf[pl +1].file = NULL;
231 logf[pl +1].alias = NULL;
232 logf[pl +1].logformat = NULL;
234 /* We can not increment the file count in here */
237 else if(strchr(node[i]->content, '%'))
239 if(strchr(node[i]->content, '%'))
242 /* We need the format file (based on date) */
245 time_t l_time = time(0);
246 char lfile[OS_FLSIZE + 1];
249 p = localtime(&l_time);
251 lfile[OS_FLSIZE] = '\0';
252 ret = strftime(lfile, OS_FLSIZE, node[i]->content, p);
255 merror(PARSE_ERROR, ARGV0, node[i]->content);
259 os_strdup(node[i]->content, logf[pl].ffile);
260 os_strdup(node[i]->content, logf[pl].file);
267 os_strdup(node[i]->content, logf[pl].file);
271 /* Getting log format */
272 else if(strcasecmp(node[i]->element,xml_localfile_logformat) == 0)
274 os_strdup(node[i]->content, logf[pl].logformat);
276 if(strcmp(logf[pl].logformat, "syslog") == 0)
279 else if(strcmp(logf[pl].logformat, "generic") == 0)
282 else if(strcmp(logf[pl].logformat, "snort-full") == 0)
285 else if(strcmp(logf[pl].logformat, "snort-fast") == 0)
288 else if(strcmp(logf[pl].logformat, "apache") == 0)
291 else if(strcmp(logf[pl].logformat, "iis") == 0)
294 else if(strcmp(logf[pl].logformat, "squid") == 0)
297 else if(strcmp(logf[pl].logformat, "nmapg") == 0)
300 else if(strcmp(logf[pl].logformat, "mysql_log") == 0)
303 else if(strcmp(logf[pl].logformat, "ossecalert") == 0)
306 else if(strcmp(logf[pl].logformat, "mssql_log") == 0)
309 else if(strcmp(logf[pl].logformat, "postgresql_log") == 0)
312 else if(strcmp(logf[pl].logformat, "djb-multilog") == 0)
315 else if(strcmp(logf[pl].logformat, "syslog-pipe") == 0)
318 else if(strcmp(logf[pl].logformat, "command") == 0)
321 else if(strcmp(logf[pl].logformat, "full_command") == 0)
324 else if(strncmp(logf[pl].logformat, "multi-line", 10) == 0)
327 logf[pl].logformat+=10;
329 while(logf[pl].logformat[0] == ' ')
330 logf[pl].logformat++;
332 if(logf[pl].logformat[0] != ':')
334 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
337 logf[pl].logformat++;
339 while(*logf[pl].logformat == ' ')
340 logf[pl].logformat++;
342 while(logf[pl].logformat[x] >= '0' && logf[pl].logformat[x] <= '9')
345 while(logf[pl].logformat[x] == ' ')
348 if(logf[pl].logformat[x] != '\0')
350 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
354 else if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
359 merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content);
363 else if(strcasecmp(node[i]->element,xml_localfile_alias) == 0)
365 os_strdup(node[i]->content, logf[pl].alias);
369 merror(XML_INVELEM, ARGV0, node[i]->element);
377 /* Validating glob entries */
382 /* Getting log format */
383 if(logf[pl].logformat)
385 format = logf[pl].logformat;
387 else if(logf[glob_set -1].logformat)
389 format = logf[glob_set -1].logformat;
393 merror(MISS_LOG_FORMAT, ARGV0);
397 /* The last entry is always null on glob */
401 /* Setting format for all entries */
402 for(i = (glob_set -1); i<= pl; i++)
404 /* Every entry must be valid */
407 merror(MISS_FILE, ARGV0);
411 if(logf[i].logformat == NULL)
413 logf[i].logformat = format;
419 /* Missing log format */
420 if(!logf[pl].logformat)
422 merror(MISS_LOG_FORMAT, ARGV0);
429 merror(MISS_FILE, ARGV0);
433 /* Verifying a valid event log config */
434 if(strcmp(logf[pl].logformat, EVENTLOG) == 0)
436 if((strcmp(logf[pl].file, "Application") != 0)&&
437 (strcmp(logf[pl].file, "System") != 0)&&
438 (strcmp(logf[pl].file, "Security") != 0))
440 /* Invalid event log */
441 merror(NSTD_EVTLOG, ARGV0, logf[pl].file);
446 if((strcmp(logf[pl].logformat, "command") == 0)||
447 (strcmp(logf[pl].logformat, "full_command") == 0))
449 if(!logf[pl].command)
451 merror("%s: ERROR: Missing 'command' argument. "
452 "This option will be ignored.", ARGV0);