コード例 #1
0
void
rspamd_controller_send_ucl (struct rspamd_http_connection_entry *entry,
	ucl_object_t *obj)
{
	struct rspamd_http_message *msg;
	rspamd_fstring_t *reply;

	msg = rspamd_http_new_message (HTTP_RESPONSE);
	msg->date = time (NULL);
	msg->code = 200;
	msg->status = rspamd_fstring_new_init ("OK", 2);
	reply = rspamd_fstring_sized_new (BUFSIZ);
	rspamd_ucl_emit_fstring (obj, UCL_EMIT_JSON_COMPACT, &reply);
	rspamd_http_message_set_body_from_fstring_steal (msg, reply);
	rspamd_http_connection_reset (entry->conn);
	rspamd_http_router_insert_headers (entry->rt, msg);
	rspamd_http_connection_write_message (entry->conn,
		msg,
		NULL,
		"application/json",
		entry,
		entry->conn->fd,
		entry->rt->ptv,
		entry->rt->ev_base);
	entry->is_reply = TRUE;
}
コード例 #2
0
void
rspamd_controller_send_error (struct rspamd_http_connection_entry *entry,
	gint code, const gchar *error_msg, ...)
{
	struct rspamd_http_message *msg;
	va_list args;
	rspamd_fstring_t *reply;

	msg = rspamd_http_new_message (HTTP_RESPONSE);

	va_start (args, error_msg);
	msg->status = rspamd_fstring_new ();
	rspamd_vprintf_fstring (&msg->status, error_msg, args);
	va_end (args);

	msg->date = time (NULL);
	msg->code = code;
	reply = rspamd_fstring_sized_new (msg->status->len + 16);
	rspamd_printf_fstring (&reply, "{\"error\":\"%V\"}", msg->status);
	rspamd_http_message_set_body_from_fstring_steal (msg, reply);
	rspamd_http_connection_reset (entry->conn);
	rspamd_http_router_insert_headers (entry->rt, msg);
	rspamd_http_connection_write_message (entry->conn,
		msg,
		NULL,
		"application/json",
		entry,
		entry->conn->fd,
		entry->rt->ptv,
		entry->rt->ev_base);
	entry->is_reply = TRUE;
}
コード例 #3
0
ファイル: lua_rsa.c プロジェクト: bryongloden/rspamd
/**
 * Sign file using specified rsa key and signature
 *
 * arguments:
 * (rsa_privkey, rsa_signature, string)
 *
 * returns:
 * true - if string match rsa signature
 * false - otherwise
 */
static gint
lua_rsa_sign_file (lua_State *L)
{
	RSA *rsa;
	rspamd_fstring_t *signature, **psig;
	const gchar *filename;
	gchar *data = NULL, *data_sig;
	gint ret, fd;
	struct stat st;

	rsa = lua_check_rsa_privkey (L, 1);
	filename = luaL_checkstring (L, 2);

	if (rsa != NULL && filename != NULL) {
		fd = open (filename, O_RDONLY);
		if (fd == -1) {
			msg_err ("cannot open file %s: %s", filename, strerror (errno));
			lua_pushnil (L);
		}
		else {
			if (fstat (fd, &st) == -1 ||
				(data =
				mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd,
				0)) == MAP_FAILED) {
				msg_err ("cannot mmap file %s: %s", filename, strerror (errno));
				lua_pushnil (L);
			}
			else {
				signature = rspamd_fstring_sized_new (RSA_size (rsa));
				data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256,
						data,
						st.st_size);
				ret = RSA_sign (NID_sha1, data_sig, strlen (data_sig),
						signature->str, (guint *)&signature->len, rsa);
				if (ret == 0) {
					msg_info ("cannot make a signature for data: %s",
						ERR_error_string (ERR_get_error (), NULL));
					lua_pushnil (L);
					rspamd_fstring_free (signature);
				}
				else {
					psig = lua_newuserdata (L, sizeof (rspamd_fstring_t *));
					rspamd_lua_setclass (L, "rspamd{rsa_signature}", -1);
					*psig = signature;
				}
				g_free (data_sig);
				munmap (data, st.st_size);
			}
			close (fd);
		}
	}
	else {
		lua_pushnil (L);
	}

	return 1;
}
コード例 #4
0
static int
rspamd_server_finish (struct rspamd_http_connection *conn,
		struct rspamd_http_message *msg)
{
	struct rspamd_http_server_session *session = conn->ud;
	struct rspamd_http_message *reply;
	gulong size;
	const gchar *url_str;
	guint url_len;
	rspamd_fstring_t *body;

