Beispiel #1
0
static gboolean
rspamd_map_check_file_sig (const char *fname,
		struct rspamd_map *map,
		struct rspamd_map_backend *bk,
		const guchar *input,
		gsize inlen)
{
	gchar fpath[PATH_MAX];
	guchar *data;
	struct rspamd_cryptobox_pubkey *pk = NULL;
	GString *b32_key;
	gboolean ret;
	gsize len = 0;

	if (bk->trusted_pubkey == NULL) {
		/* Try to load and check pubkey */
		rspamd_snprintf (fpath, sizeof (fpath), "%s.pub", fname);

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

		if (data == NULL) {
			msg_err_map ("can't open pubkey %s: %s", fpath, strerror (errno));
			return FALSE;
		}

		pk = rspamd_pubkey_from_base32 (data, len, RSPAMD_KEYPAIR_SIGN,
				RSPAMD_CRYPTOBOX_MODE_25519);
		munmap (data, len);

		if (pk == NULL) {
			msg_err_map ("can't load pubkey %s", fpath);
			return FALSE;
		}

		/* We just check pk against the trusted db of keys */
		b32_key = rspamd_pubkey_print (pk,
				RSPAMD_KEYPAIR_BASE32|RSPAMD_KEYPAIR_PUBKEY);
		g_assert (b32_key != NULL);

		if (g_hash_table_lookup (map->cfg->trusted_keys, b32_key->str) == NULL) {
			msg_err_map ("pubkey loaded from %s is untrusted: %v", fpath,
					b32_key);
			g_string_free (b32_key, TRUE);
			rspamd_pubkey_unref (pk);

			return FALSE;
		}

		g_string_free (b32_key, TRUE);
	}
	else {
		pk = rspamd_pubkey_ref (bk->trusted_pubkey);
	}

	ret = rspamd_map_check_sig_pk (fname, map, input, inlen, pk);
	rspamd_pubkey_unref (pk);

	return ret;
}
Beispiel #2
0
/***
 * @function rspamd_cryptobox_pubkey.create(data[, type[, alg]])
 * Loads public key from base32 encoded file
 * @param {base32 string} base32 string with the key
 * @param {string} type optional 'sign' or 'kex' for signing and encryption
 * @param {string} alg optional 'default' or 'nist' for curve25519/nistp256 keys
 * @return {cryptobox_pubkey} new public key
 */
