new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / logcollector / read_nmapg.c
1 /* Copyright (C) 2009 Trend Micro Inc.
2  * All right 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 #include "shared.h"
11 #include "logcollector.h"
12
13 #define NMAPG_HOST  "Host: "
14 #define NMAPG_PORT  "Ports:"
15 #define NMAPG_OPEN  "open/"
16 #define NMAPG_STAT  "Status:"
17
18 /* Prototypes */
19 static char *__go_after(char *x, const char *y);
20 static char *__get_port(char *str, char *proto, char *port, size_t msize);
21
22
23 /* Get port and protocol */
24 static char *__get_port(char *str, char *proto, char *port, size_t msize)
25 {
26     int filtered = 0;
27     char *p, *q;
28
29     /* Remov whitespace */
30     while (*str == ' ') {
31         str++;
32     }
33
34     /* Get port */
35     p = strchr(str, '/');
36     if (!p) {
37         return (NULL);
38     }
39     *p = '\0';
40     p++;
41
42     /* Get port */
43     strncpy(port, str, msize);
44     port[msize - 1] = '\0';
45
46     /* Check if the port is open */
47     q = __go_after(p, NMAPG_OPEN);
48     if (!q) {
49         /* Port is not open */
50         filtered = 1;
51         q = p;
52
53         /* Going to the start of protocol field */
54         p = strchr(q, '/');
55         if (!p) {
56             return (NULL);
57         }
58         p++;
59     } else {
60         p = q;
61     }
62
63     /* Get protocol */
64     str = p;
65     p = strchr(str, '/');
66     if (!p) {
67         return (NULL);
68     }
69     *p = '\0';
70     p++;
71
72     strncpy(proto, str, msize);
73     proto[msize - 1] = '\0';
74
75     /* Set proto to null if port is not open */
76     if (filtered) {
77         proto[0] = '\0';
78     }
79
80     /* Remove slashes */
81     if (*p == '/') {
82         p++;
83         q = p;
84         p = strchr(p, ',');
85         if (p) {
86             return (p);
87         }
88
89         return (q);
90     }
91
92     return (NULL);
93 }
94
95 /* Check if the string matches */
96 static char *__go_after(char *x, const char *y)
97 {
98     size_t x_s;
99     size_t y_s;
100
101     /* X and Y must be not null */
102     if (!x || !y) {
103         return (NULL);
104     }
105
106     x_s = strlen(x);
107     y_s = strlen(y);
108
109     if (x_s <= y_s) {
110         return (NULL);
111     }
112
113     /* String does not match */
114     if (strncmp(x, y, y_s) != 0) {
115         return (NULL);
116     }
117
118     x += y_s;
119
120     return (x);
121 }
122
123 /* Read Nmap grepable files */
124 void *read_nmapg(int pos, int *rc, int drop_it)
125 {
126     int final_msg_s;
127     int need_clear = 0;
128
129     char str[OS_MAXSTR + 1];
130     char final_msg[OS_MAXSTR + 1];
131     char buffer[OS_MAXSTR + 1];
132     char port[17];
133     char proto[17];
134
135     char *ip = NULL;
136     char *p;
137     char *q;
138
139     *rc = 0;
140     str[OS_MAXSTR] = '\0';
141     final_msg[OS_MAXSTR] = '\0';
142     buffer[OS_MAXSTR] = '\0';
143
144     port[16] = '\0';
145     proto[16] = '\0';
146
147     while (fgets(str, OS_MAXSTR - OS_LOG_HEADER, logff[pos].fp) != NULL) {
148         /* If need clear is set, we need to clear the line */
149         if (need_clear) {
150             if ((q = strchr(str, '\n')) != NULL) {
151                 need_clear = 0;
152             }
153             continue;
154         }
155
156         /* Remove \n at the end of the string */
157         if ((q = strchr(str, '\n')) != NULL) {
158             *q = '\0';
159         } else {
160             need_clear = 1;
161         }
162
163         /* Do not get commented lines */
164         if ((str[0] == '#') || (str[0] == '\0')) {
165             continue;
166         }
167
168         /* Get host */
169         q = __go_after(str, NMAPG_HOST);
170         if (!q) {
171             goto file_error;
172         }
173
174         /* Get ip/hostname */
175         p = strchr(q, ')');
176         if (!p) {
177             goto file_error;
178         }
179
180         /* Setting the valid ip */
181         ip = q;
182
183         /* Get the ports */
184         q = strchr(p, '\t');
185         if (!q) {
186             goto file_error;
187         }
188         q++;
189
190         /* Now fixing p, to have the closing parenthesis */
191         p++;
192         *p = '\0';
193
194         /* q now should point to the ports */
195         p = __go_after(q, NMAPG_PORT);
196         if (!p) {
197             /* Check if no port is available */
198             p = __go_after(q, NMAPG_STAT);
199             if (p) {
200                 continue;
201             }
202
203             goto file_error;
204         }
205
206         /* Generate final msg */
207         snprintf(final_msg, OS_MAXSTR, "Host: %s, open ports:",
208                  ip);
209         final_msg_s = OS_MAXSTR - ((strlen(final_msg) + 3));
210
211         /* Get port and protocol */
212         do {
213             /* Avoid filling the buffer (3*port size) */
214             if (final_msg_s < 27) {
215                 break;
216             }
217
218             p = __get_port(p, proto, port, 9);
219             if (!p) {
220                 debug1("%s: Bad formatted nmap grepable file (port).", ARGV0);
221                 break;
222             }
223
224             /* Port not open */
225             if (proto[0] == '\0') {
226                 continue;
227             }
228
229             /* Add ports */
230             snprintf(buffer, OS_MAXSTR, " %s(%s)", port, proto);
231             strncat(final_msg, buffer, final_msg_s);
232             final_msg_s -= (strlen(buffer) + 2);
233
234         } while (*p == ',' && (p++));
235
236         if (drop_it == 0) {
237             /* Send message to queue */
238             if (SendMSG(logr_queue, final_msg, logff[pos].file,
239                         HOSTINFO_MQ) < 0) {
240                 merror(QUEUE_SEND, ARGV0);
241                 if ((logr_queue = StartMQ(DEFAULTQPATH, WRITE)) < 0) {
242                     ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQPATH);
243                 }
244             }
245         }
246
247         /* Get next */
248         continue;
249
250         /* Handle errors */
251 file_error:
252
253         merror("%s: Bad formatted nmap grepable file.", ARGV0);
254         *rc = -1;
255         return (NULL);
256
257     }
258
259     return (NULL);
260 }
261