1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
12 #include "mail_list.h"
15 #define ARGV0 "ossec-maild"
18 /* Global variables */
19 unsigned int mail_timeout;
20 unsigned int _g_subject_level;
21 char _g_subject[SUBJECT_SIZE + 2];
24 static void OS_Run(MailConfig *mail) __attribute__((nonnull)) __attribute__((noreturn));
25 static void help_maild(void) __attribute__((noreturn));
28 /* Print help statement */
29 static void help_maild()
32 print_out(" %s: -[Vhdtf] [-u user] [-g group] [-c config] [-D dir]", ARGV0);
33 print_out(" -V Version and license message");
34 print_out(" -h This help message");
35 print_out(" -d Execute in debug mode. This parameter");
36 print_out(" can be specified multiple times");
37 print_out(" to increase the debug level.");
38 print_out(" -t Test configuration");
39 print_out(" -f Run in foreground");
40 print_out(" -u <user> User to run as (default: %s)", MAILUSER);
41 print_out(" -g <group> Group to run as (default: %s)", GROUPGLOBAL);
42 print_out(" -c <config> Configuration file to use (default: %s)", DEFAULTCPATH);
43 print_out(" -D <dir> Directory to chroot into (default: %s)", DEFAULTDIR);
48 int main(int argc, char **argv)
50 int c, test_config = 0, run_foreground = 0;
53 const char *dir = DEFAULTDIR;
54 const char *user = MAILUSER;
55 const char *group = GROUPGLOBAL;
56 const char *cfg = DEFAULTCPATH;
64 while ((c = getopt(argc, argv, "Vdhtfu:g:D:c:")) != -1) {
80 ErrorExit("%s: -u needs an argument", ARGV0);
86 ErrorExit("%s: -g needs an argument", ARGV0);
92 ErrorExit("%s: -D needs an argument", ARGV0);
98 ErrorExit("%s: -c needs an argument", ARGV0);
112 debug1(STARTED_MSG, ARGV0);
114 /* Check if the user/group given are valid */
115 uid = Privsep_GetUser(user);
116 gid = Privsep_GetGroup(group);
117 if (uid == (uid_t) - 1 || gid == (gid_t) - 1) {
118 ErrorExit(USER_ERROR, ARGV0, user, group);
121 /* Read configuration */
122 if (MailConf(test_config, cfg, &mail) < 0) {
123 ErrorExit(CONFIG_ERROR, ARGV0, cfg);
126 /* Read internal options */
127 mail.strict_checking = getDefine_Int("maild",
132 mail.groupping = getDefine_Int("maild",
136 /* Get subject type */
137 mail.subject_full = getDefine_Int("maild",
141 #ifdef LIBGEOIP_ENABLED
143 mail.geoip = getDefine_Int("maild",
148 /* Exit here if test config is set */
153 if (!run_foreground) {
158 /* Privilege separation */
159 if (Privsep_SetGroup(gid) < 0) {
160 ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
163 if (mail.smtpserver[0] != '/') {
165 if (Privsep_Chroot(dir) < 0) {
166 ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
169 debug1(CHROOT_MSG, ARGV0, dir);
173 if (Privsep_SetUser(uid) < 0) {
174 ErrorExit(SETUID_ERROR, ARGV0, user, errno, strerror(errno));
177 debug1(PRIVSEP_MSG, ARGV0, user);
179 /* Signal manipulation */
182 /* Create PID files */
183 if (CreatePID(ARGV0, getpid()) < 0) {
184 ErrorExit(PID_ERROR, ARGV0);
187 /* Start up message */
188 verbose(STARTUP_MSG, ARGV0, (int)getpid());
190 /* The real daemon now */
194 /* Read the queue and send the appropriate alerts
195 * Not supposed to return
197 static void OS_Run(MailConfig *mail)
200 MailMsg *s_msg = NULL;
201 MailMsg *msg_sms = NULL;
215 /* Get current time before starting */
218 thishour = p->tm_hour;
220 /* Initialize file queue */
222 i |= CRALERT_MAIL_SET;
223 os_calloc(1, sizeof(file_queue), fileq);
224 Init_FileQueue(fileq, p, i);
226 /* Create the list */
227 OS_CreateMailList(MAIL_LIST_SIZE);
229 /* Set default timeout */
230 mail_timeout = DEFAULT_TIMEOUT;
232 /* Clear global variables */
233 _g_subject_level = 0;
234 memset(_g_subject, '\0', SUBJECT_SIZE + 2);
241 /* If mail_timeout == NEXTMAIL_TIMEOUT, we will try to get
242 * more messages, before sending anything
244 if ((mail_timeout == NEXTMAIL_TIMEOUT) && (p->tm_hour == thishour)) {
245 /* Get more messages */
248 /* Hour changed: send all suppressed mails */
249 else if (((mailtosend < mail->maxperhour) && (mailtosend != 0)) ||
250 ((p->tm_hour != thishour) && (childcount < MAXCHILDPROCESS))) {
254 /* Check if we have anything to send */
255 mailmsg = OS_CheckLastMail();
256 if (mailmsg == NULL) {
257 /* Don't fork in here */
264 merror(FORK_ERROR, ARGV0, errno, strerror(errno));
267 } else if (pid == 0) {
268 if (OS_Sendmail(mail, p) < 0) {
269 merror(SNDMAIL_ERROR, ARGV0, mail->smtpserver);
275 /* Clean the memory */
276 mailmsg = OS_PopLastMail();
279 mailmsg = OS_PopLastMail();
282 /* Increase child count */
285 /* Clear global variables */
286 _g_subject[0] = '\0';
287 _g_subject[SUBJECT_SIZE - 1] = '\0';
288 _g_subject_level = 0;
290 /* Clean up set values */
293 while (mail->gran_to[i] != NULL) {
294 if (s_msg && mail->gran_set[i] == DONOTGROUP) {
295 mail->gran_set[i] = FULL_FORMAT;
297 mail->gran_set[i] = 0;
304 /* If we sent everything */
305 if (p->tm_hour != thishour) {
306 thishour = p->tm_hour;
312 /* Saved message for the do_not_group option */
314 /* Set the remaining do no group to full format */
317 while (mail->gran_to[i] != NULL) {
318 if (mail->gran_set[i] == DONOTGROUP) {
319 mail->gran_set[i] = FULL_FORMAT;
325 OS_AddMailtoList(s_msg);
332 /* Receive message from queue */
333 if ((msg = OS_RecvMailQ(fileq, p, mail, &msg_sms)) != NULL) {
334 /* If the e-mail priority is do_not_group,
335 * flush all previous entries and then send it.
336 * Use s_msg to hold the pointer to the message while we flush it.
338 if (mail->priority == DONOTGROUP) {
341 OS_AddMailtoList(msg);
344 /* Change timeout to see if any new message is coming shortly */
345 if (mail->groupping) {
346 /* If priority is set, send email now */
347 if (mail->priority) {
348 mail_timeout = DEFAULT_TIMEOUT;
350 /* If do_not_group is set, we do not increase the list count */
351 if (mail->priority != DONOTGROUP) {
356 mail_timeout = NEXTMAIL_TIMEOUT;
359 /* Send message by itself */
363 if (mail_timeout == NEXTMAIL_TIMEOUT) {
366 /* Default timeout */
367 mail_timeout = DEFAULT_TIMEOUT;
371 /* Wait for the children */
375 wp = waitpid((pid_t) - 1, &p_status, WNOHANG);
377 merror(WAITPID_ERROR, ARGV0, errno, strerror(errno));
381 /* if = 0, we still need to wait for the child process */
386 merror(CHLDWAIT_ERROR, ARGV0, p_status);
387 merror(SNDMAIL_ERROR, ARGV0, mail->smtpserver);
393 /* Too many errors */
395 merror(TOOMANY_WAIT_ERROR, ARGV0);
396 merror(SNDMAIL_ERROR, ARGV0, mail->smtpserver);