static gint
lua_cryptobox_pubkey_create (lua_State *L)
{
	struct rspamd_cryptobox_pubkey *pkey = NULL, **ppkey;
	const gchar *buf, *arg;
	gsize len;
	gint type = RSPAMD_KEYPAIR_SIGN;
	gint alg = RSPAMD_CRYPTOBOX_MODE_25519;

	buf = luaL_checklstring (L, 1, &len);
	if (buf != NULL) {
		if (lua_type (L, 2) == LUA_TSTRING) {
			/* keypair type */
			arg = lua_tostring (L, 2);

			if (strcmp (arg, "sign") == 0) {
				type = RSPAMD_KEYPAIR_SIGN;
			}
			else if (strcmp (arg, "kex") == 0) {
				type = RSPAMD_KEYPAIR_KEX;
			}
		}
		if (lua_type (L, 3) == LUA_TSTRING) {
			/* algorithm */
			arg = lua_tostring (L, 3);

			if (strcmp (arg, "default") == 0 || strcmp (arg, "curve25519") == 0) {
				type = RSPAMD_CRYPTOBOX_MODE_25519;
			}
			else if (strcmp (arg, "nist") == 0) {
				type = RSPAMD_CRYPTOBOX_MODE_NIST;
			}
		}

		pkey = rspamd_pubkey_from_base32 (buf, len, type, alg);

		if (pkey == NULL) {
			msg_err ("cannot load pubkey from string");
			lua_pushnil (L);
		}
		else {
			ppkey = lua_newuserdata (L, sizeof (void *));
			rspamd_lua_setclass (L, "rspamd{cryptobox_pubkey}", -1);
			*ppkey = pkey;
		}

	}
	else {
		return luaL_error (L, "bad input arguments");
	}

	return 1;
}
Beispiel #3
0
struct rspamd_client_connection *
rspamd_client_init (struct event_base *ev_base, const gchar *name,
	guint16 port, gdouble timeout, const gchar *key)
{
	struct rspamd_client_connection *conn;
	gint fd;

	fd = rspamd_socket (name, port, SOCK_STREAM, TRUE, FALSE, TRUE);
	if (fd == -1) {
		return NULL;
	}

	conn = g_slice_alloc0 (sizeof (struct rspamd_client_connection));
	conn->ev_base = ev_base;
	conn->fd = fd;
	conn->req_sent = FALSE;
	conn->keys_cache = rspamd_keypair_cache_new (32);
	conn->http_conn = rspamd_http_connection_new (rspamd_client_body_handler,
			rspamd_client_error_handler,
			rspamd_client_finish_handler,
			0,
			RSPAMD_HTTP_CLIENT,
			conn->keys_cache,
			NULL);

	conn->server_name = g_string_new (name);
	if (port != 0) {
		rspamd_printf_gstring (conn->server_name, ":%d", (int)port);
	}

	double_to_tv (timeout, &conn->timeout);

	if (key) {
		conn->key = rspamd_pubkey_from_base32 (key, 0, RSPAMD_KEYPAIR_KEX,
				RSPAMD_CRYPTOBOX_MODE_25519);

		if (conn->key) {
			conn->keypair = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
					RSPAMD_CRYPTOBOX_MODE_25519);
			rspamd_http_connection_set_key (conn->http_conn, conn->keypair);
		}
		else {
			rspamd_client_destroy (conn);
			return NULL;
		}
	}

	return conn;
}
Beispiel #4
0
Datei: map.c Projekt: Sp1l/rspamd
static const gchar *
rspamd_map_check_proto (struct rspamd_config *cfg,
		const gchar *map_line, struct rspamd_map *map)
{
	const gchar *pos = map_line, *end, *end_key;

	g_assert (map != NULL);
	g_assert (pos != NULL);

	end = pos + strlen (pos);

	if (g_ascii_strncasecmp (pos, "sign+", sizeof ("sign+") - 1) == 0) {
		map->is_signed = TRUE;
		pos += sizeof ("sign+") - 1;
	}

	if (g_ascii_strncasecmp (pos, "key=", sizeof ("key=") - 1) == 0) {
		pos += sizeof ("key=") - 1;
		end_key = memchr (pos, '+', end - pos);

		if (end_key != NULL) {
			map->trusted_pubkey = rspamd_pubkey_from_base32 (pos, end_key - pos,
					RSPAMD_KEYPAIR_SIGN, RSPAMD_CRYPTOBOX_MODE_25519);

			if (map->trusted_pubkey == NULL) {
				msg_err_config ("cannot read pubkey from map: %s",
						map_line);
				return NULL;
			}
			pos = end_key + 1;
		}
		else if (end - pos > 64) {
			/* Try hex encoding */
			map->trusted_pubkey = rspamd_pubkey_from_hex (pos, 64,
					RSPAMD_KEYPAIR_SIGN, RSPAMD_CRYPTOBOX_MODE_25519);

			if (map->trusted_pubkey == NULL) {
				msg_err_config ("cannot read pubkey from map: %s",
						map_line);
				return NULL;
			}
			pos += 64;
		}
		else {
			msg_err_config ("cannot read pubkey from map: %s",
					map_line);
			return NULL;
		}

		if (*pos == '+' || *pos == ':') {
			pos ++;
		}
	}

	map->protocol = MAP_PROTO_FILE;

	if (g_ascii_strncasecmp (pos, "http://",
			sizeof ("http://") - 1) == 0) {
		map->protocol = MAP_PROTO_HTTP;
		/* Include http:// */
		map->uri = rspamd_mempool_strdup (cfg->cfg_pool, pos);
		pos += sizeof ("http://") - 1;
	}
	else if (g_ascii_strncasecmp (pos, "file://", sizeof ("file://") -
			1) == 0) {
		pos += sizeof ("file://") - 1;
		/* Exclude file:// */
		map->uri = rspamd_mempool_strdup (cfg->cfg_pool, pos);
	}
	else if (*pos == '/') {
		/* Trivial file case */
		map->uri = rspamd_mempool_strdup (cfg->cfg_pool, pos);
	}
	else {
		msg_err_config ("invalid map fetching protocol: %s", map_line);

		return NULL;
	}


	return pos;
}
Beispiel #5
0
Datei: map.c Projekt: Sp1l/rspamd
static int
http_map_finish (struct rspamd_http_connection *conn,
		struct rspamd_http_message *msg)
{
	struct http_callback_data *cbd = conn->ud;
	struct rspamd_map *map;
	rspamd_mempool_t *pool;
	char fpath[PATH_MAX];
	guchar *aux_data, *in = NULL;
	gsize inlen = 0;
	struct stat st;

	map = cbd->map;
	pool = cbd->map->pool;

