commit 5fe4378: [Project] Adopt librspamdserver for http context

Vsevolod Stakhov vsevolod at highsecure.ru
Tue Feb 19 18:00:08 UTC 2019


Author: Vsevolod Stakhov
Date: 2019-02-19 17:56:42 +0000
URL: https://github.com/rspamd/rspamd/commit/5fe437851dc63bf9c7488d34e434b0e00fd2656a

[Project] Adopt librspamdserver for http context

---
 src/libserver/rspamd_control.c |   7 +-
 src/libutil/CMakeLists.txt     |   1 +
 src/libutil/http_connection.c  | 310 +++++------------------------------------
 src/libutil/http_connection.h  |   9 +-
 src/libutil/http_private.h     |  13 ++
 src/libutil/http_router.c      |  18 +--
 src/libutil/http_router.h      |   5 +-
 src/libutil/http_util.c        | 266 +++++++++++++++++++++++++++++++++++
 src/libutil/map.c              |  13 +-
 src/libutil/util.c             | 152 ++++++++++++--------
 src/libutil/util.h             |   3 +
 11 files changed, 431 insertions(+), 366 deletions(-)

diff --git a/src/libserver/rspamd_control.c b/src/libserver/rspamd_control.c
index 2fd1d983f..fb0fc22b6 100644
--- a/src/libserver/rspamd_control.c
+++ b/src/libserver/rspamd_control.c
@@ -511,13 +511,12 @@ rspamd_control_process_client_socket (struct rspamd_main *rspamd_main,
 	session = g_malloc0 (sizeof (*session));
 
 	session->fd = fd;
-	session->conn = rspamd_http_connection_new (NULL,
+	session->conn = rspamd_http_connection_new (rspamd_main->http_ctx,
+			NULL,
 			rspamd_control_error_handler,
 			rspamd_control_finish_handler,
 			0,
-			RSPAMD_HTTP_SERVER,
-			NULL,
-			NULL);
+			RSPAMD_HTTP_SERVER);
 	session->rspamd_main = rspamd_main;
 	rspamd_http_connection_read_message (session->conn, session, session->fd,
 			&io_timeout, rspamd_main->ev_base);
diff --git a/src/libutil/CMakeLists.txt b/src/libutil/CMakeLists.txt
index 4d4f8c7bd..f86d650f0 100644
--- a/src/libutil/CMakeLists.txt
+++ b/src/libutil/CMakeLists.txt
@@ -10,6 +10,7 @@ SET(LIBRSPAMDUTILSRC
 				${CMAKE_CURRENT_SOURCE_DIR}/http_message.c
 				${CMAKE_CURRENT_SOURCE_DIR}/http_connection.c
 				${CMAKE_CURRENT_SOURCE_DIR}/http_router.c
+				${CMAKE_CURRENT_SOURCE_DIR}/http_context.c
 				${CMAKE_CURRENT_SOURCE_DIR}/logger.c
 				${CMAKE_CURRENT_SOURCE_DIR}/map.c
 				${CMAKE_CURRENT_SOURCE_DIR}/map_helpers.c
diff --git a/src/libutil/http_connection.c b/src/libutil/http_connection.c
index df283f752..8463ff762 100644
--- a/src/libutil/http_connection.c
+++ b/src/libutil/http_connection.c
@@ -55,9 +55,10 @@ enum rspamd_http_priv_flags {
 #define IS_CONN_RESETED(c) ((c)->flags & RSPAMD_HTTP_CONN_FLAG_RESETED)
 
 struct rspamd_http_connection_private {
-	gpointer ssl_ctx;
+	struct rspamd_http_context *ctx;
 	struct rspamd_ssl_connection *ssl;
 	struct _rspamd_http_privbuf *buf;
+	struct rspamd_keypair_cache *cache;
 	struct rspamd_cryptobox_pubkey *peer_key;
 	struct rspamd_cryptobox_keypair *local_key;
 	struct rspamd_http_header *header;
@@ -133,272 +134,6 @@ rspamd_http_code_to_str (gint code)
 	return "Unknown error";
 }
 
-/*
- * Obtained from nginx
- * Copyright (C) Igor Sysoev
- */
-static guint mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-time_t
-rspamd_http_parse_date (const gchar *header, gsize len)
-{
-	const gchar *p, *end;
-	gint month;
-	guint day, year, hour, min, sec;
-	guint64 time;
-	enum {
-		no = 0, rfc822, /* Tue, 10 Nov 2002 23:50:13   */
-		rfc850, /* Tuesday, 10-Dec-02 23:50:13 */
-		isoc /* Tue Dec 10 23:50:13 2002    */
-	} fmt;
-
-	fmt = 0;
-	if (len > 0) {
-		end = header + len;
-	}
-	else {
-		end = header + strlen (header);
-	}
-
-	day = 32;
-	year = 2038;
-
-	for (p = header; p < end; p++) {
-		if (*p == ',') {
-			break;
-		}
-
-		if (*p == ' ') {
-			fmt = isoc;
-			break;
-		}
-	}
-
-	for (p++; p < end; p++)
-		if (*p != ' ') {
-			break;
-		}
-
-	if (end - p < 18) {
-		return (time_t)-1;
-	}
-
-	if (fmt != isoc) {
-		if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
-			return (time_t)-1;
-		}
-
-		day = (*p - '0') * 10 + *(p + 1) - '0';
-		p += 2;
-
-		if (*p == ' ') {
-			if (end - p < 18) {
-				return (time_t)-1;
-			}
-			fmt = rfc822;
-
-		}
-		else if (*p == '-') {
-			fmt = rfc850;
-
-		}
-		else {
-			return (time_t)-1;
-		}
-
-		p++;
-	}
-
-	switch (*p) {
-
-	case 'J':
-		month = *(p + 1) == 'a' ? 0 : *(p + 2) == 'n' ? 5 : 6;
-		break;
-
-	case 'F':
-		month = 1;
-		break;
-
-	case 'M':
-		month = *(p + 2) == 'r' ? 2 : 4;
-		break;
-
-	case 'A':
-		month = *(p + 1) == 'p' ? 3 : 7;
-		break;
-
-	case 'S':
-		month = 8;
-		break;
-
-	case 'O':
-		month = 9;
-		break;
-
-	case 'N':
-		month = 10;
-		break;
-
-	case 'D':
-		month = 11;
-		break;
-
-	default:
-		return (time_t)-1;
-	}
-
-	p += 3;
-
-	if ((fmt == rfc822 && *p != ' ') || (fmt == rfc850 && *p != '-')) {
-		return (time_t)-1;
-	}
-
-	p++;
-
-	if (fmt == rfc822) {
-		if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
-			|| *(p + 2) < '0' || *(p + 2) > '9' || *(p + 3) < '0'
-			|| *(p + 3) > '9') {
-			return (time_t)-1;
-		}
-
-		year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
-			+ (*(p + 2) - '0') * 10 + *(p + 3) - '0';
-		p += 4;
-
-	}
-	else if (fmt == rfc850) {
-		if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
-			return (time_t)-1;
-		}
-
-		year = (*p - '0') * 10 + *(p + 1) - '0';
-		year += (year < 70) ? 2000 : 1900;
-		p += 2;
-	}
-
-	if (fmt == isoc) {
-		if (*p == ' ') {
-			p++;
-		}
-
-		if (*p < '0' || *p > '9') {
-			return (time_t)-1;
-		}
-
-		day = *p++ - '0';
-
-		if (*p != ' ') {
-			if (*p < '0' || *p > '9') {
-				return (time_t)-1;
-			}
-
-			day = day * 10 + *p++ - '0';
-		}
-
-		if (end - p < 14) {
-			return (time_t)-1;
-		}
-	}
-
-	if (*p++ != ' ') {
-		return (time_t)-1;
-	}
-
-	if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
-		return (time_t)-1;
-	}
-
-	hour = (*p - '0') * 10 + *(p + 1) - '0';
-	p += 2;
-
-	if (*p++ != ':') {
-		return (time_t)-1;
-	}
-
-	if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
-		return (time_t)-1;
-	}
-
-	min = (*p - '0') * 10 + *(p + 1) - '0';
-	p += 2;
-
-	if (*p++ != ':') {
-		return (time_t)-1;
-	}
-
-	if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
-		return (time_t)-1;
-	}
-
-	sec = (*p - '0') * 10 + *(p + 1) - '0';
-
-	if (fmt == isoc) {
-		p += 2;
-
-		if (*p++ != ' ') {
-			return (time_t)-1;
-		}
-
-		if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
-			|| *(p + 2) < '0' || *(p + 2) > '9' || *(p + 3) < '0'
-			|| *(p + 3) > '9') {
-			return (time_t)-1;
-		}
-
-		year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
-			+ (*(p + 2) - '0') * 10 + *(p + 3) - '0';
-	}
-
-	if (hour > 23 || min > 59 || sec > 59) {
-		return (time_t)-1;
-	}
-
-	if (day == 29 && month == 1) {
-		if ((year & 3) || ((year % 100 == 0) && (year % 400) != 0)) {
-			return (time_t)-1;
-		}
-
-	}
-	else if (day > mday[month]) {
-		return (time_t)-1;
-	}
-
-	/*
-	 * shift new year to March 1 and start months from 1 (not 0),
-	 * it is needed for Gauss' formula
-	 */
-
-	if (--month <= 0) {
-		month += 12;
-		year -= 1;
-	}
-
-	/* Gauss' formula for Gregorian days since March 1, 1 BC */
-
-	time = (guint64) (
-	    /* days in years including leap years since March 1, 1 BC */
-
-		365 * year + year / 4 - year / 100 + year / 400
-
-	    /* days before the month */
-
-		+ 367 * month / 12 - 30
-
-	    /* days before the day */
-
-		+ day - 1
-
-	    /*
-	     * 719527 days were between March 1, 1 BC and March 1, 1970,
-	     * 31 and 28 days were in January and February 1970
-	     */
-
-		- 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;
-
-	return (time_t) time;
-}
-
 static void
 rspamd_http_parse_key (rspamd_ftok_t *data, struct rspamd_http_connection *conn,
 		struct rspamd_http_connection_private *priv)
