new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / analysisd / decoders / hostinfo.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 /* Hostinfo decoder */
11 #include "decoder.h"
12
13 #include "config.h"
14 #include "os_regex/os_regex.h"
15 #include "eventinfo.h"
16 #include "alerts/alerts.h"
17
18 #define HOSTINFO_FILE   "/queue/fts/hostinfo"
19 #define HOST_HOST       "Host: "
20 /*#define HOST_PORT       " open ports: "
21 #define HOST_CHANGED    "Host information changed."
22 #define HOST_NEW        "New host information added."*/
23 #define PREV_OPEN       "Previously"
24
25 /* Local variables */
26 static int hi_err = 0;
27 static int id_new = 0;
28 static int id_mod = 0;
29 static char _hi_buf[OS_MAXSTR + 1];
30 static FILE *_hi_fp = NULL;
31
32 /* Hostinfo decoder */
33 static OSDecoderInfo *hostinfo_dec = NULL;
34
35
36 /* Check if the string matches */
37 static char *__go_after(char *x, const char *y)
38 {
39     size_t x_s;
40     size_t y_s;
41
42     /* X and Y must be not null */
43     if (!x || !y) {
44         return (NULL);
45     }
46
47     x_s = strlen(x);
48     y_s = strlen(y);
49
50     if (x_s <= y_s) {
51         return (NULL);
52     }
53
54     /* String does not match */
55     if (strncmp(x, y, y_s) != 0) {
56         return (NULL);
57     }
58
59     x += y_s;
60
61     return (x);
62 }
63
64 /* Initialize the necessary information to process the host information */
65 void HostinfoInit()
66 {
67     hi_err = 0;
68
69     /* Zero decoder */
70     os_calloc(1, sizeof(OSDecoderInfo), hostinfo_dec);
71     hostinfo_dec->id = getDecoderfromlist(HOSTINFO_MOD);
72     hostinfo_dec->type = OSSEC_RL;
73     hostinfo_dec->name = HOSTINFO_MOD;
74     hostinfo_dec->fts = 0;
75     id_new = getDecoderfromlist(HOSTINFO_NEW);
76     id_mod = getDecoderfromlist(HOSTINFO_MOD);
77
78     /* Open HOSTINFO_FILE */
79     snprintf(_hi_buf, OS_SIZE_1024, "%s", HOSTINFO_FILE);
80
81     /* r+ to read and write. Do not truncate */
82     _hi_fp = fopen(_hi_buf, "r+");
83     if (!_hi_fp) {
84         /* Try opening with a w flag, file probably does not exist */
85         _hi_fp = fopen(_hi_buf, "w");
86         if (_hi_fp) {
87             fclose(_hi_fp);
88             _hi_fp = fopen(_hi_buf, "r+");
89         }
90     }
91     if (!_hi_fp) {
92         merror(FOPEN_ERROR, ARGV0, _hi_buf, errno, strerror(errno));
93         return;
94     }
95
96     /* Clear the buffer */
97     memset(_hi_buf, '\0', OS_MAXSTR + 1);
98
99     return;
100 }
101
102 /* Return the file pointer to be used */
103 static FILE *HI_File(void)
104 {
105     if (_hi_fp) {
106         fseek(_hi_fp, 0, SEEK_SET);
107         return (_hi_fp);
108     }
109
110     return (NULL);
111 }
112
113 /* Special decoder for Hostinformation
114  * Not using the default rendering tools for simplicity
115  * and to be less resource intensive
116  */
117 int DecodeHostinfo(Eventinfo *lf)
118 {
119     int changed = 0;
120     size_t bf_size;
121
122     char *ip;
123     char *portss;
124     char *tmpstr;
125
126     char buffer[OS_MAXSTR + 1];
127     char opened[OS_MAXSTR + 1];
128     FILE *fp;
129
130     /* Check maximum number of errors */
131     if (hi_err > 30) {
132         merror("%s: Too many errors handling host information db. "
133                "Ignoring it.", ARGV0);
134         return (0);
135     }
136
137     /* Zero buffers */
138     buffer[OS_MAXSTR] = '\0';
139     opened[OS_MAXSTR] = '\0';
140     fp = HI_File();
141     if (!fp) {
142         merror("%s: Error handling host information database.", ARGV0);
143         hi_err++;
144         return (0);
145     }
146
147     /* Copy log to buffer */
148     strncpy(buffer, lf->log, OS_MAXSTR);
149
150     /* Get IP */
151     tmpstr = __go_after(buffer, HOST_HOST);
152     if (!tmpstr) {
153         merror("%s: Error handling host information database.", ARGV0);
154         hi_err++;
155
156         return (0);
157     }
158
159     /* Setting IP */
160     ip = tmpstr;
161     tmpstr = strchr(tmpstr, ',');
162     if (!tmpstr) {
163         merror("%s: Error handling host information database.", ARGV0);
164         hi_err++;
165
166         return (0);
167     }
168     *tmpstr = '\0';
169     tmpstr++;
170     portss = tmpstr;
171
172     /* Get IP only information -- to store */
173     tmpstr = strchr(ip, ' ');
174     if (tmpstr) {
175         *tmpstr = '\0';
176     }
177     bf_size = strlen(ip);
178
179     /* Read the file and search for a possible entry */
180     while (fgets(_hi_buf, OS_MAXSTR - 1, fp) != NULL) {
181         /* Ignore blank lines and lines with a comment */
182         if (_hi_buf[0] == '\n' || _hi_buf[0] == '#') {
183             continue;
184         }
185
186         /* Remove newline */
187         tmpstr = strchr(_hi_buf, '\n');
188         if (tmpstr) {
189             *tmpstr = '\0';
190         }
191
192         /* Check for IP */
193         if (strncmp(ip, _hi_buf, bf_size) == 0) {
194             /* Cannot use strncmp to avoid errors with crafted files */
195             if (strcmp(portss, _hi_buf + bf_size) == 0) {
196                 return (0);
197             } else {
198                 char *tmp_ports;
199
200                 tmp_ports = _hi_buf + (bf_size + 1);
201                 snprintf(opened, OS_MAXSTR, "%s %s", PREV_OPEN, tmp_ports);
202                 changed = 1;
203             }
204         }
205     }
206
207     /* Add the new entry at the end of the file */
208     fseek(fp, 0, SEEK_END);
209     fprintf(fp, "%s%s\n", ip, portss);
210
211     /* Set decoder */
212     lf->decoder_info = hostinfo_dec;
213
214     /* Set comment */
215     if (changed == 1) {
216         hostinfo_dec->id = id_mod;
217         /* lf->generated_rule->last_events[0] = opened; */
218     } else {
219         hostinfo_dec->id = id_new;
220     }
221
222     return (1);
223 }
224