	if (msg->code == 200) {

		if (cbd->stage == map_load_file) {
			if (msg->last_modified) {
				cbd->data->last_checked = msg->last_modified;
			}
			else {
				cbd->data->last_checked = msg->date;
			}

			/* Maybe we need to check signature ? */
			if (map->is_signed) {
				close (cbd->out_fd);

				if (map->trusted_pubkey) {
					/* No need to load key */
					cbd->stage = map_load_signature;
					cbd->pk = rspamd_pubkey_ref (map->trusted_pubkey);
					rspamd_snprintf (fpath, sizeof (fpath), "%s.sig",
							cbd->tmpfile);
				}
				else {
					rspamd_snprintf (fpath, sizeof (fpath), "%s.pub",
							cbd->tmpfile);
					cbd->stage = map_load_pubkey;
				}

				cbd->out_fd = rspamd_file_xopen (fpath, O_RDWR|O_CREAT, 00644);

				if (cbd->out_fd == -1) {
					msg_err_pool ("cannot open pubkey file %s for writing: %s",
							fpath, strerror (errno));
					goto end;
				}

				rspamd_http_connection_reset (cbd->conn);
				write_http_request (cbd);

				goto end;
			}
			else {
				/* Unsinged version - just open file */
				in = rspamd_file_xmap (cbd->tmpfile, PROT_READ, &inlen);

				if (in == NULL) {
					msg_err_pool ("cannot read tempfile %s: %s", cbd->tmpfile,
							strerror (errno));
					goto end;
				}
			}
		}
		else if (cbd->stage == map_load_pubkey) {
			/* We now can load pubkey */
			(void)lseek (cbd->out_fd, 0, SEEK_SET);

			if (fstat (cbd->out_fd, &st) == -1) {
				msg_err_pool ("cannot stat pubkey file %s: %s",
						fpath, strerror (errno));
				goto end;
			}

			aux_data = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED,
					cbd->out_fd, 0);
			close (cbd->out_fd);
			cbd->out_fd = -1;

			if (aux_data == MAP_FAILED) {
				msg_err_pool ("cannot map pubkey file %s: %s",
						fpath, strerror (errno));
				goto end;
			}

			cbd->pk = rspamd_pubkey_from_base32 (aux_data, st.st_size,
					RSPAMD_KEYPAIR_SIGN, RSPAMD_CRYPTOBOX_MODE_25519);
			munmap (aux_data, st.st_size);

			if (cbd->pk == NULL) {
				msg_err_pool ("cannot load pubkey file %s: bad pubkey",
						fpath);
				goto end;
			}

			rspamd_snprintf (fpath, sizeof (fpath), "%s.sig", cbd->tmpfile);
			cbd->out_fd = rspamd_file_xopen (fpath, O_RDWR|O_CREAT, 00644);

			if (cbd->out_fd == -1) {
				msg_err_pool ("cannot open signature file %s for writing: %s",
						fpath, strerror (errno));
				goto end;
			}

			cbd->stage = map_load_signature;
			rspamd_http_connection_reset (cbd->conn);
			write_http_request (cbd);

			goto end;
		}
		else if (cbd->stage == map_load_signature) {
			/* We can now check signature */
			close (cbd->out_fd);
			cbd->out_fd = -1;

			in = rspamd_file_xmap (cbd->tmpfile, PROT_READ, &inlen);

			if (in == NULL) {
				msg_err_pool ("cannot read tempfile %s: %s", cbd->tmpfile,
						strerror (errno));
				goto end;
			}

			if (!rspamd_map_check_sig_pk (cbd->tmpfile, map, in, inlen, cbd->pk)) {
				goto end;
			}
		}

		g_assert (in != NULL);

		map->read_callback (map->pool, in, inlen, &cbd->cbdata, TRUE);
		map->fin_callback (map->pool, &cbd->cbdata);

		*map->user_data = cbd->cbdata.cur_data;
		msg_info_pool ("read map data from %s", cbd->data->host);
	}
	else if (msg->code == 304 && cbd->stage == map_load_file) {
		msg_debug_pool ("data is not modified for server %s",
				cbd->data->host);

		if (msg->last_modified) {
			cbd->data->last_checked = msg->last_modified;
		}
		else {
			cbd->data->last_checked = msg->date;
		}
	}
	else {
		msg_info_pool ("cannot load map %s from %s: HTTP error %d",
				map->uri, cbd->data->host, msg->code);
	}

end:
	REF_RELEASE (cbd);

	return 0;
}
Beispiel #6
0
/***
 * @function rspamd_cryptobox_pubkey.load(file[, type[, alg]])
 * Loads public key from base32 encoded file
 * @param {string} file filename to load
 * @param {string} type optional 'sign' or 'kex' for signing and encryption
 * @param {string} alg optional 'default' or 'nist' for curve25519/nistp256 keys
 * @return {cryptobox_pubkey} new public key
 */
