-/* @(#) $Id$ */
-
/* Copyright (C) 2009 Trend Micro Inc.
* All rights reserved.
*
* This program is a free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
- * License (version 2) as published by the FSF - Free Software
+ * License (version 2) as published by the FSF - Free Software
* Foundation
*/
-
/* Basic e-mailing operations */
-
#include "shared.h"
#include "os_net/os_net.h"
-#include "maild.h"
-
/* Return codes (from SMTP server) */
-#define VALIDBANNER "220"
-#define VALIDMAIL "250"
-#define VALIDDATA "354"
-
-
-/* Default values use to connect */
-#define SMTP_DEFAULT_PORT 25
-#define HELOMSG "Helo notify.ossec.net\r\n"
-#define MAILFROM "Mail From: <%s>\r\n"
-#define RCPTTO "Rcpt To: <%s>\r\n"
-#define DATAMSG "DATA\r\n"
-#define FROM "From: OSSEC HIDS <%s>\r\n"
-#define TO "To: <%s>\r\n"
-#define CC "Cc: <%s>\r\n"
-#define SUBJECT "Subject: %s\r\n"
-#define ENDDATA "\r\n.\r\n"
-#define QUITMSG "QUIT\r\n"
-
+#define VALIDBANNER "220"
+#define VALIDMAIL "250"
+#define VALIDDATA "354"
+
+/* Default values used to connect */
+#define SMTP_DEFAULT_PORT "25"
+#define HELOMSG "Helo notify.ossec.net\r\n"
+#define MAILFROM "Mail From: <%s>\r\n"
+#define RCPTTO "Rcpt To: <%s>\r\n"
+#define DATAMSG "DATA\r\n"
+#define FROM "From: OSSEC HIDS <%s>\r\n"
+#define REPLYTO "Reply-To: OSSEC HIDS <%s>\r\n"
+#define TO "To: <%s>\r\n"
+#define CC "Cc: <%s>\r\n"
+#define SUBJECT "Subject: %s\r\n"
+#define ENDHEADER "\r\n"
+#define ENDDATA "\r\n.\r\n"
+#define QUITMSG "QUIT\r\n"
+#define XHEADER "X-IDS-OSSEC: %s\r\n"
/* Error messages - Can be translated */
-#define INTERNAL_ERROR "os_maild (1760): ERROR: Memory/configuration error"
-#define BANNER_ERROR "os_sendmail(1762): WARN: Banner not received from server"
-#define HELO_ERROR "os_sendmail(1763): WARN: Hello not accepted by server"
-#define FROM_ERROR "os_sendmail(1764): WARN: Mail from not accepted by server"
-#define TO_ERROR "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'."
-#define DATA_ERROR "os_sendmail(1766): WARN: DATA not accepted by server"
-#define END_DATA_ERROR "os_sendmail(1767): WARN: End of DATA not accepted by server"
-
+#define INTERNAL_ERROR "os_maild (1760): ERROR: Memory/configuration error"
+#define BANNER_ERROR "os_sendmail(1762): WARN: Banner not received from server"
+#define HELO_ERROR "os_sendmail(1763): WARN: Hello not accepted by server"
+#define FROM_ERROR "os_sendmail(1764): WARN: Mail from not accepted by server"
+#define TO_ERROR "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'."
+#define DATA_ERROR "os_sendmail(1766): WARN: DATA not accepted by server"
+#define END_DATA_ERROR "os_sendmail(1767): WARN: End of DATA not accepted by server"
#define MAIL_DEBUG_FLAG 0
#define MAIL_DEBUG(x,y,z) if(MAIL_DEBUG_FLAG) merror(x,y,z)
-
-/* OS_SendCustomEmail
- */
-int OS_SendCustomEmail(char **to, char *subject, char *smtpserver, char *from, FILE *fp, struct tm *p)
+int OS_SendCustomEmail(char **to, char *subject, char *smtpserver, char *from, char *replyto, char *idsname, char *fname, const struct tm *p)
{
- int socket,i = 0;
+ FILE *sendmail = NULL;
+ int socket = -1, i = 0;
char *msg;
-
char snd_msg[128];
char buffer[2049];
buffer[2048] = '\0';
+ if (smtpserver[0] == '/') {
+ sendmail = popen(smtpserver, "w");
+ if (!sendmail) {
+ return (OS_INVALID);
+ }
+ } else {
+ /* Connect to the SMTP server */
+ socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, smtpserver);
+ if (socket < 0) {
+ return (socket);
+ }
- /* Connecting to the smtp server */
- socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, smtpserver);
- if(socket < 0)
- {
- return(socket);
- }
-
-
- /* Receiving the banner */
- msg = OS_RecvTCP(socket, OS_SIZE_1024);
- if((msg == NULL)||(!OS_Match(VALIDBANNER, msg)))
- {
- merror(BANNER_ERROR);
- if(msg)
- free(msg);
- close(socket);
- return(OS_INVALID);
- }
- MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
- free(msg);
-
-
-
- /* Sending HELO message */
- OS_SendTCP(socket,HELOMSG);
- msg = OS_RecvTCP(socket, OS_SIZE_1024);
- if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
- {
- if(msg)
- {
- /* Ugly fix warning :) */
- /* In some cases (with virus scans in the middle)
- * we may get two banners. Check for that in here.
- */
- if(OS_Match(VALIDBANNER, msg))
- {
+ /* Receive the banner */
+ msg = OS_RecvTCP(socket, OS_SIZE_1024);
+ if ((msg == NULL) || (!OS_Match(VALIDBANNER, msg))) {
+ merror(BANNER_ERROR);
+ if (msg) {
free(msg);
+ }
+ close(socket);
+ return (OS_INVALID);
+ }
+ MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
+ free(msg);
- /* Try again */
- msg = OS_RecvTCP(socket, OS_SIZE_1024);
- if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
- {
- merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null");
- if(msg)
- free(msg);
+ /* Send HELO message */
+ OS_SendTCP(socket, HELOMSG);
+ msg = OS_RecvTCP(socket, OS_SIZE_1024);
+ if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
+ if (msg) {
+ /* In some cases (with virus scans in the middle)
+ * we may get two banners. Check for that in here.
+ */
+ if (OS_Match(VALIDBANNER, msg)) {
+ free(msg);
+
+ /* Try again */
+ msg = OS_RecvTCP(socket, OS_SIZE_1024);
+ if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
+ merror("%s:%s", HELO_ERROR, msg != NULL ? msg : "null");
+ if (msg) {
+ free(msg);
+ }
+ close(socket);
+ return (OS_INVALID);
+ }
+ } else {
+ merror("%s:%s", HELO_ERROR, msg);
+ free(msg);
close(socket);
- return(OS_INVALID);
+ return (OS_INVALID);
}
- }
- else
- {
- merror("%s:%s",HELO_ERROR,msg);
- free(msg);
+ } else {
+ merror("%s:%s", HELO_ERROR, "null");
close(socket);
- return(OS_INVALID);
+ return (OS_INVALID);
}
}
- else
- {
- merror("%s:%s",HELO_ERROR,"null");
- close(socket);
- return(OS_INVALID);
- }
- }
- MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
- free(msg);
+ MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
+ free(msg);
+ /* Build "Mail from" msg */
+ memset(snd_msg, '\0', 128);
+ snprintf(snd_msg, 127, MAILFROM, from);
+ OS_SendTCP(socket, snd_msg);
+ msg = OS_RecvTCP(socket, OS_SIZE_1024);
+ if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
+ merror(FROM_ERROR);
+ if (msg) {
+ free(msg);
+ }
+ close(socket);
+ return (OS_INVALID);
+ }
+ MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
+ free(msg);
- /* Building "Mail from" msg */
- memset(snd_msg,'\0',128);
- snprintf(snd_msg,127, MAILFROM, from);
- OS_SendTCP(socket, snd_msg);
- msg = OS_RecvTCP(socket, OS_SIZE_1024);
- if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
- {
- merror(FROM_ERROR);
- if(msg)
+ /* Build "RCPT TO" msg */
+ while (to[i]) {
+ memset(snd_msg, '\0', 128);
+ snprintf(snd_msg, 127, RCPTTO, to[i]);
+ OS_SendTCP(socket, snd_msg);
+ msg = OS_RecvTCP(socket, OS_SIZE_1024);
+ if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
+ merror(TO_ERROR, to[i]);
+ if (msg) {
+ free(msg);
+ }
+ close(socket);
+ return (OS_INVALID);
+ }
+ MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
free(msg);
- close(socket);
- return(OS_INVALID);
- }
- MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
- free(msg);
+ i++;
+ }
- /* Building "RCPT TO" msg */
- while(to[i])
- {
- memset(snd_msg,'\0',128);
- snprintf(snd_msg,127,RCPTTO, to[i]);
- OS_SendTCP(socket,snd_msg);
+ /* Send the "DATA" msg */
+ OS_SendTCP(socket, DATAMSG);
msg = OS_RecvTCP(socket, OS_SIZE_1024);
- if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
- {
- merror(TO_ERROR, to[i]);
- if(msg)
+ if ((msg == NULL) || (!OS_Match(VALIDDATA, msg))) {
+ merror(DATA_ERROR);
+ if (msg) {
free(msg);
+ }
close(socket);
- return(OS_INVALID);
+ return (OS_INVALID);
}
- MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
+ MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
free(msg);
-
- i++;
}
+ /* Build "From" and "To" in the e-mail header */
+ memset(snd_msg, '\0', 128);
+ snprintf(snd_msg, 127, TO, to[0]);
- /* Sending the "DATA" msg */
- OS_SendTCP(socket,DATAMSG);
- msg = OS_RecvTCP(socket, OS_SIZE_1024);
- if((msg == NULL)||(!OS_Match(VALIDDATA, msg)))
- {
- merror(DATA_ERROR);
- if(msg)
- free(msg);
- close(socket);
- return(OS_INVALID);
+ if (sendmail) {
+ fprintf(sendmail, "%s", snd_msg);
+ } else {
+ OS_SendTCP(socket, snd_msg);
}
- MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
- free(msg);
+ memset(snd_msg, '\0', 128);
+ snprintf(snd_msg, 127, FROM, from);
- /* Building "From" and "To" in the e-mail header */
- memset(snd_msg,'\0',128);
- snprintf(snd_msg,127, TO, to[0]);
- OS_SendTCP(socket, snd_msg);
-
- memset(snd_msg,'\0',128);
- snprintf(snd_msg,127, FROM, from);
- OS_SendTCP(socket, snd_msg);
+ if (sendmail) {
+ fprintf(sendmail, "%s", snd_msg);
+ } else {
+ OS_SendTCP(socket, snd_msg);
+ }
+ if (replyto) {
+ memset(snd_msg, '\0', 128);
+ snprintf(snd_msg, 127, REPLYTO, replyto);
+ if(sendmail) {
+ fprintf(sendmail, "%s", snd_msg);
+ } else {
+ OS_SendTCP(socket, snd_msg);
+ }
+ }
- /* Adding CCs */
- if(to[1])
- {
+ /* Add CCs */
+ if (to[1]) {
i = 1;
- while(1)
- {
- if(to[i] == NULL)
- {
+ while (1) {
+ if (to[i] == NULL) {
break;
}
-
- memset(snd_msg,'\0',128);
- snprintf(snd_msg,127, TO, to[i]);
- OS_SendTCP(socket,snd_msg);
+
+ memset(snd_msg, '\0', 128);
+ snprintf(snd_msg, 127, TO, to[i]);
+
+ if (sendmail) {
+ fprintf(sendmail, "%s", snd_msg);
+ } else {
+ OS_SendTCP(socket, snd_msg);
+ }
i++;
}
}
+ /* Send date */
+ memset(snd_msg, '\0', 128);
- /* Sending date */
- memset(snd_msg,'\0',128);
-
+ /* Solaris doesn't have the "%z", so we set the timezone to 0 */
+#ifdef SOLARIS
+ strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n", p);
+#else
+ strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n", p);
+#endif
+
+ if (sendmail) {
+ fprintf(sendmail, "%s", snd_msg);
+ } else {
+ OS_SendTCP(socket, snd_msg);
+ }
- /* Solaris doesn't have the "%z", so we set the timezone to 0. */
- #ifdef SOLARIS
- strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p);
- #else
- strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p);
- #endif
-
- OS_SendTCP(socket,snd_msg);
+ if (idsname) {
+ /* Send server name header */
+ memset(snd_msg, '\0', 128);
+ snprintf(snd_msg, 127, XHEADER, idsname);
+ if (sendmail) {
+ fprintf(sendmail, "%s", snd_msg);
+ } else {
+ OS_SendTCP(socket, snd_msg);
+ }
+ }
- /* Sending subject */
+ /* Send subject */
memset(snd_msg, '\0', 128);
snprintf(snd_msg, 127, SUBJECT, subject);
- OS_SendTCP(socket, snd_msg);
-
-
-
- /* Sending body */
- fseek(fp, 0, SEEK_SET);
- while(fgets(buffer, 2048, fp) != NULL)
- {
- OS_SendTCP(socket,buffer);
- }
-
-
- /* Sending end of data \r\n.\r\n */
- OS_SendTCP(socket,ENDDATA);
- msg = OS_RecvTCP(socket, OS_SIZE_1024);
+ if (sendmail) {
+ fprintf(sendmail, "%s", snd_msg);
+ fprintf(sendmail, ENDHEADER);
+ } else {
+ OS_SendTCP(socket, snd_msg);
+ OS_SendTCP(socket, ENDHEADER);
+ }
+ /* Send body */
+ FILE *fp;
+ fp = fopen(fname, "r");
+ if(!fp) {
+ merror("%s: ERROR: Cannot open %s: %s", __local_name, fname, strerror(errno));
+ if(socket >= 0) {
+ close(socket);
+ }
+ if(sendmail) {
+ pclose(sendmail);
+ }
+ return(1);
+ }
- /* Checking msg in here, since it may be null */
- if(msg)
- free(msg);
+ struct stat sb;
+ int sr;
+ sr = stat(fname, &sb);
+ if(sr < 0) {
+ merror("Cannot stat %s: %s", fname, strerror(errno));
+ }
+ if(sb.st_size == 0) {
+ merror("Report is empty");
+ if(socket >= 0) {
+ close(socket);
+ }
+ if(sendmail) {
+ pclose(sendmail);
+ }
+ if(fp) {
+ fclose(fp);
+ }
+ return(0);
+ }
+ while (fgets(buffer, 2048, fp) != NULL) {
+ if (sendmail) {
+ fprintf(sendmail, "%s", buffer);
+ } else {
+ OS_SendTCP(socket, buffer);
+ }
+ }
+ fclose(fp);
- /* quitting and closing socket */
- OS_SendTCP(socket,QUITMSG);
- msg = OS_RecvTCP(socket, OS_SIZE_1024);
+ if (sendmail) {
+ if (pclose(sendmail) == -1) {
+ merror(WAITPID_ERROR, ARGV0, errno, strerror(errno));
+ }
+ } else {
+ /* Send end of data \r\n.\r\n */
+ OS_SendTCP(socket, ENDDATA);
+ msg = OS_RecvTCP(socket, OS_SIZE_1024);
- if(msg)
- free(msg);
+ /* Check msg, since it may be null */
+ if (msg) {
+ free(msg);
+ }
- memset(snd_msg,'\0',128);
+ /* Quit and close socket */
+ OS_SendTCP(socket, QUITMSG);
+ msg = OS_RecvTCP(socket, OS_SIZE_1024);
+ if (msg) {
+ free(msg);
+ }
- /* Returning 0 (success) */
- close(socket);
+ close(socket);
+ }
- return(0);
+ memset_secure(snd_msg, '\0', 128);
+ return (0);
}
-
-
-/* EOF */