	if (!session->reply) {
		session->reply = TRUE;
		reply = rspamd_http_new_message (HTTP_RESPONSE);
		url_str = msg->url->str;
		url_len = msg->url->len;

		if (url_str[0] == '/') {
			url_str ++;
			url_len --;
		}

		if (rspamd_strtoul (url_str, url_len, &size)) {
			session->req_size = size;

			reply->code = 200;
			reply->status = rspamd_fstring_new_init ("OK", 2);
			body = rspamd_fstring_sized_new (size);
			body->len = size;
			memset (body->str, 0, size);
			rspamd_http_message_set_body_from_fstring_steal (msg, body);

		}
		else {
			reply->code = 404;
			reply->status = rspamd_fstring_new_init ("Not found", 9);
		}

		rspamd_http_connection_reset (conn);
		rspamd_http_connection_write_message (conn, reply, NULL,
				"application/octet-stream", session, session->fd,
				&io_tv, session->ev_base);
	}
	else {
		/* Destroy session */
		rspamd_http_connection_unref (conn);
		close (session->fd);
		g_slice_free1 (sizeof (*session), session);
	}

	return 0;
}
コード例 #5
0
ファイル: lua_cryptobox.c プロジェクト: cequencer/rspamd
/***
 * @function rspamd_cryptobox.sign_memory(kp, data)
 * Sign data using specified keypair
 * @param {keypair} kp keypair to sign
 * @param {string} data
 * @return {cryptobox_signature} signature object
 */
static gint
lua_cryptobox_sign_memory (lua_State *L)
{
	struct rspamd_cryptobox_keypair *kp;
	const gchar *data;
	struct rspamd_lua_text *t;
	gsize len = 0;
	rspamd_fstring_t *sig, **psig;

	kp = lua_check_cryptobox_keypair (L, 1);

	if (lua_isuserdata (L, 2)) {
		t = lua_check_text (L, 2);

		if (!t) {
			return luaL_error (L, "invalid arguments");
		}

		data = t->start;
		len = t->len;
	}
	else {
		data = luaL_checklstring (L, 2, &len);
	}


	if (!kp || !data) {
		return luaL_error (L, "invalid arguments");
	}

	sig = rspamd_fstring_sized_new (rspamd_cryptobox_signature_bytes (
			rspamd_keypair_alg (kp)));
	rspamd_cryptobox_sign (sig->str, &sig->len, data,
			len, rspamd_keypair_component (kp, RSPAMD_KEYPAIR_COMPONENT_SK,
					NULL), rspamd_keypair_alg (kp));

	psig = lua_newuserdata (L, sizeof (void *));
	*psig = sig;
	rspamd_lua_setclass (L, "rspamd{cryptobox_signature}", -1);

	return 1;
}
コード例 #6
0
ファイル: lua_cryptobox.c プロジェクト: cequencer/rspamd
/***
 * @function rspamd_cryptobox.sign_file(kp, file)
 * Sign file using specified keypair
 * @param {keypair} kp keypair to sign
 * @param {string} filename
 * @return {cryptobox_signature} signature object
 */
static gint
lua_cryptobox_sign_file (lua_State *L)
{
	struct rspamd_cryptobox_keypair *kp;
	const gchar *filename;
	gchar *data;
	gsize len = 0;
	rspamd_fstring_t *sig, **psig;

	kp = lua_check_cryptobox_keypair (L, 1);
	filename = luaL_checkstring (L, 2);

	if (!kp || !filename) {
		return luaL_error (L, "invalid arguments");
	}

	data = rspamd_file_xmap (filename, PROT_READ, &len);

	if (data == NULL) {
		msg_err ("cannot mmap file %s: %s", filename, strerror (errno));
		lua_pushnil (L);
	}
	else {
		sig = rspamd_fstring_sized_new (rspamd_cryptobox_signature_bytes (
				rspamd_keypair_alg (kp)));
		rspamd_cryptobox_sign (sig->str, &sig->len, data,
				len, rspamd_keypair_component (kp, RSPAMD_KEYPAIR_COMPONENT_SK,
						NULL), rspamd_keypair_alg (kp));

		psig = lua_newuserdata (L, sizeof (void *));
		*psig = sig;
		rspamd_lua_setclass (L, "rspamd{cryptobox_signature}", -1);
		munmap (data, len);
	}

	return 1;
}
コード例 #7
0
ファイル: lua_rsa.c プロジェクト: bryongloden/rspamd
/**
 * Sign memory using specified rsa key and signature
 *
 * arguments:
 * (rsa_privkey, string)
 *
 * returns:
 * rspamd_signature object
 * nil - otherwise
 */