@@ -430,9 +165,10 @@ rspamd_http_parse_key (rspamd_ftok_t *data, struct rspamd_http_connection *conn,
 							RSPAMD_KEYPAIR_SHORT_ID_LEN) == 0) {
 						priv->msg->peer_key = pk;
 
-						if (conn->cache && priv->msg->peer_key) {
-							rspamd_keypair_cache_process (conn->cache,
-									priv->local_key, priv->msg->peer_key);
+						if (priv->cache && priv->msg->peer_key) {
+							rspamd_keypair_cache_process (priv->cache,
+									priv->local_key,
+									priv->msg->peer_key);
 						}
 					}
 					else {
@@ -1299,13 +1035,12 @@ rspamd_http_parser_reset (struct rspamd_http_connection *conn)
 
 struct rspamd_http_connection *
 rspamd_http_connection_new (
+		struct rspamd_http_context *ctx,
 		rspamd_http_body_handler_t body_handler,
 		rspamd_http_error_handler_t error_handler,
 		rspamd_http_finish_handler_t finish_handler,
 		unsigned opts,
-		enum rspamd_http_connection_type type,
-		struct rspamd_keypair_cache *cache,
-		gpointer ssl_ctx)
+		enum rspamd_http_connection_type type)
 {
 	struct rspamd_http_connection *conn;
 	struct rspamd_http_connection_private *priv;
@@ -1323,12 +1058,25 @@ rspamd_http_connection_new (
 	conn->fd = -1;
 	conn->ref = 1;
 	conn->finished = FALSE;
-	conn->cache = cache;
 
 	/* Init priv */
+	if (ctx == NULL) {
+		ctx = rspamd_http_context_default ();
+	}
+
 	priv = g_malloc0 (sizeof (struct rspamd_http_connection_private));
 	conn->priv = priv;
-	priv->ssl_ctx = ssl_ctx;
+	priv->ctx = ctx;
+
+	if (conn->type == RSPAMD_HTTP_CLIENT) {
+		priv->cache = ctx->client_kp_cache;
+		if (ctx->client_kp) {
+			priv->local_key = rspamd_keypair_ref (ctx->client_kp);
+		}
+	}
+	else {
+		priv->cache = ctx->server_kp_cache;
+	}
 
 	rspamd_http_parser_reset (conn);
 	priv->parser.data = conn;
@@ -2022,8 +1770,8 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn
 
 		encrypted = TRUE;
 
-		if (conn->cache) {
-			rspamd_keypair_cache_process (conn->cache,
+		if (priv->cache) {
+			rspamd_keypair_cache_process (priv->cache,
 					priv->local_key, priv->msg->peer_key);
 		}
 	}
@@ -2287,10 +2035,14 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn
 	}
 
 	if (msg->flags & RSPAMD_HTTP_FLAG_SSL) {
+		gpointer ssl_ctx = (msg->flags & RSPAMD_HTTP_FLAG_SSL_NOVERIFY) ?
+				priv->ctx->ssl_ctx_noverify : priv->ctx->ssl_ctx;
+
 		if (base != NULL) {
 			event_base_set (base, &priv->ev);
 		}
-		if (!priv->ssl_ctx) {
+
+		if (!ssl_ctx) {
 			err = g_error_new (HTTP_ERROR, errno, "ssl message requested "
 					"with no ssl ctx");
 			rspamd_http_connection_ref (conn);
@@ -2305,7 +2057,7 @@ rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn
 				rspamd_ssl_connection_free (priv->ssl);
 			}
 
-			priv->ssl = rspamd_ssl_connection_new (priv->ssl_ctx, base,
+			priv->ssl = rspamd_ssl_connection_new (ssl_ctx, base,
 					!(msg->flags & RSPAMD_HTTP_FLAG_SSL_NOVERIFY));
 			g_assert (priv->ssl != NULL);
 
diff --git a/src/libutil/http_connection.h b/src/libutil/http_connection.h
index 1fa1170b2..4e9f9f800 100644
--- a/src/libutil/http_connection.h
+++ b/src/libutil/http_connection.h
@@ -24,8 +24,7 @@
  */
 
 #include "config.h"
-#include "keypair.h"
-#include "keypairs_cache.h"
+#include "http_context.h"
 #include "fstring.h"
 #include "ref.h"
 #include "http_message.h"
@@ -104,7 +103,6 @@ struct rspamd_http_connection {
 	rspamd_http_body_handler_t body_handler;
 	rspamd_http_error_handler_t error_handler;
 	rspamd_http_finish_handler_t finish_handler;
-	struct rspamd_keypair_cache *cache;
 	gpointer ud;
 	gsize max_size;
 	unsigned opts;
@@ -121,13 +119,12 @@ struct rspamd_http_connection {
  * @return new connection structure
  */
 struct rspamd_http_connection *rspamd_http_connection_new (
+		struct rspamd_http_context *ctx,
 		rspamd_http_body_handler_t body_handler,
 		rspamd_http_error_handler_t error_handler,
 		rspamd_http_finish_handler_t finish_handler,
 		unsigned opts,
-		enum rspamd_http_connection_type type,
-		struct rspamd_keypair_cache *cache,
-		gpointer ssl_ctx);
+		enum rspamd_http_connection_type type);
 
 
 /**
diff --git a/src/libutil/http_private.h b/src/libutil/http_private.h
index df1233d8b..0f8c847a2 100644
--- a/src/libutil/http_private.h
+++ b/src/libutil/http_private.h
@@ -19,6 +19,8 @@
 #include "http_connection.h"
 #include "http_parser.h"
 #include "str_util.h"
+#include "keypair.h"
+#include "keypairs_cache.h"
 #include "ref.h"
 #define HASH_CASELESS
 #include "uthash_strcase.h"
@@ -74,6 +76,17 @@ struct rspamd_http_message {
 	ref_entry_t ref;
 };
 
+struct rspamd_http_context {
+	struct rspamd_http_context_cfg config;
+	struct rspamd_keypair_cache *client_kp_cache;
+	struct rspamd_cryptobox_keypair *client_kp;
+	struct rspamd_keypair_cache *server_kp_cache;
+	gpointer ssl_ctx;
+	gpointer ssl_ctx_noverify;
+	struct event_base *ev_base;
+	struct event client_rotate_ev;
+};
+
 #define HTTP_ERROR http_error_quark ()
 GQuark http_error_quark (void);
 
diff --git a/src/libutil/http_router.c b/src/libutil/http_router.c
index 0dc597788..be45c4351 100644
--- a/src/libutil/http_router.c
+++ b/src/libutil/http_router.c
@@ -373,9 +373,9 @@ rspamd_http_router_finish_handler (struct rspamd_http_connection *conn,
 struct rspamd_http_connection_router *
 rspamd_http_router_new (rspamd_http_router_error_handler_t eh,
 						rspamd_http_router_finish_handler_t fh,
-						struct timeval *timeout, struct event_base *base,
+						struct timeval *timeout,
 						const char *default_fs_path,
-						struct rspamd_keypair_cache *cache)
+						struct rspamd_http_context *ctx)
 {
 	struct rspamd_http_connection_router * new;
 	struct stat st;
@@ -387,7 +387,6 @@ rspamd_http_router_new (rspamd_http_router_error_handler_t eh,
 	new->conns = NULL;
 	new->error_handler = eh;
 	new->finish_handler = fh;
-	new->ev_base = base;
 	new->response_headers = g_hash_table_new_full (rspamd_strcase_hash,
 			rspamd_strcase_equal, g_free, g_free);
 
@@ -415,7 +414,7 @@ rspamd_http_router_new (rspamd_http_router_error_handler_t eh,
 		}
 	}
 
-	new->cache = cache;
+	new->ctx = ctx;
 
 	return new;
 }
@@ -510,13 +509,12 @@ rspamd_http_router_handle_socket (struct rspamd_http_connection_router *router,
 	conn->ud = ud;
 	conn->is_reply = FALSE;
 
-	conn->conn = rspamd_http_connection_new (NULL,
+	conn->conn = rspamd_http_connection_new (router->ctx,
+			NULL,
 			rspamd_http_router_error_handler,
 			rspamd_http_router_finish_handler,
 			0,
-			RSPAMD_HTTP_SERVER,
-			router->cache,
-			NULL);
+			RSPAMD_HTTP_SERVER);
 
 	if (router->key) {
 		rspamd_http_connection_set_key (conn->conn, router->key);
@@ -543,10 +541,6 @@ rspamd_http_router_free (struct rspamd_http_connection_router *router)
 			rspamd_keypair_unref (router->key);
 		}
 
-		if (router->cache) {
-			rspamd_keypair_cache_destroy (router->cache);
-		}
-
 		if (router->default_fs_path != NULL) {
 			g_free (router->default_fs_path);
 		}
diff --git a/src/libutil/http_router.h b/src/libutil/http_router.h
index 7440c519e..8e8056240 100644
--- a/src/libutil/http_router.h
+++ b/src/libutil/http_router.h
@@ -47,7 +47,7 @@ struct rspamd_http_connection_router {
 	struct timeval tv;
 	struct timeval *ptv;
 	struct event_base *ev_base;
-	struct rspamd_keypair_cache *cache;
+	struct rspamd_http_context *ctx;
 	gchar *default_fs_path;
 	rspamd_http_router_handler_t unknown_method_handler;
 	struct rspamd_cryptobox_keypair *key;
@@ -67,9 +67,8 @@ struct rspamd_http_connection_router * rspamd_http_router_new (
 		rspamd_http_router_error_handler_t eh,
 		rspamd_http_router_finish_handler_t fh,
 		struct timeval *timeout,
-		struct event_base *base,
 		const char *default_fs_path,
-		struct rspamd_keypair_cache *cache);
+		struct rspamd_http_context *ctx);
 
 /**
  * Set encryption key for the HTTP router
diff --git a/src/libutil/http_util.c b/src/libutil/http_util.c
index 8e220adfa..8fb658e08 100644
--- a/src/libutil/http_util.c
+++ b/src/libutil/http_util.c
@@ -22,6 +22,272 @@ static const gchar *http_week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "S
 static const gchar *http_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
 									 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
+/*
+ * Obtained from nginx
+ * Copyright (C) Igor Sysoev
+ */
+static guint mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+time_t
+rspamd_http_parse_date (const gchar *header, gsize len)
+{
+	const gchar *p, *end;
+	gint month;
+	guint day, year, hour, min, sec;
+	guint64 time;
+	enum {
+		no = 0, rfc822, /* Tue, 10 Nov 2002 23:50:13   */
+		rfc850, /* Tuesday, 10-Dec-02 23:50:13 */
+		isoc /* Tue Dec 10 23:50:13 2002    */
+	} fmt;
+
+	fmt = 0;
+	if (len > 0) {
+		end = header + len;
+	}
+	else {
+		end = header + strlen (header);
+	}
+
+	day = 32;
+	year = 2038;
+
+	for (p = header; p < end; p++) {
+		if (*p == ',') {
+			break;
+		}
+
+		if (*p == ' ') {
+			fmt = isoc;
+			break;
+		}
+	}
+
+	for (p++; p < end; p++)
+		if (*p != ' ') {
+			break;
+		}
+
+	if (end - p < 18) {
+		return (time_t)-1;
+	}
+
+	if (fmt != isoc) {
+		if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
+			return (time_t)-1;
+		}
+
+		day = (*p - '0') * 10 + *(p + 1) - '0';
+		p += 2;
+
+		if (*p == ' ') {
+			if (end - p < 18) {
+				return (time_t)-1;
+			}
+			fmt = rfc822;
+
+		}
+		else if (*p == '-') {
+			fmt = rfc850;
+
+		}
+		else {
+			return (time_t)-1;
+		}
+
+		p++;
+	}
+
+	switch (*p) {
+
+	case 'J':
+		month = *(p + 1) == 'a' ? 0 : *(p + 2) == 'n' ? 5 : 6;
+		break;
+
+	case 'F':
+		month = 1;
+		break;
+
+	case 'M':
+		month = *(p + 2) == 'r' ? 2 : 4;
+		break;
+
+	case 'A':
+		month = *(p + 1) == 'p' ? 3 : 7;
+		break;
+
+	case 'S':
+		month = 8;
+		break;
+
+	case 'O':
+		month = 9;
+		break;
+
*** OUTPUT TRUNCATED, 405 LINES SKIPPED ***


More information about the Commits mailing list