static gint
lua_cryptobox_pubkey_load (lua_State *L)
{
	struct rspamd_cryptobox_pubkey *pkey = NULL, **ppkey;
	const gchar *filename, *arg;
	gint type = RSPAMD_KEYPAIR_SIGN;
	gint alg = RSPAMD_CRYPTOBOX_MODE_25519;
	guchar *map;
	gsize len;

	filename = luaL_checkstring (L, 1);
	if (filename != NULL) {
		map = rspamd_file_xmap (filename, PROT_READ, &len);

		if (map == NULL) {
			msg_err ("cannot open pubkey from file: %s, %s",
				filename,
				strerror (errno));
			lua_pushnil (L);
		}
		else {
			if (lua_type (L, 2) == LUA_TSTRING) {
				/* keypair type */
				arg = lua_tostring (L, 2);

				if (strcmp (arg, "sign") == 0) {
					type = RSPAMD_KEYPAIR_SIGN;
				}
				else if (strcmp (arg, "kex") == 0) {
					type = RSPAMD_KEYPAIR_KEX;
				}
			}
			if (lua_type (L, 3) == LUA_TSTRING) {
				/* algorithm */
				arg = lua_tostring (L, 3);

				if (strcmp (arg, "default") == 0 || strcmp (arg, "curve25519") == 0) {
					type = RSPAMD_CRYPTOBOX_MODE_25519;
				}
				else if (strcmp (arg, "nist") == 0) {
					type = RSPAMD_CRYPTOBOX_MODE_NIST;
				}
			}

			pkey = rspamd_pubkey_from_base32 (map, len, type, alg);

			if (pkey == NULL) {
				msg_err ("cannot open pubkey from file: %s", filename);
				munmap (map, len);
				lua_pushnil (L);
			}
			else {
				munmap (map, len);
				ppkey = lua_newuserdata (L, sizeof (void *));
				rspamd_lua_setclass (L, "rspamd{cryptobox_pubkey}", -1);
				*ppkey = pkey;
			}
		}
	}
	else {
		return luaL_error (L, "bad input arguments");
	}

	return 1;
}
Beispiel #7
0
static int
http_map_finish (struct rspamd_http_connection *conn,
		struct rspamd_http_message *msg)
{
	struct http_callback_data *cbd = conn->ud;
	struct rspamd_map *map;
	struct rspamd_map_backend *bk;
	guchar *aux_data, *in = NULL;
	gsize inlen = 0, dlen = 0;

	map = cbd->map;
	bk = cbd->bk;

	if (msg->code == 200) {

		if (cbd->check) {
			cbd->periodic->need_modify = TRUE;
			/* Reset the whole chain */
			cbd->periodic->cur_backend = 0;
			rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic);
			MAP_RELEASE (cbd, "http_callback_data");

			return 0;
		}

