Imported Upstream version 2.7
[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 ENDDATA                 "\r\n.\r\n"
40 #define QUITMSG                 "QUIT\r\n"
41
42
43 /* Error messages - Can be translated */
44 #define INTERNAL_ERROR  "os_maild (1760): ERROR: Memory/configuration error"
45 #define BANNER_ERROR    "os_sendmail(1762): WARN: Banner not received from server"
46 #define HELO_ERROR          "os_sendmail(1763): WARN: Hello not accepted by server"
47 #define FROM_ERROR          "os_sendmail(1764): WARN: Mail from not accepted by server"
48 #define TO_ERROR            "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'."
49 #define DATA_ERROR          "os_sendmail(1766): WARN: DATA not accepted by server"
50 #define END_DATA_ERROR  "os_sendmail(1767): WARN: End of DATA not accepted by server"
51
52
53 #define MAIL_DEBUG_FLAG     0
54 #define MAIL_DEBUG(x,y,z) if(MAIL_DEBUG_FLAG) merror(x,y,z)
55
56
57 /* OS_Sendsms.
58  */
59 int OS_Sendsms(MailConfig *mail, struct tm *p, MailMsg *sms_msg)
60 {
61     int socket, i = 0, final_to_sz;
62     char *msg;
63     char snd_msg[128];
64     char final_to[512];
65
66
67     /* Connecting to the smtp server */ 
68     socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, mail->smtpserver, 0);
69     if(socket < 0)
70     {
71         return(socket);
72     }
73
74
75     /* Receiving the banner */
76     msg = OS_RecvTCP(socket, OS_SIZE_1024);
77     if((msg == NULL)||(!OS_Match(VALIDBANNER, msg)))
78     {
79         merror(BANNER_ERROR);
80         if(msg)
81             free(msg);
82         close(socket);
83         return(OS_INVALID);     
84     }
85     MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
86     free(msg);
87
88
89
90     /* Sending HELO message */
91     OS_SendTCP(socket,HELOMSG);
92     msg = OS_RecvTCP(socket, OS_SIZE_1024);
93     if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
94     {
95         if(msg)
96         {
97             /* Ugly fix warning :) */
98             /* In some cases (with virus scans in the middle)
99              * we may get two banners. Check for that in here.
100              */
101             if(OS_Match(VALIDBANNER, msg))
102             {
103                 free(msg);
104
105                 /* Try again */
106                 msg = OS_RecvTCP(socket, OS_SIZE_1024);
107                 if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
108                 {
109                     merror("%s:%s",HELO_ERROR,msg!= NULL?msg:"null");
110                     if(msg)
111                         free(msg);
112                     close(socket);
113                     return(OS_INVALID);
114                 }
115             }
116             else
117             {
118                 merror("%s:%s",HELO_ERROR,msg);
119                 free(msg);
120                 close(socket);
121                 return(OS_INVALID);
122             }
123         }
124         else
125         {
126             merror("%s:%s",HELO_ERROR,"null");
127             close(socket);
128             return(OS_INVALID);
129         }
130     }
131
132     MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
133     free(msg);  
134
135
136     /* Building "Mail from" msg */
137     memset(snd_msg,'\0',128);
138     snprintf(snd_msg,127, MAILFROM, mail->from);
139     OS_SendTCP(socket, snd_msg);
140     msg = OS_RecvTCP(socket, OS_SIZE_1024);
141     if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
142     {
143         merror(FROM_ERROR);
144         if(msg)
145             free(msg);
146         close(socket);
147         return(OS_INVALID);     
148     }
149     MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
150     free(msg);  
151
152
153     /* Additional RCPT to */
154     final_to[0] = '\0';
155     final_to_sz = sizeof(final_to) -2;
156
157     if(mail->gran_to)
158     {
159         i = 0;
160         while(mail->gran_to[i] != NULL)
161         {
162             if(mail->gran_set[i] != SMS_FORMAT)
163             {
164                 i++;
165                 continue;
166             }
167
168             memset(snd_msg,'\0',128);
169             snprintf(snd_msg,127, RCPTTO, mail->gran_to[i]);
170             OS_SendTCP(socket, snd_msg);
171             msg = OS_RecvTCP(socket, OS_SIZE_1024);
172             if((msg == NULL)||(!OS_Match(VALIDMAIL, msg)))
173             {
174                 merror(TO_ERROR, mail->gran_to[i]);
175                 if(msg)
176                     free(msg);
177                 close(socket);
178                 return(OS_INVALID);
179             }
180             MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
181             free(msg);
182
183
184             /* Creating header for to */
185             memset(snd_msg,'\0',128);
186             snprintf(snd_msg,127, TO, mail->gran_to[i]);
187             strncat(final_to, snd_msg, final_to_sz);
188             final_to_sz -= strlen(snd_msg) +2;
189
190             i++;
191             continue;
192         }
193     }
194
195
196     /* Sending the "DATA" msg */
197     OS_SendTCP(socket,DATAMSG);
198     msg = OS_RecvTCP(socket, OS_SIZE_1024);
199     if((msg == NULL)||(!OS_Match(VALIDDATA, msg)))
200     {
201         merror(DATA_ERROR);
202         if(msg)
203             free(msg);
204         close(socket);
205         return(OS_INVALID);     
206     }
207     MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
208     free(msg);
209
210
211     /* Building "From" and "To" in the e-mail header */
212     OS_SendTCP(socket, final_to);
213
214
215     memset(snd_msg,'\0',128);
216     snprintf(snd_msg,127, FROM, mail->from);
217     OS_SendTCP(socket, snd_msg);
218
219
220     /* Sending date */
221     memset(snd_msg,'\0',128);
222
223
224     /* Solaris doesn't have the "%z", so we set the timezone to 0. */
225     #ifdef SOLARIS
226     strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n",p);
227     #else
228     strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n",p);
229     #endif
230
231     OS_SendTCP(socket,snd_msg);
232
233
234     /* Sending subject */
235     memset(snd_msg,'\0',128);
236     snprintf(snd_msg, 127, SUBJECT, sms_msg->subject);
237     OS_SendTCP(socket,snd_msg);
238
239
240
241     /* Sending body */
242     OS_SendTCP(socket, sms_msg->body);
243
244
245     /* Sending end of data \r\n.\r\n */
246     OS_SendTCP(socket,ENDDATA); 
247     msg = OS_RecvTCP(socket, OS_SIZE_1024);
248     if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg))))
249     {
250         merror(END_DATA_ERROR);
251         if(msg)
252             free(msg);
253         close(socket);
254         return(OS_INVALID);     
255     }
256     /* Checking msg in here, since it may be null */
257     if(msg)
258         free(msg);
259
260
261     /* quitting and closing socket */
262     OS_SendTCP(socket,QUITMSG);
263     msg = OS_RecvTCP(socket, OS_SIZE_1024);
264
265     if(msg)
266         free(msg);
267
268     memset(snd_msg,'\0',128);   
269
270
271     /* Returning 0 (success) */
272     close(socket);
273
274     return(0);
275 }
276
277
278
279 /* OS_Sendmail v0.1: 2005/03/18
280  */
281 int OS_Sendmail(MailConfig *mail, struct tm *p)
282 {
283     int socket,i=0;
284     char *msg;
285     char snd_msg[128];
286     char additional_to[512];
287
288     MailNode *mailmsg;
289
290     additional_to[0] = '\0';
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
533     /* Sending subject */
534     memset(snd_msg,'\0',128);
535
536
537     /* Checking if global subject is available */
538     if((_g_subject_level != 0) && (_g_subject[0] != '\0'))
539     {
540         snprintf(snd_msg, 127, SUBJECT, _g_subject);    
541
542         /* Clearing global values */
543         _g_subject[0] = '\0';
544         _g_subject_level = 0;
545     }
546     else
547     {
548         snprintf(snd_msg, 127, SUBJECT, mailmsg->mail->subject);
549     }
550     OS_SendTCP(socket,snd_msg);
551
552
553
554     /* Sending body */
555
556     /* Sending multiple emails together if we have to */
557     do
558     {
559         OS_SendTCP(socket, mailmsg->mail->body);
560         mailmsg = OS_PopLastMail();
561     }while(mailmsg);
562
563
564     /* Sending end of data \r\n.\r\n */
565     OS_SendTCP(socket,ENDDATA); 
566     msg = OS_RecvTCP(socket, OS_SIZE_1024);
567     if(mail->strict_checking && ((msg == NULL)||(!OS_Match(VALIDMAIL, msg))))
568     {
569         merror(END_DATA_ERROR);
570         if(msg)
571             free(msg);
572         close(socket);
573         return(OS_INVALID);     
574     }
575     /* Checking msg in here, since it may be null */
576     if(msg)
577         free(msg);
578
579
580     /* quitting and closing socket */
581     OS_SendTCP(socket,QUITMSG);
582     msg = OS_RecvTCP(socket, OS_SIZE_1024);
583
584     if(msg)
585         free(msg);
586
587     memset(snd_msg,'\0',128);   
588
589
590     /* Returning 0 (success) */
591     close(socket);
592
593     return(0);
594 }
595 /* EOF */