d937a15a6f1c92d8fc0d6516e64725f3ac0a66a4
[ossec-hids.git] / src / os_maild / sendmail.c
1 /* @(#) $Id: ./src/os_maild/sendmail.c, 2011/09/08 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 Trend Micro Inc.
5  * All rights reserved.
6  *
7  * This program is a free software; you can redistribute it
8  * and/or modify it under the terms of the GNU General Public
9  * License (version 2) as published by the FSF - Free Software
10  * Foundation
11  */
12
13
14 /* Basic e-mailing operations */
15
16
17 #include "shared.h"
18 #include "os_net/os_net.h"
19 #include "maild.h"
20 #include "mail_list.h"
21
22
23 /* Return codes (from SMTP server) */
24 #define VALIDBANNER             "220"
25 #define VALIDMAIL               "250"
26 #define VALIDDATA               "354"
27
28
29 /* Default values use to connect */
30 #define SMTP_DEFAULT_PORT       25
31 #define HELOMSG                 "Helo notify.ossec.net\r\n"
32 #define MAILFROM                "Mail From: <%s>\r\n"
33 #define RCPTTO                  "Rcpt To: <%s>\r\n"
34 #define DATAMSG                 "DATA\r\n"
35 #define FROM                    "From: OSSEC HIDS <%s>\r\n"
36 #define TO                          "To: <%s>\r\n"
37 #define CC                          "Cc: <%s>\r\n"
38 #define SUBJECT                 "Subject: %s\r\n"
39 #define ENDHEADER               "\r\n"
40 #define ENDDATA                 "\r\n.\r\n"
41 #define QUITMSG                 "QUIT\r\n"
42 #define XHEADER                 "X-IDS-OSSEC: %s\r\n"
43
44
45 /* Error messages - Can be translated */
46 #define INTERNAL_ERROR  "os_maild (1760): ERROR: Memory/configuration error"
47 #define BANNER_ERROR    "os_sendmail(1762): WARN: Banner not received from server"
48 #define HELO_ERROR          "os_sendmail(1763): WARN: Hello not accepted by server"
49 #define FROM_ERROR          "os_sendmail(1764): WARN: Mail from not accepted by server"
50 #define TO_ERROR            "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'."
51 #define DATA_ERROR          "os_sendmail(1766): WARN: DATA not accepted by server"
52 #define END_DATA_ERROR  "os_sendmail(1767): WARN: End of DATA not accepted by server"
53
54
55 #define MAIL_DEBUG_FLAG     0
56 #define MAIL_DEBUG(x,y,z) if(MAIL_DEBUG_FLAG) merror(x,y,z)
57
58
59 /* OS_Sendsms.
60  */
61 int OS_Sendsms(MailConfig *mail, struct tm *p, MailMsg *sms_msg)
62 {
63     int socket, i = 0, final_to_sz;
64     char *msg;
65     char snd_msg[128];
66     char final_to[512];
67
68
69     /* Connecting to the smtp server */
70     socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver, 0);
71     if(socket < 0)
72     {
73         return(socket);
74     }
75
76
77     /* Receiving the banner */
78     msg = OS_RecvTCP(socket, OS_SIZE_1024);
79     if((msg == NULL)||(!OS_Match(VALIDBANNER, msg)))
80     {
81         merror(BANNER_ERROR);
82         if(msg)
83             free(msg);
84         close(socket);
85         return(OS_INVALID);
86     }
87     MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
88     free(msg);
89
90
91
92     /* Sending HELO message */
93     OS_SendTCP(socket,HELOMSG);
94     msg = OS_RecvTCP(socket, OS_SIZE_1024);
95     if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
96     {
97         if(msg)
98         {
99             /* Ugly fix warning :) */
100             /* In some cases (with virus scans in the middle)
101              * we may get two banners. Check for that in here.
102              */
103             if(OS_Match(VALIDBANNER, msg))
104             {
105                 free(msg);
106
107                 /* Try again */
108                 msg = OS_RecvTCP(socket, OS_SIZE_1024);
109                 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
110                 {
111                     merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null");
112                     if(msg)
113                         free(msg);
114                     close(socket);
115                     return(OS_INVALID);
116                 }
117             }
118             else
119             {
120                 merror("%s:%s",HELO_ERROR,msg);
121                 free(msg);
122                 close(socket);
123                 return(OS_INVALID);
124             }
125         }
126         else
127         {
128             merror("%s:%s",HELO_ERROR,"null");
129             close(socket);
130             return(OS_INVALID);
131         }
132     }
133
134     MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
135     free(msg);
136
137
138     /* Building "Mail from" msg */
139     memset(snd_msg,'\0',128);
140     snprintf(snd_msg,127, MAILFROM, mail->from);
141     OS_SendTCP(socket, snd_msg);
142     msg = OS_RecvTCP(socket, OS_SIZE_1024);
143     if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
144     {
145         merror(FROM_ERROR);
146         if(msg)
147             free(msg);
148         close(socket);
149         return(OS_INVALID);
150     }
151     MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
152     free(msg);
153
154
155     /* Additional RCPT to */
156     final_to[0] = '\0';
157     final_to_sz = sizeof(final_to) -2;
158
159     if(mail->gran_to)
160     {
161         i = 0;
162         while(mail->gran_to[i] != NULL)
163         {
164             if(mail->gran_set[i] != SMS_FORMAT)
165             {
166                 i++;
167                 continue;
168             }
169
170             memset(snd_msg,'\0',128);
171             snprintf(snd_msg,127, RCPTTO, mail->gran_to[i]);
172             OS_SendTCP(socket, snd_msg);
173             msg = OS_RecvTCP(socket, OS_SIZE_1024);
174             if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
175             {
176                 merror(TO_ERROR, mail->gran_to[i]);
177                 if(msg)
178                     free(msg);
179                 close(socket);
180                 return(OS_INVALID);
181             }
182             MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
183             free(msg);
184
185
186             /* Creating header for to */
187             memset(snd_msg,'\0',128);
188             snprintf(snd_msg,127, TO, mail->gran_to[i]);
189             strncat(final_to, snd_msg, final_to_sz);
190             final_to_sz -= strlen(snd_msg) +2;
191
192             i++;
193             continue;
194         }
195     }
196
197
198     /* Sending the "DATA" msg */
199     OS_SendTCP(socket,DATAMSG);
200     msg = OS_RecvTCP(socket, OS_SIZE_1024);
201     if((msg == NULL)||(!OS_Match(VALIDDATA, msg)))
202     {
203         merror(DATA_ERROR);
204         if(msg)
205             free(msg);
206         close(socket);
207         return(OS_INVALID);
208     }
209     MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
210     free(msg);
211
212
213     /* Building "From" and "To" in the e-mail header */
214     OS_SendTCP(socket, final_to);
215
216
217     memset(snd_msg,'\0',128);
218     snprintf(snd_msg,127, FROM, mail->from);
219     OS_SendTCP(socket, snd_msg);
220
221
222     /* Sending date */
223     memset(snd_msg,'\0',128);
224
225
226     /* Solaris doesn't have the "%z", so we set the timezone to 0. */
227     #ifdef SOLARIS
228     strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p);
229     #else
230     strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p);
231     #endif
232
233     OS_SendTCP(socket,snd_msg);
234
235
236     /* Sending subject */
237     memset(snd_msg,'\0',128);
238     snprintf(snd_msg, 127, SUBJECT, sms_msg->subject);
239     OS_SendTCP(socket,snd_msg);
240
241     OS_SendTCP(socket,ENDHEADER);
242
243
244     /* Sending body */
245     OS_SendTCP(socket, sms_msg->body);
246
247
248     /* Sending end of data \r\n.\r\n */
249     OS_SendTCP(socket,ENDDATA);
250     msg = OS_RecvTCP(socket, OS_SIZE_1024);
251     if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg))))
252     {
253         merror(END_DATA_ERROR);
254         if(msg)
255             free(msg);
256         close(socket);
257         return(OS_INVALID);
258     }
259     /* Checking msg in here, since it may be null */
260     if(msg)
261         free(msg);
262
263
264     /* quitting and closing socket */
265     OS_SendTCP(socket,QUITMSG);
266     msg = OS_RecvTCP(socket, OS_SIZE_1024);
267
268     if(msg)
269         free(msg);
270
271     memset(snd_msg,'\0',128);
272
273
274     /* Returning 0 (success) */
275     close(socket);
276
277     return(0);
278 }
279
280
281
282 /* OS_Sendmail v0.1: 2005/03/18
283  */
284 int OS_Sendmail(MailConfig *mail, struct tm *p)
285 {
286     int socket,i=0;
287     char *msg;
288     char snd_msg[128];
289
290     MailNode *mailmsg;
291
292    /* If there is no sms message, we attempt to get from the
293      * email list.
294      */
295     mailmsg = OS_PopLastMail();
296
297     if(mailmsg == NULL)
298     {
299         merror("%s: No email to be sent. Inconsistent state.",ARGV0);
300     }
301
302
303     /* Connecting to the smtp server */
304     socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver, 0);
305     if(socket < 0)
306     {
307         return(socket);
308     }
309
310
311     /* Receiving the banner */
312     msg = OS_RecvTCP(socket, OS_SIZE_1024);
313     if((msg == NULL)||(!OS_Match(VALIDBANNER, msg)))
314     {
315         merror(BANNER_ERROR);
316         if(msg)
317             free(msg);
318         close(socket);
319         return(OS_INVALID);
320     }
321     MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
322     free(msg);
323
324
325
326     /* Sending HELO message */
327     OS_SendTCP(socket,HELOMSG);
328     msg = OS_RecvTCP(socket, OS_SIZE_1024);
329     if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
330     {
331         if(msg)
332         {
333             /* Ugly fix warning :) */
334             /* In some cases (with virus scans in the middle)
335              * we may get two banners. Check for that in here.
336              */
337             if(OS_Match(VALIDBANNER, msg))
338             {
339                 free(msg);
340
341                 /* Try again */
342                 msg = OS_RecvTCP(socket, OS_SIZE_1024);
343                 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
344                 {
345                     merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null");
346                     if(msg)
347                         free(msg);
348                     close(socket);
349                     return(OS_INVALID);
350                 }
351             }
352             else
353             {
354                 merror("%s:%s",HELO_ERROR,msg);
355                 free(msg);
356                 close(socket);
357                 return(OS_INVALID);
358             }
359         }
360         else
361         {
362             merror("%s:%s",HELO_ERROR,"null");
363             close(socket);
364             return(OS_INVALID);
365         }
366     }
367
368     MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
369     free(msg);
370
371
372     /* Building "Mail from" msg */
373     memset(snd_msg,'\0',128);
374     snprintf(snd_msg,127, MAILFROM, mail->from);
375     OS_SendTCP(socket, snd_msg);
376     msg = OS_RecvTCP(socket, OS_SIZE_1024);
377     if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
378     {
379         merror(FROM_ERROR);
380         if(msg)
381             free(msg);
382         close(socket);
383         return(OS_INVALID);
384     }
385     MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
386     free(msg);
387
388
389     /* Building "RCPT TO" msg */
390     while(1)
391     {
392         if(mail->to[i] == NULL)
393         {
394             if(i == 0)
395             {
396                 merror(INTERNAL_ERROR);
397                 close(socket);
398                 return(OS_INVALID);
399             }
400             break;
401         }
402         memset(snd_msg,'\0',128);
403         snprintf(snd_msg,127,RCPTTO, mail->to[i++]);
404         OS_SendTCP(socket,snd_msg);
405         msg = OS_RecvTCP(socket, OS_SIZE_1024);
406         if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
407         {
408             merror(TO_ERROR, mail->to[i -1]);
409             if(msg)
410                 free(msg);
411             close(socket);
412             return(OS_INVALID);
413         }
414         MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
415         free(msg);
416     }
417
418
419     /* Additional RCPT to */
420     if(mail->gran_to)
421     {
422         i = 0;
423         while(mail->gran_to[i] != NULL)
424         {
425             if(mail->gran_set[i] != FULL_FORMAT)
426             {
427                 i++;
428                 continue;
429             }
430
431             memset(snd_msg,'\0',128);
432             snprintf(snd_msg,127,RCPTTO, mail->gran_to[i]);
433             OS_SendTCP(socket,snd_msg);
434             msg = OS_RecvTCP(socket, OS_SIZE_1024);
435             if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
436             {
437                 merror(TO_ERROR, mail->gran_to[i]);
438                 if(msg)
439                     free(msg);
440
441                 i++;
442                 continue;
443             }
444
445             MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
446             free(msg);
447             i++;
448             continue;
449         }
450     }
451
452
453     /* Sending the "DATA" msg */
454     OS_SendTCP(socket,DATAMSG);
455     msg = OS_RecvTCP(socket, OS_SIZE_1024);
456     if((msg == NULL)||(!OS_Match(VALIDDATA, msg)))
457     {
458         merror(DATA_ERROR);
459         if(msg)
460             free(msg);
461         close(socket);
462         return(OS_INVALID);
463     }
464     MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
465     free(msg);
466
467
468     /* Building "From" and "To" in the e-mail header */
469     memset(snd_msg,'\0',128);
470     snprintf(snd_msg,127, TO, mail->to[0]);
471     OS_SendTCP(socket, snd_msg);
472
473     memset(snd_msg,'\0',128);
474     snprintf(snd_msg,127, FROM, mail->from);
475     OS_SendTCP(socket, snd_msg);
476
477
478     /* Adding CCs */
479     if(mail->to[1])
480     {
481         i = 1;
482         while(1)
483         {
484             if(mail->to[i] == NULL)
485             {
486                 break;
487             }
488
489             memset(snd_msg,'\0',128);
490             snprintf(snd_msg,127, TO, mail->to[i]);
491             OS_SendTCP(socket,snd_msg);
492
493             i++;
494         }
495     }
496
497
498     /* More CCs - from granular options */
499     if(mail->gran_to)
500     {
501         i = 0;
502         while(mail->gran_to[i] != NULL)
503         {
504             if(mail->gran_set[i] != FULL_FORMAT)
505             {
506                 i++;
507                 continue;
508             }
509
510             memset(snd_msg,'\0',128);
511             snprintf(snd_msg,127, TO, mail->gran_to[i]);
512             OS_SendTCP(socket, snd_msg);
513             i++;
514             continue;
515         }
516     }
517
518
519     /* Sending date */
520     memset(snd_msg,'\0',128);
521
522
523     /* Solaris doesn't have the "%z", so we set the timezone to 0. */
524     #ifdef SOLARIS
525     strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p);
526     #else
527     strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p);
528     #endif
529
530     OS_SendTCP(socket,snd_msg);
531
532     if(mail->idsname)
533     {
534         /* Sending server name header */
535         memset(snd_msg,'\0',128);
536         snprintf(snd_msg,127, XHEADER, mail->idsname);
537         OS_SendTCP(socket, snd_msg);
538     }
539
540     /* Sending subject */
541     memset(snd_msg,'\0',128);
542
543
544     /* Checking if global subject is available */
545     if((_g_subject_level != 0) && (_g_subject[0] != '\0'))
546     {
547         snprintf(snd_msg, 127, SUBJECT, _g_subject);
548
549         /* Clearing global values */
550         _g_subject[0] = '\0';
551         _g_subject_level = 0;
552     }
553     else
554     {
555         snprintf(snd_msg, 127, SUBJECT, mailmsg->mail->subject);
556     }
557     OS_SendTCP(socket,snd_msg);
558
559     OS_SendTCP(socket,ENDHEADER);
560
561
562     /* Sending body */
563
564     /* Sending multiple emails together if we have to */
565     do
566     {
567         OS_SendTCP(socket, mailmsg->mail->body);
568         mailmsg = OS_PopLastMail();
569     }while(mailmsg);
570
571
572     /* Sending end of data \r\n.\r\n */
573     OS_SendTCP(socket,ENDDATA);
574     msg = OS_RecvTCP(socket, OS_SIZE_1024);
575     if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg))))
576     {
577         merror(END_DATA_ERROR);
578         if(msg)
579             free(msg);
580         close(socket);
581         return(OS_INVALID);
582     }
583     /* Checking msg in here, since it may be null */
584     if(msg)
585         free(msg);
586
587
588     /* quitting and closing socket */
589     OS_SendTCP(socket,QUITMSG);
590     msg = OS_RecvTCP(socket, OS_SIZE_1024);
591
592     if(msg)
593         free(msg);
594
595     memset(snd_msg,'\0',128);
596
597
598     /* Returning 0 (success) */
599     close(socket);
600
601     return(0);
602 }
603 /* EOF */