1 /* Copyright (C) 2009 Trend Micro Inc.
2 * All rights reserved.
3 *
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
7 * Foundation
8 */
9
10 /* Basic e-mailing operations */
11
12 #include "shared.h"
13 #include "os_net/os_net.h"
14
15 /* Return codes (from SMTP server) */
16 #define VALIDBANNER "220"
17 #define VALIDMAIL "250"
18 #define VALIDDATA "354"
19
20 /* Default values used to connect */
21 #define SMTP_DEFAULT_PORT "25"
22 #define HELOMSG "Helo notify.ossec.net\r\n"
23 #define MAILFROM "Mail From: <%s>\r\n"
24 #define RCPTTO "Rcpt To: <%s>\r\n"
25 #define DATAMSG "DATA\r\n"
26 #define FROM "From: OSSEC HIDS <%s>\r\n"
27 #define REPLYTO "Reply-To: OSSEC HIDS <%s>\r\n"
28 #define TO "To: <%s>\r\n"
29 #define CC "Cc: <%s>\r\n"
30 #define SUBJECT "Subject: %s\r\n"
31 #define ENDHEADER "\r\n"
32 #define ENDDATA "\r\n.\r\n"
33 #define QUITMSG "QUIT\r\n"
34 #define XHEADER "X-IDS-OSSEC: %s\r\n"
35
36 /* Error messages - Can be translated */
37 #define INTERNAL_ERROR "os_maild (1760): ERROR: Memory/configuration error"
38 #define BANNER_ERROR "os_sendmail(1762): WARN: Banner not received from server"
39 #define HELO_ERROR "os_sendmail(1763): WARN: Hello not accepted by server"
40 #define FROM_ERROR "os_sendmail(1764): WARN: Mail from not accepted by server"
41 #define TO_ERROR "os_sendmail(1765): WARN: RCPT TO not accepted by server - '%s'."
42 #define DATA_ERROR "os_sendmail(1766): WARN: DATA not accepted by server"
43 #define END_DATA_ERROR "os_sendmail(1767): WARN: End of DATA not accepted by server"
44
45 #define MAIL_DEBUG_FLAG 0
46 #define MAIL_DEBUG(x,y,z) if(MAIL_DEBUG_FLAG) merror(x,y,z)
47
48
OS_SendCustomEmail(char ** to,char * subject,char * smtpserver,char * from,char * replyto,char * idsname,char * fname,const struct tm * p)49 int OS_SendCustomEmail(char **to, char *subject, char *smtpserver, char *from, char *replyto, char *idsname, char *fname, const struct tm *p)
50 {
51 FILE *sendmail = NULL;
52 int socket = -1, i = 0;
53 char *msg;
54 char snd_msg[128];
55 char buffer[2049];
56
57 buffer[2048] = '\0';
58
59 if (smtpserver[0] == '/') {
60 sendmail = popen(smtpserver, "w");
61 if (!sendmail) {
62 return (OS_INVALID);
63 }
64 } else {
65 /* Connect to the SMTP server */
66 socket = OS_ConnectTCP(SMTP_DEFAULT_PORT, smtpserver);
67 if (socket < 0) {
68 return (socket);
69 }
70
71 /* Receive the banner */
72 msg = OS_RecvTCP(socket, OS_SIZE_1024);
73 if ((msg == NULL) || (!OS_Match(VALIDBANNER, msg))) {
74 merror(BANNER_ERROR);
75 if (msg) {
76 free(msg);
77 }
78 close(socket);
79 return (OS_INVALID);
80 }
81 MAIL_DEBUG("DEBUG: Received banner: '%s' %s", msg, "");
82 free(msg);
83
84 /* Send HELO message */
85 OS_SendTCP(socket, HELOMSG);
86 msg = OS_RecvTCP(socket, OS_SIZE_1024);
87 if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
88 if (msg) {
89 /* In some cases (with virus scans in the middle)
90 * we may get two banners. Check for that in here.
91 */
92 if (OS_Match(VALIDBANNER, msg)) {
93 free(msg);
94
95 /* Try again */
96 msg = OS_RecvTCP(socket, OS_SIZE_1024);
97 if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
98 merror("%s:%s", HELO_ERROR, msg != NULL ? msg : "null");
99 if (msg) {
100 free(msg);
101 }
102 close(socket);
103 return (OS_INVALID);
104 }
105 } else {
106 merror("%s:%s", HELO_ERROR, msg);
107 free(msg);
108 close(socket);
109 return (OS_INVALID);
110 }
111 } else {
112 merror("%s:%s", HELO_ERROR, "null");
113 close(socket);
114 return (OS_INVALID);
115 }
116 }
117
118 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", HELOMSG, msg);
119 free(msg);
120
121 /* Build "Mail from" msg */
122 memset(snd_msg, '\0', 128);
123 snprintf(snd_msg, 127, MAILFROM, from);
124 OS_SendTCP(socket, snd_msg);
125 msg = OS_RecvTCP(socket, OS_SIZE_1024);
126 if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
127 merror(FROM_ERROR);
128 if (msg) {
129 free(msg);
130 }
131 close(socket);
132 return (OS_INVALID);
133 }
134 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
135 free(msg);
136
137 /* Build "RCPT TO" msg */
138 while (to[i]) {
139 memset(snd_msg, '\0', 128);
140 snprintf(snd_msg, 127, RCPTTO, to[i]);
141 OS_SendTCP(socket, snd_msg);
142 msg = OS_RecvTCP(socket, OS_SIZE_1024);
143 if ((msg == NULL) || (!OS_Match(VALIDMAIL, msg))) {
144 merror(TO_ERROR, to[i]);
145 if (msg) {
146 free(msg);
147 }
148 close(socket);
149 return (OS_INVALID);
150 }
151 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", snd_msg, msg);
152 free(msg);
153
154 i++;
155 }
156
157 /* Send the "DATA" msg */
158 OS_SendTCP(socket, DATAMSG);
159 msg = OS_RecvTCP(socket, OS_SIZE_1024);
160 if ((msg == NULL) || (!OS_Match(VALIDDATA, msg))) {
161 merror(DATA_ERROR);
162 if (msg) {
163 free(msg);
164 }
165 close(socket);
166 return (OS_INVALID);
167 }
168 MAIL_DEBUG("DEBUG: Sent '%s', received: '%s'", DATAMSG, msg);
169 free(msg);
170 }
171
172 /* Build "From" and "To" in the e-mail header */
173 memset(snd_msg, '\0', 128);
174 snprintf(snd_msg, 127, TO, to[0]);
175
176 if (sendmail) {
177 fprintf(sendmail, "%s", snd_msg);
178 } else {
179 OS_SendTCP(socket, snd_msg);
180 }
181
182 memset(snd_msg, '\0', 128);
183 snprintf(snd_msg, 127, FROM, from);
184
185 if (sendmail) {
186 fprintf(sendmail, "%s", snd_msg);
187 } else {
188 OS_SendTCP(socket, snd_msg);
189 }
190
191 if (replyto) {
192 memset(snd_msg, '\0', 128);
193 snprintf(snd_msg, 127, REPLYTO, replyto);
194 if(sendmail) {
195 fprintf(sendmail, "%s", snd_msg);
196 } else {
197 OS_SendTCP(socket, snd_msg);
198 }
199 }
200
201 /* Add CCs */
202 if (to[1]) {
203 i = 1;
204 while (1) {
205 if (to[i] == NULL) {
206 break;
207 }
208
209 memset(snd_msg, '\0', 128);
210 snprintf(snd_msg, 127, TO, to[i]);
211
212 if (sendmail) {
213 fprintf(sendmail, "%s", snd_msg);
214 } else {
215 OS_SendTCP(socket, snd_msg);
216 }
217
218 i++;
219 }
220 }
221
222 /* Send date */
223 memset(snd_msg, '\0', 128);
224
225 /* Solaris doesn't have the "%z", so we set the timezone to 0 */
226 #ifdef SOLARIS
227 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T -0000\r\n", p);
228 #else
229 strftime(snd_msg, 127, "Date: %a, %d %b %Y %T %z\r\n", p);
230 #endif
231
232 if (sendmail) {
233 fprintf(sendmail, "%s", snd_msg);
234 } else {
235 OS_SendTCP(socket, snd_msg);
236 }
237
238 if (idsname) {
239 /* Send server name header */
240 memset(snd_msg, '\0', 128);
241 snprintf(snd_msg, 127, XHEADER, idsname);
242
243 if (sendmail) {
244 fprintf(sendmail, "%s", snd_msg);
245 } else {
246 OS_SendTCP(socket, snd_msg);
247 }
248 }
249
250 /* Send subject */
251 memset(snd_msg, '\0', 128);
252 snprintf(snd_msg, 127, SUBJECT, subject);
253
254 if (sendmail) {
255 fprintf(sendmail, "%s", snd_msg);
256 fprintf(sendmail, ENDHEADER);
257 } else {
258 OS_SendTCP(socket, snd_msg);
259 OS_SendTCP(socket, ENDHEADER);
260 }
261
262 /* Send body */
263 FILE *fp;
264 fp = fopen(fname, "r");
265 if(!fp) {
266 merror("%s: ERROR: Cannot open %s: %s", __local_name, fname, strerror(errno));
267 if(socket >= 0) {
268 close(socket);
269 }
270 if(sendmail) {
271 pclose(sendmail);
272 }
273 return(1);
274 }
275
276
277 struct stat sb;
278 int sr;
279 sr = stat(fname, &sb);
280 if(sr < 0) {
281 merror("Cannot stat %s: %s", fname, strerror(errno));
282 }
283 if(sb.st_size == 0) {
284 merror("Report is empty");
285 if(socket >= 0) {
286 close(socket);
287 }
288 if(sendmail) {
289 pclose(sendmail);
290 }
291 if(fp) {
292 fclose(fp);
293 }
294 return(0);
295 }
296 while (fgets(buffer, 2048, fp) != NULL) {
297 if (sendmail) {
298 fprintf(sendmail, "%s", buffer);
299 } else {
300 OS_SendTCP(socket, buffer);
301 }
302 }
303 fclose(fp);
304
305 if (sendmail) {
306 if (pclose(sendmail) == -1) {
307 merror(WAITPID_ERROR, ARGV0, errno, strerror(errno));
308 }
309 } else {
310 /* Send end of data \r\n.\r\n */
311 OS_SendTCP(socket, ENDDATA);
312 msg = OS_RecvTCP(socket, OS_SIZE_1024);
313
314 /* Check msg, since it may be null */
315 if (msg) {
316 free(msg);
317 }
318
319 /* Quit and close socket */
320 OS_SendTCP(socket, QUITMSG);
321 msg = OS_RecvTCP(socket, OS_SIZE_1024);
322
323 if (msg) {
324 free(msg);
325 }
326
327 close(socket);
328 }
329
330 memset_secure(snd_msg, '\0', 128);
331 return (0);
332 }
333
334