aboutsummaryrefslogtreecommitdiffstats
path: root/src/smtp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/smtp.c')
-rw-r--r--src/smtp.c819
1 files changed, 453 insertions, 366 deletions
diff --git a/src/smtp.c b/src/smtp.c
index dc3ff6089..98b012e3e 100644
--- a/src/smtp.c
+++ b/src/smtp.c
@@ -53,26 +53,26 @@ gpointer init_smtp (struct rspamd_config *cfg);
void start_smtp (struct rspamd_worker *worker);
worker_t smtp_worker = {
- "smtp", /* Name */
- init_smtp, /* Init function */
- start_smtp, /* Start function */
- TRUE, /* Has socket */
- FALSE, /* Non unique */
- FALSE, /* Non threaded */
- TRUE, /* Killable */
- SOCK_STREAM /* TCP socket */
+ "smtp", /* Name */
+ init_smtp, /* Init function */
+ start_smtp, /* Start function */
+ TRUE, /* Has socket */
+ FALSE, /* Non unique */
+ FALSE, /* Non threaded */
+ TRUE, /* Killable */
+ SOCK_STREAM /* TCP socket */
};
static gboolean
call_stage_filters (struct smtp_session *session, enum rspamd_smtp_stage stage)
{
- gboolean res = TRUE;
- GList *list = session->ctx->smtp_filters[stage];
- struct smtp_filter *filter;
-
+ gboolean res = TRUE;
+ GList *list = session->ctx->smtp_filters[stage];
+ struct smtp_filter *filter;
+
while (list) {
filter = list->data;
- if (! filter->filter (session, filter->filter_data)) {
+ if (!filter->filter (session, filter->filter_data)) {
res = FALSE;
break;
}
@@ -85,144 +85,159 @@ call_stage_filters (struct smtp_session *session, enum rspamd_smtp_stage stage)
static gboolean
read_smtp_command (struct smtp_session *session, f_str_t *line)
{
- struct smtp_command *cmd;
- gchar outbuf[BUFSIZ];
- gint r;
-
- if (! parse_smtp_command (session, line, &cmd)) {
+ struct smtp_command *cmd;
+ gchar outbuf[BUFSIZ];
+ gint r;
+
+ if (!parse_smtp_command (session, line, &cmd)) {
session->error = SMTP_ERROR_BAD_COMMAND;
- session->errors ++;
+ session->errors++;
return FALSE;
}
-
+
switch (cmd->command) {
- case SMTP_COMMAND_HELO:
- case SMTP_COMMAND_EHLO:
- if (session->state == SMTP_STATE_GREETING || session->state == SMTP_STATE_HELO) {
- if (parse_smtp_helo (session, cmd)) {
- session->state = SMTP_STATE_FROM;
- }
- else {
- session->errors ++;
- }
- if (! call_stage_filters (session, SMTP_STAGE_HELO)) {
- return FALSE;
- }
- return TRUE;
+ case SMTP_COMMAND_HELO:
+ case SMTP_COMMAND_EHLO:
+ if (session->state == SMTP_STATE_GREETING || session->state ==
+ SMTP_STATE_HELO) {
+ if (parse_smtp_helo (session, cmd)) {
+ session->state = SMTP_STATE_FROM;
}
else {
- goto improper_sequence;
+ session->errors++;
}
- break;
- case SMTP_COMMAND_QUIT:
- session->state = SMTP_STATE_QUIT;
- break;
- case SMTP_COMMAND_NOOP:
- break;
- case SMTP_COMMAND_MAIL:
- if (((session->state == SMTP_STATE_GREETING || session->state == SMTP_STATE_HELO) && !session->ctx->helo_required)
- || session->state == SMTP_STATE_FROM) {
- if (parse_smtp_from (session, cmd)) {
- session->state = SMTP_STATE_RCPT;
- }
- else {
- session->errors ++;
- return FALSE;
- }
- if (! call_stage_filters (session, SMTP_STAGE_MAIL)) {
- return FALSE;
- }
+ if (!call_stage_filters (session, SMTP_STAGE_HELO)) {
+ return FALSE;
+ }
+ return TRUE;
+ }
+ else {
+ goto improper_sequence;
+ }
+ break;
+ case SMTP_COMMAND_QUIT:
+ session->state = SMTP_STATE_QUIT;
+ break;
+ case SMTP_COMMAND_NOOP:
+ break;
+ case SMTP_COMMAND_MAIL:
+ if (((session->state == SMTP_STATE_GREETING || session->state ==
+ SMTP_STATE_HELO) && !session->ctx->helo_required)
+ || session->state == SMTP_STATE_FROM) {
+ if (parse_smtp_from (session, cmd)) {
+ session->state = SMTP_STATE_RCPT;
}
else {
- goto improper_sequence;
+ session->errors++;
+ return FALSE;
}
- break;
- case SMTP_COMMAND_RCPT:
- if (session->state == SMTP_STATE_RCPT) {
- if (parse_smtp_rcpt (session, cmd)) {
- if (! call_stage_filters (session, SMTP_STAGE_RCPT)) {
+ if (!call_stage_filters (session, SMTP_STAGE_MAIL)) {
+ return FALSE;
+ }
+ }
+ else {
+ goto improper_sequence;
+ }
+ break;
+ case SMTP_COMMAND_RCPT:
+ if (session->state == SMTP_STATE_RCPT) {
+ if (parse_smtp_rcpt (session, cmd)) {
+ if (!call_stage_filters (session, SMTP_STAGE_RCPT)) {
+ return FALSE;
+ }
+ /* Make upstream connection */
+ if (session->upstream == NULL) {
+ if (!create_smtp_upstream_connection (session)) {
+ session->error = SMTP_ERROR_UPSTREAM;
+ session->state = SMTP_STATE_CRITICAL_ERROR;
return FALSE;
}
- /* Make upstream connection */
- if (session->upstream == NULL) {
- if (!create_smtp_upstream_connection (session)) {
- session->error = SMTP_ERROR_UPSTREAM;
- session->state = SMTP_STATE_CRITICAL_ERROR;
- return FALSE;
- }
- }
- else {
- /* Send next rcpt to upstream */
- session->state = SMTP_STATE_WAIT_UPSTREAM;
- session->upstream_state = SMTP_STATE_BEFORE_DATA;
- rspamd_dispatcher_restore (session->upstream_dispatcher);
- r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: ");
- r += smtp_upstream_write_list (session->rcpt->data, outbuf + r, sizeof (outbuf) - r);
- session->cur_rcpt = NULL;
- return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE);
- }
- session->state = SMTP_STATE_WAIT_UPSTREAM;
- return TRUE;
}
else {
- session->errors ++;
- return FALSE;
+ /* Send next rcpt to upstream */
+ session->state = SMTP_STATE_WAIT_UPSTREAM;
+ session->upstream_state = SMTP_STATE_BEFORE_DATA;
+ rspamd_dispatcher_restore (session->upstream_dispatcher);
+ r = rspamd_snprintf (outbuf, sizeof (outbuf), "RCPT TO: ");
+ r += smtp_upstream_write_list (session->rcpt->data,
+ outbuf + r,
+ sizeof (outbuf) - r);
+ session->cur_rcpt = NULL;
+ return rspamd_dispatcher_write (
+ session->upstream_dispatcher,
+ outbuf,
+ r,
+ FALSE,
+ FALSE);
}
+ session->state = SMTP_STATE_WAIT_UPSTREAM;
+ return TRUE;
}
else {
- goto improper_sequence;
+ session->errors++;
+ return FALSE;
}
- break;
- case SMTP_COMMAND_RSET:
- session->from = NULL;
- if (session->rcpt) {
- g_list_free (session->rcpt);
+ }
+ else {
+ goto improper_sequence;
+ }
+ break;
+ case SMTP_COMMAND_RSET:
+ session->from = NULL;
+ if (session->rcpt) {
+ g_list_free (session->rcpt);
+ }
+ if (session->upstream) {
+ remove_normal_event (session->s,
+ smtp_upstream_finalize_connection,
+ session);
+ session->upstream = NULL;
+ }
+ session->state = SMTP_STATE_GREETING;
+ break;
+ case SMTP_COMMAND_DATA:
+ if (session->state == SMTP_STATE_RCPT) {
+ if (session->rcpt == NULL) {
+ session->error = SMTP_ERROR_RECIPIENTS;
+ session->errors++;
+ return FALSE;
}
- if (session->upstream) {
- remove_normal_event (session->s, smtp_upstream_finalize_connection, session);
- session->upstream = NULL;
+ if (!call_stage_filters (session, SMTP_STAGE_DATA)) {
+ return FALSE;
}
- session->state = SMTP_STATE_GREETING;
- break;
- case SMTP_COMMAND_DATA:
- if (session->state == SMTP_STATE_RCPT) {
- if (session->rcpt == NULL) {
- session->error = SMTP_ERROR_RECIPIENTS;
- session->errors ++;
- return FALSE;
- }
- if (! call_stage_filters (session, SMTP_STAGE_DATA)) {
- return FALSE;
- }
- if (session->upstream == NULL) {
- session->error = SMTP_ERROR_UPSTREAM;
- session->state = SMTP_STATE_CRITICAL_ERROR;
- return FALSE;
- }
- else {
- session->upstream_state = SMTP_STATE_DATA;
- rspamd_dispatcher_restore (session->upstream_dispatcher);
- r = rspamd_snprintf (outbuf, sizeof (outbuf), "DATA" CRLF);
- session->state = SMTP_STATE_WAIT_UPSTREAM;
- session->error = SMTP_ERROR_DATA_OK;
- return rspamd_dispatcher_write (session->upstream_dispatcher, outbuf, r, FALSE, FALSE);
- }
+ if (session->upstream == NULL) {
+ session->error = SMTP_ERROR_UPSTREAM;
+ session->state = SMTP_STATE_CRITICAL_ERROR;
+ return FALSE;
}
else {
- goto improper_sequence;
+ session->upstream_state = SMTP_STATE_DATA;
+ rspamd_dispatcher_restore (session->upstream_dispatcher);
+ r = rspamd_snprintf (outbuf, sizeof (outbuf), "DATA" CRLF);
+ session->state = SMTP_STATE_WAIT_UPSTREAM;
+ session->error = SMTP_ERROR_DATA_OK;
+ return rspamd_dispatcher_write (session->upstream_dispatcher,
+ outbuf,
+ r,
+ FALSE,
+ FALSE);
}
- case SMTP_COMMAND_VRFY:
- case SMTP_COMMAND_EXPN:
- case SMTP_COMMAND_HELP:
- session->error = SMTP_ERROR_UNIMPLIMENTED;
- return FALSE;
+ }
+ else {
+ goto improper_sequence;
+ }
+ case SMTP_COMMAND_VRFY:
+ case SMTP_COMMAND_EXPN:
+ case SMTP_COMMAND_HELP:
+ session->error = SMTP_ERROR_UNIMPLIMENTED;
+ return FALSE;
}
-
+
session->error = SMTP_ERROR_OK;
return TRUE;
improper_sequence:
- session->errors ++;
+ session->errors++;
session->error = SMTP_ERROR_SEQUENCE;
return FALSE;
}
@@ -230,11 +245,11 @@ improper_sequence:
static gboolean
process_smtp_data (struct smtp_session *session)
{
- struct stat st;
- gint r;
- GList *cur, *t;
- f_str_t *f;
- gchar *s;
+ struct stat st;
+ gint r;
+ GList *cur, *t;
+ f_str_t *f;
+ gchar *s;
if (fstat (session->temp_fd, &st) == -1) {
msg_err ("fstat failed: %s", strerror (errno));
@@ -242,17 +257,23 @@ process_smtp_data (struct smtp_session *session)
}
/* Now mmap temp file if it is small enough */
session->temp_size = st.st_size;
- if (session->ctx->max_size == 0 || st.st_size < (off_t)session->ctx->max_size) {
+ if (session->ctx->max_size == 0 || st.st_size <
+ (off_t)session->ctx->max_size) {
session->task = rspamd_task_new (session->worker);
session->task->resolver = session->resolver;
session->task->fin_callback = smtp_write_socket;
session->task->fin_arg = session;
- session->task->msg = rspamd_mempool_alloc (session->pool, sizeof (GString));
+ session->task->msg =
+ rspamd_mempool_alloc (session->pool, sizeof (GString));
session->task->s = session->s;
#ifdef HAVE_MMAP_NOCORE
- if ((session->task->msg->str = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED | MAP_NOCORE, session->temp_fd, 0)) == MAP_FAILED) {
+ if ((session->task->msg->str =
+ mmap (NULL, st.st_size, PROT_READ, MAP_SHARED | MAP_NOCORE,
+ session->temp_fd, 0)) == MAP_FAILED) {
#else
- if ((session->task->msg->str = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, session->temp_fd, 0)) == MAP_FAILED) {
+ if ((session->task->msg->str =
+ mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, session->temp_fd,
+ 0)) == MAP_FAILED) {
#endif
msg_err ("mmap failed: %s", strerror (errno));
goto err;
@@ -280,7 +301,8 @@ process_smtp_data (struct smtp_session *session)
t = g_list_next (t);
}
- memcpy (&session->task->from_addr, &session->client_addr, sizeof (struct in_addr));
+ memcpy (&session->task->from_addr, &session->client_addr,
+ sizeof (struct in_addr));
session->task->cmd = CMD_CHECK;
if (process_message (session->task) == -1) {
@@ -305,7 +327,9 @@ process_smtp_data (struct smtp_session *session)
}
}
else {
- msg_info ("not scan message as it is %z bytes and maximum is %z", st.st_size, session->ctx->max_size);
+ msg_info ("not scan message as it is %z bytes and maximum is %z",
+ st.st_size,
+ session->ctx->max_size);
session->task = NULL;
return smtp_send_upstream_message (session);
}
@@ -314,7 +338,8 @@ process_smtp_data (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);
@@ -324,65 +349,74 @@ err:
/*
* Callback that is called when there is data to read in buffer
*/
-static gboolean
+static gboolean
smtp_read_socket (f_str_t * in, void *arg)
{
- struct smtp_session *session = arg;
+ struct smtp_session *session = arg;
switch (session->state) {
- case SMTP_STATE_RESOLVE_REVERSE:
- case SMTP_STATE_RESOLVE_NORMAL:
- case SMTP_STATE_DELAY:
- session->error = make_smtp_error (session->pool, 550, "%s Improper use of SMTP command pipelining", "5.5.0");
- session->state = SMTP_STATE_ERROR;
- break;
- case SMTP_STATE_GREETING:
- case SMTP_STATE_HELO:
- case SMTP_STATE_FROM:
- case SMTP_STATE_RCPT:
- case SMTP_STATE_DATA:
- read_smtp_command (session, in);
- if (session->state != SMTP_STATE_WAIT_UPSTREAM) {
- if (session->errors > session->ctx->max_errors) {
- session->error = SMTP_ERROR_LIMIT;
- session->state = SMTP_STATE_CRITICAL_ERROR;
- if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) {
- return FALSE;
- }
- destroy_session (session->s);
- return FALSE;
- }
- if (! smtp_write_socket (session)) {
+ case SMTP_STATE_RESOLVE_REVERSE:
+ case SMTP_STATE_RESOLVE_NORMAL:
+ case SMTP_STATE_DELAY:
+ session->error = make_smtp_error (session->pool,
+ 550,
+ "%s Improper use of SMTP command pipelining",
+ "5.5.0");
+ session->state = SMTP_STATE_ERROR;
+ break;
+ case SMTP_STATE_GREETING:
+ case SMTP_STATE_HELO:
+ case SMTP_STATE_FROM:
+ case SMTP_STATE_RCPT:
+ case SMTP_STATE_DATA:
+ read_smtp_command (session, in);
+ if (session->state != SMTP_STATE_WAIT_UPSTREAM) {
+ if (session->errors > session->ctx->max_errors) {
+ session->error = SMTP_ERROR_LIMIT;
+ session->state = SMTP_STATE_CRITICAL_ERROR;
+ if (!rspamd_dispatcher_write (session->dispatcher,
+ session->error, 0, FALSE, TRUE)) {
return FALSE;
}
+ destroy_session (session->s);
+ return FALSE;
}
- break;
- case SMTP_STATE_AFTER_DATA:
- if (in->len == 0) {
- return TRUE;
- }
- if (in->len == 3 && memcmp (in->begin, DATA_END_TRAILER, in->len) == 0) {
- return process_smtp_data (session);
+ if (!smtp_write_socket (session)) {
+ return FALSE;
}
+ }
+ break;
+ case SMTP_STATE_AFTER_DATA:
+ if (in->len == 0) {
+ return TRUE;
+ }
+ if (in->len == 3 &&
+ memcmp (in->begin, DATA_END_TRAILER, in->len) == 0) {
+ return process_smtp_data (session);
+ }
- if (write (session->temp_fd, in->begin, in->len) != (ssize_t)in->len) {
- msg_err ("cannot write to temp file: %s", strerror (errno));
- session->error = SMTP_ERROR_FILE;
- session->state = SMTP_STATE_CRITICAL_ERROR;
- if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) {
- return FALSE;
- }
- destroy_session (session->s);
+ if (write (session->temp_fd, in->begin, in->len) != (ssize_t)in->len) {
+ msg_err ("cannot write to temp file: %s", strerror (errno));
+ session->error = SMTP_ERROR_FILE;
+ session->state = SMTP_STATE_CRITICAL_ERROR;
+ if (!rspamd_dispatcher_write (session->dispatcher, session->error,
+ 0, FALSE, TRUE)) {
return FALSE;
}
- break;
- case SMTP_STATE_WAIT_UPSTREAM:
- rspamd_dispatcher_pause (session->dispatcher);
- break;
- default:
- session->error = make_smtp_error (session->pool, 550, "%s Internal error", "5.5.0");
- session->state = SMTP_STATE_ERROR;
- break;
+ destroy_session (session->s);
+ return FALSE;
+ }
+ break;
+ case SMTP_STATE_WAIT_UPSTREAM:
+ rspamd_dispatcher_pause (session->dispatcher);
+ break;
+ default:
+ session->error = make_smtp_error (session->pool,
+ 550,
+ "%s Internal error",
+ "5.5.0");
+ session->state = SMTP_STATE_ERROR;
+ break;
}
if (session->state == SMTP_STATE_QUIT) {
@@ -399,14 +433,15 @@ smtp_read_socket (f_str_t * in, void *arg)
/*
* Callback for socket writing
*/
-static gboolean
+static gboolean
smtp_write_socket (void *arg)
{
- struct smtp_session *session = arg;
+ struct smtp_session *session = arg;
if (session->state == SMTP_STATE_CRITICAL_ERROR) {
if (session->error != NULL) {
- if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) {
+ if (!rspamd_dispatcher_write (session->dispatcher, session->error,
+ 0, FALSE, TRUE)) {
return FALSE;
}
}
@@ -419,7 +454,8 @@ smtp_write_socket (void *arg)
}
else {
if (session->error != NULL) {
- if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) {
+ if (!rspamd_dispatcher_write (session->dispatcher,
+ session->error, 0, FALSE, TRUE)) {
return FALSE;
}
}
@@ -427,12 +463,13 @@ smtp_write_socket (void *arg)
}
else {
if (session->error != NULL) {
- if (! rspamd_dispatcher_write (session->dispatcher, session->error, 0, FALSE, TRUE)) {
+ if (!rspamd_dispatcher_write (session->dispatcher, session->error,
+ 0, FALSE, TRUE)) {
return FALSE;
}
}
}
-
+
return TRUE;
}
@@ -442,7 +479,7 @@ smtp_write_socket (void *arg)
static void
smtp_err_socket (GError * err, void *arg)
{
- struct smtp_session *session = arg;
+ struct smtp_session *session = arg;
msg_info ("abnormally closing connection, error: %s", err->message);
/* Free buffers */
@@ -456,7 +493,8 @@ static gboolean
write_smtp_greeting (struct smtp_session *session)
{
if (session->ctx->smtp_banner) {
- if (! rspamd_dispatcher_write (session->dispatcher, session->ctx->smtp_banner, 0, FALSE, TRUE)) {
+ if (!rspamd_dispatcher_write (session->dispatcher,
+ session->ctx->smtp_banner, 0, FALSE, TRUE)) {
return FALSE;
}
}
@@ -470,9 +508,11 @@ write_smtp_greeting (struct smtp_session *session)
static void
smtp_delay_handler (gint fd, short what, void *arg)
{
- struct smtp_session *session = arg;
-
- remove_normal_event (session->s, (event_finalizer_t)event_del, session->delay_timer);
+ struct smtp_session *session = arg;
+
+ remove_normal_event (session->s,
+ (event_finalizer_t)event_del,
+ session->delay_timer);
if (session->state == SMTP_STATE_DELAY) {
session->state = SMTP_STATE_GREETING;
write_smtp_greeting (session);
@@ -489,9 +529,9 @@ smtp_delay_handler (gint fd, short what, void *arg)
static void
smtp_make_delay (struct smtp_session *session)
{
- struct event *tev;
- struct timeval *tv;
- gint32 jitter;
+ struct event *tev;
+ struct timeval *tv;
+ gint32 jitter;
if (session->ctx->smtp_delay != 0 && session->state == SMTP_STATE_DELAY) {
tev = rspamd_mempool_alloc (session->pool, sizeof (struct event));
@@ -506,7 +546,10 @@ smtp_make_delay (struct smtp_session *session)
evtimer_set (tev, smtp_delay_handler, session);
evtimer_add (tev, tv);
- register_async_event (session->s, (event_finalizer_t)event_del, tev, g_quark_from_static_string ("smtp proxy"));
+ register_async_event (session->s,
+ (event_finalizer_t)event_del,
+ tev,
+ g_quark_from_static_string ("smtp proxy"));
session->delay_timer = tev;
}
else if (session->state == SMTP_STATE_DELAY) {
@@ -521,83 +564,98 @@ smtp_make_delay (struct smtp_session *session)
static void
smtp_dns_cb (struct rspamd_dns_reply *reply, void *arg)
{
- struct smtp_session *session = arg;
- gint res = 0;
- union rspamd_reply_element *elt;
- GList *cur;
+ struct smtp_session *session = arg;
+ gint res = 0;
+ union rspamd_reply_element *elt;
+ GList *cur;
switch (session->state) {
- case SMTP_STATE_RESOLVE_REVERSE:
- /* Parse reverse reply and start resolve of this ip */
- if (reply->code != RDNS_RC_NOERROR) {
- rspamd_conditional_debug(rspamd_main->logger, session->client_addr.s_addr, __FUNCTION__,
- "DNS error: %s", dns_strerror (reply->code));
-
- if (reply->code == RDNS_RC_NXDOMAIN) {
- session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_UNAVAILABLE);
- }
- else {
- session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_TEMPFAIL);
- }
- session->state = SMTP_STATE_DELAY;
- smtp_make_delay (session);
+ case SMTP_STATE_RESOLVE_REVERSE:
+ /* Parse reverse reply and start resolve of this ip */
+ if (reply->code != RDNS_RC_NOERROR) {
+ rspamd_conditional_debug (rspamd_main->logger,
+ session->client_addr.s_addr,
+ __FUNCTION__,
+ "DNS error: %s",
+ dns_strerror (reply->code));
+
+ if (reply->code == RDNS_RC_NXDOMAIN) {
+ session->hostname = rspamd_mempool_strdup (session->pool,
+ XCLIENT_HOST_UNAVAILABLE);
}
else {
- if (reply->elements) {
- elt = reply->elements->data;
- session->hostname = rspamd_mempool_strdup (session->pool, elt->ptr.name);
- session->state = SMTP_STATE_RESOLVE_NORMAL;
- make_dns_request (session->resolver, session->s, session->pool,
- smtp_dns_cb, session, RDNS_REQUEST_A, session->hostname);
-
- }
+ session->hostname = rspamd_mempool_strdup (session->pool,
+ XCLIENT_HOST_TEMPFAIL);
}
- break;
- case SMTP_STATE_RESOLVE_NORMAL:
- if (reply->code != RDNS_RC_NOERROR) {
- rspamd_conditional_debug(rspamd_main->logger, session->client_addr.s_addr, __FUNCTION__,
- "DNS error: %s", dns_strerror (reply->code));
+ session->state = SMTP_STATE_DELAY;
+ smtp_make_delay (session);
+ }
+ else {
+ if (reply->elements) {
+ elt = reply->elements->data;
+ session->hostname = rspamd_mempool_strdup (session->pool,
+ elt->ptr.name);
+ session->state = SMTP_STATE_RESOLVE_NORMAL;
+ make_dns_request (session->resolver, session->s, session->pool,
+ smtp_dns_cb, session, RDNS_REQUEST_A, session->hostname);
- if (reply->code == RDNS_RC_NXDOMAIN) {
- session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_UNAVAILABLE);
- }
- else {
- session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_TEMPFAIL);
- }
- session->state = SMTP_STATE_DELAY;
- smtp_make_delay (session);
+ }
+ }
+ break;
+ case SMTP_STATE_RESOLVE_NORMAL:
+ if (reply->code != RDNS_RC_NOERROR) {
+ rspamd_conditional_debug (rspamd_main->logger,
+ session->client_addr.s_addr,
+ __FUNCTION__,
+ "DNS error: %s",
+ dns_strerror (reply->code));
+
+ if (reply->code == RDNS_RC_NXDOMAIN) {
+ session->hostname = rspamd_mempool_strdup (session->pool,
+ XCLIENT_HOST_UNAVAILABLE);
}
else {
- res = 0;
- cur = reply->elements;
- while (cur) {
- elt = cur->data;
- if (memcmp (&session->client_addr, &elt->a.addr[0], sizeof (struct in_addr)) == 0) {
- res = 1;
- session->resolved = TRUE;
- break;
- }
- cur = g_list_next (cur);
+ session->hostname = rspamd_mempool_strdup (session->pool,
+ XCLIENT_HOST_TEMPFAIL);
+ }
+ session->state = SMTP_STATE_DELAY;
+ smtp_make_delay (session);
+ }
+ else {
+ res = 0;
+ cur = reply->elements;
+ while (cur) {
+ elt = cur->data;
+ if (memcmp (&session->client_addr, &elt->a.addr[0],
+ sizeof (struct in_addr)) == 0) {
+ res = 1;
+ session->resolved = TRUE;
+ break;
}
+ cur = g_list_next (cur);
+ }
- if (res == 0) {
- msg_info ("cannot find address for hostname: %s, ip: %s", session->hostname, inet_ntoa (session->client_addr));
- session->hostname = rspamd_mempool_strdup (session->pool, XCLIENT_HOST_UNAVAILABLE);
- }
- session->state = SMTP_STATE_DELAY;
- smtp_make_delay (session);
+ if (res == 0) {
+ msg_info ("cannot find address for hostname: %s, ip: %s",
+ session->hostname,
+ inet_ntoa (session->client_addr));
+ session->hostname = rspamd_mempool_strdup (session->pool,
+ XCLIENT_HOST_UNAVAILABLE);
}
- break;
- case SMTP_STATE_ERROR:
- session->state = SMTP_STATE_WRITE_ERROR;
- smtp_write_socket (session);
- break;
- default:
- /*
- * This callback is called on unknown state, usually this indicates
- * an error (invalid pipelining)
- */
- break;
+ session->state = SMTP_STATE_DELAY;
+ smtp_make_delay (session);
+ }
+ break;
+ case SMTP_STATE_ERROR:
+ session->state = SMTP_STATE_WRITE_ERROR;
+ smtp_write_socket (session);
+ break;
+ default:
+ /*
+ * This callback is called on unknown state, usually this indicates
+ * an error (invalid pipelining)
+ */
+ break;
}
}
@@ -607,15 +665,16 @@ smtp_dns_cb (struct rspamd_dns_reply *reply, void *arg)
static void
accept_socket (gint fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
- union sa_union su;
- struct smtp_session *session;
- struct smtp_worker_ctx *ctx;
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ union sa_union su;
+ struct smtp_session *session;
+ struct smtp_worker_ctx *ctx;
- socklen_t addrlen = sizeof (su.ss);
- gint nfd;
+ socklen_t addrlen = sizeof (su.ss);
+ gint nfd;
- if ((nfd = accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) {
+ if ((nfd =
+ accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) {
msg_warn ("accept failed: %s", strerror (errno));
return;
}
@@ -633,8 +692,10 @@ accept_socket (gint fd, short what, void *arg)
session->client_addr.s_addr = INADDR_NONE;
}
else if (su.ss.ss_family == AF_INET) {
- msg_info ("accepted connection from %s port %d", inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port));
- memcpy (&session->client_addr, &su.s4.sin_addr, sizeof (struct in_addr));
+ msg_info ("accepted connection from %s port %d",
+ inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port));
+ memcpy (&session->client_addr, &su.s4.sin_addr,
+ sizeof (struct in_addr));
}
session->sock = nfd;
@@ -649,18 +710,28 @@ accept_socket (gint fd, short what, void *arg)
/* Resolve client's addr */
/* Set up async session */
- session->s = new_async_session (session->pool, NULL, NULL, free_smtp_session, session);
+ session->s = new_async_session (session->pool,
+ NULL,
+ NULL,
+ free_smtp_session,
+ session);
session->state = SMTP_STATE_RESOLVE_REVERSE;
- if (! make_dns_request (session->resolver, session->s, session->pool,
- smtp_dns_cb, session, RDNS_REQUEST_PTR, &session->client_addr)) {
+ if (!make_dns_request (session->resolver, session->s, session->pool,
+ smtp_dns_cb, session, RDNS_REQUEST_PTR, &session->client_addr)) {
msg_err ("cannot resolve %s", inet_ntoa (session->client_addr));
g_free (session);
close (nfd);
return;
}
else {
- session->dispatcher = rspamd_create_dispatcher (session->ev_base, nfd, BUFFER_LINE,
- smtp_read_socket, smtp_write_socket, smtp_err_socket, &session->ctx->smtp_timeout, session);
+ session->dispatcher = rspamd_create_dispatcher (session->ev_base,
+ nfd,
+ BUFFER_LINE,
+ smtp_read_socket,
+ smtp_write_socket,
+ smtp_err_socket,
+ &session->ctx->smtp_timeout,
+ session);
session->dispatcher->peer_addr = session->client_addr.s_addr;
}
}
@@ -668,41 +739,41 @@ accept_socket (gint fd, short what, void *arg)
static void
parse_smtp_banner (struct smtp_worker_ctx *ctx, const gchar *line)
{
- gint hostmax, banner_len = sizeof ("220 ") - 1;
- gchar *p, *t, *hostbuf = NULL;
- gboolean has_crlf = FALSE;
+ gint hostmax, banner_len = sizeof ("220 ") - 1;
+ gchar *p, *t, *hostbuf = NULL;
+ gboolean has_crlf = FALSE;
p = (gchar *)line;
while (*p) {
if (*p == '%') {
- p ++;
+ p++;
switch (*p) {
- case 'n':
- /* Assume %n as CRLF */
- banner_len += sizeof (CRLF) - 1 + sizeof ("220 -") - 1;
- has_crlf = TRUE;
- break;
- case 'h':
- hostmax = sysconf (_SC_HOST_NAME_MAX) + 1;
- hostbuf = alloca (hostmax);
- gethostname (hostbuf, hostmax);
- hostbuf[hostmax - 1] = '\0';
- banner_len += strlen (hostbuf);
- break;
- case '%':
- banner_len += 1;
- break;
- default:
- banner_len += 2;
- break;
+ case 'n':
+ /* Assume %n as CRLF */
+ banner_len += sizeof (CRLF) - 1 + sizeof ("220 -") - 1;
+ has_crlf = TRUE;
+ break;
+ case 'h':
+ hostmax = sysconf (_SC_HOST_NAME_MAX) + 1;
+ hostbuf = alloca (hostmax);
+ gethostname (hostbuf, hostmax);
+ hostbuf[hostmax - 1] = '\0';
+ banner_len += strlen (hostbuf);
+ break;
+ case '%':
+ banner_len += 1;
+ break;
+ default:
+ banner_len += 2;
+ break;
}
}
else {
- banner_len ++;
+ banner_len++;
}
- p ++;
+ p++;
}
-
+
if (has_crlf) {
banner_len += sizeof (CRLF "220 " CRLF);
}
@@ -723,30 +794,30 @@ parse_smtp_banner (struct smtp_worker_ctx *ctx, const gchar *line)
while (*p) {
if (*p == '%') {
- p ++;
+ p++;
switch (*p) {
- case 'n':
- /* Assume %n as CRLF */
- *t++ = CR; *t++ = LF;
- t = g_stpcpy (t, "220-");
- p ++;
- break;
- case 'h':
- t = g_stpcpy (t, hostbuf);
- p ++;
- break;
- case '%':
- *t++ = '%';
- p ++;
- break;
- default:
- /* Copy all %<gchar> to dest */
- *t++ = *(p - 1); *t++ = *p;
- break;
+ case 'n':
+ /* Assume %n as CRLF */
+ *t++ = CR; *t++ = LF;
+ t = g_stpcpy (t, "220-");
+ p++;
+ break;
+ case 'h':
+ t = g_stpcpy (t, hostbuf);
+ p++;
+ break;
+ case '%':
+ *t++ = '%';
+ p++;
+ break;
+ default:
+ /* Copy all %<gchar> to dest */
+ *t++ = *(p - 1); *t++ = *p;
+ break;
}
}
else {
- *t ++ = *p ++;
+ *t++ = *p++;
}
}
if (has_crlf) {
@@ -760,12 +831,12 @@ parse_smtp_banner (struct smtp_worker_ctx *ctx, const gchar *line)
static void
make_capabilities (struct smtp_worker_ctx *ctx, const gchar *line)
{
- gchar **strv, *p, *result, *hostbuf;
- guint32 num, i, len, hostmax;
+ gchar **strv, *p, *result, *hostbuf;
+ guint32 num, i, len, hostmax;
strv = g_strsplit_set (line, ",;", -1);
num = g_strv_length (strv);
-
+
hostmax = sysconf (_SC_HOST_NAME_MAX) + 1;
hostbuf = alloca (hostmax);
gethostname (hostbuf, hostmax);
@@ -773,26 +844,32 @@ make_capabilities (struct smtp_worker_ctx *ctx, const gchar *line)
len = sizeof ("250-") + strlen (hostbuf) + sizeof (CRLF) - 1;
- for (i = 0; i < num; i ++) {
+ for (i = 0; i < num; i++) {
p = strv[i];
len += sizeof ("250-") + sizeof (CRLF) + strlen (p) - 2;
}
result = rspamd_mempool_alloc (ctx->pool, len);
ctx->smtp_capabilities = result;
-
+
p = result;
if (num == 0) {
p += rspamd_snprintf (p, len - (p - result), "250 %s" CRLF, hostbuf);
}
else {
p += rspamd_snprintf (p, len - (p - result), "250-%s" CRLF, hostbuf);
- for (i = 0; i < num; i ++) {
+ for (i = 0; i < num; i++) {
if (i != num - 1) {
- p += rspamd_snprintf (p, len - (p - result), "250-%s" CRLF, strv[i]);
+ p += rspamd_snprintf (p,
+ len - (p - result),
+ "250-%s" CRLF,
+ strv[i]);
}
else {
- p += rspamd_snprintf (p, len - (p - result), "250 %s" CRLF, strv[i]);
+ p += rspamd_snprintf (p,
+ len - (p - result),
+ "250 %s" CRLF,
+ strv[i]);
}
}
}
@@ -803,14 +880,14 @@ make_capabilities (struct smtp_worker_ctx *ctx, const gchar *line)
gpointer
init_smtp (struct rspamd_config *cfg)
{
- struct smtp_worker_ctx *ctx;
- GQuark type;
+ struct smtp_worker_ctx *ctx;
+ GQuark type;
type = g_quark_try_string ("smtp");
ctx = g_malloc0 (sizeof (struct smtp_worker_ctx));
ctx->pool = rspamd_mempool_new (rspamd_mempool_suggest_size ());
-
+
/* Set default values */
ctx->smtp_timeout_raw = 300000;
ctx->smtp_delay = 0;
@@ -820,44 +897,49 @@ init_smtp (struct rspamd_config *cfg)
ctx->reject_message = DEFAULT_REJECT_MESSAGE;
rspamd_rcl_register_worker_option (cfg, type, "upstreams",
- rspamd_rcl_parse_struct_string, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, upstreams_str), 0);
+ rspamd_rcl_parse_struct_string, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, upstreams_str), 0);
rspamd_rcl_register_worker_option (cfg, type, "banner",
- rspamd_rcl_parse_struct_string, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_banner_str), 0);
+ rspamd_rcl_parse_struct_string, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_banner_str), 0);
rspamd_rcl_register_worker_option (cfg, type, "timeout",
- rspamd_rcl_parse_struct_time, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_timeout_raw), RSPAMD_CL_FLAG_TIME_UINT_32);
+ rspamd_rcl_parse_struct_time, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx,
+ smtp_timeout_raw), RSPAMD_CL_FLAG_TIME_UINT_32);
rspamd_rcl_register_worker_option (cfg, type, "delay",
- rspamd_rcl_parse_struct_time, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_delay), RSPAMD_CL_FLAG_TIME_UINT_32);
+ rspamd_rcl_parse_struct_time, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx,
+ smtp_delay), RSPAMD_CL_FLAG_TIME_UINT_32);
rspamd_rcl_register_worker_option (cfg, type, "jitter",
- rspamd_rcl_parse_struct_time, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, delay_jitter), RSPAMD_CL_FLAG_TIME_UINT_32);
+ rspamd_rcl_parse_struct_time, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx,
+ delay_jitter), RSPAMD_CL_FLAG_TIME_UINT_32);
rspamd_rcl_register_worker_option (cfg, type, "capabilities",
- rspamd_rcl_parse_struct_string, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_capabilities_str), 0);
+ rspamd_rcl_parse_struct_string, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, smtp_capabilities_str), 0);
rspamd_rcl_register_worker_option (cfg, type, "xclient",
- rspamd_rcl_parse_struct_boolean, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, use_xclient), 0);
+ rspamd_rcl_parse_struct_boolean, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, use_xclient), 0);
rspamd_rcl_register_worker_option (cfg, type, "reject_message",
- rspamd_rcl_parse_struct_string, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, reject_message), 0);
+ rspamd_rcl_parse_struct_string, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx, reject_message), 0);
rspamd_rcl_register_worker_option (cfg, type, "max_errors",
- rspamd_rcl_parse_struct_integer, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, max_errors), RSPAMD_CL_FLAG_INT_32);
+ rspamd_rcl_parse_struct_integer, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx,
+ max_errors), RSPAMD_CL_FLAG_INT_32);
rspamd_rcl_register_worker_option (cfg, type, "max_size",
- rspamd_rcl_parse_struct_integer, ctx,
- G_STRUCT_OFFSET (struct smtp_worker_ctx, max_size), RSPAMD_CL_FLAG_INT_SIZE);
+ rspamd_rcl_parse_struct_integer, ctx,
+ G_STRUCT_OFFSET (struct smtp_worker_ctx,
+ max_size), RSPAMD_CL_FLAG_INT_SIZE);
return ctx;
}
@@ -866,15 +948,16 @@ init_smtp (struct rspamd_config *cfg)
static gboolean
config_smtp_worker (struct rspamd_worker *worker)
{
- struct smtp_worker_ctx *ctx = worker->ctx;
- gchar *value;
+ struct smtp_worker_ctx *ctx = worker->ctx;
+ gchar *value;
/* Init timeval */
msec_to_tv (ctx->smtp_timeout_raw, &ctx->smtp_timeout);
/* Init upstreams */
if ((value = ctx->upstreams_str) != NULL) {
- if (!parse_upstreams_line (ctx->pool, ctx->upstreams, value, &ctx->upstream_num)) {
+ if (!parse_upstreams_line (ctx->pool, ctx->upstreams, value,
+ &ctx->upstream_num)) {
return FALSE;
}
}
@@ -891,7 +974,7 @@ config_smtp_worker (struct rspamd_worker *worker)
if ((value = ctx->smtp_capabilities_str) != NULL) {
make_capabilities (ctx, value);
}
-
+
return TRUE;
}
@@ -902,7 +985,7 @@ config_smtp_worker (struct rspamd_worker *worker)
void
start_smtp (struct rspamd_worker *worker)
{
- struct smtp_worker_ctx *ctx = worker->ctx;
+ struct smtp_worker_ctx *ctx = worker->ctx;
ctx->ev_base = rspamd_prepare_worker (worker, "smtp_worker", accept_socket);
@@ -922,15 +1005,18 @@ start_smtp (struct rspamd_worker *worker)
umask (S_IWGRP | S_IWOTH | S_IROTH | S_IRGRP);
event_base_loop (ctx->ev_base, 0);
-
+
close_log (rspamd_main->logger);
exit (EXIT_SUCCESS);
}
-void
-register_smtp_filter (struct smtp_worker_ctx *ctx, enum rspamd_smtp_stage stage, smtp_filter_t filter, gpointer filter_data)
+void
+register_smtp_filter (struct smtp_worker_ctx *ctx,
+ enum rspamd_smtp_stage stage,
+ smtp_filter_t filter,
+ gpointer filter_data)
{
- struct smtp_filter *new;
+ struct smtp_filter *new;
new = rspamd_mempool_alloc (ctx->pool, sizeof (struct smtp_filter));
@@ -941,10 +1027,11 @@ register_smtp_filter (struct smtp_worker_ctx *ctx, enum rspamd_smtp_stage stage,
msg_err ("invalid smtp stage: %d", stage);
}
else {
- ctx->smtp_filters[stage] = g_list_prepend (ctx->smtp_filters[stage], new);
+ ctx->smtp_filters[stage] =
+ g_list_prepend (ctx->smtp_filters[stage], new);
}
}
-/*
- * vi:ts=4
+/*
+ * vi:ts=4
*/