		if (cbd->stage == map_load_file) {
			if (msg->last_modified) {
				cbd->data->last_checked = msg->last_modified;
			}
			else {
				cbd->data->last_checked = msg->date;
			}

			/* Maybe we need to check signature ? */
			if (bk->is_signed) {

				if (bk->trusted_pubkey) {
					/* No need to load key */
					cbd->stage = map_load_signature;
					cbd->pk = rspamd_pubkey_ref (bk->trusted_pubkey);
				}
				else {
					cbd->stage = map_load_pubkey;
				}

				cbd->shmem_data = rspamd_http_message_shmem_ref (msg);
				cbd->data_len = msg->body_buf.len;
				rspamd_http_connection_reset (cbd->conn);
				write_http_request (cbd);
				MAP_RELEASE (cbd, "http_callback_data");

				return 0;
			}
			else {
				/* Unsinged version - just open file */
				cbd->shmem_data = rspamd_http_message_shmem_ref (msg);
				cbd->data_len = msg->body_buf.len;

				goto read_data;
			}
		}
		else if (cbd->stage == map_load_pubkey) {
			/* We now can load pubkey */
			cbd->shmem_pubkey = rspamd_http_message_shmem_ref (msg);
			cbd->pubkey_len = msg->body_buf.len;

			aux_data = rspamd_shmem_xmap (cbd->shmem_pubkey->shm_name,
					PROT_READ, &inlen);

			if (aux_data == NULL) {
				msg_err_map ("cannot map pubkey file %s: %s",
						cbd->shmem_pubkey->shm_name, strerror (errno));
				goto err;
			}

			if (inlen < cbd->pubkey_len) {
				msg_err_map ("cannot map pubkey file %s: %s",
						cbd->shmem_pubkey->shm_name, strerror (errno));
				munmap (aux_data, inlen);
				goto err;
			}

			cbd->pk = rspamd_pubkey_from_base32 (aux_data, cbd->pubkey_len,
					RSPAMD_KEYPAIR_SIGN, RSPAMD_CRYPTOBOX_MODE_25519);
			munmap (aux_data, inlen);

			if (cbd->pk == NULL) {
				msg_err_map ("cannot load pubkey file %s: bad pubkey",
						cbd->shmem_pubkey->shm_name);
				goto err;
			}

			cbd->stage = map_load_signature;
			rspamd_http_connection_reset (cbd->conn);
			write_http_request (cbd);
			MAP_RELEASE (cbd, "http_callback_data");

			return 0;
		}
		else if (cbd->stage == map_load_signature) {
			/* We can now check signature */
			cbd->shmem_sig = rspamd_http_message_shmem_ref (msg);
			cbd->sig_len = msg->body_buf.len;

			aux_data = rspamd_shmem_xmap (cbd->shmem_sig->shm_name,
					PROT_READ, &inlen);

			if (aux_data == NULL) {
				msg_err_map ("cannot map signature file %s: %s",
						cbd->shmem_sig->shm_name, strerror (errno));
				goto err;
			}

			if (inlen < cbd->sig_len) {
				msg_err_map ("cannot map pubkey file %s: %s",
						cbd->shmem_pubkey->shm_name, strerror (errno));
				munmap (aux_data, inlen);
				goto err;
			}

			in = rspamd_shmem_xmap (cbd->shmem_data->shm_name, PROT_READ, &dlen);

			if (in == NULL) {
				msg_err_map ("cannot read tempfile %s: %s",
						cbd->shmem_data->shm_name,
						strerror (errno));
				munmap (aux_data, inlen);
				goto err;
			}

			if (!rspamd_map_check_sig_pk_mem (aux_data, cbd->sig_len, map, in,
					cbd->data_len, cbd->pk)) {
				munmap (aux_data, inlen);
				munmap (in, dlen);
				goto err;
			}

			munmap (in, dlen);
		}

read_data:
		g_assert (cbd->shmem_data != NULL);

		in = rspamd_shmem_xmap (cbd->shmem_data->shm_name, PROT_READ, &dlen);

		if (in == NULL) {
			msg_err_map ("cannot read tempfile %s: %s",
					cbd->shmem_data->shm_name,
					strerror (errno));
			goto err;
		}

		map->read_callback (in, cbd->data_len, &cbd->periodic->cbdata, TRUE);
		msg_info_map ("read map data from %s", cbd->data->host);

		/*
		 * We know that a map is in the locked state
		 */
		if (g_atomic_int_compare_and_exchange (&map->cache->available, 0, 1)) {
			/* Store cached data */
			struct rspamd_http_map_cached_cbdata *cache_cbd;
			struct timeval tv;

			rspamd_strlcpy (map->cache->shmem_name, cbd->shmem_data->shm_name,
					sizeof (map->cache->shmem_name));
			map->cache->len = cbd->data_len;
			map->cache->last_checked = cbd->data->last_checked;
			cache_cbd = g_slice_alloc0 (sizeof (*cache_cbd));
			cache_cbd->shm = cbd->shmem_data;
			cache_cbd->map = map;
			MAP_RETAIN (cache_cbd->shm, "shmem_data");
			event_set (&cache_cbd->timeout, -1, EV_TIMEOUT, rspamd_map_cache_cb,
					cache_cbd);
			event_base_set (cbd->ev_base, &cache_cbd->timeout);
			double_to_tv (map->poll_timeout, &tv);
			event_add (&cache_cbd->timeout, &tv);
		}

		cbd->periodic->cur_backend ++;
		munmap (in, dlen);
		rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic);
	}
	else if (msg->code == 304 && (cbd->check && cbd->stage == map_load_file)) {
		msg_debug_map ("data is not modified for server %s",
				cbd->data->host);

		if (msg->last_modified) {
			cbd->data->last_checked = msg->last_modified;
		}
		else {
			cbd->data->last_checked = msg->date;
		}

		cbd->periodic->cur_backend ++;
		rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic);
	}
	else {
		msg_info_map ("cannot load map %s from %s: HTTP error %d",
				bk->uri, cbd->data->host, msg->code);
	}

	MAP_RELEASE (cbd, "http_callback_data");
	return 0;

