new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / monitord / sendcustomemail.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 /* Basic e-mailing operations */
11
12 #include "shared.h"
13 #include "os_net/os_net.h"
14
15 /* Return codes (from SMTP server) */
16 #define VALIDBANNER     "220"
17 #define VALIDMAIL       "250"
18 #define VALIDDATA       "354"
19
20 /* Default values used to connect */
21 #define SMTP_DEFAULT_PORT   "25"
22 #define HELOMSG             "Helo notify.ossec.net\r\n"
23 #define MAILFROM            "Mail From: <%s>\r\n"
24 #define RCPTTO              "Rcpt To: <%s>\r\n"
25 #define DATAMSG             "DATA\r\n"
26 #define FROM                "From: OSSEC HIDS <%s>\r\n"
27 #define REPLYTO             "Reply-To: OSSEC HIDS <%s>\r\n"
28 #define TO                  "To: <%s>\r\n"
29 #define CC                  "Cc: <%s>\r\n"
30 #define SUBJECT             "Subject: %s\r\n"
31 #define ENDHEADER           "\r\n"
32 #define ENDDATA             "\r\n.\r\n"
33 #define QUITMSG             "QUIT\r\n"
34 #define XHEADER             "X-IDS-OSSEC: %s\r\n"
35
36 /* Error messages - Can be translated */
37 #define INTERNAL_ERROR  "os_maild (1760): ERROR: Memory/configuration error"
38 #define BANNER_ERROR    "os_sendmail(1762): WARN: Banner not received from server"
39 #define HELO_ERROR      "os_sendmail(1763): WARN: Hello not accepted by server"
40 #define FROM_ERROR      "os_sendmail(1764): WARN: Mail from not accepted by server"
41 #define TO_ERROR        "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'."
42 #define DATA_ERROR      "os_sendmail(1766): WARN: DATA not accepted by server"
43 #define END_DATA_ERROR  "os_sendmail(1767): WARN: End of DATA not accepted by server"
44
45 #define MAIL_DEBUG_FLAG     0
46 #define MAIL_DEBUG(x,y,z) if(MAIL_DEBUG_FLAG) merror(x,y,z)
47
48
49 int OS_SendCustomEmail2(char **to, char *subject, char *smtpserver, char *from, char *replyto, char *idsname, __attribute__((unused)) char *fname)
50 {
51     FILE *sendmail = NULL;
52     int socket = -1, i = 0;
53     char *msg;
54     char snd_msg[128];
55     char buffer[2049];
56
57     buffer[2048] = '\0';
58
59     if (smtpserver[0] == '/') {
60         sendmail = popen(smtpserver, "w");
61         if (!sendmail) {
62             return (OS_INVALID);
63         }
64     } else {
65         /* Connect to the SMTP server */
66         socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, smtpserver);
67         if (socket < 0) {
68             return (socket);
69         }
70
71         /* Receive the banner */
72         msg = OS_RecvTCP(socket, OS_SIZE_1024);
73         if ((msg == NULL) || (!OS_Match(VALIDBANNER, msg))) {
74             merror(BANNER_ERROR);
75             if (msg) {
76                 free(msg);
77             }
78             close(socket);
79             return (OS_INVALID);
80         }
81         MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
82         free(msg);
83
84         /* Send HELO message */
85         OS_SendTCP(socket, HELOMSG);
86         msg = OS_RecvTCP(socket, OS_SIZE_1024);
87         if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
88             if (msg) {
89                 /* In some cases (with virus scans in the middle)
90                  * we may get two banners. Check for that in here.
91                  */
92                 if (OS_Match(VALIDBANNER, msg)) {
93                     free(msg);
94
95                     /* Try again */
96                     msg = OS_RecvTCP(socket, OS_SIZE_1024);
97                     if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
98                         merror("%s:%s", HELO_ERROR, msg != NULL ? msg : "null");
99                         if (msg) {
100                             free(msg);
101                         }
102                         close(socket);
103                         return (OS_INVALID);
104                     }
105                 } else {
106                     merror("%s:%s", HELO_ERROR, msg);
107                     free(msg);
108                     close(socket);
109                     return (OS_INVALID);
110                 }
111             } else {
112                 merror("%s:%s", HELO_ERROR, "null");
113                 close(socket);
114                 return (OS_INVALID);
115             }
116         }
117
118         MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
119         free(msg);
120
121         /* Build "Mail from" msg */
122         memset(snd_msg, '\0', 128);
123         snprintf(snd_msg, 127, MAILFROM, from);
124         OS_SendTCP(socket, snd_msg);
125         msg = OS_RecvTCP(socket, OS_SIZE_1024);
126         if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
127             merror(FROM_ERROR);
128             if (msg) {
129                 free(msg);
130             }
131             close(socket);
132             return (OS_INVALID);
133         }
134         MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
135         free(msg);
136
137         /* Build "RCPT TO" msg */
138         while (to[i]) {
139             memset(snd_msg, '\0', 128);
140             snprintf(snd_msg, 127, RCPTTO, to[i]);
141             OS_SendTCP(socket, snd_msg);
142             msg = OS_RecvTCP(socket, OS_SIZE_1024);
143             if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
144                 merror(TO_ERROR, to[i]);
145                 if (msg) {
146                     free(msg);
147                 }
148                 close(socket);
149                 return (OS_INVALID);
150             }
151             MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
152             free(msg);
153
154             i++;
155         }
156
157         /* Send the "DATA" msg */
158         OS_SendTCP(socket, DATAMSG);
159         msg = OS_RecvTCP(socket, OS_SIZE_1024);
160         if ((msg == NULL) || (!OS_Match(VALIDDATA, msg))) {
161             merror(DATA_ERROR);
162             if (msg) {
163                 free(msg);
164             }
165             close(socket);
166             return (OS_INVALID);
167         }
168         MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
169         free(msg);
170     }
171
172     /* Build "From" and "To" in the e-mail header */
173     memset(snd_msg, '\0', 128);
174     snprintf(snd_msg, 127, TO, to[0]);
175
176     if (sendmail) {
177         fprintf(sendmail, "%s", snd_msg);
178     } else {
179         OS_SendTCP(socket, snd_msg);
180     }
181
182     memset(snd_msg, '\0', 128);
183     snprintf(snd_msg, 127, FROM, from);
184
185     if (sendmail) {
186         fprintf(sendmail, "%s", snd_msg);
187     } else {
188         OS_SendTCP(socket, snd_msg);
189     }
190
191     if (replyto) {
192         memset(snd_msg, '\0', 128);
193         snprintf(snd_msg, 127, REPLYTO, replyto);
194         if(sendmail) {
195             fprintf(sendmail, "%s", snd_msg);
196         } else {
197             OS_SendTCP(socket, snd_msg);
198         }
199
200     }
201
202     /* Add CCs */
203     if (to[1]) {
204         i = 1;
205         while (1) {
206             if (to[i] == NULL) {
207                 break;
208             }
209
210             memset(snd_msg, '\0', 128);
211             snprintf(snd_msg, 127, TO, to[i]);
212
213             if (sendmail) {
214                 fprintf(sendmail, "%s", snd_msg);
215             } else {
216                 OS_SendTCP(socket, snd_msg);
217             }
218
219             i++;
220         }
221     }
222
223     /* Send date */
224     memset(snd_msg, '\0', 128);
225     time_t tm;
226     tm = time(NULL);
227     const struct tm *p;
228     p = localtime(&tm);
229
230     /* Solaris doesn't have the "%z", so we set the timezone to 0 */
231 #ifdef SOLARIS
232     strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n", p);
233 #else
234     strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n", p);
235 #endif
236
237     if (sendmail) {
238         fprintf(sendmail, "%s", snd_msg);
239     } else {
240         OS_SendTCP(socket, snd_msg);
241     }
242
243     if (idsname) {
244         /* Send server name header */
245         memset(snd_msg, '\0', 128);
246         snprintf(snd_msg, 127, XHEADER, idsname);
247
248         if (sendmail) {
249             fprintf(sendmail, "%s", snd_msg);
250         } else {
251             OS_SendTCP(socket, snd_msg);
252         }
253     }
254
255     /* Send subject */
256     memset(snd_msg, '\0', 128);
257     snprintf(snd_msg, 127, SUBJECT, subject);
258
259     if (sendmail) {
260         fprintf(sendmail, "%s", snd_msg);
261         fprintf(sendmail, ENDHEADER);
262     } else {
263         OS_SendTCP(socket, snd_msg);
264         OS_SendTCP(socket, ENDHEADER);
265     }
266
267
268     char fname2[256];
269     fname2[255] = '\0';
270     snprintf(fname2, 255, "/logs/.report-%d.log", getpid());
271
272     /* Send body */
273     FILE *fp;
274     fp = fopen(fname2, "r");
275     if(!fp) {
276         merror("%s: ERROR: Cannot open %s: %s", __local_name, fname2, strerror(errno));
277         if(socket >= 0) {
278             close(socket);
279         }
280         if(sendmail) {
281             pclose(sendmail);
282         }
283         return(1);
284     }
285
286
287     while (fgets(buffer, 2048, fp) != NULL) {
288         if (sendmail) {
289             fprintf(sendmail, "%s", buffer);
290         } else {
291             OS_SendTCP(socket, buffer);
292         }
293     }
294     fclose(fp);
295
296     if (sendmail) {
297         if (pclose(sendmail) == -1) {
298             merror(WAITPID_ERROR, ARGV0, errno, strerror(errno));
299         }
300     } else {
301         /* Send end of data \r\n.\r\n */
302         OS_SendTCP(socket, ENDDATA);
303         msg = OS_RecvTCP(socket, OS_SIZE_1024);
304
305         /* Check msg, since it may be null */
306         if (msg) {
307             free(msg);
308         }
309
310         /* Quit and close socket */
311         OS_SendTCP(socket, QUITMSG);
312         msg = OS_RecvTCP(socket, OS_SIZE_1024);
313
314         if (msg) {
315             free(msg);
316         }
317
318         close(socket);
319     }
320
321     memset_secure(snd_msg, '\0', 128);
322     return (0);
323 }
324