new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / logcollector / read_mssql_log.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All rights reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation.
8  */
9
10 /* Read MS SQL logs */
11
12 #include "shared.h"
13 #include "logcollector.h"
14
15
16 /* Send MS SQL message and check the return code */
17 static void __send_mssql_msg(int pos, int drop_it, char *buffer)
18 {
19     debug2("%s: DEBUG: Reading MSSQL message: '%s'", ARGV0, buffer);
20     if (drop_it == 0) {
21         if (SendMSG(logr_queue, buffer, logff[pos].file, LOCALFILE_MQ) < 0) {
22             merror(QUEUE_SEND, ARGV0);
23             if ((logr_queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) {
24                 ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
25             }
26         }
27     }
28 }
29
30 /* Read MS SQL log files */
31 void *read_mssql_log(int pos, int *rc, int drop_it)
32 {
33     size_t str_len = 0;
34     int need_clear = 0;
35     char *p;
36     char str[OS_MAXSTR + 1];
37     char buffer[OS_MAXSTR + 1];
38
39     /* Zero buffer and str */
40     buffer[0] = '\0';
41     buffer[OS_MAXSTR] = '\0';
42     str[OS_MAXSTR] = '\0';
43     *rc = 0;
44
45     /* Get new entry */
46     while (fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) {
47         /* Get buffer size */
48         str_len = strlen(str);
49
50         /* Check str_len size. Very useless, but just to make sure */
51         if (str_len >= sizeof(buffer) - 2) {
52             str_len = sizeof(buffer) - 10;
53         }
54
55         /* Get the last occurrence of \n */
56         if ((p = strrchr(str, '\n')) != NULL) {
57             *p = '\0';
58
59             /* If need clear is set, we just get the line and ignore it */
60             if (need_clear) {
61                 need_clear = 0;
62                 continue;
63             }
64         } else {
65             need_clear = 1;
66         }
67
68 #ifdef WIN32
69         if ((p = strrchr(str, '\r')) != NULL) {
70             *p = '\0';
71         }
72
73         /* Look for empty string (only on windows) */
74         if (str_len <= 1) {
75             continue;
76         }
77
78         /* Windows can have comment on their logs */
79         if (str[0] == '#') {
80             continue;
81         }
82 #endif
83
84         /* MS SQL messages have the following formats:
85          * 2009-03-25 04:47:30.01 Server
86          * 2003-10-09 00:00:06.68 sys1
87          * 2009-02-06 11:48:59     Server
88          */
89         if ((str_len > 19) &&
90                 (str[4] == '-') &&
91                 (str[7] == '-') &&
92                 (str[10] == ' ') &&
93                 (str[13] == ':') &&
94                 (str[16] == ':') &&
95                 isdigit((int)str[0]) &&
96                 isdigit((int)str[1]) &&
97                 isdigit((int)str[2]) &&
98                 isdigit((int)str[3])) {
99
100             /* If the saved message is empty, set it and continue */
101             if (buffer[0] == '\0') {
102                 strncpy(buffer, str, OS_MAXSTR);
103                 continue;
104             }
105
106             /* If not, send the saved one and store the new one for later */
107             else {
108                 __send_mssql_msg(pos, drop_it, buffer);
109
110                 /* Store current one at the buffer */
111                 strncpy(buffer, str, OS_MAXSTR);
112             }
113         }
114
115         /* Query logs can be in multiple lines
116          * They always start with a tab in the additional lines
117          */
118         else if ((str_len > 2) && (buffer[0] != '\0')) {
119             /* Size of the buffer */
120             size_t buffer_len = strlen(buffer);
121
122             p = str;
123
124             /* Remove extra spaces and tabs */
125             while (*p == ' ' || *p == '\t') {
126                 p++;
127             }
128
129             /* Add additional message to the saved buffer */
130             if (sizeof(buffer) - buffer_len > str_len + 256) {
131                 /* Here we make sure that the size of the buffer
132                  * minus what was used (strlen) is greater than
133                  * the length of the received message.
134                  */
135                 buffer[buffer_len] = ' ';
136                 buffer[buffer_len + 1] = '\0';
137                 strncat(buffer, str, OS_MAXSTR);
138             }
139         }
140
141         continue;
142     }
143
144     /* Send whatever is stored */
145     if (buffer[0] != '\0') {
146         __send_mssql_msg(pos, drop_it, buffer);
147     }
148
149     return (NULL);
150 }
151