1 /* @(#) $Id: ./src/os_maild/sendmail.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
14 /* Basic e-mailing operations */
18 #include "os_net/os_net.h"
20 #include "mail_list.h"
23 /* Return codes (from SMTP server) */
24 #define VALIDBANNER "220"
25 #define VALIDMAIL "250"
26 #define VALIDDATA "354"
29 /* Default values use to connect */
30 #define SMTP_DEFAULT_PORT 25
31 #define HELOMSG "Helo notify.ossec.net\r\n"
32 #define MAILFROM "Mail From: <%s>\r\n"
33 #define RCPTTO "Rcpt To: <%s>\r\n"
34 #define DATAMSG "DATA\r\n"
35 #define FROM "From: OSSEC HIDS <%s>\r\n"
36 #define TO "To: <%s>\r\n"
37 #define CC "Cc: <%s>\r\n"
38 #define SUBJECT "Subject: %s\r\n"
39 #define ENDHEADER "\r\n"
40 #define ENDDATA "\r\n.\r\n"
41 #define QUITMSG "QUIT\r\n"
42 #define XHEADER "X-IDS-OSSEC: %s\r\n"
45 /* Error messages - Can be translated */
46 #define INTERNAL_ERROR "os_maild (1760): ERROR: Memory/configuration error"
47 #define BANNER_ERROR "os_sendmail(1762): WARN: Banner not received from server"
48 #define HELO_ERROR "os_sendmail(1763): WARN: Hello not accepted by server"
49 #define FROM_ERROR "os_sendmail(1764): WARN: Mail from not accepted by server"
50 #define TO_ERROR "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'."
51 #define DATA_ERROR "os_sendmail(1766): WARN: DATA not accepted by server"
52 #define END_DATA_ERROR "os_sendmail(1767): WARN: End of DATA not accepted by server"
55 #define MAIL_DEBUG_FLAG 0
56 #define MAIL_DEBUG(x,y,z) if(MAIL_DEBUG_FLAG) merror(x,y,z)
61 int OS_Sendsms(MailConfig *mail, struct tm *p, MailMsg *sms_msg)
63 int socket, i = 0, final_to_sz;
69 /* Connecting to the smtp server */
70 socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver, 0);
77 /* Receiving the banner */
78 msg = OS_RecvTCP(socket, OS_SIZE_1024);
79 if((msg == NULL)||(!OS_Match(VALIDBANNER, msg)))
87 MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
92 /* Sending HELO message */
93 OS_SendTCP(socket,HELOMSG);
94 msg = OS_RecvTCP(socket, OS_SIZE_1024);
95 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
99 /* Ugly fix warning :) */
100 /* In some cases (with virus scans in the middle)
101 * we may get two banners. Check for that in here.
103 if(OS_Match(VALIDBANNER, msg))
108 msg = OS_RecvTCP(socket, OS_SIZE_1024);
109 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
111 merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null");
120 merror("%s:%s",HELO_ERROR,msg);
128 merror("%s:%s",HELO_ERROR,"null");
134 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
138 /* Building "Mail from" msg */
139 memset(snd_msg,'\0',128);
140 snprintf(snd_msg,127, MAILFROM, mail->from);
141 OS_SendTCP(socket, snd_msg);
142 msg = OS_RecvTCP(socket, OS_SIZE_1024);
143 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
151 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
155 /* Additional RCPT to */
157 final_to_sz = sizeof(final_to) -2;
162 while(mail->gran_to[i] != NULL)
164 if(mail->gran_set[i] != SMS_FORMAT)
170 memset(snd_msg,'\0',128);
171 snprintf(snd_msg,127, RCPTTO, mail->gran_to[i]);
172 OS_SendTCP(socket, snd_msg);
173 msg = OS_RecvTCP(socket, OS_SIZE_1024);
174 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
176 merror(TO_ERROR, mail->gran_to[i]);
182 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
186 /* Creating header for to */
187 memset(snd_msg,'\0',128);
188 snprintf(snd_msg,127, TO, mail->gran_to[i]);
189 strncat(final_to, snd_msg, final_to_sz);
190 final_to_sz -= strlen(snd_msg) +2;
198 /* Sending the "DATA" msg */
199 OS_SendTCP(socket,DATAMSG);
200 msg = OS_RecvTCP(socket, OS_SIZE_1024);
201 if((msg == NULL)||(!OS_Match(VALIDDATA, msg)))
209 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
213 /* Building "From" and "To" in the e-mail header */
214 OS_SendTCP(socket, final_to);
217 memset(snd_msg,'\0',128);
218 snprintf(snd_msg,127, FROM, mail->from);
219 OS_SendTCP(socket, snd_msg);
223 memset(snd_msg,'\0',128);
226 /* Solaris doesn't have the "%z", so we set the timezone to 0. */
228 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p);
230 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p);
233 OS_SendTCP(socket,snd_msg);
236 /* Sending subject */
237 memset(snd_msg,'\0',128);
238 snprintf(snd_msg, 127, SUBJECT, sms_msg->subject);
239 OS_SendTCP(socket,snd_msg);
241 OS_SendTCP(socket,ENDHEADER);
245 OS_SendTCP(socket, sms_msg->body);
248 /* Sending end of data \r\n.\r\n */
249 OS_SendTCP(socket,ENDDATA);
250 msg = OS_RecvTCP(socket, OS_SIZE_1024);
251 if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg))))
253 merror(END_DATA_ERROR);
259 /* Checking msg in here, since it may be null */
264 /* quitting and closing socket */
265 OS_SendTCP(socket,QUITMSG);
266 msg = OS_RecvTCP(socket, OS_SIZE_1024);
271 memset(snd_msg,'\0',128);
274 /* Returning 0 (success) */
282 /* OS_Sendmail v0.1: 2005/03/18
284 int OS_Sendmail(MailConfig *mail, struct tm *p)
292 /* If there is no sms message, we attempt to get from the
295 mailmsg = OS_PopLastMail();
299 merror("%s: No email to be sent. Inconsistent state.",ARGV0);
303 /* Connecting to the smtp server */
304 socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver, 0);
311 /* Receiving the banner */
312 msg = OS_RecvTCP(socket, OS_SIZE_1024);
313 if((msg == NULL)||(!OS_Match(VALIDBANNER, msg)))
315 merror(BANNER_ERROR);
321 MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
326 /* Sending HELO message */
327 OS_SendTCP(socket,HELOMSG);
328 msg = OS_RecvTCP(socket, OS_SIZE_1024);
329 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
333 /* Ugly fix warning :) */
334 /* In some cases (with virus scans in the middle)
335 * we may get two banners. Check for that in here.
337 if(OS_Match(VALIDBANNER, msg))
342 msg = OS_RecvTCP(socket, OS_SIZE_1024);
343 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
345 merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null");
354 merror("%s:%s",HELO_ERROR,msg);
362 merror("%s:%s",HELO_ERROR,"null");
368 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
372 /* Building "Mail from" msg */
373 memset(snd_msg,'\0',128);
374 snprintf(snd_msg,127, MAILFROM, mail->from);
375 OS_SendTCP(socket, snd_msg);
376 msg = OS_RecvTCP(socket, OS_SIZE_1024);
377 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
385 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
389 /* Building "RCPT TO" msg */
392 if(mail->to[i] == NULL)
396 merror(INTERNAL_ERROR);
402 memset(snd_msg,'\0',128);
403 snprintf(snd_msg,127,RCPTTO, mail->to[i++]);
404 OS_SendTCP(socket,snd_msg);
405 msg = OS_RecvTCP(socket, OS_SIZE_1024);
406 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
408 merror(TO_ERROR, mail->to[i -1]);
414 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
419 /* Additional RCPT to */
423 while(mail->gran_to[i] != NULL)
425 if(mail->gran_set[i] != FULL_FORMAT)
431 memset(snd_msg,'\0',128);
432 snprintf(snd_msg,127,RCPTTO, mail->gran_to[i]);
433 OS_SendTCP(socket,snd_msg);
434 msg = OS_RecvTCP(socket, OS_SIZE_1024);
435 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
437 merror(TO_ERROR, mail->gran_to[i]);
445 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
453 /* Sending the "DATA" msg */
454 OS_SendTCP(socket,DATAMSG);
455 msg = OS_RecvTCP(socket, OS_SIZE_1024);
456 if((msg == NULL)||(!OS_Match(VALIDDATA, msg)))
464 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
468 /* Building "From" and "To" in the e-mail header */
469 memset(snd_msg,'\0',128);
470 snprintf(snd_msg,127, TO, mail->to[0]);
471 OS_SendTCP(socket, snd_msg);
473 memset(snd_msg,'\0',128);
474 snprintf(snd_msg,127, FROM, mail->from);
475 OS_SendTCP(socket, snd_msg);
484 if(mail->to[i] == NULL)
489 memset(snd_msg,'\0',128);
490 snprintf(snd_msg,127, TO, mail->to[i]);
491 OS_SendTCP(socket,snd_msg);
498 /* More CCs - from granular options */
502 while(mail->gran_to[i] != NULL)
504 if(mail->gran_set[i] != FULL_FORMAT)
510 memset(snd_msg,'\0',128);
511 snprintf(snd_msg,127, TO, mail->gran_to[i]);
512 OS_SendTCP(socket, snd_msg);
520 memset(snd_msg,'\0',128);
523 /* Solaris doesn't have the "%z", so we set the timezone to 0. */
525 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p);
527 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p);
530 OS_SendTCP(socket,snd_msg);
534 /* Sending server name header */
535 memset(snd_msg,'\0',128);
536 snprintf(snd_msg,127, XHEADER, mail->idsname);
537 OS_SendTCP(socket, snd_msg);
540 /* Sending subject */
541 memset(snd_msg,'\0',128);
544 /* Checking if global subject is available */
545 if((_g_subject_level != 0) && (_g_subject[0] != '\0'))
547 snprintf(snd_msg, 127, SUBJECT, _g_subject);
549 /* Clearing global values */
550 _g_subject[0] = '\0';
551 _g_subject_level = 0;
555 snprintf(snd_msg, 127, SUBJECT, mailmsg->mail->subject);
557 OS_SendTCP(socket,snd_msg);
559 OS_SendTCP(socket,ENDHEADER);
564 /* Sending multiple emails together if we have to */
567 OS_SendTCP(socket, mailmsg->mail->body);
568 mailmsg = OS_PopLastMail();
572 /* Sending end of data \r\n.\r\n */
573 OS_SendTCP(socket,ENDDATA);
574 msg = OS_RecvTCP(socket, OS_SIZE_1024);
575 if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg))))
577 merror(END_DATA_ERROR);
583 /* Checking msg in here, since it may be null */
588 /* quitting and closing socket */
589 OS_SendTCP(socket,QUITMSG);
590 msg = OS_RecvTCP(socket, OS_SIZE_1024);
595 memset(snd_msg,'\0',128);
598 /* Returning 0 (success) */