aboutsummaryrefslogtreecommitdiffstats
path: root/src/protocol.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2014-01-18 18:20:54 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2014-01-18 18:20:54 +0000
commite2f2eed337ecdb17c897fe7e04626dfffe32f2a2 (patch)
tree25f39a0aef9ed9eacc117407cc3824b16acccb9c /src/protocol.c
parentf5933d697d2cd9854afcbc7421efda353e165aea (diff)
downloadrspamd-e2f2eed337ecdb17c897fe7e04626dfffe32f2a2.tar.gz
rspamd-e2f2eed337ecdb17c897fe7e04626dfffe32f2a2.zip
Parse HTTP requests, cleanup the code.
--HG-- extra : rebase_source : 6b35fbf55fc9fe65d7f033620670bb210928e9b4
Diffstat (limited to 'src/protocol.c')
-rw-r--r--src/protocol.c659
1 files changed, 198 insertions, 461 deletions
diff --git a/src/protocol.c b/src/protocol.c
index 02ba94e39..3351a5195 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -97,161 +97,109 @@
static GList *custom_commands = NULL;
-/* XXX: remove this legacy sometimes */
-static const gchar *
-str_action_metric_spamc (enum rspamd_metric_action action)
-{
- switch (action) {
- case METRIC_ACTION_REJECT:
- return "reject";
- case METRIC_ACTION_SOFT_REJECT:
- return "soft reject";
- case METRIC_ACTION_REWRITE_SUBJECT:
- return "rewrite subject";
- case METRIC_ACTION_ADD_HEADER:
- return "add header";
- case METRIC_ACTION_GREYLIST:
- return "greylist";
- case METRIC_ACTION_NOACTION:
- return "no action";
- case METRIC_ACTION_MAX:
- return "invalid max action";
- }
- return "unknown action";
-}
-
-static inline const gchar *
-rspamc_proto_str (guint ver)
+/*
+ * Remove <> from the fixed string and copy it to the pool
+ */
+static gchar *
+rspamd_protocol_escape_braces (GString *in)
{
+ gint len = 0;
+ gchar *orig, *p;
- if (G_LIKELY (ver == 12)) {
- return "1.2";
+ orig = in->str;
+ while ((g_ascii_isspace (*orig) || *orig == '<') && orig - in->str < (gint)in->len) {
+ orig ++;
}
- else if (G_UNLIKELY (ver == 11)) {
- return "1.1";
- }
- else if (G_UNLIKELY (ver == 13)) {
- return "1.3";
- }
- else if (G_UNLIKELY (ver == 14)) {
- return "1.4";
- }
- else if (G_UNLIKELY (ver == 15)) {
- return "1.5";
- }
- else {
- return "1.0";
- }
-}
-gchar *
-separate_command (f_str_t * in, gchar c)
-{
- guint r = 0;
- gchar *p = in->begin, *b;
- b = p;
+ g_string_erase (in, 0, orig - in->str);
- while (r < in->len) {
- if (*p == c) {
- *p = '\0';
- in->begin = p + 1;
- in->len -= r + 1;
- return b;
- }
- else if (*p == '\0') {
- /* Actually we cannot allow several \0 characters in string, so write to the log about it */
- msg_warn ("cannot separate command with \0 character, this can be an attack attempt");
- return NULL;
- }
- p++;
- r++;
+ p = orig;
+ while ((!g_ascii_isspace (*p) && *p != '>') && p - in->str < (gint)in->len) {
+ p ++;
+ len ++;
}
- return NULL;
+ g_string_truncate (in, len);
+
+ return in->str;
}
static gboolean
-parse_check_command (struct worker_task *task, gchar *token)
+rspamd_protocol_handle_url (struct worker_task *task, struct rspamd_http_message *msg)
{
GList *cur;
struct custom_command *cmd;
+ const gchar *p;
+
+ if (msg->url == NULL || msg->url->len == 0) {
+ task->last_error = "command is absent";
+ task->error_code = 400;
+ return FALSE;
+ }
+
+ if (msg->url->str[0] == '/') {
+ p = &msg->url->str[1];
+ }
+ else {
+ p = msg->url->str;
+ }
- switch (token[0]) {
+ switch (*p) {
case 'c':
case 'C':
/* check */
- if (g_ascii_strcasecmp (token + 1, MSG_CMD_CHECK + 1) == 0) {
+ if (g_ascii_strcasecmp (p + 1, MSG_CMD_CHECK + 1) == 0) {
task->cmd = CMD_CHECK;
}
else {
- debug_task ("bad command: %s", token);
- return FALSE;
+ goto err;
}
break;
case 's':
case 'S':
/* symbols, skip */
- if (g_ascii_strcasecmp (token + 1, MSG_CMD_SYMBOLS + 1) == 0) {
+ if (g_ascii_strcasecmp (p + 1, MSG_CMD_SYMBOLS + 1) == 0) {
task->cmd = CMD_SYMBOLS;
}
- else if (g_ascii_strcasecmp (token + 1, MSG_CMD_SKIP + 1) == 0) {
+ else if (g_ascii_strcasecmp (p + 1, MSG_CMD_SKIP + 1) == 0) {
task->cmd = CMD_SKIP;
}
else {
- debug_task ("bad command: %s", token);
- return FALSE;
+ goto err;
}
break;
case 'p':
case 'P':
/* ping, process */
- if (g_ascii_strcasecmp (token + 1, MSG_CMD_PING + 1) == 0) {
+ if (g_ascii_strcasecmp (p + 1, MSG_CMD_PING + 1) == 0) {
task->cmd = CMD_PING;
}
- else if (g_ascii_strcasecmp (token + 1, MSG_CMD_PROCESS + 1) == 0) {
+ else if (g_ascii_strcasecmp (p + 1, MSG_CMD_PROCESS + 1) == 0) {
task->cmd = CMD_PROCESS;
}
else {
- debug_task ("bad command: %s", token);
- return FALSE;
+ goto err;
}
break;
case 'r':
case 'R':
/* report, report_ifspam */
- if (g_ascii_strcasecmp (token + 1, MSG_CMD_REPORT + 1) == 0) {
+ if (g_ascii_strcasecmp (p + 1, MSG_CMD_REPORT + 1) == 0) {
task->cmd = CMD_REPORT;
}
- else if (g_ascii_strcasecmp (token + 1, MSG_CMD_REPORT_IFSPAM + 1) == 0) {
+ else if (g_ascii_strcasecmp (p + 1, MSG_CMD_REPORT_IFSPAM + 1) == 0) {
task->cmd = CMD_REPORT_IFSPAM;
}
else {
- debug_task ("bad command: %s", token);
- return FALSE;
- }
- break;
- case 'l':
- case 'L':
- if (g_ascii_strcasecmp (token + 1, MSG_CMD_LEARN + 1) == 0) {
- if (task->allow_learn) {
- task->cmd = CMD_LEARN;
- }
- else {
- msg_info ("learning is disabled");
- return FALSE;
- }
- }
- else {
- debug_task ("bad command: %s", token);
- return FALSE;
+ goto err;
}
break;
default:
cur = custom_commands;
while (cur) {
cmd = cur->data;
- if (g_ascii_strcasecmp (token, cmd->name) == 0) {
+ if (g_ascii_strcasecmp (p, cmd->name) == 0) {
task->cmd = CMD_OTHER;
task->custom_cmd = cmd;
break;
@@ -260,402 +208,191 @@ parse_check_command (struct worker_task *task, gchar *token)
}
if (cur == NULL) {
- debug_task ("bad command: %s", token);
- return FALSE;
+ goto err;
}
break;
}
return TRUE;
+
+err:
+ debug_task ("bad command: %s", p);
+ task->last_error = "invalid command";
+ task->error_code = 400;
+ return FALSE;
}
static gboolean
-parse_rspamc_command (struct worker_task *task, f_str_t * line)
+rspamd_protocol_handle_headers (struct worker_task *task, struct rspamd_http_message *msg)
{
- gchar *token;
+ gchar *headern, *err, *tmp;
+ gboolean res = TRUE;
+ struct rspamd_http_header *h;
- /* Separate line */
- token = separate_command (line, ' ');
- if (line == NULL || token == NULL) {
- debug_task ("bad command");
- return FALSE;
- }
+ LL_FOREACH (msg->headers, h) {
+ headern = h->name->str;
- if (!parse_check_command (task, token)) {
- return FALSE;
- }
-
- if (g_ascii_strncasecmp (line->begin, RSPAMC_GREETING, sizeof (RSPAMC_GREETING) - 1) == 0) {
- task->proto = RSPAMC_PROTO;
- task->proto_ver = 10;
- if (*(line->begin + sizeof (RSPAMC_GREETING) - 1) == '/') {
- /* Extract protocol version */
- token = line->begin + sizeof (RSPAMC_GREETING);
- if (strncmp (token, RSPAMC_PROTO_1_1, sizeof (RSPAMC_PROTO_1_1) - 1) == 0) {
- task->proto_ver = 11;
+ switch (headern[0]) {
+ case 'd':
+ case 'D':
+ if (g_ascii_strcasecmp (headern, DELIVER_TO_HEADER) == 0) {
+ task->deliver_to = rspamd_protocol_escape_braces (h->value);
+ debug_task ("read deliver-to header, value: %s", task->deliver_to);
}
- else if (strncmp (token, RSPAMC_PROTO_1_2, sizeof (RSPAMC_PROTO_1_2) - 1) == 0) {
- task->proto_ver = 12;
+ else {
+ debug_task ("wrong header: %s", headern);
+ res = FALSE;
}
- else if (strncmp (token, RSPAMC_PROTO_1_3, sizeof (RSPAMC_PROTO_1_3) - 1) == 0) {
- task->proto_ver = 13;
+ break;
+ case 'h':
+ case 'H':
+ if (g_ascii_strcasecmp (headern, HELO_HEADER) == 0) {
+ task->helo = h->value->str;
+ debug_task ("read helo header, value: %s", task->helo);
}
- }
- }
- else if (g_ascii_strncasecmp (line->begin, SPAMC_GREETING, sizeof (SPAMC_GREETING) - 1) == 0) {
- task->proto = SPAMC_PROTO;
- task->proto_ver = 12;
- }
- else {
- return FALSE;
- }
-
- task->state = READ_HEADER;
-
- return TRUE;
-}
-
-static gboolean
-parse_http_command (struct worker_task *task, f_str_t * line)
-{
- guint8 *p, *end, *c;
- gint state = 0, next_state = 0;
- gchar *cmd;
-
- p = line->begin;
- c = p;
- end = p + line->len;
- task->proto = RSPAMC_PROTO;
-
- while (p < end) {
- switch (state) {
- case 0:
- /* Expect GET or POST here */
- if ((end - p > 3 &&
- (*p == 'G' || *p == 'g') &&
- (p[1] == 'E' || p[1] == 'e') &&
- (p[2] == 'T' || p[2] == 't')) ||
- (end - p > 4 &&
- (*p == 'P' || *p == 'p') &&
- (p[1] == 'O' || p[1] == 'o') &&
- (p[2] == 'S' || p[2] == 's') &&
- (p[3] == 'T' || p[3] == 't'))) {
- state = 99;
- next_state = 1;
- p += (*p == 'g' || *p == 'G') ? 3 : 4;
+ else if (g_ascii_strcasecmp (headern, HOSTNAME_HEADER) == 0) {
+ task->hostname = h->value->str;
+ debug_task ("read hostname header, value: %s", task->hostname);
}
else {
- msg_info ("invalid HTTP request: %V", line);
- return FALSE;
+ debug_task ("wrong header: %s", headern);
+ res = FALSE;
}
break;
- case 1:
- /* Get command or path */
- if (!g_ascii_isspace (*p)) {
- p ++;
+ case 'f':
+ case 'F':
+ if (g_ascii_strcasecmp (headern, FROM_HEADER) == 0) {
+ task->from = rspamd_protocol_escape_braces (h->value);
+ debug_task ("read from header, value: %s", task->from);
}
else {
- /* Copy command */
- cmd = memory_pool_alloc (task->task_pool, p - c + 1);
- rspamd_strlcpy (cmd, c, p - c + 1);
- /* Skip the first '/' */
- if (*cmd == '/') {
- cmd ++;
- }
- if (!parse_check_command (task, cmd)) {
- /* Assume that command is symbols */
- task->cmd = CMD_SYMBOLS;
- }
- state = 99;
- next_state = 2;
+ debug_task ("wrong header: %s", headern);
+ res = FALSE;
}
break;
- case 2:
- /* Get HTTP/1.0 or HTTP/1.1 */
- if (p == end - 1) {
- /* We are at the end */
- if (g_ascii_strncasecmp (c, "HTTP/1.0", sizeof ("HTTP/1.0") - 1) == 0 ||
- g_ascii_strncasecmp (c, "HTTP/1.1", sizeof ("HTTP/1.1") - 1) == 0) {
- task->state = READ_HEADER;
- return TRUE;
- }
+ case 'j':
+ case 'J':
+ if (g_ascii_strcasecmp (headern, JSON_HEADER) == 0) {
+ task->is_json = parse_flag (h->value->str);
}
else {
- p ++;
+ debug_task ("wrong header: %s", headern);
+ res = FALSE;
}
break;
- case 99:
- /* Skip spaces */
- if (g_ascii_isspace (*p)) {
- p ++;
+ case 'q':
+ case 'Q':
+ if (g_ascii_strcasecmp (headern, QUEUE_ID_HEADER) == 0) {
+ task->queue_id = h->value->str;
+ debug_task ("read queue_id header, value: %s", task->queue_id);
}
else {
- state = next_state;
- c = p;
+ debug_task ("wrong header: %s", headern);
+ res = FALSE;
}
break;
- }
- }
-
- return FALSE;
-}
-
-static gboolean
-parse_command (struct worker_task *task, f_str_t * line)
-{
- task->proto_ver = 11;
-
- if (! task->is_http) {
- return parse_rspamc_command (task, line);
- }
- else {
- return parse_http_command (task, line);
- }
-
- /* Unreached */
- return FALSE;
-}
-
-static gboolean
-parse_header (struct worker_task *task, f_str_t * line)
-{
- gchar *headern, *err, *tmp;
- gboolean res = TRUE;
-
- /* Check end of headers */
- if (line->len == 0) {
- debug_task ("got empty line, assume it as end of headers");
- if (task->cmd == CMD_PING || task->cmd == CMD_SKIP) {
- task->state = WRITE_REPLY;
- }
- else {
- if (task->content_length > 0) {
- if (task->cmd == CMD_LEARN) {
- if (task->statfile != NULL) {
- rspamd_set_dispatcher_policy (task->dispatcher, BUFFER_CHARACTER, task->content_length);
- task->state = READ_MESSAGE;
- }
- else {
- task->last_error = "Unknown statfile";
- task->error_code = RSPAMD_STATFILE_ERROR;
- task->state = WRITE_ERROR;
- return FALSE;
- }
- }
- else {
- rspamd_set_dispatcher_policy (task->dispatcher, BUFFER_CHARACTER, task->content_length);
- task->state = READ_MESSAGE;
- task->msg = memory_pool_alloc0 (task->task_pool, sizeof (f_str_t));
- }
+ case 'r':
+ case 'R':
+ if (g_ascii_strcasecmp (headern, RCPT_HEADER) == 0) {
+ tmp = rspamd_protocol_escape_braces (h->value);
+ task->rcpt = g_list_prepend (task->rcpt, tmp);
+ debug_task ("read rcpt header, value: %s", tmp);
}
- else if (task->cmd != CMD_LEARN && task->cmd != CMD_OTHER) {
- rspamd_set_dispatcher_policy (task->dispatcher, BUFFER_ANY, 0);
- task->state = READ_MESSAGE;
- task->msg = memory_pool_alloc0 (task->task_pool, sizeof (f_str_t));
+ else if (g_ascii_strcasecmp (headern, NRCPT_HEADER) == 0) {
+ task->nrcpt = strtoul (h->value->str, &err, 10);
+ debug_task ("read rcpt header, value: %d", (gint)task->nrcpt);
}
else {
- task->last_error = "Unknown content length";
- task->error_code = RSPAMD_LENGTH_ERROR;
- task->state = WRITE_ERROR;
- return FALSE;
+ msg_info ("wrong header: %s", headern);
+ res = FALSE;
}
- }
- return TRUE;
- }
-
- headern = separate_command (line, ':');
-
- if (line == NULL || headern == NULL) {
- return FALSE;
- }
- /* Eat whitespaces */
- g_strstrip (headern);
- fstrstrip (line);
-
- switch (headern[0]) {
- case 'c':
- case 'C':
- /* content-length */
- if (g_ascii_strncasecmp (headern, CONTENT_LENGTH_HEADER, sizeof (CONTENT_LENGTH_HEADER) - 1) == 0) {
- if (task->content_length == 0) {
- tmp = memory_pool_fstrdup (task->task_pool, line);
- task->content_length = strtoul (tmp, &err, 10);
- debug_task ("read Content-Length header, value: %ul", (guint32)task->content_length);
- }
- }
- else {
- msg_info ("wrong header: %s", headern);
- res = FALSE;
- }
- break;
- case 'd':
- case 'D':
- /* Deliver-To */
- if (g_ascii_strncasecmp (headern, DELIVER_TO_HEADER, sizeof (DELIVER_TO_HEADER) - 1) == 0) {
- task->deliver_to = escape_braces_addr_fstr (task->task_pool, line);
- debug_task ("read deliver-to header, value: %s", task->deliver_to);
- }
- else {
- msg_info ("wrong header: %s", headern);
- res = FALSE;
- }
- break;
- case 'h':
- case 'H':
- /* helo */
- if (g_ascii_strncasecmp (headern, HELO_HEADER, sizeof (HELO_HEADER) - 1) == 0) {
- task->helo = memory_pool_fstrdup (task->task_pool, line);
- debug_task ("read helo header, value: %s", task->helo);
- }
- else if (g_ascii_strncasecmp (headern, HOSTNAME_HEADER, sizeof (HOSTNAME_HEADER) - 1) == 0) {
- task->hostname = memory_pool_fstrdup (task->task_pool, line);
- debug_task ("read hostname header, value: %s", task->hostname);
- }
- else {
- msg_info ("wrong header: %s", headern);
- res = FALSE;
- }
- break;
- case 'f':
- case 'F':
- /* from */
- if (g_ascii_strncasecmp (headern, FROM_HEADER, sizeof (FROM_HEADER) - 1) == 0) {
- task->from = escape_braces_addr_fstr (task->task_pool, line);
- debug_task ("read from header, value: %s", task->from);
- }
- else {
- msg_info ("wrong header: %s", headern);
- res = FALSE;
- }
- break;
- case 'j':
- case 'J':
- /* json */
- if (g_ascii_strncasecmp (headern, JSON_HEADER, sizeof (JSON_HEADER) - 1) == 0) {
- task->is_json = parse_flag (memory_pool_fstrdup (task->task_pool, line));
- }
- else {
- msg_info ("wrong header: %s", headern);
- res = FALSE;
- }
- break;
- case 'q':
- case 'Q':
- /* Queue id */
- if (g_ascii_strncasecmp (headern, QUEUE_ID_HEADER, sizeof (QUEUE_ID_HEADER) - 1) == 0) {
- task->queue_id = memory_pool_fstrdup (task->task_pool, line);
- debug_task ("read queue_id header, value: %s", task->queue_id);
- }
- else {
- msg_info ("wrong header: %s", headern);
- res = FALSE;
- }
- break;
- case 'r':
- case 'R':
- /* rcpt */
- if (g_ascii_strncasecmp (headern, RCPT_HEADER, sizeof (RCPT_HEADER) - 1) == 0) {
- tmp = escape_braces_addr_fstr (task->task_pool, line);
- task->rcpt = g_list_prepend (task->rcpt, tmp);
- debug_task ("read rcpt header, value: %s", tmp);
- }
- else if (g_ascii_strncasecmp (headern, NRCPT_HEADER, sizeof (NRCPT_HEADER) - 1) == 0) {
- tmp = memory_pool_fstrdup (task->task_pool, line);
- task->nrcpt = strtoul (tmp, &err, 10);
- debug_task ("read rcpt header, value: %d", (gint)task->nrcpt);
- }
- else {
- msg_info ("wrong header: %s", headern);
- res = FALSE;
- }
- break;
- case 'i':
- case 'I':
- /* ip_addr */
- if (g_ascii_strncasecmp (headern, IP_ADDR_HEADER, sizeof (IP_ADDR_HEADER) - 1) == 0) {
- tmp = memory_pool_fstrdup (task->task_pool, line);
+ break;
+ case 'i':
+ case 'I':
+ if (g_ascii_strcasecmp (headern, IP_ADDR_HEADER) == 0) {
+ tmp = h->value->str;
#ifdef HAVE_INET_PTON
- if (g_ascii_strncasecmp (tmp, "IPv6:", 5) == 0) {
- if (inet_pton (AF_INET6, tmp + 6, &task->from_addr.d.in6) == 1) {
- task->from_addr.ipv6 = TRUE;
- }
- else {
- msg_err ("bad ip header: '%s'", tmp);
- return FALSE;
- }
- task->from_addr.has_addr = TRUE;
- }
- else {
- if (inet_pton (AF_INET, tmp, &task->from_addr.d.in4) != 1) {
- /* Try ipv6 */
- if (inet_pton (AF_INET6, tmp, &task->from_addr.d.in6) == 1) {
+ if (g_ascii_strncasecmp (tmp, "IPv6:", 5) == 0) {
+ if (inet_pton (AF_INET6, tmp + 6, &task->from_addr.d.in6) == 1) {
task->from_addr.ipv6 = TRUE;
}
else {
msg_err ("bad ip header: '%s'", tmp);
return FALSE;
}
+ task->from_addr.has_addr = TRUE;
}
else {
- task->from_addr.ipv6 = FALSE;
+ if (inet_pton (AF_INET, tmp, &task->from_addr.d.in4) != 1) {
+ /* Try ipv6 */
+ if (inet_pton (AF_INET6, tmp, &task->from_addr.d.in6) == 1) {
+ task->from_addr.ipv6 = TRUE;
+ }
+ else {
+ msg_err ("bad ip header: '%s'", tmp);
+ return FALSE;
+ }
+ }
+ else {
+ task->from_addr.ipv6 = FALSE;
+ }
+ task->from_addr.has_addr = TRUE;
}
- task->from_addr.has_addr = TRUE;
- }
#else
- if (!inet_aton (tmp, &task->from_addr)) {
- msg_err ("bad ip header: '%s'", tmp);
- return FALSE;
- }
+ if (!inet_aton (tmp, &task->from_addr)) {
+ msg_err ("bad ip header: '%s'", tmp);
+ return FALSE;
+ }
#endif
- debug_task ("read IP header, value: %s", tmp);
- }
- else {
- msg_info ("wrong header: %s", headern);
- res = FALSE;
- }
- break;
- case 'p':
- case 'P':
- /* Pass header */
- if (g_ascii_strncasecmp (headern, PASS_HEADER, sizeof (PASS_HEADER) - 1) == 0) {
- if (line->len == sizeof ("all") - 1 && g_ascii_strncasecmp (line->begin, "all", sizeof ("all") - 1) == 0) {
- task->pass_all_filters = TRUE;
- msg_info ("pass all filters");
- }
- }
- else {
- res = FALSE;
- }
- break;
- case 's':
- case 'S':
- if (g_ascii_strncasecmp (headern, SUBJECT_HEADER, sizeof (SUBJECT_HEADER) - 1) == 0) {
- task->subject = memory_pool_fstrdup (task->task_pool, line);
- }
- else if (g_ascii_strncasecmp (headern, STATFILE_HEADER, sizeof (STATFILE_HEADER) - 1) == 0) {
- task->statfile = memory_pool_fstrdup (task->task_pool, line);
- }
- else {
- res = FALSE;
- }
- break;
- case 'u':
- case 'U':
- if (g_ascii_strncasecmp (headern, USER_HEADER, sizeof (USER_HEADER) - 1) == 0) {
- task->user = memory_pool_fstrdup (task->task_pool, line);
- }
- else {
+ debug_task ("read IP header, value: %s", tmp);
+ }
+ else {
+ debug_task ("wrong header: %s", headern);
+ res = FALSE;
+ }
+ break;
+ case 'p':
+ case 'P':
+ if (g_ascii_strcasecmp (headern, PASS_HEADER) == 0) {
+ if (h->value->len == sizeof ("all") - 1 &&
+ g_ascii_strcasecmp (h->value->str, "all") == 0) {
+ task->pass_all_filters = TRUE;
+ debug_task ("pass all filters");
+ }
+ }
+ else {
+ res = FALSE;
+ }
+ break;
+ case 's':
+ case 'S':
+ if (g_ascii_strcasecmp (headern, SUBJECT_HEADER) == 0) {
+ task->subject = h->value->str;
+ }
+ else {
+ res = FALSE;
+ }
+ break;
+ case 'u':
+ case 'U':
+ if (g_ascii_strcasecmp (headern, USER_HEADER) == 0) {
+ task->user = h->value->str;
+ }
+ else {
+ res = FALSE;
+ }
+ break;
+ default:
+ debug_task ("wrong header: %s", headern);
res = FALSE;
+ break;
}
- break;
- default:
- msg_info ("wrong header: %s", headern);
- res = FALSE;
- break;
}
if (!res && task->cfg->strict_protocol_headers) {
msg_err ("deny processing of a request with incorrect or unknown headers");
+ task->last_error = "invalid header";
+ task->error_code = 400;
return FALSE;
}
@@ -663,18 +400,13 @@ parse_header (struct worker_task *task, f_str_t * line)
}
gboolean
-read_rspamd_input_line (struct worker_task *task, f_str_t * line)
+rspamd_protocol_handle_request (struct worker_task *task,
+ struct rspamd_http_message *msg)
{
- switch (task->state) {
- case READ_COMMAND:
- return parse_command (task, line);
- break;
- case READ_HEADER:
- return parse_header (task, line);
- break;
- default:
- return FALSE;
+ if (rspamd_protocol_handle_url (task, msg)) {
+ return rspamd_protocol_handle_headers (task, msg);
}
+
return FALSE;
}
@@ -878,7 +610,17 @@ rspamd_metric_result_ucl (struct worker_task *task, struct metric_result *mres,
if (logbuf->str[logbuf->len - 1] == ',') {
logbuf->len --;
}
- rspamd_printf_gstring (logbuf, "]), ");
+
+#ifdef HAVE_CLOCK_GETTIME
+ rspamd_printf_gstring (logbuf, "]), len: %z, time: %s, dns req: %d,",
+ task->msg->len, calculate_check_time (&task->tv, &task->ts,
+ task->cfg->clock_res, &task->scan_milliseconds), task->dns_requests);
+#else
+ rspamd_printf_gstring (logbuf, "]), len: %z, time: %s, dns req: %d,",
+ task->msg->len,
+ calculate_check_time (&task->tv, task->cfg->clock_res, &task->scan_milliseconds),
+ task->dns_requests);
+#endif
return obj;
}
@@ -992,10 +734,12 @@ write_check_reply (struct rspamd_http_message *msg, struct worker_task *task)
write_hashes_to_log (task, logbuf);
msg_info ("%v", logbuf);
+ g_string_free (logbuf, TRUE);
msg->body = g_string_sized_new (BUFSIZ);
func.ud = msg->body;
ucl_object_emit_full (top, UCL_EMIT_JSON_COMPACT, &func);
+ ucl_object_unref (top);
/* Increase counters */
task->worker->srv->stat->messages_scanned++;
@@ -1006,7 +750,7 @@ write_check_reply (struct rspamd_http_message *msg, struct worker_task *task)
}
gboolean
-write_reply (struct worker_task *task)
+rspamd_protocol_write_reply (struct worker_task *task)
{
struct rspamd_http_message *msg;
@@ -1038,13 +782,6 @@ write_reply (struct worker_task *task)
"text/plain", task, task->sock, &task->tv, task->ev_base);
task->state = CLOSING_CONNECTION;
break;
- case CMD_LEARN:
- msg->code = task->error_code;
- rspamd_http_connection_write_message (task->http_conn, msg, NULL,
- "text/plain", task, task->sock, &task->tv, task->ev_base);
- task->state = CLOSING_CONNECTION;
- return TRUE;
- break;
case CMD_OTHER:
task->state = CLOSING_CONNECTION;
return task->custom_cmd->func (task);