commit d793446: [Fix] Allow spaces in DKIM key records

Vsevolod Stakhov vsevolod at highsecure.ru
Tue Nov 2 21:28:04 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-11-02 21:24:36 +0000
URL: https://github.com/rspamd/rspamd/commit/d793446a7bcf4ec5ab8697f0598fd4e5b1ac5960 (HEAD -> master)

[Fix] Allow spaces in DKIM key records
Issue: #3955

---
 src/libserver/dkim.c | 101 +++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 89 insertions(+), 12 deletions(-)

diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c
index f83c64931..06318c847 100644
--- a/src/libserver/dkim.c
+++ b/src/libserver/dkim.c
@@ -1503,10 +1503,13 @@ rspamd_dkim_parse_key (const gchar *txt, gsize *keylen, GError **err)
 	const gchar *c, *p, *end, *key = NULL, *alg = "rsa";
 	enum {
 		read_tag = 0,
+		read_tag_before_eqsign,
 		read_eqsign,
 		read_p_tag,
 		read_k_tag,
-	} state = read_tag;
+		ignore_value,
+		skip_spaces,
+	} state = read_tag, next_state;
 	gchar tag = '\0';
 	gsize klen = 0, alglen = 0;
 
@@ -1519,23 +1522,52 @@ rspamd_dkim_parse_key (const gchar *txt, gsize *keylen, GError **err)
 		case read_tag:
 			if (*p == '=') {
 				state = read_eqsign;
-			} else {
+			}
+			else if (g_ascii_isspace (*p)) {
+				state = skip_spaces;
+
+				if (tag != '\0') {
+					/* We had tag letter */
+					next_state = read_tag_before_eqsign;
+				}
+				else {
+					/* We had no tag letter, so we ignore empty tag */
+					next_state = read_tag;
+				}
+			}
+			else {
 				tag = *p;
 			}
 			p++;
 			break;
+		case read_tag_before_eqsign:
+			/* Input: spaces before eqsign
+			 * Output: either read a next tag (previous had no value), or read value
+			 * p is moved forward
+			 */
+			if (*p == '=') {
+				state = read_eqsign;
+			}
+			else {
+				tag = *p;
+				state = read_tag;
+			}
+			p ++;
+			break;
 		case read_eqsign:
+			/* Always switch to skip spaces state and do not advance p */
+			state = skip_spaces;
+
 			if (tag == 'p') {
-				state = read_p_tag;
-				c = p;
-			} else if (tag == 'k') {
-				state = read_k_tag;
-				c = p;
-			} else {
+				next_state = read_p_tag;
+			}
+			else if (tag == 'k') {
+				next_state = read_k_tag;
+			}
+			else {
 				/* Unknown tag, ignore */
-				state = read_tag;
+				next_state = ignore_value;
 				tag = '\0';
-				p++;
 			}
 			break;
 		case read_p_tag:
@@ -1544,8 +1576,18 @@ rspamd_dkim_parse_key (const gchar *txt, gsize *keylen, GError **err)
 				key = c;
 				state = read_tag;
 				tag = '\0';
+				p++;
+			}
+			else if (g_ascii_isspace (*p)) {
+				klen = p - c;
+				key = c;
+				state = skip_spaces;
+				next_state = read_tag;
+				tag = '\0';
+			}
+			else {
+				p ++;
 			}
-			p++;
 			break;
 		case read_k_tag:
 			if (*p == ';') {
@@ -1553,8 +1595,43 @@ rspamd_dkim_parse_key (const gchar *txt, gsize *keylen, GError **err)
 				alg = c;
 				state = read_tag;
 				tag = '\0';
+				p++;
+			}
+			else if (g_ascii_isspace (*p)) {
+				alglen = p - c;
+				alg = c;
+				state = skip_spaces;
+				next_state = read_tag;
+				tag = '\0';
+			}
+			else {
+				p ++;
+			}
+			break;
+		case ignore_value:
+			if (*p == ';') {
+				state = read_tag;
+				tag = '\0';
+				p ++;
+			}
+			else if (g_ascii_isspace (*p)) {
+				state = skip_spaces;
+				next_state = read_tag;
+				tag = '\0';
+			}
+			else {
+				p ++;
+			}
+			break;
+		case skip_spaces:
+			/* Skip spaces and switch to the next state if needed */
+			if (g_ascii_isspace(*p)) {
+				p ++;
+			}
+			else {
+				c = p;
+				state = next_state;
 			}
-			p++;
 			break;
 		default:
 			break;


More information about the Commits mailing list