]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Feature] Implement fuzzy collection mode
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 26 Jan 2017 15:50:16 +0000 (15:50 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 26 Jan 2017 15:50:43 +0000 (15:50 +0000)
src/fuzzy_storage.c

index d1cb2053aa938424b560cc9949370dca7b987cdf..69c48260d5db8915bb68d42cebd3d6dbeb1390da 100644 (file)
@@ -1493,11 +1493,91 @@ rspamd_fuzzy_collection_data_handler (struct rspamd_http_connection_entry *conn_
        struct rspamd_http_message *msg)
 {
        struct rspamd_fuzzy_collection_session *session = conn_ent->ud;
-       rspamd_fstring_t *cookie;
+       const rspamd_ftok_t *sign_header;
+       struct rspamd_fuzzy_storage_ctx *ctx;
+       GList *cur;
+       struct fuzzy_peer_cmd *io_cmd;
+       rspamd_fstring_t *reply;
+       GError *err = NULL;
+       guchar *decoded_signature;
+       gsize dec_len;
+       guint32 cmdlen;
 
-       cookie = rspamd_fstring_new_init (session->ctx->cookie,
-                       sizeof (session->ctx->cookie));
-       rspamd_fuzzy_collection_send_fstring (conn_ent, cookie);
+       sign_header = rspamd_http_message_find_header (msg, "Signature");
+
+       if (sign_header == NULL) {
+               rspamd_fuzzy_collection_send_error (conn_ent, 403, "Missing signature");
+
+               return 0;
+       }
+
+       ctx = session->ctx;
+
+       if (ctx->collection_sign_key == NULL) {
+               rspamd_fuzzy_collection_send_error (conn_ent, 500, "Misconfigured signature key");
+
+               return 0;
+       }
+
+       decoded_signature = g_malloc (sign_header->len * 2 + 1);
+       dec_len = rspamd_decode_hex_buf (sign_header->begin, sign_header->len,
+                       decoded_signature, sign_header->len * 2 + 1);
+
+       if (dec_len == -1 || !rspamd_keypair_verify (ctx->collection_sign_key,
+                       ctx->cookie, sizeof (ctx->cookie),
+                       decoded_signature, dec_len, &err)) {
+               if (err) {
+                       rspamd_fuzzy_collection_send_error (conn_ent, 403, "Signature verification error: %e",
+                                       err);
+                       g_error_free (err);
+               }
+               else {
+                       rspamd_fuzzy_collection_send_error (conn_ent, 403, "Signature verification error");
+               }
+
+               g_free (decoded_signature);
+
+               return 0;
+       }
+
+       g_free (decoded_signature);
+
+       /* Generate new cookie */
+       ottery_rand_bytes (ctx->cookie, sizeof (ctx->cookie));
+
+       /* Send&Clear updates */
+       cur = ctx->updates_pending->head;
+       reply = rspamd_fstring_sized_new (8192);
+
+       while (cur) {
+               io_cmd = cur->data;
+
+               if (io_cmd->is_shingle) {
+                       cmdlen = sizeof (io_cmd->cmd.shingle);
+
+               }
+               else {
+                       cmdlen = sizeof (io_cmd->cmd.normal);
+               }
+
+               cmdlen = GUINT32_TO_LE (cmdlen);
+               reply = rspamd_fstring_append (reply, (const gchar *)&cmdlen,
+                               sizeof (cmdlen));
+               reply = rspamd_fstring_append (reply, (const gchar *)&io_cmd->cmd,
+                               cmdlen);
+               g_slice_free1 (sizeof (*io_cmd), io_cmd);
+               cur = g_list_next (cur);
+       }
+
+       /* Last command */
+       cmdlen = 0;
+       reply = rspamd_fstring_append (reply, (const gchar *)&cmdlen,
+                       sizeof (cmdlen));
+
+       g_queue_clear (ctx->updates_pending);
+       /* Clear failed attempts counter */
+       ctx->updates_failed = 0;
+       rspamd_fuzzy_collection_send_fstring (conn_ent, reply);
 
        return 0;
 }