From 6c5304b5da6e44cfce9b03f469fa3d3b528ed1ff Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 28 Jan 2015 17:25:07 +0000 Subject: [PATCH] Implement key parsing from an HTTP request. --- src/libutil/http.c | 64 +++++++++++++++++++++++++++++++++++++++++----- src/libutil/http.h | 3 ++- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/libutil/http.c b/src/libutil/http.c index 5a597fbd2..41053e9ed 100644 --- a/src/libutil/http.c +++ b/src/libutil/http.c @@ -28,15 +28,27 @@ #include "printf.h" #include "logger.h" #include "ref.h" +#include "tweetnacl.h" +#include "blake2.h" #include +struct rspamd_http_keypair { + guchar beforenm[crypto_box_BEFORENMBYTES]; + guchar pk[crypto_box_PUBLICKEYBYTES]; + guchar sk[crypto_box_SECRETKEYBYTES]; + guchar id[BLAKE2B_OUTBYTES]; +}; + struct rspamd_http_connection_private { struct _rspamd_http_privbuf { GString *data; ref_entry_t ref; } *buf; gboolean new_header; + gboolean encrypted; + struct rspamd_http_keypair *local_key; + GString *peer_key; struct rspamd_http_header *header; struct http_parser parser; struct http_parser_settings parser_cb; @@ -71,9 +83,11 @@ static const struct _rspamd_http_magic { [HTTP_MAGIC_JPG] = { "jpg", "image/jpeg" }, }; -static gchar *http_week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; -static gchar *http_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", +static const gchar *http_week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; +static const gchar *http_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +static const gchar *key_header = "Key"; +static const gchar *date_header = "Date"; #define HTTP_ERROR http_error_quark () @@ -387,13 +401,46 @@ rspamd_http_parse_date (const gchar *header, gsize len) return (time_t) time; } +static void +rspamd_http_parse_key (GString *data, struct rspamd_http_connection_private *priv) +{ + guchar *decoded; + gsize decoded_len; + + if (priv->local_key == NULL) { + /* In this case we cannot do anything, e.g. we cannot decrypt payload */ + priv->encrypted = TRUE; + } + else { + /* Check sanity of what we have */ + decoded = rspamd_decode_base32 (data->str, data->len, &decoded_len); + if (decoded != NULL) { + if (decoded_len >= sizeof (priv->local_key->id) + + sizeof (priv->local_key->pk)) { + if (memcmp (priv->local_key->id, decoded, + sizeof (priv->local_key->id)) == 0) { + priv->peer_key = g_string_sized_new (sizeof (priv->local_key->pk)); + g_string_append_len (priv->peer_key, + decoded + sizeof (priv->local_key->id), + sizeof (priv->local_key->pk)); + } + } + } + priv->encrypted = TRUE; + g_free (decoded); + } +} + static inline void -rspamd_http_check_date (struct rspamd_http_connection_private *priv) +rspamd_http_check_special_header (struct rspamd_http_connection_private *priv) { - if (g_ascii_strcasecmp (priv->header->name->str, "date") == 0) { + if (g_ascii_strcasecmp (priv->header->name->str, date_header) == 0) { priv->msg->date = rspamd_http_parse_date (priv->header->value->str, priv->header->value->len); } + else if (g_ascii_strcasecmp (priv->header->name->str, key_header) == 0) { + rspamd_http_parse_key (priv->header->value, priv); + } } static gint @@ -447,7 +494,7 @@ rspamd_http_on_header_field (http_parser * parser, } else if (priv->new_header) { DL_APPEND (priv->msg->headers, priv->header); - rspamd_http_check_date (priv); + rspamd_http_check_special_header (priv); priv->header = g_slice_alloc (sizeof (struct rspamd_http_header)); priv->header->name = g_string_sized_new (32); priv->header->value = g_string_sized_new (32); @@ -492,7 +539,7 @@ rspamd_http_on_headers_complete (http_parser * parser) if (priv->header != NULL) { DL_APPEND (priv->msg->headers, priv->header); - rspamd_http_check_date (priv); + rspamd_http_check_special_header (priv); priv->header = NULL; } @@ -821,6 +868,11 @@ rspamd_http_connection_reset (struct rspamd_http_connection *conn) REF_RELEASE (priv->buf); } + if (priv->peer_key != NULL) { + g_string_free (priv->peer_key, TRUE); + } + priv->encrypted = FALSE; + rspamd_http_parser_reset (conn); if (priv->out != NULL) { diff --git a/src/libutil/http.h b/src/libutil/http.h index c6fcf0b83..ca037c702 100644 --- a/src/libutil/http.h +++ b/src/libutil/http.h @@ -70,7 +70,8 @@ struct rspamd_http_message { */ enum rspamd_http_options { RSPAMD_HTTP_BODY_PARTIAL = 0x1, /**< Call body handler on all body data portions */ - RSPAMD_HTTP_CLIENT_SIMPLE = 0x2 /**< Read HTTP client reply automatically */ + RSPAMD_HTTP_CLIENT_SIMPLE = 0x2, /**< Read HTTP client reply automatically */ + RSPAMD_HTTP_CLIENT_ENCRYPTED = 0x4 /**< Encrypt data for client */ }; struct rspamd_http_connection_private; -- 2.39.5