diff options
Diffstat (limited to 'src/libmime/smtp_utils.c')
-rw-r--r-- | src/libmime/smtp_utils.c | 218 |
1 files changed, 147 insertions, 71 deletions
diff --git a/src/libmime/smtp_utils.c b/src/libmime/smtp_utils.c index 8ed169fa7..606d7de51 100644 --- a/src/libmime/smtp_utils.c +++ b/src/libmime/smtp_utils.c @@ -30,7 +30,7 @@ void free_smtp_session (gpointer arg) { - struct smtp_session *session = arg; + struct smtp_session *session = arg; if (session) { if (session->task) { @@ -60,12 +60,17 @@ free_smtp_session (gpointer arg) gboolean create_smtp_upstream_connection (struct smtp_session *session) { - struct smtp_upstream *selected; + struct smtp_upstream *selected; /* Try to select upstream */ - selected = (struct smtp_upstream *)get_upstream_round_robin (session->ctx->upstreams, - session->ctx->upstream_num, sizeof (struct smtp_upstream), - session->session_time, DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS); + selected = (struct smtp_upstream *)get_upstream_round_robin ( + session->ctx->upstreams, + session->ctx->upstream_num, + sizeof (struct smtp_upstream), + session->session_time, + DEFAULT_UPSTREAM_ERROR_TIME, + DEFAULT_UPSTREAM_DEAD_TIME, + DEFAULT_UPSTREAM_MAXERRORS); if (selected == NULL) { msg_err ("no upstreams suitable found"); return FALSE; @@ -74,19 +79,32 @@ create_smtp_upstream_connection (struct smtp_session *session) session->upstream = selected; /* Now try to create socket */ - session->upstream_sock = make_universal_socket (selected->addr, selected->port, SOCK_STREAM, TRUE, FALSE, FALSE); + session->upstream_sock = make_universal_socket (selected->addr, + selected->port, + SOCK_STREAM, + TRUE, + FALSE, + FALSE); if (session->upstream_sock == -1) { msg_err ("cannot make a connection to %s", selected->name); upstream_fail (&selected->up, session->session_time); return FALSE; } /* Create a dispatcher for upstream connection */ - session->upstream_dispatcher = rspamd_create_dispatcher (session->ev_base, session->upstream_sock, BUFFER_LINE, - smtp_upstream_read_socket, smtp_upstream_write_socket, smtp_upstream_err_socket, - &session->ctx->smtp_timeout, session); + session->upstream_dispatcher = rspamd_create_dispatcher (session->ev_base, + session->upstream_sock, + BUFFER_LINE, + smtp_upstream_read_socket, + smtp_upstream_write_socket, + smtp_upstream_err_socket, + &session->ctx->smtp_timeout, + session); session->state = SMTP_STATE_WAIT_UPSTREAM; session->upstream_state = SMTP_STATE_GREETING; - register_async_event (session->s, (event_finalizer_t)smtp_upstream_finalize_connection, session, g_quark_from_static_string ("smtp proxy")); + register_async_event (session->s, + (event_finalizer_t)smtp_upstream_finalize_connection, + session, + g_quark_from_static_string ("smtp proxy")); return TRUE; } @@ -98,7 +116,8 @@ smtp_send_upstream_message (struct smtp_session *session) session->upstream_state = SMTP_STATE_IN_SENDFILE; session->state = SMTP_STATE_WAIT_UPSTREAM; - if (! rspamd_dispatcher_sendfile (session->upstream_dispatcher, session->temp_fd, session->temp_size)) { + if (!rspamd_dispatcher_sendfile (session->upstream_dispatcher, + session->temp_fd, session->temp_size)) { msg_err ("sendfile failed: %s", strerror (errno)); goto err; } @@ -107,7 +126,8 @@ smtp_send_upstream_message (struct smtp_session *session) err: session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, + TRUE)) { return FALSE; } destroy_session (session->s); @@ -115,32 +135,35 @@ err: } struct smtp_metric_callback_data { - struct smtp_session *session; - enum rspamd_metric_action action; - struct metric_result *res; - gchar *log_buf; - gint log_offset; - gint log_size; - gboolean alive; + struct smtp_session *session; + enum rspamd_metric_action action; + struct metric_result *res; + gchar *log_buf; + gint log_offset; + gint log_size; + gboolean alive; }; static void smtp_metric_symbols_callback (gpointer key, gpointer value, void *user_data) { - struct smtp_metric_callback_data *cd = user_data; + struct smtp_metric_callback_data *cd = user_data; - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "%s,", (gchar *)key); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "%s,", + (gchar *)key); } static void smtp_metric_callback (gpointer key, gpointer value, gpointer ud) { struct smtp_metric_callback_data *cd = ud; - struct metric_result *metric_res = value; - enum rspamd_metric_action action = METRIC_ACTION_NOACTION; - double ms = 0, rs = 0; - gboolean is_spam = FALSE; - struct rspamd_task *task; + struct metric_result *metric_res = value; + enum rspamd_metric_action action = METRIC_ACTION_NOACTION; + double ms = 0, rs = 0; + gboolean is_spam = FALSE; + struct rspamd_task *task; task = cd->session->task; @@ -152,8 +175,10 @@ smtp_metric_callback (gpointer key, gpointer value, gpointer ud) ms = metric_res->metric->actions[METRIC_ACTION_REJECT].score; rs = metric_res->metric->actions[METRIC_ACTION_REJECT].score; } - if (! check_metric_action_settings (task, metric_res, metric_res->score, &action)) { - action = check_metric_action (metric_res->score, ms, metric_res->metric); + if (!check_metric_action_settings (task, metric_res, metric_res->score, + &action)) { + action = + check_metric_action (metric_res->score, ms, metric_res->metric); } #endif if (metric_res->score >= ms) { @@ -165,42 +190,70 @@ smtp_metric_callback (gpointer key, gpointer value, gpointer ud) } if (!task->is_skipped) { - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: %c (%s): [%.2f/%.2f/%.2f] [", - (gchar *)key, is_spam ? 'T' : 'F', str_action_metric (action), metric_res->score, ms, rs); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "(%s: %c (%s): [%.2f/%.2f/%.2f] [", + (gchar *)key, + is_spam ? 'T' : 'F', + str_action_metric (action), + metric_res->score, + ms, + rs); } else { - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: %c (default): [%.2f/%.2f/%.2f] [", - (gchar *)key, 'S', metric_res->score, ms, rs); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "(%s: %c (default): [%.2f/%.2f/%.2f] [", + (gchar *)key, + 'S', + metric_res->score, + ms, + rs); } - g_hash_table_foreach (metric_res->symbols, smtp_metric_symbols_callback, cd); + g_hash_table_foreach (metric_res->symbols, smtp_metric_symbols_callback, + cd); /* Remove last , from log buf */ if (cd->log_buf[cd->log_offset - 1] == ',') { cd->log_buf[--cd->log_offset] = '\0'; } #ifdef HAVE_CLOCK_GETTIME - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "]), len: %z, time: %s,", - task->msg->len, calculate_check_time (&task->tv, &task->ts, task->cfg->clock_res, &task->scan_milliseconds)); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "]), len: %z, time: %s,", + task->msg->len, + calculate_check_time (&task->tv, &task->ts, task->cfg->clock_res, + &task->scan_milliseconds)); #else - cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "]), len: %z, time: %s,", - task->msg->len, calculate_check_time (&task->tv, task->cfg->clock_res, &task->scan_milliseconds)); + cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, + cd->log_size - cd->log_offset, + "]), len: %z, time: %s,", + task->msg->len, + calculate_check_time (&task->tv, task->cfg->clock_res, + &task->scan_milliseconds)); #endif } gboolean make_smtp_tempfile (struct smtp_session *session) { - gsize r; + gsize r; r = strlen (session->cfg->temp_dir) + sizeof ("/rspamd-XXXXXX"); session->temp_name = rspamd_mempool_alloc (session->pool, r); - rspamd_snprintf (session->temp_name, r, "%s%crspamd-XXXXXX", session->cfg->temp_dir, G_DIR_SEPARATOR); + rspamd_snprintf (session->temp_name, + r, + "%s%crspamd-XXXXXX", + session->cfg->temp_dir, + G_DIR_SEPARATOR); #ifdef HAVE_MKSTEMP /* Umask is set before */ session->temp_fd = mkstemp (session->temp_name); #else - session->temp_fd = g_mkstemp_full (session->temp_name, O_RDWR, S_IWUSR | S_IRUSR); + session->temp_fd = g_mkstemp_full (session->temp_name, + O_RDWR, + S_IWUSR | S_IRUSR); #endif if (session->temp_fd == -1) { msg_err ("mkstemp error: %s", strerror (errno)); @@ -214,23 +267,28 @@ make_smtp_tempfile (struct smtp_session *session) gboolean write_smtp_reply (struct smtp_session *session) { - gchar logbuf[1024], *new_subject; - const gchar *old_subject; + gchar logbuf[1024], *new_subject; + const gchar *old_subject; struct smtp_metric_callback_data cd; - GMimeStream *stream; - gint old_fd, sublen; + GMimeStream *stream; + gint old_fd, sublen; /* Check metrics */ cd.session = session; cd.action = METRIC_ACTION_NOACTION; cd.res = NULL; cd.log_buf = logbuf; - cd.log_offset = rspamd_snprintf (logbuf, sizeof (logbuf), "id: <%s>, qid: <%s>, ", - session->task->message_id, session->task->queue_id); + cd.log_offset = rspamd_snprintf (logbuf, + sizeof (logbuf), + "id: <%s>, qid: <%s>, ", + session->task->message_id, + session->task->queue_id); cd.log_size = sizeof (logbuf); if (session->task->user) { - cd.log_offset += rspamd_snprintf (logbuf + cd.log_offset, sizeof (logbuf) - cd.log_offset, - "user: %s, ", session->task->user); + cd.log_offset += rspamd_snprintf (logbuf + cd.log_offset, + sizeof (logbuf) - cd.log_offset, + "user: %s, ", + session->task->user); } g_hash_table_foreach (session->task->results, smtp_metric_callback, &cd); @@ -238,22 +296,26 @@ write_smtp_reply (struct smtp_session *session) msg_info ("%s", logbuf); if (cd.action <= METRIC_ACTION_REJECT) { - if (! rspamd_dispatcher_write (session->dispatcher, session->ctx->reject_message, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, + session->ctx->reject_message, 0, FALSE, TRUE)) { return FALSE; } - if (! rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - 1, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, CRLF, sizeof (CRLF) - + 1, FALSE, TRUE)) { return FALSE; } destroy_session (session->s); return FALSE; } - else if (cd.action <= METRIC_ACTION_ADD_HEADER || cd.action <= METRIC_ACTION_REWRITE_SUBJECT) { + else if (cd.action <= METRIC_ACTION_ADD_HEADER || cd.action <= + METRIC_ACTION_REWRITE_SUBJECT) { old_fd = session->temp_fd; - if (! make_smtp_tempfile (session)) { + if (!make_smtp_tempfile (session)) { session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { goto err; } destroy_session (session->s); @@ -266,7 +328,11 @@ write_smtp_reply (struct smtp_session *session) if (old_subject != NULL) { sublen = strlen (old_subject) + sizeof (SPAM_SUBJECT); new_subject = rspamd_mempool_alloc (session->pool, sublen); - rspamd_snprintf (new_subject, sublen, "%s%s", SPAM_SUBJECT, old_subject); + rspamd_snprintf (new_subject, + sublen, + "%s%s", + SPAM_SUBJECT, + old_subject); } else { new_subject = SPAM_SUBJECT; @@ -275,21 +341,26 @@ write_smtp_reply (struct smtp_session *session) } else if (cd.action <= METRIC_ACTION_ADD_HEADER) { #ifndef GMIME24 - g_mime_message_add_header (session->task->message, "X-Spam", "true"); + g_mime_message_add_header (session->task->message, "X-Spam", + "true"); #else - g_mime_object_append_header (GMIME_OBJECT (session->task->message), "X-Spam", "true"); + g_mime_object_append_header (GMIME_OBJECT ( + session->task->message), "X-Spam", "true"); #endif } stream = g_mime_stream_fs_new (session->temp_fd); g_mime_stream_fs_set_owner (GMIME_STREAM_FS (stream), FALSE); close (old_fd); - if (g_mime_object_write_to_stream (GMIME_OBJECT (session->task->message), stream) == -1) { - msg_err ("cannot write MIME object to stream: %s", strerror (errno)); + if (g_mime_object_write_to_stream (GMIME_OBJECT (session->task->message), + stream) == -1) { + msg_err ("cannot write MIME object to stream: %s", + strerror (errno)); session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; rspamd_dispatcher_restore (session->dispatcher); - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, + 0, FALSE, TRUE)) { goto err; } destroy_session (session->s); @@ -302,7 +373,8 @@ write_smtp_reply (struct smtp_session *session) err: session->error = SMTP_ERROR_FILE; session->state = SMTP_STATE_CRITICAL_ERROR; - if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) { + if (!rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, + TRUE)) { return FALSE; } destroy_session (session->s); @@ -310,29 +382,33 @@ err: } gboolean -parse_upstreams_line (rspamd_mempool_t *pool, struct smtp_upstream *upstreams, const gchar *line, gsize *count) +parse_upstreams_line (rspamd_mempool_t *pool, + struct smtp_upstream *upstreams, + const gchar *line, + gsize *count) { - gchar **strv, *p, *t, *tt, *err_str; - guint32 num, i; - struct smtp_upstream *cur; - gchar resolved_path[PATH_MAX]; + gchar **strv, *p, *t, *tt, *err_str; + guint32 num, i; + struct smtp_upstream *cur; + gchar resolved_path[PATH_MAX]; strv = g_strsplit_set (line, ",; ", -1); num = g_strv_length (strv); if (num >= MAX_SMTP_UPSTREAMS) { - msg_err ("cannot define %d upstreams %d is max", num, MAX_SMTP_UPSTREAMS); + msg_err ("cannot define %d upstreams %d is max", num, + MAX_SMTP_UPSTREAMS); return FALSE; } *count = 0; - for (i = 0; i < num; i ++) { + for (i = 0; i < num; i++) { p = strv[i]; cur = &upstreams[*count]; if ((t = strrchr (p, ':')) != NULL && (tt = strchr (p, ':')) != t) { /* Assume that after last `:' we have weigth */ *t = '\0'; - t ++; + t++; errno = 0; cur->up.priority = strtoul (t, &err_str, 10); if (errno != 0 || (err_str && *err_str != '\0')) { @@ -349,15 +425,15 @@ parse_upstreams_line (rspamd_mempool_t *pool, struct smtp_upstream *upstreams, c return FALSE; } cur->name = rspamd_mempool_strdup (pool, resolved_path); - (*count) ++; + (*count)++; } else { - if (! rspamd_parse_host_port (pool, p, &cur->addr, &cur->port)) { + if (!rspamd_parse_host_port (pool, p, &cur->addr, &cur->port)) { g_strfreev (strv); return FALSE; } cur->name = rspamd_mempool_strdup (pool, p); - (*count) ++; + (*count)++; } } |