new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / os_maild / sendcustomemail.c
old mode 100755 (executable)
new mode 100644 (file)
index 9026d02..8a31522
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/os_maild/sendcustomemail.c, 2011/09/08 dcid Exp $
- */
-
 /* Copyright (C) 2009 Trend Micro Inc.
  * All rights reserved.
  *
  * 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 ENDHEADER               "\r\n"
-#define ENDDATA                        "\r\n.\r\n"
-#define QUITMSG                "QUIT\r\n"
-#define XHEADER                "X-IDS-OSSEC: %s\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, char *idsname, 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, 0);
-    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);
-
 
-    /* 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);
 
-    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
 
-    /* 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);
+    }
 
-    OS_SendTCP(socket,snd_msg);
+    if (idsname) {
+        /* Send server name header */
+        memset(snd_msg, '\0', 128);
+        snprintf(snd_msg, 127, XHEADER, idsname);
 
-    if (idsname)
-    {      
-        /* Sending server name header */
-        memset(snd_msg,'\0',128);
-        snprintf(snd_msg,127, XHEADER, idsname);
-        OS_SendTCP(socket, snd_msg);
+        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);
-
-    OS_SendTCP(socket,ENDHEADER);
-
-
-     /* 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 */