err:
	cbd->periodic->errored = 1;
	rspamd_map_periodic_callback (-1, EV_TIMEOUT, cbd->periodic);
	MAP_RELEASE (cbd, "http_callback_data");

	return 0;
}
Beispiel #8
0
static void
rspamadm_signtool (gint argc, gchar **argv)
{
	GOptionContext *context;
	GError *error = NULL;
	struct ucl_parser *parser;
	ucl_object_t *top;
	struct rspamd_cryptobox_pubkey *pk;
	struct rspamd_cryptobox_keypair *kp;
	gsize fsize, flen;
	gint i;

	context = g_option_context_new (
			"keypair - create encryption keys");
	g_option_context_set_summary (context,
			"Summary:\n  Rspamd administration utility version "
					RVERSION
					"\n  Release id: "
					RID);
	g_option_context_add_main_entries (context, entries, NULL);

	if (!g_option_context_parse (context, &argc, &argv, &error)) {
		rspamd_fprintf (stderr, "option parsing failed: %s\n", error->message);
		g_error_free (error);
		exit (1);
	}

	if (openssl) {
		mode = RSPAMD_CRYPTOBOX_MODE_NIST;
	}

	if (verify && (!pubkey && !pubkey_file)) {
		rspamd_fprintf (stderr, "no pubkey for verification\n");
		exit (1);
	}
	else if (!verify && (!keypair_file)) {
		rspamd_fprintf (stderr, "no keypair for signing\n");
		exit (1);
	}

	if (verify) {
		g_assert (pubkey || pubkey_file);

		if (pubkey_file) {
			gint fd;
			gchar *map;
			struct stat st;

			fd = open (pubkey_file, O_RDONLY);

			if (fd == -1) {
				rspamd_fprintf (stderr, "cannot open %s: %s\n", pubkey_file,
						strerror (errno));
				exit (errno);
			}

			g_assert (fstat (fd, &st) != -1);
			fsize = st.st_size;
			flen = fsize;
			map = mmap (NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
			close (fd);

			if (map == MAP_FAILED) {
				rspamd_fprintf (stderr, "cannot read %s: %s\n", pubkey_file,
						strerror (errno));
				exit (errno);
			}

			/* XXX: assume base32 pubkey now */
			while (flen > 0 && g_ascii_isspace (map[flen - 1])) {
				flen --;
			}

			pk = rspamd_pubkey_from_base32 (map, flen,
					RSPAMD_KEYPAIR_SIGN, mode);

			if (pk == NULL) {
				rspamd_fprintf (stderr, "bad size %s: %ud, %ud expected\n", flen,
						 rspamd_cryptobox_pk_sig_bytes (mode));
				exit (errno);
			}

			munmap (map, fsize);
		}
		else {
			pk = rspamd_pubkey_from_base32 (pubkey, strlen (pubkey),
								RSPAMD_KEYPAIR_SIGN, mode);

			if (pk == NULL) {
				rspamd_fprintf (stderr, "bad size %s: %ud, %ud expected\n",
						strlen (pubkey),
						rspamd_cryptobox_pk_sig_bytes (mode));
				exit (errno);
			}
		}

		for (i = 1; i < argc; i++) {
			/* XXX: support cmd line signature */
			if (!rspamadm_verify_file (argv[i], rspamd_pubkey_get_pk (pk, NULL))) {
				exit (EXIT_FAILURE);
			}
		}

		g_free (pk);
	}
	else {
		g_assert (keypair_file != NULL);

		parser = ucl_parser_new (0);

		if (!ucl_parser_add_file (parser, keypair_file) ||
				(top = ucl_parser_get_object (parser)) == NULL) {
			rspamd_fprintf (stderr, "cannot load keypair: %s\n",
					ucl_parser_get_error (parser));
			exit (EINVAL);
		}

		ucl_parser_free (parser);

		kp = rspamd_keypair_from_ucl (top);

		if (kp == NULL || rspamd_keypair_type (kp) != RSPAMD_KEYPAIR_SIGN) {
			rspamd_fprintf (stderr, "invalid or unsuitable for signing key\n");
			exit (EXIT_FAILURE);
		}

		for (i = 1; i < argc; i++) {
			/* XXX: support cmd line signature */
			if (!rspamadm_sign_file (argv[i], kp)) {
				rspamd_keypair_unref (kp);
				exit (EXIT_FAILURE);
			}
		}

		rspamd_keypair_unref (kp);
	}
}
Beispiel #9
0
void
rspamd_http_test_func (void)
{
	struct event_base *ev_base = event_init ();
	rspamd_mempool_t *pool = rspamd_mempool_new (rspamd_mempool_suggest_size (), NULL);
	struct rspamd_cryptobox_keypair *serv_key, *client_key;
	struct rspamd_cryptobox_pubkey *peer_key;
	struct rspamd_keypair_cache *c;
	rspamd_mempool_mutex_t *mtx;
	rspamd_inet_addr_t *addr;
	gdouble ts1, ts2;
	gchar filepath[PATH_MAX], *buf;
	gchar *env;
	gint fd;
	guint i, j;
	pid_t *sfd;
	GString *b32_key;
	double diff, total_diff = 0.0, *latency, mean, std;

	/* Read environment */
	if ((env = getenv ("RSPAMD_HTTP_CONNS")) != NULL) {
		pconns = strtoul (env, NULL, 10);
	}
	else {
		return;
	}

	if ((env = getenv ("RSPAMD_HTTP_TESTS")) != NULL) {
		ntests = strtoul (env, NULL, 10);
	}
	if ((env = getenv ("RSPAMD_HTTP_SIZE")) != NULL) {
		file_size = strtoul (env, NULL, 10);
	}
	if ((env = getenv ("RSPAMD_HTTP_SERVERS")) != NULL) {
		nservers = strtoul (env, NULL, 10);
	}

	rspamd_cryptobox_init ();
	rspamd_snprintf (filepath, sizeof (filepath), "/tmp/http-test-XXXXXX");
	g_assert ((fd = mkstemp (filepath)) != -1);

	sfd = g_alloca (sizeof (*sfd) * nservers);
	latency = g_malloc0 (pconns * ntests * sizeof (gdouble));

	buf = g_malloc (file_size);
	memset (buf, 0, file_size);
	g_assert (write (fd, buf, file_size) == file_size);
	g_free (buf);

	mtx = rspamd_mempool_get_mutex (pool);

	rspamd_parse_inet_address (&addr, "127.0.0.1", 0);
	rspamd_inet_address_set_port (addr, 43898);
	serv_key = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
			RSPAMD_CRYPTOBOX_MODE_25519);
	client_key = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
			RSPAMD_CRYPTOBOX_MODE_25519);
	c = rspamd_keypair_cache_new (16);

	rspamd_http_start_servers (sfd, addr, serv_key, NULL);
	usleep (100000);

	/* Do client stuff */
	gperf_profiler_init (NULL, "plain-http-client");
	for (i = 0; i < ntests; i ++) {
		for (j = 0; j < pconns; j ++) {
			rspamd_http_client_func (filepath + sizeof ("/tmp") - 1, addr,
					NULL, NULL, c, ev_base, &latency[i * pconns + j]);
		}
		ts1 = rspamd_get_ticks ();
		event_base_loop (ev_base, 0);
		ts2 = rspamd_get_ticks ();
		diff = (ts2 - ts1) * 1000.0;
		total_diff += diff;
	}
	gperf_profiler_stop ();

	msg_info ("Made %d connections of size %d in %.6f ms, %.6f cps",
			ntests * pconns,
			file_size,
			total_diff, ntests * pconns / total_diff * 1000.);
	mean = rspamd_http_calculate_mean (latency, &std);
	msg_info ("Latency: %.6f ms mean, %.6f dev",
			mean, std);

	rspamd_http_stop_servers (sfd);

	rspamd_http_start_servers (sfd, addr, serv_key, c);

	//rspamd_mempool_lock_mutex (mtx);
	usleep (100000);
	b32_key = rspamd_keypair_print (serv_key,
			RSPAMD_KEYPAIR_PUBKEY|RSPAMD_KEYPAIR_BASE32);
	g_assert (b32_key != NULL);
	peer_key = rspamd_pubkey_from_base32 (b32_key->str, b32_key->len,
			RSPAMD_KEYPAIR_KEX, RSPAMD_CRYPTOBOX_MODE_25519);
	g_assert (peer_key != NULL);
	total_diff = 0.0;

	gperf_profiler_init (NULL, "cached-http-client");
	for (i = 0; i < ntests; i ++) {
		for (j = 0; j < pconns; j ++) {
			rspamd_http_client_func (filepath + sizeof ("/tmp") - 1, addr,
					client_key, peer_key, c, ev_base, &latency[i * pconns + j]);
		}
		ts1 = rspamd_get_ticks ();
		event_base_loop (ev_base, 0);
		ts2 = rspamd_get_ticks ();
		diff = (ts2 - ts1) * 1000.0;
		total_diff += diff;
	}
	gperf_profiler_stop ();

	msg_info ("Made %d encrypted connections of size %d in %.6f ms, %.6f cps",
			ntests * pconns,
			file_size,
			total_diff, ntests * pconns / total_diff * 1000.);
	mean = rspamd_http_calculate_mean (latency, &std);
	msg_info ("Latency: %.6f ms mean, %.6f dev",
			mean, std);

	/* Restart server */
	rspamd_http_stop_servers (sfd);
	/* No keypairs cache */
	rspamd_http_start_servers (sfd, addr, serv_key, NULL);

	usleep (100000);
	total_diff = 0.0;

	gperf_profiler_init (NULL, "fair-http-client");
	for (i = 0; i < ntests; i ++) {
		for (j = 0; j < pconns; j ++) {
			rspamd_http_client_func (filepath + sizeof ("/tmp") - 1, addr,
					client_key, peer_key, c, ev_base, &latency[i * pconns + j]);
		}
		ts1 = rspamd_get_ticks ();
		event_base_loop (ev_base, 0);
		ts2 = rspamd_get_ticks ();
		diff = (ts2 - ts1) * 1000.0;
		total_diff += diff;
	}
	gperf_profiler_stop ();

	msg_info ("Made %d uncached encrypted connections of size %d in %.6f ms, %.6f cps",
			ntests * pconns,
			file_size,
			total_diff, ntests * pconns / total_diff * 1000.);
	mean = rspamd_http_calculate_mean (latency, &std);
	msg_info ("Latency: %.6f ms mean, %.6f dev",
			mean, std);

	/* AES mode */
	serv_key = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
			RSPAMD_CRYPTOBOX_MODE_NIST);
	client_key = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
			RSPAMD_CRYPTOBOX_MODE_NIST);
	c = rspamd_keypair_cache_new (16);

	/* Restart server */
	rspamd_http_stop_servers (sfd);
	/* No keypairs cache */
	rspamd_http_start_servers (sfd, addr, serv_key, c);

	//rspamd_mempool_lock_mutex (mtx);
	usleep (100000);
	b32_key = rspamd_keypair_print (serv_key,
			RSPAMD_KEYPAIR_PUBKEY | RSPAMD_KEYPAIR_BASE32);
	g_assert (b32_key != NULL);
	peer_key = rspamd_pubkey_from_base32 (b32_key->str, b32_key->len,
			RSPAMD_KEYPAIR_KEX, RSPAMD_CRYPTOBOX_MODE_NIST);
	g_assert (peer_key != NULL);
	total_diff = 0.0;

	gperf_profiler_init (NULL, "cached-http-client-aes");
	for (i = 0; i < ntests; i++) {
		for (j = 0; j < pconns; j++) {
			rspamd_http_client_func (filepath + sizeof ("/tmp") - 1,
					addr,
					client_key,
					peer_key,
					NULL,
					ev_base,
					&latency[i * pconns + j]);
		}
		ts1 = rspamd_get_ticks ();
		event_base_loop (ev_base, 0);
		ts2 = rspamd_get_ticks ();
		diff = (ts2 - ts1) * 1000.0;
		total_diff += diff;
	}
	gperf_profiler_stop ();

	msg_info (
			"Made %d aes encrypted connections of size %d in %.6f ms, %.6f cps",
			ntests * pconns,
			file_size,
			total_diff,
			ntests * pconns / total_diff * 1000.);
	mean = rspamd_http_calculate_mean (latency, &std);
	msg_info ("Latency: %.6f ms mean, %.6f dev",
			mean, std);

	/* Restart server */
	rspamd_http_stop_servers (sfd);
	/* No keypairs cache */
	rspamd_http_start_servers (sfd, addr, serv_key, NULL);

	//rspamd_mempool_lock_mutex (mtx);
	usleep (100000);
	total_diff = 0.0;

	gperf_profiler_init (NULL, "fair-http-client-aes");
	for (i = 0; i < ntests; i++) {
		for (j = 0; j < pconns; j++) {
			rspamd_http_client_func (filepath + sizeof ("/tmp") - 1,
					addr,
					client_key,
					peer_key,
					c,
					ev_base,
					&latency[i * pconns + j]);
		}
		ts1 = rspamd_get_ticks ();
		event_base_loop (ev_base, 0);
		ts2 = rspamd_get_ticks ();
		diff = (ts2 - ts1) * 1000.0;
		total_diff += diff;
	}
	gperf_profiler_stop ();

	msg_info (
			"Made %d uncached aes encrypted connections of size %d in %.6f ms, %.6f cps",
			ntests * pconns,
			file_size,
			total_diff,
			ntests * pconns / total_diff * 1000.);
	mean = rspamd_http_calculate_mean (latency, &std);
	msg_info ("Latency: %.6f ms mean, %.6f dev",
			mean, std);

	close (fd);
	unlink (filepath);
	rspamd_http_stop_servers (sfd);
}