18a2001e92cdc7c4d49f3e65b57f4156159387fd
[ossec-hids.git] / src / logcollector / read_djb_multilog.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All rights 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  * License details at the LICENSE file included with OSSEC or
12  * online at: http://www.ossec.net/en/licensing.html
13  */
14
15 /* Read DJB multilog */
16
17
18 #include "shared.h"
19 #include "logcollector.h"
20
21
22 /* To translante between month (int) to month (char) */
23 char *(djb_month[])={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug",
24                      "Sep","Oct","Nov","Dec"};
25
26 char djb_host[512 +1];                     
27                 
28
29
30 /* Initializes multilog. */
31 int init_djbmultilog(int pos)
32 {
33     char *djbp_name = NULL;
34     char *tmp_str = NULL;
35
36
37     logff[pos].djb_program_name = NULL;
38
39
40     /* Initializing hostname. */
41     memset(djb_host, '\0', 512 +1);
42
43     #ifndef WIN32
44     if(gethostname(djb_host, 512 -1) != 0)
45     {
46         strncpy(djb_host, "unknown", 512 -1);
47     }
48     else
49     {
50         char *_ltmp;
51
52         /* Remove domain part if available */
53         _ltmp = strchr(djb_host, '.');
54         if(_ltmp)
55             *_ltmp = '\0';
56     }
57     #else
58     strncpy(djb_host, "win32", 512 -1);
59     #endif
60                                                                                                         
61
62
63     /* Multilog must be in the following format: /path/program_name/current */
64     tmp_str = strrchr(logff[pos].file, '/');
65     if(!tmp_str)
66         return(0);
67
68     
69     /* Must end with /current and must not be in the beginning of the string. */
70     if((strcmp(tmp_str, "/current") != 0) || (tmp_str == logff[pos].file))
71     {
72         return(0);
73     }
74
75
76     tmp_str[0] = '\0';
77
78
79     /* Getting final name. */
80     djbp_name = strrchr(logff[pos].file, '/');
81     if(djbp_name == logff[pos].file)
82     {
83         tmp_str[0] = '/';
84         return(0);
85     }
86
87     
88     os_strdup(djbp_name+1, logff[pos].djb_program_name);
89     tmp_str[0] = '/';
90
91
92     verbose("%s: INFO: Using program name '%s' for DJB multilog file: '%s'.",
93             ARGV0, logff[pos].djb_program_name, logff[pos].file);
94
95
96     return(1);
97 }
98
99
100
101 /* Read DJB multilog. */
102 void *read_djbmultilog(int pos, int *rc, int drop_it)
103 {
104     int str_len = 0;
105     int need_clear = 0;
106     char *p;
107     char str[OS_MAXSTR + 1];
108     char buffer[OS_MAXSTR + 1];
109
110     str[OS_MAXSTR]= '\0';
111     *rc = 0;
112
113
114     /* Must have a valid program name. */
115     if(!logff[pos].djb_program_name)
116     {
117         return(NULL);
118     }
119     
120
121
122     /* Getting new entry */
123     while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL)
124     {
125         
126         /* Getting buffer size */
127         str_len = strlen(str);
128
129         
130         /* Getting the last occurence of \n */
131         if ((p = strrchr(str, '\n')) != NULL) 
132         {
133             *p = '\0';
134
135             /* If need clear is set, we just get the line and ignore it. */
136             if(need_clear)
137             {
138                 need_clear = 0;
139                 continue;
140             }
141         }
142         else
143         {
144             need_clear = 1;
145         }
146         
147         
148         /* Multilog messages have the following format:
149          * @40000000463246020c2ca16c xx...
150          */
151         if((str_len > 26) &&
152            (str[0] == '@') && 
153            isalnum((int)str[1]) &&
154            isalnum((int)str[2]) &&
155            isalnum((int)str[3]) &&
156            isalnum((int)str[24]) &&
157            (str[25] == ' '))
158         {
159             /* Removing spaces and tabs */
160             p = str + 26;
161             while(*p == ' ' || *p == '\t')
162             {
163                 p++;
164             }
165                 
166             
167             /* If message has a valid syslog header, send as is. */
168             if((str_len > 44) &&
169                (p[3] == ' ') &&  
170                (p[6] == ' ') &&
171                (p[9] == ':') &&
172                (p[12] == ':') &&
173                (p[15] == ' '))
174             {
175                 p+=16;
176                 strncpy(buffer, p, OS_MAXSTR);
177             }
178             else
179             {
180                 /* We will add a proper syslog header. */
181                 time_t djbtime;
182                 struct tm *pt;
183
184
185                 djbtime = time(NULL);
186                 pt = localtime(&djbtime);
187
188
189                 /* Syslog time: Apr 27 14:50:32  */
190                 snprintf(buffer, OS_MAXSTR, "%s %02d %02d:%02d:%02d %s %s: %s",
191                                              djb_month[pt->tm_mon],
192                                              pt->tm_mday,
193                                              pt->tm_hour,
194                                              pt->tm_min,
195                                              pt->tm_sec,
196                                              djb_host,
197                                              logff[pos].djb_program_name,
198                                              p);
199             }
200         }
201         
202         
203         else
204         {
205             debug2("%s: DEBUG: Invalid DJB log: '%s'", ARGV0, str);
206             continue;
207         }
208         
209         
210         debug2("%s: DEBUG: Reading DJB multilog message: '%s'", ARGV0, buffer);
211
212         
213         /* Sending message to queue */
214         if(drop_it == 0)
215         {
216             if(SendMSG(logr_queue, buffer, logff[pos].file, MYSQL_MQ) < 0)
217             {
218                 merror(QUEUE_SEND, ARGV0);
219                 if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
220                 {
221                     ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
222                 }
223             }
224         }
225         
226         continue;
227     }
228
229     return(NULL); 
230 }
231
232 /* EOF */