PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/src/os_maild/sendmail.c

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