static gint
lua_rsa_sign_memory (lua_State *L)
{
	RSA *rsa;
	rspamd_fstring_t *signature, **psig;
	const gchar *data;
	guchar *data_sig;
	gint ret;

	rsa = lua_check_rsa_privkey (L, 1);
	data = luaL_checkstring (L, 2);

	if (rsa != NULL && data != NULL) {
		signature = rspamd_fstring_sized_new (RSA_size (rsa));
		data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, -1);
		ret = RSA_sign (NID_sha1, data_sig, strlen (data_sig),
				signature->str, (guint *)&signature->len, rsa);
		if (ret == 0) {
			msg_info ("cannot make a signature for data: %s",
				ERR_error_string (ERR_get_error (), NULL));
			lua_pushnil (L);
			rspamd_fstring_free (signature);
		}
		else {
			psig = lua_newuserdata (L, sizeof (rspamd_fstring_t *));
			rspamd_lua_setclass (L, "rspamd{rsa_signature}", -1);
			*psig = signature;
		}
		g_free (data_sig);
	}
	else {
		lua_pushnil (L);
	}

	return 1;
}
コード例 #8
0
ファイル: shingles.c プロジェクト: croessner/rspamd
rspamd_shingles_from_text (GArray *input,
		const guchar key[16],
		rspamd_mempool_t *pool,
		rspamd_shingles_filter filter,
		gpointer filterd,
		enum rspamd_shingle_alg alg)
{
	struct rspamd_shingle *res;
	guint64 **hashes;
	guchar **keys;
	rspamd_fstring_t *row;
	rspamd_stat_token_t *word;
	guint64 val;
	gint i, j, k;
	gsize hlen, beg = 0;
	enum rspamd_cryptobox_fast_hash_type ht;

	if (pool != NULL) {
		res = rspamd_mempool_alloc (pool, sizeof (*res));
	}
	else {
		res = g_malloc (sizeof (*res));
	}

	row = rspamd_fstring_sized_new (256);

	/* Init hashes pipes and keys */
	hashes = g_malloc (sizeof (*hashes) * RSPAMD_SHINGLE_SIZE);
	hlen = input->len > SHINGLES_WINDOW ?
			(input->len - SHINGLES_WINDOW + 1) : 1;
	keys = rspamd_shingles_get_keys_cached (key);

	for (i = 0; i < RSPAMD_SHINGLE_SIZE; i ++) {
		hashes[i] = g_malloc (hlen * sizeof (guint64));
	}

	/* Now parse input words into a vector of hashes using rolling window */
	if (alg == RSPAMD_SHINGLES_OLD) {
		for (i = 0; i <= (gint)input->len; i ++) {
			if (i - beg >= SHINGLES_WINDOW || i == (gint)input->len) {
				for (j = beg; j < i; j ++) {
					word = &g_array_index (input, rspamd_stat_token_t, j);
					row = rspamd_fstring_append (row, word->begin, word->len);
				}

				/* Now we need to create a new row here */
				for (j = 0; j < RSPAMD_SHINGLE_SIZE; j ++) {
					rspamd_cryptobox_siphash ((guchar *)&val, row->str, row->len,
							keys[j]);
					g_assert (hlen > beg);
					hashes[j][beg] = val;
				}

				beg++;

				row = rspamd_fstring_assign (row, "", 0);
			}
		}
	}
	else {
		guint64 res[SHINGLES_WINDOW * RSPAMD_SHINGLE_SIZE], seed;

		switch (alg) {
		case RSPAMD_SHINGLES_XXHASH:
			ht = RSPAMD_CRYPTOBOX_XXHASH64;
			break;
		case RSPAMD_SHINGLES_MUMHASH:
			ht = RSPAMD_CRYPTOBOX_MUMHASH;
			break;
		default:
			ht = RSPAMD_CRYPTOBOX_HASHFAST_INDEPENDENT;
			break;
		}

		memset (res, 0, sizeof (res));
		for (i = 0; i <= (gint)input->len; i ++) {
			if (i - beg >= SHINGLES_WINDOW || i == (gint)input->len) {

				for (j = 0; j < RSPAMD_SHINGLE_SIZE; j ++) {
					/* Shift hashes window to right */
					for (k = 0; k < SHINGLES_WINDOW - 1; k ++) {
						res[j * SHINGLES_WINDOW + k] =
								res[j * SHINGLES_WINDOW + k + 1];
					}

					word = &g_array_index (input, rspamd_stat_token_t, beg);
					/* Insert the last element to the pipe */
					memcpy (&seed, keys[j], sizeof (seed));
					res[j * SHINGLES_WINDOW + SHINGLES_WINDOW - 1] =
							rspamd_cryptobox_fast_hash_specific (ht,
									word->begin, word->len,
									seed);
					val = 0;
					for (k = 0; k < SHINGLES_WINDOW; k ++) {
						val ^= res[j * SHINGLES_WINDOW + k] >>
								(8 * (SHINGLES_WINDOW - k - 1));
					}

					g_assert (hlen > beg);
					hashes[j][beg] = val;
				}
				beg++;
			}
		}
	}

