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