/* OS_Sendmail v0.1: 2005/03/18 */ int OS_Sendmail(MailConfig *mail, struct tm *p) { int socket,i=0; char *msg; char snd_msg[128]; char additional_to[512]; MailNode *mailmsg; additional_to[0] = '\0'; /* If there is no sms message, we attempt to get from the * email list. */ mailmsg = OS_PopLastMail(); if(mailmsg == NULL) { merror("%s: No email to be sent. Inconsistent state.",ARGV0); } /* Connecting to the smtp server */ socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->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)) { 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); } } else { merror("%s:%s",HELO_ERROR,"null"); close(socket); return(OS_INVALID); } } MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg); free(msg); /* Building "Mail from" msg */ memset(snd_msg,'\0',128); snprintf(snd_msg,127, MAILFROM, mail->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 "RCPT TO" msg */ while(1) { if(mail->to[i] == NULL) { if(i == 0) { merror(INTERNAL_ERROR); close(socket); return(OS_INVALID); } break; } memset(snd_msg,'\0',128); snprintf(snd_msg,127,RCPTTO, mail->to[i++]); OS_SendTCP(socket,snd_msg); msg = OS_RecvTCP(socket, OS_SIZE_1024); if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) { merror(TO_ERROR, mail->to[i -1]); if(msg) free(msg); close(socket); return(OS_INVALID); } MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg); free(msg); } /* Additional RCPT to */ if(mail->gran_to) { i = 0; while(mail->gran_to[i] != NULL) { if(mail->gran_set[i] != FULL_FORMAT) { i++; continue; } memset(snd_msg,'\0',128); snprintf(snd_msg,127,RCPTTO, mail->gran_to[i]); OS_SendTCP(socket,snd_msg); msg = OS_RecvTCP(socket, OS_SIZE_1024); if((msg == NULL)||(!OS_Match(VALIDMAIL, msg))) { merror(TO_ERROR, mail->gran_to[i]); if(msg) free(msg); i++; continue; } MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg); free(msg); i++; continue; } } /* 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); } 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, mail->to[0]); OS_SendTCP(socket, snd_msg); memset(snd_msg,'\0',128); snprintf(snd_msg,127, FROM, mail->from); OS_SendTCP(socket, snd_msg); /* Adding CCs */ if(mail->to[1]) { i = 1; while(1) { if(mail->to[i] == NULL) { break; } memset(snd_msg,'\0',128); snprintf(snd_msg,127, TO, mail->to[i]); OS_SendTCP(socket,snd_msg); i++; } } /* More CCs - from granular options */ if(mail->gran_to) { i = 0; while(mail->gran_to[i] != NULL) { if(mail->gran_set[i] != FULL_FORMAT) { i++; continue; } memset(snd_msg,'\0',128); snprintf(snd_msg,127, TO, mail->gran_to[i]); OS_SendTCP(socket, snd_msg); i++; continue; } } /* 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 OS_SendTCP(socket,snd_msg); /* Sending subject */ memset(snd_msg,'\0',128); /* Checking if global subject is available */ if((_g_subject_level != 0) && (_g_subject[0] != '\0')) { snprintf(snd_msg, 127, SUBJECT, _g_subject); /* Clearing global values */ _g_subject[0] = '\0'; _g_subject_level = 0; } else { snprintf(snd_msg, 127, SUBJECT, mailmsg->mail->subject); } OS_SendTCP(socket,snd_msg); /* Sending body */ /* Sending multiple emails together if we have to */ do { OS_SendTCP(socket, mailmsg->mail->body); mailmsg = OS_PopLastMail(); }while(mailmsg); /* Sending end of data \r\n.\r\n */ OS_SendTCP(socket,ENDDATA); msg = OS_RecvTCP(socket, OS_SIZE_1024); if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))) { merror(END_DATA_ERROR); if(msg) free(msg); close(socket); return(OS_INVALID); } /* Checking msg in here, since it may be null */ if(msg) free(msg); /* quitting and closing socket */ OS_SendTCP(socket,QUITMSG); msg = OS_RecvTCP(socket, OS_SIZE_1024); if(msg) free(msg); memset(snd_msg,'\0',128); /* Returning 0 (success) */ close(socket); return(0); }
/* OS_Run: Read the queue and send the appropriate alerts. * not supposed to return.. */ static void OS_Run(MailConfig *mail) { MailMsg *msg; MailMsg *s_msg = NULL; MailMsg *msg_sms = NULL; time_t tm; struct tm *p; int i = 0; int mailtosend = 0; int childcount = 0; int thishour = 0; int n_errs = 0; file_queue *fileq; /* Getting currently time before starting */ tm = time(NULL); p = localtime(&tm); thishour = p->tm_hour; /* Init file queue */ i = 0; i |= CRALERT_MAIL_SET; os_calloc(1, sizeof(file_queue), fileq); Init_FileQueue(fileq, p, i); /* Creating the list */ OS_CreateMailList(MAIL_LIST_SIZE); /* Setting default timeout */ mail_timeout = DEFAULT_TIMEOUT; /* Clearing global vars */ _g_subject_level = 0; memset(_g_subject, '\0', SUBJECT_SIZE +2); while(1) { tm = time(NULL); p = localtime(&tm); /* SMS messages are sent without delay */ if(msg_sms) { pid_t pid; pid = fork(); if(pid < 0) { merror("%s: Fork failed. cause: %d - %s", ARGV0, errno, strerror(errno)); merror(FORK_ERROR, ARGV0); sleep(30); continue; } else if (pid == 0) { if(OS_Sendsms(mail, p, msg_sms) < 0) merror(SNDMAIL_ERROR, ARGV0, mail->smtpserver); exit(0); } /* Freeing sms structure */ FreeMailMsg(msg_sms); msg_sms = NULL; /* Increasing child count */ childcount++; } /* If mail_timeout == NEXTMAIL_TIMEOUT, we will try to get * more messages, before sending anything */ if((mail_timeout == NEXTMAIL_TIMEOUT) && (p->tm_hour == thishour)) { /* getting more messages */ } /* Hour changed. Send all supressed mails */ else if(((mailtosend < mail->maxperhour) && (mailtosend != 0))|| ((p->tm_hour != thishour) && (childcount < MAXCHILDPROCESS))) { MailNode *mailmsg; pid_t pid; /* Checking if we have anything to sent */ mailmsg = OS_CheckLastMail(); if(mailmsg == NULL) { /* dont fork in here */ goto snd_check_hour; } pid = fork(); if(pid < 0) { merror("%s: Fork failed. cause: %d - %s", ARGV0, errno, strerror(errno)); merror(FORK_ERROR, ARGV0); sleep(30); continue; } else if (pid == 0) { if(OS_Sendmail(mail, p) < 0) merror(SNDMAIL_ERROR,ARGV0,mail->smtpserver); exit(0); } /* Cleaning the memory */ mailmsg = OS_PopLastMail(); do { FreeMail(mailmsg); mailmsg = OS_PopLastMail(); }while(mailmsg); /* Increasing child count */ childcount++; /* Clearing global vars */ _g_subject[0] = '\0'; _g_subject[SUBJECT_SIZE -1] = '\0'; _g_subject_level = 0; /* Cleaning up set values */ if(mail->gran_to) { i = 0; while(mail->gran_to[i] != NULL) { if(s_msg && mail->gran_set[i] == DONOTGROUP) { mail->gran_set[i] = FULL_FORMAT; } else { mail->gran_set[i] = 0; } i++; } } snd_check_hour: /* If we sent everything */ if(p->tm_hour != thishour) { thishour = p->tm_hour; mailtosend = 0; } } /* Saved message for the do_not_group option. */ if(s_msg) { /* We need to set the remaining do no group to * full format. */ if(mail->gran_to) { i = 0; while(mail->gran_to[i] != NULL) { if(mail->gran_set[i] == DONOTGROUP) { mail->gran_set[i] = FULL_FORMAT; } i++; } } OS_AddMailtoList(s_msg); s_msg = NULL; mailtosend++; continue; } /* Receive message from queue */ if((msg = OS_RecvMailQ(fileq, p, mail, &msg_sms)) != NULL) { /* If the e-mail priority is do_not_group, we first will * flush all previous entries and then send it. * We use s_msg to hold the pointer to the message * while we flush it. */ if(mail->priority == DONOTGROUP) { s_msg = msg; } else { OS_AddMailtoList(msg); } /* Change timeout to see if any new message is coming shortly */ if(mail->groupping) { /* If priority is set, send email now */ if(mail->priority) { mail_timeout = DEFAULT_TIMEOUT; /* If do_not_group is set, we do not increase the * list count in here. */ if(mail->priority != DONOTGROUP) { mailtosend++; } } else { /* 5 seconds only */ mail_timeout = NEXTMAIL_TIMEOUT; } } else { /* Send message by itself */ mailtosend++; } } else { if(mail_timeout == NEXTMAIL_TIMEOUT) { mailtosend++; /* Default timeout */ mail_timeout = DEFAULT_TIMEOUT; } } /* Waiting for the childs .. */ while (childcount) { int wp; int p_status; wp = waitpid((pid_t) -1, &p_status, WNOHANG); if (wp < 0) { merror(WAITPID_ERROR, ARGV0); n_errs++; } /* if = 0, we still need to wait for the child process */ else if (wp == 0) break; else { if(p_status != 0) { merror(CHLDWAIT_ERROR,ARGV0,p_status); merror(SNDMAIL_ERROR,ARGV0,mail->smtpserver); n_errs++; } childcount--; } /* Too many errors */ if(n_errs > 6) { merror(TOOMANY_WAIT_ERROR,ARGV0); merror(SNDMAIL_ERROR,ARGV0,mail->smtpserver); exit(1); } } } }