	/* Now we need to filter all hashes and make a shingles result */
	for (i = 0; i < RSPAMD_SHINGLE_SIZE; i ++) {
		res->hashes[i] = filter (hashes[i], hlen,
				i, key, filterd);
		g_free (hashes[i]);
	}

	g_free (hashes);

	rspamd_fstring_free (row);

	return res;
}
コード例 #9
0
ファイル: redis_backend.c プロジェクト: moisseev/rspamd
static rspamd_fstring_t *
rspamd_redis_tokens_to_query (struct rspamd_task *task, GPtrArray *tokens,
		const gchar *arg0, const gchar *arg1, gboolean learn, gint idx,
		gboolean intvals)
{
	rspamd_fstring_t *out;
	rspamd_token_t *tok;
	gchar n0[64], n1[64];
	guint i, l0, l1, larg0, larg1;
	guint64 num;

	g_assert (tokens != NULL);

	larg0 = strlen (arg0);
	larg1 = strlen (arg1);
	out = rspamd_fstring_sized_new (1024);

	if (!learn) {
		rspamd_printf_fstring (&out, ""
				"*%d\r\n"
				"$%d\r\n"
				"%s\r\n"
				"$%d\r\n"
				"%s\r\n",
				(tokens->len + 2),
				larg0, arg0,
				larg1, arg1);
	}

	for (i = 0; i < tokens->len; i ++) {
		tok = g_ptr_array_index (tokens, i);
		memcpy (&num, tok->data, sizeof (num));

		if (learn) {
			rspamd_printf_fstring (&out, ""
					"*4\r\n"
					"$%d\r\n"
					"%s\r\n"
					"$%d\r\n"
					"%s\r\n",
					larg0, arg0,
					larg1, arg1);

			l0 = rspamd_snprintf (n0, sizeof (n0), "%uL", num);

			if (intvals) {
				l1 = rspamd_snprintf (n1, sizeof (n1), "%L",
						(gint64)tok->values[idx]);
			}
			else {
				l1 = rspamd_snprintf (n1, sizeof (n1), "%f",
						tok->values[idx]);
			}

			rspamd_printf_fstring (&out, ""
					"$%d\r\n"
					"%s\r\n"
					"$%d\r\n"
					"%s\r\n", l0, n0, l1, n1);
		}
		else {
			l0 = rspamd_snprintf (n0, sizeof (n0), "%uL", num);
			rspamd_printf_fstring (&out, ""
					"$%d\r\n"
					"%s\r\n", l0, n0);
		}
	}

	return out;
}
コード例 #10
0
ファイル: rspamdclient.c プロジェクト: moisseev/rspamd
gboolean
rspamd_client_command (struct rspamd_client_connection *conn,
                       const gchar *command, GQueue *attrs,
                       FILE *in, rspamd_client_callback cb,
                       gpointer ud, gboolean compressed,
                       const gchar *comp_dictionary,
                       GError **err)
{
    struct rspamd_client_request *req;
    struct rspamd_http_client_header *nh;
    gchar *p;
    gsize remain, old_len;
    GList *cur;
    GString *input = NULL;
    rspamd_fstring_t *body;
    guint dict_id = 0;
    gsize dict_len = 0;
    void *dict = NULL;
    ZSTD_CCtx *zctx;

    req = g_slice_alloc0 (sizeof (struct rspamd_client_request));
    req->conn = conn;
    req->cb = cb;
    req->ud = ud;

    req->msg = rspamd_http_new_message (HTTP_REQUEST);
    if (conn->key) {
        req->msg->peer_key = rspamd_pubkey_ref (conn->key);
    }

    if (in != NULL) {
        /* Read input stream */
        input = g_string_sized_new (BUFSIZ);

        while (!feof (in)) {
            p = input->str + input->len;
            remain = input->allocated_len - input->len - 1;
            if (remain == 0) {
                old_len = input->len;
                g_string_set_size (input, old_len * 2);
                input->len = old_len;
                continue;
            }
            remain = fread (p, 1, remain, in);
            if (remain > 0) {
                input->len += remain;
                input->str[input->len] = '\0';
            }
        }
        if (ferror (in) != 0) {
            g_set_error (err, RCLIENT_ERROR, ferror (
                             in), "input IO error: %s", strerror (ferror (in)));
            g_slice_free1 (sizeof (struct rspamd_client_request), req);
            g_string_free (input, TRUE);
            return FALSE;
        }

        if (!compressed) {
            body = rspamd_fstring_new_init (input->str, input->len);
        }
        else {
            if (comp_dictionary) {
                dict = rspamd_file_xmap (comp_dictionary, PROT_READ, &dict_len);

                if (dict == NULL) {
                    g_set_error (err, RCLIENT_ERROR, errno,
                                 "cannot open dictionary %s: %s",
                                 comp_dictionary,
                                 strerror (errno));
                    g_slice_free1 (sizeof (struct rspamd_client_request), req);
                    g_string_free (input, TRUE);

                    return FALSE;
                }

                dict_id = ZDICT_getDictID (comp_dictionary, dict_len);

                if (dict_id == 0) {
                    g_set_error (err, RCLIENT_ERROR, errno,
                                 "cannot open dictionary %s: %s",
                                 comp_dictionary,
                                 strerror (errno));
                    g_slice_free1 (sizeof (struct rspamd_client_request), req);
                    g_string_free (input, TRUE);
                    munmap (dict, dict_len);

                    return FALSE;
                }
            }

            body = rspamd_fstring_sized_new (ZSTD_compressBound (input->len));
            zctx = ZSTD_createCCtx ();
            body->len = ZSTD_compress_usingDict (zctx, body->str, body->allocated,
                                                 input->str, input->len,
                                                 dict, dict_len,
                                                 1);

            munmap (dict, dict_len);

            if (ZSTD_isError (body->len)) {
                g_set_error (err, RCLIENT_ERROR, ferror (
                                 in), "compression error");
                g_slice_free1 (sizeof (struct rspamd_client_request), req);
                g_string_free (input, TRUE);
                rspamd_fstring_free (body);
                ZSTD_freeCCtx (zctx);

                return FALSE;
            }

            ZSTD_freeCCtx (zctx);
        }

        rspamd_http_message_set_body_from_fstring_steal (req->msg, body);
        req->input = input;
    }
    else {
        req->input = NULL;
    }

    /* Convert headers */
    cur = attrs->head;
    while (cur != NULL) {
        nh = cur->data;

        rspamd_http_message_add_header (req->msg, nh->name, nh->value);
        cur = g_list_next (cur);
    }

    if (compressed) {
        rspamd_http_message_add_header (req->msg, "Compression", "zstd");

        if (dict_id != 0) {
            gchar dict_str[32];

            rspamd_snprintf (dict_str, sizeof (dict_str), "%ud", dict_id);
            rspamd_http_message_add_header (req->msg, "Dictionary", dict_str);
        }
    }

    req->msg->url = rspamd_fstring_append (req->msg->url, "/", 1);
    req->msg->url = rspamd_fstring_append (req->msg->url, command, strlen (command));

    conn->req = req;

    if (compressed) {
        rspamd_http_connection_write_message (conn->http_conn, req->msg, NULL,
                                              "application/x-compressed", req, conn->fd,
                                              &conn->timeout, conn->ev_base);
    }
    else {
        rspamd_http_connection_write_message (conn->http_conn, req->msg, NULL,
                                              "text/plain", req, conn->fd, &conn->timeout, conn->ev_base);
    }

    return TRUE;
}