Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077
  1. /*
  2. * Copyright (c) 2009, Rambler media
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY Rambler media ''AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL Rambler BE LIABLE FOR ANY
  17. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  20. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "config.h"
  25. #include "main.h"
  26. #include "cfg_file.h"
  27. #include "util.h"
  28. #include "smtp.h"
  29. #include "smtp_proto.h"
  30. #include "map.h"
  31. #include "message.h"
  32. #include "settings.h"
  33. #include "evdns/evdns.h"
  34. /* Max line size as it is defined in rfc2822 */
  35. #define OUTBUFSIZ 1000
  36. /* Upstream timeouts */
  37. #define DEFAULT_UPSTREAM_ERROR_TIME 10
  38. #define DEFAULT_UPSTREAM_DEAD_TIME 300
  39. #define DEFAULT_UPSTREAM_MAXERRORS 10
  40. #define DEFAULT_REJECT_MESSAGE "450 4.5.0 Spam message rejected"
  41. static gboolean smtp_write_socket (void *arg);
  42. static sig_atomic_t wanna_die = 0;
  43. #ifndef HAVE_SA_SIGINFO
  44. static void
  45. sig_handler (int signo)
  46. #else
  47. static void
  48. sig_handler (int signo, siginfo_t *info, void *unused)
  49. #endif
  50. {
  51. struct timeval tv;
  52. switch (signo) {
  53. case SIGINT:
  54. case SIGTERM:
  55. if (!wanna_die) {
  56. wanna_die = 1;
  57. tv.tv_sec = 0;
  58. tv.tv_usec = 0;
  59. event_loopexit (&tv);
  60. #ifdef WITH_GPERF_TOOLS
  61. ProfilerStop ();
  62. #endif
  63. }
  64. break;
  65. }
  66. }
  67. static void
  68. free_smtp_session (gpointer arg)
  69. {
  70. struct smtp_session *session = arg;
  71. if (session) {
  72. if (session->task) {
  73. free_task (session->task, FALSE);
  74. }
  75. if (session->rcpt) {
  76. g_list_free (session->rcpt);
  77. }
  78. if (session->dispatcher) {
  79. rspamd_remove_dispatcher (session->dispatcher);
  80. }
  81. memory_pool_delete (session->pool);
  82. close (session->sock);
  83. if (session->temp_name != NULL) {
  84. unlink (session->temp_name);
  85. }
  86. if (session->temp_fd != -1) {
  87. close (session->temp_fd);
  88. }
  89. g_free (session);
  90. }
  91. }
  92. /*
  93. * Config reload is designed by sending sigusr to active workers and pending shutdown of them
  94. */
  95. static void
  96. sigusr_handler (int fd, short what, void *arg)
  97. {
  98. struct rspamd_worker *worker = (struct rspamd_worker *)arg;
  99. /* Do not accept new connections, preparing to end worker's process */
  100. struct timeval tv;
  101. if (! wanna_die) {
  102. tv.tv_sec = SOFT_SHUTDOWN_TIME;
  103. tv.tv_usec = 0;
  104. event_del (&worker->sig_ev);
  105. event_del (&worker->bind_ev);
  106. do_reopen_log = 1;
  107. msg_info ("worker's shutdown is pending in %d sec", SOFT_SHUTDOWN_TIME);
  108. event_loopexit (&tv);
  109. }
  110. return;
  111. }
  112. static gboolean
  113. create_smtp_upstream_connection (struct smtp_session *session)
  114. {
  115. struct smtp_upstream *selected;
  116. struct sockaddr_un *un;
  117. /* Try to select upstream */
  118. selected = (struct smtp_upstream *)get_upstream_round_robin (session->ctx->upstreams,
  119. session->ctx->upstream_num, sizeof (struct smtp_upstream),
  120. session->session_time, DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS);
  121. if (selected == NULL) {
  122. msg_err ("no upstreams suitable found");
  123. return FALSE;
  124. }
  125. session->upstream = selected;
  126. /* Now try to create socket */
  127. if (selected->is_unix) {
  128. un = alloca (sizeof (struct sockaddr_un));
  129. session->upstream_sock = make_unix_socket (selected->name, un, FALSE);
  130. }
  131. else {
  132. session->upstream_sock = make_tcp_socket (&selected->addr, selected->port, FALSE, TRUE);
  133. }
  134. if (session->upstream_sock == -1) {
  135. msg_err ("cannot make a connection to %s", selected->name);
  136. upstream_fail (&selected->up, session->session_time);
  137. return FALSE;
  138. }
  139. /* Create a dispatcher for upstream connection */
  140. session->upstream_dispatcher = rspamd_create_dispatcher (session->upstream_sock, BUFFER_LINE,
  141. smtp_upstream_read_socket, smtp_upstream_write_socket, smtp_upstream_err_socket,
  142. &session->ctx->smtp_timeout, session);
  143. session->state = SMTP_STATE_WAIT_UPSTREAM;
  144. session->upstream_state = SMTP_STATE_GREETING;
  145. register_async_event (session->s, (event_finalizer_t)smtp_upstream_finalize_connection, session, FALSE);
  146. return TRUE;
  147. }
  148. static gboolean
  149. read_smtp_command (struct smtp_session *session, f_str_t *line)
  150. {
  151. /* XXX: write dialog implementation */
  152. struct smtp_command *cmd;
  153. char outbuf[BUFSIZ];
  154. int r;
  155. if (! parse_smtp_command (session, line, &cmd)) {
  156. session->error = SMTP_ERROR_BAD_COMMAND;
  157. session->errors ++;
  158. return FALSE;
  159. }
  160. switch (cmd->command) {
  161. case SMTP_COMMAND_HELO:
  162. case SMTP_COMMAND_EHLO:
  163. if (session->state == SMTP_STATE_GREETING || session->state == SMTP_STATE_HELO) {
  164. if (parse_smtp_helo (session, cmd)) {
  165. session->state = SMTP_STATE_FROM;
  166. }
  167. else {
  168. session->errors ++;
  169. }
  170. return TRUE;
  171. }
  172. else {
  173. goto improper_sequence;
  174. }
  175. break;
  176. case SMTP_COMMAND_QUIT:
  177. session->state = SMTP_STATE_END;
  178. break;
  179. case SMTP_COMMAND_NOOP:
  180. break;
  181. case SMTP_COMMAND_MAIL:
  182. if (((session->state == SMTP_STATE_GREETING || session->state == SMTP_STATE_HELO) && !session->ctx->helo_required)
  183. || session->state == SMTP_STATE_FROM) {
  184. if (parse_smtp_from (session, cmd)) {
  185. session->state = SMTP_STATE_RCPT;
  186. }
  187. else {
  188. session->errors ++;
  189. return FALSE;
  190. }
  191. }
  192. else {
  193. goto improper_sequence;
  194. }
  195. break;
  196. case SMTP_COMMAND_RCPT:
  197. if (session->state == SMTP_STATE_RCPT) {
  198. if (parse_smtp_rcpt (session, cmd)) {
  199. /* Make upstream connection */
  200. if (session->upstream == NULL) {
  201. if (!create_smtp_upstream_connection (session)) {
  202. session->error = SMTP_ERROR_UPSTREAM;
  203. session->state = SMTP_STATE_CRITICAL_ERROR;
  204. return FALSE;
  205. }
  206. }
  207. else {
  208. /* Send next rcpt to upstream */
  209. session->state = SMTP_STATE_WAIT_UPSTREAM;
  210. session->upstream_state = SMTP_STATE_BEFORE_DATA;
  211. rspamd_dispatcher_restore (session->upstream_dispatcher);
  212. r = snprintf (outbuf, sizeof (outbuf), "RCPT TO: ");
  213. r += smtp_upstream_write_list (session->rcpt->data, outbuf + r, sizeof (outbuf) - r);
  214. session->cur_rcpt = NULL;
  215. return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE);
  216. }
  217. session->state = SMTP_STATE_WAIT_UPSTREAM;
  218. return TRUE;
  219. }
  220. else {
  221. session->errors ++;
  222. return FALSE;
  223. }
  224. }
  225. else {
  226. goto improper_sequence;
  227. }
  228. break;
  229. case SMTP_COMMAND_RSET:
  230. session->from = NULL;
  231. if (session->rcpt) {
  232. g_list_free (session->rcpt);
  233. }
  234. if (session->upstream) {
  235. remove_normal_event (session->s, smtp_upstream_finalize_connection, session);
  236. session->upstream = NULL;
  237. }
  238. session->state = SMTP_STATE_GREETING;
  239. break;
  240. case SMTP_COMMAND_DATA:
  241. if (session->state == SMTP_STATE_RCPT) {
  242. if (session->rcpt == NULL) {
  243. session->error = SMTP_ERROR_RECIPIENTS;
  244. session->errors ++;
  245. return FALSE;
  246. }
  247. if (session->upstream == NULL) {
  248. session->error = SMTP_ERROR_UPSTREAM;
  249. session->state = SMTP_STATE_CRITICAL_ERROR;
  250. return FALSE;
  251. }
  252. else {
  253. session->upstream_state = SMTP_STATE_DATA;
  254. rspamd_dispatcher_restore (session->upstream_dispatcher);
  255. r = snprintf (outbuf, sizeof (outbuf), "DATA" CRLF);
  256. session->state = SMTP_STATE_WAIT_UPSTREAM;
  257. session->error = SMTP_ERROR_DATA_OK;
  258. return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE);
  259. }
  260. }
  261. else {
  262. goto improper_sequence;
  263. }
  264. case SMTP_COMMAND_VRFY:
  265. case SMTP_COMMAND_EXPN:
  266. case SMTP_COMMAND_HELP:
  267. session->error = SMTP_ERROR_UNIMPLIMENTED;
  268. return FALSE;
  269. }
  270. session->error = SMTP_ERROR_OK;
  271. return TRUE;
  272. improper_sequence:
  273. session->errors ++;
  274. session->error = SMTP_ERROR_SEQUENCE;
  275. return FALSE;
  276. }
  277. static gboolean
  278. smtp_send_upstream_message (struct smtp_session *session)
  279. {
  280. rspamd_dispatcher_pause (session->dispatcher);
  281. rspamd_dispatcher_restore (session->upstream_dispatcher);
  282. session->upstream_state = SMTP_STATE_IN_SENDFILE;
  283. session->state = SMTP_STATE_WAIT_UPSTREAM;
  284. if (! rspamd_dispatcher_sendfile (session->upstream_dispatcher, session->temp_fd, session->temp_size)) {
  285. goto err;
  286. }
  287. return TRUE;
  288. err:
  289. session->error = SMTP_ERROR_FILE;
  290. session->state = SMTP_STATE_CRITICAL_ERROR;
  291. rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE);
  292. destroy_session (session->s);
  293. return FALSE;
  294. }
  295. static gboolean
  296. process_smtp_data (struct smtp_session *session)
  297. {
  298. struct stat st;
  299. int r;
  300. GList *cur, *t;
  301. f_str_t *f;
  302. char *s;
  303. if (fstat (session->temp_fd, &st) == -1) {
  304. goto err;
  305. }
  306. /* Now mmap temp file if it is small enough */
  307. session->temp_size = st.st_size;
  308. if (session->ctx->max_size == 0 || st.st_size < session->ctx->max_size) {
  309. session->task = construct_task (session->worker);
  310. session->task->fin_callback = smtp_write_socket;
  311. session->task->fin_arg = session;
  312. session->task->msg = memory_pool_alloc (session->pool, sizeof (f_str_t));
  313. #ifdef HAVE_MMAP_NOCORE
  314. if ((session->task->msg->begin = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED | MAP_NOCORE, session->temp_fd, 0)) == MAP_FAILED) {
  315. #else
  316. if ((session->task->msg->begin = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, session->temp_fd, 0)) == MAP_FAILED) {
  317. #endif
  318. goto err;
  319. }
  320. session->task->msg->len = st.st_size;
  321. session->task->helo = session->helo;
  322. /* Save MAIL FROM */
  323. cur = session->from;
  324. if (cur) {
  325. f = cur->data;
  326. s = memory_pool_alloc (session->pool, f->len + 1);
  327. g_strlcpy (s, f->begin, f->len + 1);
  328. session->task->from = s;
  329. }
  330. /* Save recipients */
  331. t = session->rcpt;
  332. while (t) {
  333. cur = t->data;
  334. if (cur) {
  335. f = cur->data;
  336. s = memory_pool_alloc (session->pool, f->len + 1);
  337. g_strlcpy (s, f->begin, f->len + 1);
  338. session->task->rcpt = g_list_prepend (session->task->rcpt, s);
  339. }
  340. t = g_list_next (t);
  341. }
  342. memcpy (&session->task->from_addr, &session->client_addr, sizeof (struct in_addr));
  343. session->task->cmd = CMD_CHECK;
  344. if (process_message (session->task) == -1) {
  345. msg_err ("cannot process message");
  346. munmap (session->task->msg->begin, st.st_size);
  347. goto err;
  348. }
  349. r = process_filters (session->task);
  350. if (r == -1) {
  351. munmap (session->task->msg->begin, st.st_size);
  352. msg_err ("cannot process filters");
  353. goto err;
  354. }
  355. else if (r == 0) {
  356. session->state = SMTP_STATE_END;
  357. rspamd_dispatcher_pause (session->dispatcher);
  358. }
  359. else {
  360. process_statfiles (session->task);
  361. session->state = SMTP_STATE_END;
  362. return smtp_write_socket (session);
  363. }
  364. }
  365. else {
  366. return smtp_send_upstream_message (session);
  367. }
  368. return TRUE;
  369. err:
  370. session->error = SMTP_ERROR_FILE;
  371. session->state = SMTP_STATE_CRITICAL_ERROR;
  372. rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE);
  373. destroy_session (session->s);
  374. return FALSE;
  375. }
  376. /*
  377. * Callback that is called when there is data to read in buffer
  378. */
  379. static gboolean
  380. smtp_read_socket (f_str_t * in, void *arg)
  381. {
  382. struct smtp_session *session = arg;
  383. switch (session->state) {
  384. case SMTP_STATE_RESOLVE_REVERSE:
  385. case SMTP_STATE_RESOLVE_NORMAL:
  386. case SMTP_STATE_DELAY:
  387. session->error = make_smtp_error (session, 550, "%s Improper use of SMTP command pipelining", "5.5.0");
  388. session->state = SMTP_STATE_ERROR;
  389. break;
  390. case SMTP_STATE_GREETING:
  391. case SMTP_STATE_HELO:
  392. case SMTP_STATE_FROM:
  393. case SMTP_STATE_RCPT:
  394. case SMTP_STATE_DATA:
  395. read_smtp_command (session, in);
  396. if (session->state != SMTP_STATE_WAIT_UPSTREAM) {
  397. if (session->errors > session->ctx->max_errors) {
  398. session->error = SMTP_ERROR_LIMIT;
  399. session->state = SMTP_STATE_CRITICAL_ERROR;
  400. rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE);
  401. destroy_session (session->s);
  402. return FALSE;
  403. }
  404. smtp_write_socket (session);
  405. }
  406. break;
  407. case SMTP_STATE_AFTER_DATA:
  408. if (in->len == 0) {
  409. return TRUE;
  410. }
  411. if (in->len == 3 && memcmp (in->begin, DATA_END_TRAILER, in->len) == 0) {
  412. return process_smtp_data (session);
  413. }
  414. if (write (session->temp_fd, in->begin, in->len) != in->len) {
  415. msg_err ("cannot write to temp file: %s", strerror (errno));
  416. session->error = SMTP_ERROR_FILE;
  417. session->state = SMTP_STATE_CRITICAL_ERROR;
  418. rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE);
  419. destroy_session (session->s);
  420. return FALSE;
  421. }
  422. break;
  423. case SMTP_STATE_WAIT_UPSTREAM:
  424. rspamd_dispatcher_pause (session->dispatcher);
  425. break;
  426. default:
  427. session->error = make_smtp_error (session, 550, "%s Internal error", "5.5.0");
  428. session->state = SMTP_STATE_ERROR;
  429. break;
  430. }
  431. if (session->state == SMTP_STATE_END) {
  432. destroy_session (session->s);
  433. return FALSE;
  434. }
  435. else if (session->state == SMTP_STATE_WAIT_UPSTREAM) {
  436. rspamd_dispatcher_pause (session->dispatcher);
  437. }
  438. return TRUE;
  439. }
  440. /*
  441. * Callback for socket writing
  442. */
  443. static gboolean
  444. smtp_write_socket (void *arg)
  445. {
  446. struct smtp_session *session = arg;
  447. double ms = 0, rs = 0;
  448. int r;
  449. struct metric_result *metric_res;
  450. struct metric *m;
  451. char logbuf[1024];
  452. gboolean is_spam = FALSE;
  453. GList *symbols, *cur;
  454. if (session->state == SMTP_STATE_CRITICAL_ERROR) {
  455. if (session->error != NULL) {
  456. rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE);
  457. }
  458. destroy_session (session->s);
  459. return FALSE;
  460. }
  461. else if (session->state == SMTP_STATE_END) {
  462. if (session->task != NULL) {
  463. /* Check metric */
  464. m = g_hash_table_lookup (session->cfg->metrics, session->ctx->metric);
  465. metric_res = g_hash_table_lookup (session->task->results, session->ctx->metric);
  466. if (m != NULL && metric_res != NULL) {
  467. if (!check_metric_settings (session->task, m, &ms, &rs)) {
  468. ms = m->required_score;
  469. rs = m->reject_score;
  470. }
  471. if (metric_res->score >= ms) {
  472. is_spam = TRUE;
  473. }
  474. r = snprintf (logbuf, sizeof (logbuf), "msg ok, id: <%s>, ", session->task->message_id);
  475. r += snprintf (logbuf + r, sizeof (logbuf) - r, "(%s: %s: [%.2f/%.2f/%.2f] [",
  476. (char *)m->name, is_spam ? "T" : "F", metric_res->score, ms, rs);
  477. symbols = g_hash_table_get_keys (metric_res->symbols);
  478. cur = symbols;
  479. while (cur) {
  480. if (g_list_next (cur) != NULL) {
  481. r += snprintf (logbuf + r, sizeof (logbuf) - r, "%s,", (char *)cur->data);
  482. }
  483. else {
  484. r += snprintf (logbuf + r, sizeof (logbuf) - r, "%s", (char *)cur->data);
  485. }
  486. cur = g_list_next (cur);
  487. }
  488. g_list_free (symbols);
  489. #ifdef HAVE_CLOCK_GETTIME
  490. r += snprintf (logbuf + r, sizeof (logbuf) - r, "]), len: %ld, time: %sms",
  491. (long int)session->task->msg->len, calculate_check_time (&session->task->ts, session->cfg->clock_res));
  492. #else
  493. r += snprintf (logbuf + r, sizeof (logbuf) - r, "]), len: %ld, time: %sms",
  494. (long int)session->task->msg->len, calculate_check_time (&session->task->tv, session->cfg->clock_res));
  495. #endif
  496. msg_info ("%s", logbuf);
  497. if (is_spam) {
  498. rspamd_dispatcher_write (session->dispatcher, session->ctx->reject_message, 0, FALSE, TRUE);
  499. rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE);
  500. destroy_session (session->s);
  501. return FALSE;
  502. }
  503. }
  504. return smtp_send_upstream_message (session);
  505. }
  506. else {
  507. if (session->error != NULL) {
  508. rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE);
  509. }
  510. }
  511. }
  512. else {
  513. if (session->error != NULL) {
  514. rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE);
  515. }
  516. }
  517. return TRUE;
  518. }
  519. /*
  520. * Called if something goes wrong
  521. */
  522. static void
  523. smtp_err_socket (GError * err, void *arg)
  524. {
  525. struct smtp_session *session = arg;
  526. msg_info ("abnormally closing connection, error: %s", err->message);
  527. /* Free buffers */
  528. destroy_session (session->s);
  529. }
  530. /*
  531. * Write greeting to client
  532. */
  533. static void
  534. write_smtp_greeting (struct smtp_session *session)
  535. {
  536. if (session->ctx->smtp_banner) {
  537. rspamd_dispatcher_write (session->dispatcher, session->ctx->smtp_banner, 0, FALSE, TRUE);
  538. }
  539. }
  540. /*
  541. * Return from a delay
  542. */
  543. static void
  544. smtp_delay_handler (int fd, short what, void *arg)
  545. {
  546. struct smtp_session *session = arg;
  547. if (session->state == SMTP_STATE_DELAY) {
  548. session->state = SMTP_STATE_GREETING;
  549. write_smtp_greeting (session);
  550. }
  551. else {
  552. session->state = SMTP_STATE_CRITICAL_ERROR;
  553. smtp_write_socket (session);
  554. }
  555. }
  556. /*
  557. * Make delay for a client
  558. */
  559. static void
  560. smtp_make_delay (struct smtp_session *session)
  561. {
  562. struct event *tev;
  563. struct timeval *tv;
  564. gint32 jitter;
  565. if (session->ctx->smtp_delay != 0 && session->state == SMTP_STATE_DELAY) {
  566. tev = memory_pool_alloc (session->pool, sizeof (struct event));
  567. tv = memory_pool_alloc (session->pool, sizeof (struct timeval));
  568. if (session->ctx->delay_jitter != 0) {
  569. jitter = g_random_int_range (0, session->ctx->delay_jitter);
  570. tv->tv_sec = (session->ctx->smtp_delay + jitter) / 1000;
  571. tv->tv_usec = session->ctx->smtp_delay + jitter - tv->tv_sec * 1000;
  572. }
  573. else {
  574. tv->tv_sec = session->ctx->smtp_delay / 1000;
  575. tv->tv_usec = session->ctx->smtp_delay - tv->tv_sec * 1000;
  576. }
  577. evtimer_set (tev, smtp_delay_handler, session);
  578. evtimer_add (tev, tv);
  579. }
  580. else if (session->state == SMTP_STATE_DELAY) {
  581. session->state = SMTP_STATE_GREETING;
  582. write_smtp_greeting (session);
  583. }
  584. }
  585. /*
  586. * Handle DNS replies
  587. */
  588. static void
  589. smtp_dns_cb (int result, char type, int count, int ttl, void *addresses, void *arg)
  590. {
  591. struct smtp_session *session = arg;
  592. int i, res = 0;
  593. switch (session->state) {
  594. case SMTP_STATE_RESOLVE_REVERSE:
  595. /* Parse reverse reply and start resolve of this ip */
  596. if (result != DNS_ERR_NONE || type != DNS_PTR) {
  597. debug_ip (session->client_addr.s_addr, "DNS error: %s", evdns_err_to_string (result));
  598. if (result == DNS_ERR_NOTEXIST) {
  599. session->hostname = memory_pool_strdup (session->pool, "unknown");
  600. }
  601. else {
  602. session->hostname = memory_pool_strdup (session->pool, "tempfail");
  603. }
  604. session->state = SMTP_STATE_DELAY;
  605. smtp_make_delay (session);
  606. }
  607. else {
  608. if (addresses) {
  609. session->hostname = memory_pool_strdup (session->pool, * ((const char**)addresses));
  610. session->state = SMTP_STATE_RESOLVE_NORMAL;
  611. evdns_resolve_ipv4 (session->hostname, DNS_QUERY_NO_SEARCH, smtp_dns_cb, (void *)session);
  612. }
  613. }
  614. break;
  615. case SMTP_STATE_RESOLVE_NORMAL:
  616. if (result != DNS_ERR_NONE || type != DNS_IPv4_A) {
  617. debug_ip (session->client_addr.s_addr, "DNS error: %s", evdns_err_to_string (result));
  618. if (result == DNS_ERR_NOTEXIST) {
  619. session->hostname = memory_pool_strdup (session->pool, "unknown");
  620. }
  621. else {
  622. session->hostname = memory_pool_strdup (session->pool, "tempfail");
  623. }
  624. session->state = SMTP_STATE_DELAY;
  625. smtp_make_delay (session);
  626. }
  627. else {
  628. res = 0;
  629. for (i = 0; i < count; i++) {
  630. if (session->client_addr.s_addr == ((in_addr_t *)addresses)[i]) {
  631. res = 1;
  632. session->resolved = TRUE;
  633. break;
  634. }
  635. }
  636. if (res == 0) {
  637. msg_info ("cannot find address for hostname: %s, ip: %s", session->hostname, inet_ntoa (session->client_addr));
  638. session->hostname = memory_pool_strdup (session->pool, "unknown");
  639. }
  640. session->state = SMTP_STATE_DELAY;
  641. smtp_make_delay (session);
  642. }
  643. break;
  644. case SMTP_STATE_ERROR:
  645. session->state = SMTP_STATE_WRITE_ERROR;
  646. smtp_write_socket (session);
  647. break;
  648. default:
  649. /*
  650. * This callback is called on unknown state, usually this indicates
  651. * an error (invalid pipelining)
  652. */
  653. break;
  654. }
  655. }
  656. /*
  657. * Accept new connection and construct task
  658. */
  659. static void
  660. accept_socket (int fd, short what, void *arg)
  661. {
  662. struct rspamd_worker *worker = (struct rspamd_worker *)arg;
  663. union sa_union su;
  664. struct smtp_session *session;
  665. socklen_t addrlen = sizeof (su.ss);
  666. int nfd;
  667. if ((nfd = accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) {
  668. msg_warn ("accept failed: %s", strerror (errno));
  669. return;
  670. }
  671. /* Check for EAGAIN */
  672. if (nfd == 0) {
  673. return;
  674. }
  675. session = g_malloc0 (sizeof (struct smtp_session));
  676. session->pool = memory_pool_new (memory_pool_get_size ());
  677. if (su.ss.ss_family == AF_UNIX) {
  678. msg_info ("accepted connection from unix socket");
  679. session->client_addr.s_addr = INADDR_NONE;
  680. }
  681. else if (su.ss.ss_family == AF_INET) {
  682. msg_info ("accepted connection from %s port %d", inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port));
  683. memcpy (&session->client_addr, &su.s4.sin_addr, sizeof (struct in_addr));
  684. }
  685. session->sock = nfd;
  686. session->temp_fd = -1;
  687. session->worker = worker;
  688. session->ctx = worker->ctx;
  689. session->cfg = worker->srv->cfg;
  690. session->session_time = time (NULL);
  691. worker->srv->stat->connections_count++;
  692. /* Resolve client's addr */
  693. session->state = SMTP_STATE_RESOLVE_REVERSE;
  694. if (evdns_resolve_reverse (&session->client_addr, DNS_QUERY_NO_SEARCH, smtp_dns_cb, session) != 0) {
  695. msg_err ("cannot resolve %s", inet_ntoa (session->client_addr));
  696. g_free (session);
  697. close (nfd);
  698. }
  699. /* Set up dispatcher */
  700. session->dispatcher = rspamd_create_dispatcher (nfd, BUFFER_LINE,
  701. smtp_read_socket, smtp_write_socket, smtp_err_socket, &session->ctx->smtp_timeout, session);
  702. session->dispatcher->peer_addr = session->client_addr.s_addr;
  703. /* Set up async session */
  704. session->s = new_async_session (session->pool, free_smtp_session, session);
  705. }
  706. static void
  707. parse_smtp_banner (struct smtp_worker_ctx *ctx, const char *line)
  708. {
  709. int hostmax, banner_len = sizeof ("220 ") - 1;
  710. char *p, *t, *hostbuf = NULL;
  711. gboolean has_crlf = FALSE;
  712. p = (char *)line;
  713. while (*p) {
  714. if (*p == '%') {
  715. p ++;
  716. switch (*p) {
  717. case 'n':
  718. /* Assume %n as CRLF */
  719. banner_len += sizeof (CRLF) - 1 + sizeof ("220 -") - 1;
  720. has_crlf = TRUE;
  721. break;
  722. case 'h':
  723. hostmax = sysconf (_SC_HOST_NAME_MAX) + 1;
  724. hostbuf = alloca (hostmax);
  725. gethostname (hostbuf, hostmax);
  726. hostbuf[hostmax - 1] = '\0';
  727. banner_len += strlen (hostbuf);
  728. break;
  729. case '%':
  730. banner_len += 1;
  731. break;
  732. default:
  733. banner_len += 2;
  734. break;
  735. }
  736. }
  737. else {
  738. banner_len ++;
  739. }
  740. p ++;
  741. }
  742. if (has_crlf) {
  743. banner_len += sizeof (CRLF "220 " CRLF);
  744. }
  745. else {
  746. banner_len += sizeof (CRLF);
  747. }
  748. ctx->smtp_banner = memory_pool_alloc (ctx->pool, banner_len + 1);
  749. t = ctx->smtp_banner;
  750. p = (char *)line;
  751. if (has_crlf) {
  752. t = g_stpcpy (t, "220-");
  753. }
  754. else {
  755. t = g_stpcpy (t, "220 ");
  756. }
  757. while (*p) {
  758. if (*p == '%') {
  759. p ++;
  760. switch (*p) {
  761. case 'n':
  762. /* Assume %n as CRLF */
  763. *t++ = CR; *t++ = LF;
  764. t = g_stpcpy (t, "220-");
  765. p ++;
  766. break;
  767. case 'h':
  768. t = g_stpcpy (t, hostbuf);
  769. p ++;
  770. break;
  771. case '%':
  772. *t++ = '%';
  773. p ++;
  774. break;
  775. default:
  776. /* Copy all %<char> to dest */
  777. *t++ = *(p - 1); *t++ = *p;
  778. break;
  779. }
  780. }
  781. else {
  782. *t ++ = *p ++;
  783. }
  784. }
  785. if (has_crlf) {
  786. t = g_stpcpy (t, CRLF "220 " CRLF);
  787. }
  788. else {
  789. t = g_stpcpy (t, CRLF);
  790. }
  791. }
  792. static gboolean
  793. parse_upstreams_line (struct smtp_worker_ctx *ctx, const char *line)
  794. {
  795. char **strv, *p, *t, *tt, *err_str;
  796. uint32_t num, i;
  797. struct smtp_upstream *cur;
  798. char resolved_path[PATH_MAX];
  799. strv = g_strsplit_set (line, ",; ", -1);
  800. num = g_strv_length (strv);
  801. if (num >= MAX_UPSTREAM) {
  802. msg_err ("cannot define %d upstreams %d is max", num, MAX_UPSTREAM);
  803. return FALSE;
  804. }
  805. for (i = 0; i < num; i ++) {
  806. p = strv[i];
  807. cur = &ctx->upstreams[ctx->upstream_num];
  808. if ((t = strrchr (p, ':')) != NULL && (tt = strchr (p, ':')) != t) {
  809. /* Assume that after last `:' we have weigth */
  810. *t = '\0';
  811. t ++;
  812. errno = 0;
  813. cur->up.weight = strtoul (t, &err_str, 10);
  814. if (errno != 0 || (err_str && *err_str != '\0')) {
  815. msg_err ("cannot convert weight: %s, %s", t, strerror (errno));
  816. g_strfreev (strv);
  817. return FALSE;
  818. }
  819. }
  820. if (*p == '/') {
  821. cur->is_unix = TRUE;
  822. if (realpath (p, resolved_path) == NULL) {
  823. msg_err ("cannot resolve path: %s", resolved_path);
  824. g_strfreev (strv);
  825. return FALSE;
  826. }
  827. cur->name = memory_pool_strdup (ctx->pool, resolved_path);
  828. ctx->upstream_num ++;
  829. }
  830. else {
  831. if (! parse_host_port (p, &cur->addr, &cur->port)) {
  832. g_strfreev (strv);
  833. return FALSE;
  834. }
  835. cur->name = memory_pool_strdup (ctx->pool, p);
  836. ctx->upstream_num ++;
  837. }
  838. }
  839. g_strfreev (strv);
  840. return TRUE;
  841. }
  842. static void
  843. make_capabilities (struct smtp_worker_ctx *ctx, const char *line)
  844. {
  845. char **strv, *p, *result, *hostbuf;
  846. uint32_t num, i, len, hostmax;
  847. strv = g_strsplit_set (line, ",;", -1);
  848. num = g_strv_length (strv);
  849. hostmax = sysconf (_SC_HOST_NAME_MAX) + 1;
  850. hostbuf = alloca (hostmax);
  851. gethostname (hostbuf, hostmax);
  852. hostbuf[hostmax - 1] = '\0';
  853. len = sizeof ("250-") + strlen (hostbuf) + sizeof (CRLF) - 1;
  854. for (i = 0; i < num; i ++) {
  855. p = strv[i];
  856. len += sizeof ("250-") + sizeof (CRLF) + strlen (p) - 2;
  857. }
  858. result = memory_pool_alloc (ctx->pool, len);
  859. ctx->smtp_capabilities = result;
  860. p = result;
  861. if (num == 0) {
  862. p += snprintf (p, len - (p - result), "250 %s" CRLF, hostbuf);
  863. }
  864. else {
  865. p += snprintf (p, len - (p - result), "250-%s" CRLF, hostbuf);
  866. for (i = 0; i < num; i ++) {
  867. if (i != num - 1) {
  868. p += snprintf (p, len - (p - result), "250-%s" CRLF, strv[i]);
  869. }
  870. else {
  871. p += snprintf (p, len - (p - result), "250 %s" CRLF, strv[i]);
  872. }
  873. }
  874. }
  875. g_strfreev (strv);
  876. }
  877. static gboolean
  878. config_smtp_worker (struct rspamd_worker *worker)
  879. {
  880. struct smtp_worker_ctx *ctx;
  881. char *value;
  882. uint32_t timeout;
  883. ctx = g_malloc0 (sizeof (struct smtp_worker_ctx));
  884. ctx->pool = memory_pool_new (memory_pool_get_size ());
  885. /* Set default values */
  886. ctx->smtp_timeout.tv_sec = 300;
  887. ctx->smtp_timeout.tv_usec = 0;
  888. ctx->smtp_delay = 0;
  889. ctx->smtp_banner = "220 ESMTP Ready." CRLF;
  890. if ((value = g_hash_table_lookup (worker->cf->params, "upstreams")) != NULL) {
  891. if (!parse_upstreams_line (ctx, value)) {
  892. return FALSE;
  893. }
  894. }
  895. else {
  896. msg_err ("no upstreams defined, don't know what to do");
  897. return FALSE;
  898. }
  899. if ((value = g_hash_table_lookup (worker->cf->params, "smtp_banner")) != NULL) {
  900. parse_smtp_banner (ctx, value);
  901. }
  902. if ((value = g_hash_table_lookup (worker->cf->params, "smtp_timeout")) != NULL) {
  903. errno = 0;
  904. timeout = parse_seconds (value);
  905. ctx->smtp_timeout.tv_sec = timeout / 1000;
  906. ctx->smtp_timeout.tv_usec = timeout - ctx->smtp_timeout.tv_sec * 1000;
  907. }
  908. if ((value = g_hash_table_lookup (worker->cf->params, "smtp_delay")) != NULL) {
  909. ctx->smtp_delay = parse_seconds (value);
  910. }
  911. if ((value = g_hash_table_lookup (worker->cf->params, "smtp_jitter")) != NULL) {
  912. ctx->delay_jitter = parse_seconds (value);
  913. }
  914. if ((value = g_hash_table_lookup (worker->cf->params, "smtp_capabilities")) != NULL) {
  915. make_capabilities (ctx, value);
  916. }
  917. if ((value = g_hash_table_lookup (worker->cf->params, "smtp_metric")) != NULL) {
  918. ctx->metric = memory_pool_strdup (ctx->pool, value);
  919. }
  920. else {
  921. ctx->metric = DEFAULT_METRIC;
  922. }
  923. if ((value = g_hash_table_lookup (worker->cf->params, "smtp_max_errors")) != NULL) {
  924. ctx->max_errors = strtoul (value, NULL, 10);
  925. }
  926. else {
  927. ctx->max_errors = DEFAULT_MAX_ERRORS;
  928. }
  929. if ((value = g_hash_table_lookup (worker->cf->params, "smtp_reject_message")) != NULL) {
  930. ctx->reject_message = memory_pool_strdup (ctx->pool, value);
  931. }
  932. else {
  933. ctx->reject_message = DEFAULT_REJECT_MESSAGE;
  934. }
  935. /* Set ctx */
  936. worker->ctx = ctx;
  937. return TRUE;
  938. }
  939. /*
  940. * Start worker process
  941. */
  942. void
  943. start_smtp_worker (struct rspamd_worker *worker)
  944. {
  945. struct sigaction signals;
  946. gperf_profiler_init (worker->srv->cfg, "worker");
  947. worker->srv->pid = getpid ();
  948. /* Set smtp options */
  949. if ( !config_smtp_worker (worker)) {
  950. msg_err ("cannot configure smtp worker, exiting");
  951. exit (EXIT_SUCCESS);
  952. }
  953. event_init ();
  954. evdns_init ();
  955. init_signals (&signals, sig_handler);
  956. sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL);
  957. /* SIGUSR2 handler */
  958. signal_set (&worker->sig_ev, SIGUSR2, sigusr_handler, (void *)worker);
  959. signal_add (&worker->sig_ev, NULL);
  960. /* Accept event */
  961. event_set (&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_socket, (void *)worker);
  962. event_add (&worker->bind_ev, NULL);
  963. /* Maps events */
  964. start_map_watch ();
  965. /* Set umask */
  966. umask (S_IWGRP | S_IWOTH | S_IROTH | S_IRGRP);
  967. event_loop (0);
  968. close_log ();
  969. exit (EXIT_SUCCESS);
  970. }
  971. /*
  972. * vi:ts=4
  973. */