1 /* Copyright (C) 2009 Trend Micro Inc.
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
10 /* Basic e-mailing operations */
13 #include "os_net/os_net.h"
15 #include "mail_list.h"
17 /* Return codes (from SMTP server) */
18 #define VALIDBANNER "220"
19 #define VALIDMAIL "250"
20 #define VALIDDATA "354"
22 /* Default values used to connect */
23 #define SMTP_DEFAULT_PORT "25"
24 #define MAILFROM "Mail From: <%s>\r\n"
25 #define RCPTTO "Rcpt To: <%s>\r\n"
26 #define DATAMSG "DATA\r\n"
27 #define FROM "From: OSSEC HIDS <%s>\r\n"
28 #define TO "To: <%s>\r\n"
29 #define REPLYTO "Reply-To: OSSEC HIDS <%s>\r\n"
30 /*#define CC "Cc: <%s>\r\n"*/
31 #define SUBJECT "Subject: %s\r\n"
32 #define ENDHEADER "\r\n"
33 #define ENDDATA "\r\n.\r\n"
34 #define QUITMSG "QUIT\r\n"
35 #define XHEADER "X-IDS-OSSEC: %s\r\n"
37 /* Error messages - Can be translated */
38 #define INTERNAL_ERROR "os_maild (1760): ERROR: Memory/configuration error"
39 #define BANNER_ERROR "os_sendmail(1762): WARN: Banner not received from server"
40 #define HELO_ERROR "os_sendmail(1763): WARN: Hello not accepted by server"
41 #define FROM_ERROR "os_sendmail(1764): WARN: Mail from not accepted by server"
42 #define TO_ERROR "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'."
43 #define DATA_ERROR "os_sendmail(1766): WARN: DATA not accepted by server"
44 #define END_DATA_ERROR "os_sendmail(1767): WARN: End of DATA not accepted by server"
46 #define MAIL_DEBUG_FLAG 0
47 #define MAIL_DEBUG(x,y,z) if(MAIL_DEBUG_FLAG) merror(x,y,z)
50 int OS_Sendmail(MailConfig *mail, struct tm *p)
52 FILE *sendmail = NULL;
60 /* If there is no sms message, attempt to get from the email list */
61 mailmsg = OS_PopLastMail();
63 if (mailmsg == NULL) {
64 merror("%s: No email to be sent. Inconsistent state.", ARGV0);
68 if (mail->smtpserver[0] == '/') {
69 sendmail = popen(mail->smtpserver, "w");
74 /* Connect to the SMTP server */
75 socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver);
80 /* Receive the banner */
81 msg = OS_RecvTCP(socket, OS_SIZE_1024);
82 if ((msg == NULL) || (!OS_Match(VALIDBANNER, msg))) {
90 MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
93 /* Send HELO message */
94 memset(snd_msg, '\0', 128);
95 if (mail->heloserver) {
96 snprintf(snd_msg, 127, "Helo %s\r\n", mail->heloserver);
98 snprintf(snd_msg, 127, "Helo %s\r\n", "notify.ossec.net");
100 OS_SendTCP(socket, snd_msg);
101 msg = OS_RecvTCP(socket, OS_SIZE_1024);
102 if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
104 /* In some cases (with virus scans in the middle)
105 * we may get two banners. Check for that in here.
107 if (OS_Match(VALIDBANNER, msg)) {
111 msg = OS_RecvTCP(socket, OS_SIZE_1024);
112 if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
113 merror("%s:%s", HELO_ERROR, msg != NULL ? msg : "null");
121 merror("%s:%s", HELO_ERROR, msg);
127 merror("%s:%s", HELO_ERROR, "null");
133 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
136 /* Build "Mail from" msg */
137 memset(snd_msg, '\0', 128);
138 snprintf(snd_msg, 127, MAILFROM, mail->from);
139 OS_SendTCP(socket, snd_msg);
140 msg = OS_RecvTCP(socket, OS_SIZE_1024);
141 if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
149 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
152 /* Build "RCPT TO" msg */
154 if (mail->to[i] == NULL) {
156 merror(INTERNAL_ERROR);
162 memset(snd_msg, '\0', 128);
163 snprintf(snd_msg, 127, RCPTTO, mail->to[i++]);
164 OS_SendTCP(socket, snd_msg);
165 msg = OS_RecvTCP(socket, OS_SIZE_1024);
166 if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
167 merror(TO_ERROR, mail->to[i - 1]);
174 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
178 /* Additional RCPT to */
181 while (mail->gran_to[i] != NULL) {
182 if (mail->gran_set[i] != FULL_FORMAT) {
187 memset(snd_msg, '\0', 128);
188 snprintf(snd_msg, 127, RCPTTO, mail->gran_to[i]);
189 OS_SendTCP(socket, snd_msg);
190 msg = OS_RecvTCP(socket, OS_SIZE_1024);
191 if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
192 merror(TO_ERROR, mail->gran_to[i]);
201 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
208 /* Send the "DATA" msg */
209 OS_SendTCP(socket, DATAMSG);
210 msg = OS_RecvTCP(socket, OS_SIZE_1024);
211 if ((msg == NULL) || (!OS_Match(VALIDDATA, msg))) {
219 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
223 /* Building "From" and "To" in the e-mail header */
224 memset(snd_msg, '\0', 128);
225 snprintf(snd_msg, 127, TO, mail->to[0]);
228 fprintf(sendmail, "%s", snd_msg);
230 OS_SendTCP(socket, snd_msg);
233 memset(snd_msg, '\0', 128);
234 snprintf(snd_msg, 127, FROM, mail->from);
237 fprintf(sendmail, "%s", snd_msg);
239 OS_SendTCP(socket, snd_msg);
242 /* Send reply-to if set */
244 memset(snd_msg, '\0', 128);
245 snprintf(snd_msg, 127, REPLYTO, mail->reply_to);
247 fprintf(sendmail, "%s", snd_msg);
249 OS_SendTCP(socket, snd_msg);
257 if (mail->to[i] == NULL) {
261 memset(snd_msg, '\0', 128);
262 snprintf(snd_msg, 127, TO, mail->to[i]);
265 fprintf(sendmail, "%s", snd_msg);
267 OS_SendTCP(socket, snd_msg);
274 /* More CCs - from granular options */
277 while (mail->gran_to[i] != NULL) {
278 if (mail->gran_set[i] != FULL_FORMAT) {
283 memset(snd_msg, '\0', 128);
284 snprintf(snd_msg, 127, TO, mail->gran_to[i]);
287 fprintf(sendmail, "%s", snd_msg);
289 OS_SendTCP(socket, snd_msg);
298 memset(snd_msg, '\0', 128);
300 /* Solaris doesn't have the "%z", so we set the timezone to 0 */
302 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n", p);
304 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n", p);
308 fprintf(sendmail, "%s", snd_msg);
310 OS_SendTCP(socket, snd_msg);
314 /* Send server name header */
315 memset(snd_msg, '\0', 128);
316 snprintf(snd_msg, 127, XHEADER, mail->idsname);
319 fprintf(sendmail, "%s", snd_msg);
321 OS_SendTCP(socket, snd_msg);
326 memset(snd_msg, '\0', 128);
328 /* Check if global subject is available */
329 if ((_g_subject_level != 0) && (_g_subject[0] != '\0')) {
330 snprintf(snd_msg, 127, SUBJECT, _g_subject);
332 /* Clear global values */
333 _g_subject[0] = '\0';
334 _g_subject_level = 0;
336 snprintf(snd_msg, 127, SUBJECT, mailmsg->mail->subject);
340 fprintf(sendmail, "%s", snd_msg);
341 fprintf(sendmail, ENDHEADER);
343 OS_SendTCP(socket, snd_msg);
344 OS_SendTCP(socket, ENDHEADER);
349 /* Send multiple emails together if we have to */
352 fprintf(sendmail, "%s", mailmsg->mail->body);
354 OS_SendTCP(socket, mailmsg->mail->body);
356 mailmsg = OS_PopLastMail();
360 if (pclose(sendmail) == -1) {
361 merror(WAITPID_ERROR, ARGV0, errno, strerror(errno));
364 /* Send end of data \r\n.\r\n */
365 OS_SendTCP(socket, ENDDATA);
366 msg = OS_RecvTCP(socket, OS_SIZE_1024);
367 if (mail->strict_checking && ((msg == NULL) || (!OS_Match(VALIDMAIL, msg)))) {
368 merror(END_DATA_ERROR);
376 /* Check msg, since it may be null */
381 /* Quit and close socket */
382 OS_SendTCP(socket, QUITMSG);
383 msg = OS_RecvTCP(socket, OS_SIZE_1024);
392 memset_secure(snd_msg, '\0', 128);