6fea175fd91cafe87916caded2b97302801728f7
[ossec-hids.git] / src / logcollector / read_postgresql_log.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 PostgreSQL logs */
16
17
18 #include "shared.h"
19 #include "logcollector.h"
20
21
22
23 /* Send pgsql message and check the return code. 
24  */
25 void __send_pgsql_msg(int pos, int drop_it, char *buffer)
26 {
27     debug2("%s: DEBUG: Reading PostgreSQL message: '%s'", ARGV0, buffer);
28     if(drop_it == 0)
29     {
30         if(SendMSG(logr_queue, buffer, logff[pos].file, POSTGRESQL_MQ) < 0)
31         {
32             merror(QUEUE_SEND, ARGV0);
33             if((logr_queue = StartMQ(DEFAULTQPATH,WRITE)) < 0)
34             {
35                 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
36             }
37         }
38     }
39 }
40
41
42
43 /* Read PostgreSQL log files */
44 void *read_postgresql_log(int pos, int *rc, int drop_it)
45 {
46     int str_len = 0;
47     int need_clear = 0;
48     char *p;
49     char str[OS_MAXSTR + 1];
50     char buffer[OS_MAXSTR + 1];
51
52
53     /* Zeroing buffer and str */
54     buffer[0] = '\0';
55     buffer[OS_MAXSTR] = '\0';    
56     str[OS_MAXSTR]= '\0';
57     *rc = 0;
58
59
60     /* Getting new entry */
61     while(fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL)
62     {
63         
64         /* Getting buffer size */
65         str_len = strlen(str);
66
67         
68         /* Checking str_len size. Very useless, but just to make sure.. */
69         if(str_len >= sizeof(buffer) -2)
70         {
71             str_len = sizeof(buffer) -10;
72         }
73
74         
75         /* Getting the last occurence of \n */
76         if ((p = strrchr(str, '\n')) != NULL) 
77         {
78             *p = '\0';
79
80             /* If need clear is set, we just get the line and ignore it. */
81             if(need_clear)
82             {
83                 need_clear = 0;
84                 continue;
85             }
86         }
87         else
88         {
89             need_clear = 1;
90         }
91         
92         
93         #ifdef WIN32
94         if ((p = strrchr(str, '\r')) != NULL)
95         {
96             *p = '\0';
97         }
98
99
100         /* Looking for empty string (only on windows) */
101         if(str_len <= 1)
102         {
103             continue;
104         }
105
106
107         /* Windows can have comment on their logs */
108         if(str[0] == '#')
109         {
110             continue;
111         }
112         #endif
113
114        
115
116         /* PostgreSQL messages have the following format:
117          * [2007-08-31 19:17:32.186 ADT] 192.168.2.99:db_name
118          */
119         if((str_len > 32) &&
120            (str[0] == '[') && 
121            (str[5] == '-') && 
122            (str[8] == '-') && 
123            (str[11] == ' ') && 
124            (str[14] == ':') && 
125            (str[17] == ':') && 
126            isdigit((int)str[1]) &&
127            isdigit((int)str[12]))
128         {
129             
130             /* If the saved message is empty, set it and continue. */
131             if(buffer[0] == '\0')
132             {
133                 strncpy(buffer, str, str_len + 2);
134                 continue;
135             }
136
137             /* If not, send the saved one and store the new one for later */
138             else
139             {
140                 __send_pgsql_msg(pos, drop_it, buffer);
141
142
143                 /* Storing current one at the buffer */
144                 strncpy(buffer, str, str_len + 2);
145             }
146         }
147         
148         
149         /* Query logs can be in multiple lines.
150          * They always start with a tab in the additional ones.
151          */
152         else if((str_len > 2) && (buffer[0] != '\0') &&
153                 (str[0] == '\t'))
154         {
155             /* Size of the buffer */
156             int buffer_len = strlen(buffer);
157             
158             p = str +1;
159             
160             /* Removing extra spaces and tabs */
161             while(*p == ' ' || *p == '\t')
162             {
163                 p++;
164             }
165            
166            
167             /* Adding additional message to the saved buffer. */
168             if(sizeof(buffer) - buffer_len > str_len +256)
169             {
170                 /* Here we make sure that the size of the buffer
171                  * minus what was used (strlen) is greater than
172                  * the length of the received message.
173                  */
174                  buffer[buffer_len] = ' ';
175                  buffer[buffer_len +1] = '\0';
176                  strncat(buffer, str, str_len +3);
177             }
178         }
179         
180         continue;
181     }
182
183
184     /* Send whatever is stored. */
185     if(buffer[0] != '\0')
186     {
187         __send_pgsql_msg(pos, drop_it, buffer);
188     }
189     
190     return(NULL); 
191 }
192
193 /* EOF */