new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / os_maild / os_maild_client.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 #include "shared.h"
11 #include "maild.h"
12 #ifdef LIBGEOIP_ENABLED
13 #include "config/config.h"
14 #endif
15
16
17 /* Receive a Message on the Mail queue */
18 MailMsg *OS_RecvMailQ(file_queue *fileq, struct tm *p,
19                       MailConfig *Mail, MailMsg **msg_sms)
20 {
21     int i = 0, sms_set = 0, donotgroup = 0;
22     size_t body_size = OS_MAXSTR - 3, log_size;
23     char logs[OS_MAXSTR + 1];
24     char extra_data[OS_MAXSTR + 1];
25     char log_string[OS_MAXSTR / 4 + 1];
26     char *subject_host;
27 #ifdef LIBGEOIP_ENABLED
28     char geoip_msg_src[OS_SIZE_1024 + 1];
29     char geoip_msg_dst[OS_SIZE_1024 + 1];
30 #endif
31
32     MailMsg *mail;
33     alert_data *al_data;
34
35     Mail->priority = 0;
36
37     /* Get message if available */
38     al_data = Read_FileMon(fileq, p, mail_timeout);
39     if (!al_data) {
40         return (NULL);
41     }
42
43     /* If e-mail came correctly, generate the e-mail body/subject */
44     os_calloc(1, sizeof(MailMsg), mail);
45     os_calloc(BODY_SIZE, sizeof(char), mail->body);
46     os_calloc(SUBJECT_SIZE, sizeof(char), mail->subject);
47
48     /* Generate the logs */
49     logs[0] = '\0';
50     extra_data[0] = '\0';
51     logs[OS_MAXSTR] = '\0';
52
53     while (al_data->log[i]) {
54         log_size = strlen(al_data->log[i]) + 4;
55
56         /* If size left is small than the size of the log, stop it */
57         if (body_size <= log_size) {
58             break;
59         }
60
61         strncat(logs, al_data->log[i], body_size);
62         strncat(logs, "\r\n", body_size);
63         body_size -= log_size;
64         i++;
65     }
66
67     if (al_data->old_md5) {
68         log_size = strlen(al_data->old_md5) + 16 + 4;
69         if (body_size > log_size) {
70             strncat(logs, "Old md5sum was: ", 16);
71             strncat(logs, al_data->old_md5, body_size);
72             strncat(logs, "\r\n", 4);
73             body_size -= log_size;
74         }
75     }
76     if (al_data->new_md5) {
77         log_size = strlen(al_data->new_md5) + 16 + 4;
78         if (body_size > log_size) {
79             strncat(logs, "New md5sum is : ", 16);
80             strncat(logs, al_data->new_md5, body_size);
81             strncat(logs, "\r\n", 4);
82             body_size -= log_size;
83         }
84     }
85     if (al_data->old_sha1) {
86         log_size = strlen(al_data->old_sha1) + 17 + 4;
87         if (body_size > log_size) {
88             strncat(logs, "Old sha1sum was: ", 17);
89             strncat(logs, al_data->old_sha1, body_size);
90             strncat(logs, "\r\n", 4);
91             body_size -= log_size;
92         }
93     }
94     if (al_data->new_sha1) {
95         log_size = strlen(al_data->new_sha1) + 17 + 4;
96         if (body_size > log_size) {
97             strncat(logs, "New sha1sum is : ", 17);
98             strncat(logs, al_data->new_sha1, body_size);
99             strncat(logs, "\r\n", 4);
100             body_size -= log_size;
101         }
102     }
103     if (al_data->perm_chg) {
104        log_size = strlen(al_data->perm_chg) + 17 + 4;
105        if (body_size > log_size) {
106            strncat(logs, "Permission change: ", 20);
107            strncat(logs, al_data->perm_chg, body_size);
108            strncat(logs, "\r\n", 4);
109            body_size -= log_size;
110        }
111     }
112
113
114     /* EXTRA DATA */
115     if (al_data->srcip) {
116         log_size = snprintf(log_string, sizeof(log_string) - 1, "Src IP: %s\r\n", al_data->srcip );
117         if (body_size > log_size) {
118             if ( strncat(extra_data, log_string, log_size) != NULL ) {
119                 body_size -= log_size;
120             }
121         }
122     }
123     if (al_data->dstip) {
124         log_size = snprintf(log_string, sizeof(log_string) - 1, "Dst IP: %s\r\n", al_data->dstip );
125         if (body_size > log_size) {
126             if ( strncat(extra_data, log_string, log_size) != NULL ) {
127                 body_size -= log_size;
128             }
129         }
130     }
131     if (al_data->user) {
132         log_size = snprintf(log_string, sizeof(log_string) - 1, "User: %s\r\n", al_data->user );
133         if (body_size > log_size) {
134             if ( strncat(extra_data, log_string, log_size) != NULL ) {
135                 body_size -= log_size;
136             }
137         }
138     }
139
140     /* Subject */
141     subject_host = strchr(al_data->location, '>');
142     if (subject_host) {
143         subject_host--;
144         *subject_host = '\0';
145     }
146
147     /* We have two subject options - full and normal */
148     if (Mail->subject_full == 0) {
149         /* Option for a clean full subject (without ossec in the name) */
150 #ifdef CLEANFULL
151         snprintf(mail->subject, SUBJECT_SIZE - 1, MAIL_SUBJECT_FULL2,
152                  al_data->level,
153                  al_data->comment,
154                  al_data->location);
155 #else
156         snprintf(mail->subject, SUBJECT_SIZE - 1, MAIL_SUBJECT_FULL,
157                  al_data->location,
158                  al_data->level,
159                  al_data->comment);
160 #endif
161     } else {
162         snprintf(mail->subject, SUBJECT_SIZE - 1, MAIL_SUBJECT,
163                  al_data->location,
164                  al_data->level);
165     }
166
167
168     /* Fix subject back */
169     if (subject_host) {
170         *subject_host = '-';
171     }
172
173 #ifdef LIBGEOIP_ENABLED
174     /* Get GeoIP information */
175     if (Mail->geoip) {
176         if (al_data->srcgeoip) {
177             snprintf(geoip_msg_src, OS_SIZE_1024, "Src Location: %s\r\n", al_data->srcgeoip);
178         } else {
179             geoip_msg_src[0] = '\0';
180         }
181         if (al_data->dstgeoip) {
182             snprintf(geoip_msg_dst, OS_SIZE_1024, "Dst Location: %s\r\n", al_data->dstgeoip);
183         } else {
184             geoip_msg_dst[0] = '\0';
185         }
186     } else {
187         geoip_msg_src[0] = '\0';
188         geoip_msg_dst[0] = '\0';
189     }
190 #endif
191
192     /* Body */
193 #ifdef LIBGEOIP_ENABLED
194     snprintf(mail->body, BODY_SIZE - 1, MAIL_BODY,
195              al_data->date,
196              al_data->location,
197              al_data->rule,
198              al_data->level,
199              al_data->comment,
200              geoip_msg_src,
201              geoip_msg_dst,
202              extra_data,
203              logs);
204 #else
205     snprintf(mail->body, BODY_SIZE - 1, MAIL_BODY,
206              al_data->date,
207              al_data->location,
208              al_data->rule,
209              al_data->level,
210              al_data->comment,
211              extra_data,
212              logs);
213 #endif
214     debug2("OS_RecvMailQ: mail->body[%s]", mail->body);
215
216     /* Check for granular email configs */
217     if (Mail->gran_to) {
218         i = 0;
219         while (Mail->gran_to[i] != NULL) {
220             int gr_set = 0;
221
222             /* Look if location is set */
223             if (Mail->gran_location[i]) {
224                 if (OSMatch_Execute(al_data->location,
225                                     strlen(al_data->location),
226                                     Mail->gran_location[i])) {
227                     gr_set = 1;
228                 } else {
229                     i++;
230                     continue;
231                 }
232             }
233
234             /* Look for the level */
235             if (Mail->gran_level[i]) {
236                 if (al_data->level >= Mail->gran_level[i]) {
237                     gr_set = 1;
238                 } else {
239                     i++;
240                     continue;
241                 }
242             }
243
244             /* Look for rule id */
245             if (Mail->gran_id[i]) {
246                 int id_i = 0;
247                 while (Mail->gran_id[i][id_i] != 0) {
248                     if (Mail->gran_id[i][id_i] == al_data->rule) {
249                         break;
250                     }
251                     id_i++;
252                 }
253
254                 /* If we found, id is going to be a valid rule */
255                 if (Mail->gran_id[i][id_i]) {
256                     gr_set = 1;
257                 } else {
258                     i++;
259                     continue;
260                 }
261             }
262
263             /* Look for the group */
264             if (Mail->gran_group[i]) {
265                 if (OSMatch_Execute(al_data->group,
266                                     strlen(al_data->group),
267                                     Mail->gran_group[i])) {
268                     gr_set = 1;
269                 } else {
270                     i++;
271                     continue;
272                 }
273             }
274
275             /* If we got here, everything matched. Set this e-mail to be used. */
276             if (gr_set) {
277                 if (Mail->gran_format[i] == SMS_FORMAT) {
278                     Mail->gran_set[i] = SMS_FORMAT;
279
280                     /* Set the SMS flag */
281                     sms_set = 1;
282                 } else {
283                     /* Options */
284                     if (Mail->gran_format[i] == FORWARD_NOW) {
285                         Mail->priority = 1;
286                         Mail->gran_set[i] = FULL_FORMAT;
287                     } else if (Mail->gran_format[i] == DONOTGROUP) {
288                         Mail->priority = DONOTGROUP;
289                         Mail->gran_set[i] = DONOTGROUP;
290                         donotgroup = 1;
291                     } else {
292                         Mail->gran_set[i] = FULL_FORMAT;
293                     }
294                 }
295             }
296             i++;
297         }
298     }
299
300
301     /* If DONOTGROUP is set, we can't assign the new subject */
302     if (!donotgroup) {
303         /* Get highest level for alert */
304         if (_g_subject[0] != '\0') {
305             if (_g_subject_level < al_data->level) {
306                 strncpy(_g_subject, mail->subject, SUBJECT_SIZE);
307                 _g_subject_level = al_data->level;
308             }
309         } else {
310             strncpy(_g_subject, mail->subject, SUBJECT_SIZE);
311             _g_subject_level = al_data->level;
312         }
313     }
314
315     /* If SMS is set, create the SMS output */
316     if (sms_set) {
317         MailMsg *msg_sms_tmp;
318
319         /* Allocate memory for SMS */
320         os_calloc(1, sizeof(MailMsg), msg_sms_tmp);
321         os_calloc(BODY_SIZE, sizeof(char), msg_sms_tmp->body);
322         os_calloc(SUBJECT_SIZE, sizeof(char), msg_sms_tmp->subject);
323
324         snprintf(msg_sms_tmp->subject, SUBJECT_SIZE - 1, SMS_SUBJECT,
325                  al_data->level,
326                  al_data->rule,
327                  al_data->comment);
328
329
330         strncpy(msg_sms_tmp->body, logs, 128);
331         msg_sms_tmp->body[127] = '\0';
332         *msg_sms = msg_sms_tmp;
333     }
334
335     /* Clear the memory */
336     FreeAlertData(al_data);
337
338     return (mail);
339 }
340