1 /* @(#) $Id: sendmail.c,v 1.30 2009/06/24 17:06:31 dcid Exp $ */
3 /* Copyright (C) 2009 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 3) as published by the FSF - Free Software
13 /* Basic e-mailing operations */
17 #include "os_net/os_net.h"
19 #include "mail_list.h"
22 /* Return codes (from SMTP server) */
23 #define VALIDBANNER "220"
24 #define VALIDMAIL "250"
25 #define VALIDDATA "354"
28 /* Default values use to connect */
29 #define SMTP_DEFAULT_PORT 25
30 #define HELOMSG "Helo notify.ossec.net\r\n"
31 #define MAILFROM "Mail From: <%s>\r\n"
32 #define RCPTTO "Rcpt To: <%s>\r\n"
33 #define DATAMSG "DATA\r\n"
34 #define FROM "From: OSSEC HIDS <%s>\r\n"
35 #define TO "To: <%s>\r\n"
36 #define CC "Cc: <%s>\r\n"
37 #define SUBJECT "Subject: %s\r\n"
38 #define ENDDATA "\r\n.\r\n"
39 #define QUITMSG "QUIT\r\n"
42 /* Error messages - Can be translated */
43 #define INTERNAL_ERROR "os_maild (1760): ERROR: Memory/configuration error"
44 #define BANNER_ERROR "os_sendmail(1762): WARN: Banner not received from server"
45 #define HELO_ERROR "os_sendmail(1763): WARN: Hello not accepted by server"
46 #define FROM_ERROR "os_sendmail(1764): WARN: Mail from not accepted by server"
47 #define TO_ERROR "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'."
48 #define DATA_ERROR "os_sendmail(1766): WARN: DATA not accepted by server"
49 #define END_DATA_ERROR "os_sendmail(1767): WARN: End of DATA not accepted by server"
52 #define MAIL_DEBUG_FLAG 0
53 #define MAIL_DEBUG(x,y,z) if(MAIL_DEBUG_FLAG) merror(x,y,z)
58 int OS_Sendsms(MailConfig *mail, struct tm *p, MailMsg *sms_msg)
60 int socket, i = 0, final_to_sz;
66 /* Connecting to the smtp server */
67 socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver);
74 /* Receiving the banner */
75 msg = OS_RecvTCP(socket, OS_SIZE_1024);
76 if((msg == NULL)||(!OS_Match(VALIDBANNER, msg)))
84 MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
89 /* Sending HELO message */
90 OS_SendTCP(socket,HELOMSG);
91 msg = OS_RecvTCP(socket, OS_SIZE_1024);
92 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
96 /* Ugly fix warning :) */
97 /* In some cases (with virus scans in the middle)
98 * we may get two banners. Check for that in here.
100 if(OS_Match(VALIDBANNER, msg))
105 msg = OS_RecvTCP(socket, OS_SIZE_1024);
106 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
108 merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null");
117 merror("%s:%s",HELO_ERROR,msg);
125 merror("%s:%s",HELO_ERROR,"null");
131 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
135 /* Building "Mail from" msg */
136 memset(snd_msg,'\0',128);
137 snprintf(snd_msg,127, MAILFROM, mail->from);
138 OS_SendTCP(socket, snd_msg);
139 msg = OS_RecvTCP(socket, OS_SIZE_1024);
140 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
148 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
152 /* Additional RCPT to */
154 final_to_sz = sizeof(final_to) -2;
159 while(mail->gran_to[i] != NULL)
161 if(mail->gran_set[i] != SMS_FORMAT)
167 memset(snd_msg,'\0',128);
168 snprintf(snd_msg,127, RCPTTO, mail->gran_to[i]);
169 OS_SendTCP(socket, snd_msg);
170 msg = OS_RecvTCP(socket, OS_SIZE_1024);
171 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
173 merror(TO_ERROR, mail->gran_to[i]);
179 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
183 /* Creating header for to */
184 memset(snd_msg,'\0',128);
185 snprintf(snd_msg,127, TO, mail->gran_to[i]);
186 strncat(final_to, snd_msg, final_to_sz);
187 final_to_sz -= strlen(snd_msg) +2;
195 /* Sending the "DATA" msg */
196 OS_SendTCP(socket,DATAMSG);
197 msg = OS_RecvTCP(socket, OS_SIZE_1024);
198 if((msg == NULL)||(!OS_Match(VALIDDATA, msg)))
206 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
210 /* Building "From" and "To" in the e-mail header */
211 OS_SendTCP(socket, final_to);
214 memset(snd_msg,'\0',128);
215 snprintf(snd_msg,127, FROM, mail->from);
216 OS_SendTCP(socket, snd_msg);
220 memset(snd_msg,'\0',128);
223 /* Solaris doesn't have the "%z", so we set the timezone to 0. */
225 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p);
227 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p);
230 OS_SendTCP(socket,snd_msg);
233 /* Sending subject */
234 memset(snd_msg,'\0',128);
235 snprintf(snd_msg, 127, SUBJECT, sms_msg->subject);
236 OS_SendTCP(socket,snd_msg);
241 OS_SendTCP(socket, sms_msg->body);
244 /* Sending end of data \r\n.\r\n */
245 OS_SendTCP(socket,ENDDATA);
246 msg = OS_RecvTCP(socket, OS_SIZE_1024);
247 if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg))))
249 merror(END_DATA_ERROR);
255 /* Checking msg in here, since it may be null */
260 /* quitting and closing socket */
261 OS_SendTCP(socket,QUITMSG);
262 msg = OS_RecvTCP(socket, OS_SIZE_1024);
267 memset(snd_msg,'\0',128);
270 /* Returning 0 (success) */
278 /* OS_Sendmail v0.1: 2005/03/18
280 int OS_Sendmail(MailConfig *mail, struct tm *p)
285 char additional_to[512];
289 additional_to[0] = '\0';
291 /* If there is no sms message, we attempt to get from the
294 mailmsg = OS_PopLastMail();
298 merror("%s: No email to be sent. Inconsistent state.",ARGV0);
302 /* Connecting to the smtp server */
303 socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver);
310 /* Receiving the banner */
311 msg = OS_RecvTCP(socket, OS_SIZE_1024);
312 if((msg == NULL)||(!OS_Match(VALIDBANNER, msg)))
314 merror(BANNER_ERROR);
320 MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
325 /* Sending HELO message */
326 OS_SendTCP(socket,HELOMSG);
327 msg = OS_RecvTCP(socket, OS_SIZE_1024);
328 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
332 /* Ugly fix warning :) */
333 /* In some cases (with virus scans in the middle)
334 * we may get two banners. Check for that in here.
336 if(OS_Match(VALIDBANNER, msg))
341 msg = OS_RecvTCP(socket, OS_SIZE_1024);
342 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
344 merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null");
353 merror("%s:%s",HELO_ERROR,msg);
361 merror("%s:%s",HELO_ERROR,"null");
367 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
371 /* Building "Mail from" msg */
372 memset(snd_msg,'\0',128);
373 snprintf(snd_msg,127, MAILFROM, mail->from);
374 OS_SendTCP(socket, snd_msg);
375 msg = OS_RecvTCP(socket, OS_SIZE_1024);
376 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
384 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
388 /* Building "RCPT TO" msg */
391 if(mail->to[i] == NULL)
395 merror(INTERNAL_ERROR);
401 memset(snd_msg,'\0',128);
402 snprintf(snd_msg,127,RCPTTO, mail->to[i++]);
403 OS_SendTCP(socket,snd_msg);
404 msg = OS_RecvTCP(socket, OS_SIZE_1024);
405 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
407 merror(TO_ERROR, mail->to[i -1]);
413 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
418 /* Additional RCPT to */
422 while(mail->gran_to[i] != NULL)
424 if(mail->gran_set[i] != FULL_FORMAT)
430 memset(snd_msg,'\0',128);
431 snprintf(snd_msg,127,RCPTTO, mail->gran_to[i]);
432 OS_SendTCP(socket,snd_msg);
433 msg = OS_RecvTCP(socket, OS_SIZE_1024);
434 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
436 merror(TO_ERROR, mail->gran_to[i]);
444 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
452 /* Sending the "DATA" msg */
453 OS_SendTCP(socket,DATAMSG);
454 msg = OS_RecvTCP(socket, OS_SIZE_1024);
455 if((msg == NULL)||(!OS_Match(VALIDDATA, msg)))
463 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
467 /* Building "From" and "To" in the e-mail header */
468 memset(snd_msg,'\0',128);
469 snprintf(snd_msg,127, TO, mail->to[0]);
470 OS_SendTCP(socket, snd_msg);
472 memset(snd_msg,'\0',128);
473 snprintf(snd_msg,127, FROM, mail->from);
474 OS_SendTCP(socket, snd_msg);
483 if(mail->to[i] == NULL)
488 memset(snd_msg,'\0',128);
489 snprintf(snd_msg,127, TO, mail->to[i]);
490 OS_SendTCP(socket,snd_msg);
497 /* More CCs - from granular options */
501 while(mail->gran_to[i] != NULL)
503 if(mail->gran_set[i] != FULL_FORMAT)
509 memset(snd_msg,'\0',128);
510 snprintf(snd_msg,127, TO, mail->gran_to[i]);
511 OS_SendTCP(socket, snd_msg);
519 memset(snd_msg,'\0',128);
522 /* Solaris doesn't have the "%z", so we set the timezone to 0. */
524 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p);
526 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p);
529 OS_SendTCP(socket,snd_msg);
532 /* Sending subject */
533 memset(snd_msg,'\0',128);
536 /* Checking if global subject is available */
537 if((_g_subject_level != 0) && (_g_subject[0] != '\0'))
539 snprintf(snd_msg, 127, SUBJECT, _g_subject);
541 /* Clearing global values */
542 _g_subject[0] = '\0';
543 _g_subject_level = 0;
547 snprintf(snd_msg, 127, SUBJECT, mailmsg->mail->subject);
549 OS_SendTCP(socket,snd_msg);
555 /* Sending multiple emails together if we have to */
558 OS_SendTCP(socket, mailmsg->mail->body);
559 mailmsg = OS_PopLastMail();
563 /* Sending end of data \r\n.\r\n */
564 OS_SendTCP(socket,ENDDATA);
565 msg = OS_RecvTCP(socket, OS_SIZE_1024);
566 if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg))))
568 merror(END_DATA_ERROR);
574 /* Checking msg in here, since it may be null */
579 /* quitting and closing socket */
580 OS_SendTCP(socket,QUITMSG);
581 msg = OS_RecvTCP(socket, OS_SIZE_1024);
586 memset(snd_msg,'\0',128);
589 /* Returning 0 (success) */