diff mbox series

[meta-networking,kirkstone,3/4] dovecot: patch CVE-2021-29157

Message ID 20260227154032.499047-3-skandigraun@gmail.com
State New
Headers show
Series [meta-multimedia,kirkstone,1/4] streamripper: ignore CVE-2020-37065 | expand

Commit Message

Gyorgy Sarvari Feb. 27, 2026, 3:40 p.m. UTC
Details: https://nvd.nist.gov/vuln/detail/CVE-2021-29157

Backport the patch that it used by Debian[1] to fix this CVE.

[1]: https://sources.debian.org/src/dovecot/1%3A2.3.13%2Bdfsg1-2%2Bdeb11u1/debian/patches
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
---
 .../dovecot/dovecot/CVE-2021-29157.patch      | 152 ++++++++++++++++++
 .../recipes-support/dovecot/dovecot_2.3.14.bb |   1 +
 2 files changed, 153 insertions(+)
 create mode 100644 meta-networking/recipes-support/dovecot/dovecot/CVE-2021-29157.patch
diff mbox series

Patch

diff --git a/meta-networking/recipes-support/dovecot/dovecot/CVE-2021-29157.patch b/meta-networking/recipes-support/dovecot/dovecot/CVE-2021-29157.patch
new file mode 100644
index 0000000000..cb0cba6f98
--- /dev/null
+++ b/meta-networking/recipes-support/dovecot/dovecot/CVE-2021-29157.patch
@@ -0,0 +1,152 @@ 
+From 1ee6540ef6ffa8cefade0161f4dcd47d82a1d10b Mon Sep 17 00:00:00 2001
+From: Gyorgy Sarvari <skandigraun@gmail.com>
+Date: Fri, 27 Feb 2026 16:10:35 +0100
+Subject: [PATCH] Fix CVE-2021-29157
+
+CVE: CVE-2021-29157
+Upstream-Status: Backport [the patch was taken from Debian: https://sources.debian.org/src/dovecot/1%3A2.3.13%2Bdfsg1-2%2Bdeb11u1/debian/patches/CVE-2021-29157.patch]
+Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
+---
+ src/lib-dict-extra/dict-fs.c     | 29 ++++++++++++++++
+ src/lib-oauth2/oauth2-jwt.c      | 58 ++++++++++++++++++--------------
+ src/lib-oauth2/test-oauth2-jwt.c |  2 +-
+ 3 files changed, 62 insertions(+), 27 deletions(-)
+
+diff --git a/src/lib-dict-extra/dict-fs.c b/src/lib-dict-extra/dict-fs.c
+index 31af578..f39c86c 100644
+--- a/src/lib-dict-extra/dict-fs.c
++++ b/src/lib-dict-extra/dict-fs.c
+@@ -68,8 +68,37 @@ static void fs_dict_deinit(struct dict *_dict)
+ 	i_free(dict);
+ }
+ 
++/* Remove unsafe paths */
++static const char *fs_dict_escape_key(const char *key)
++{
++	const char *ptr;
++	string_t *new_key = NULL;
++	/* we take the slow path always if we see potential
++	   need for escaping */
++	while ((ptr = strstr(key, "/.")) != NULL) {
++		/* move to the first dot */
++		const char *ptr2 = ptr + 1;
++		/* find position of non-dot */
++		while (*ptr2 == '.') ptr2++;
++		if (new_key == NULL)
++			new_key = t_str_new(strlen(key));
++		str_append_data(new_key, key, ptr - key);
++		/* if ptr2 is / or end of string, escape */
++		if (*ptr2 == '/' || *ptr2 == '\0')
++			str_append(new_key, "/...");
++		else
++			str_append(new_key, "/.");
++		key = ptr + 2;
++	}
++	if (new_key == NULL)
++		return key;
++	str_append(new_key, key);
++	return str_c(new_key);
++}
++
+ static const char *fs_dict_get_full_key(struct fs_dict *dict, const char *key)
+ {
++	key = fs_dict_escape_key(key);
+ 	if (str_begins(key, DICT_PATH_SHARED))
+ 		return key + strlen(DICT_PATH_SHARED);
+ 	else if (str_begins(key, DICT_PATH_PRIVATE)) {
+diff --git a/src/lib-oauth2/oauth2-jwt.c b/src/lib-oauth2/oauth2-jwt.c
+index 83b241c..8e43cf9 100644
+--- a/src/lib-oauth2/oauth2-jwt.c
++++ b/src/lib-oauth2/oauth2-jwt.c
+@@ -277,6 +277,34 @@ oauth2_jwt_copy_fields(ARRAY_TYPE(oauth2_field) *fields, struct json_tree *tree)
+ 	}
+ }
+ 
++/* Escapes '/' and '%' in identifier to %hex */
++static const char *escape_identifier(const char *identifier)
++{
++	size_t pos = strcspn(identifier, "/%");
++	/* nothing to escape */
++	if (identifier[pos] == '\0')
++		return identifier;
++
++	size_t len = strlen(identifier);
++	string_t *new_id = t_str_new(len);
++	str_append_data(new_id, identifier, pos);
++
++	for (size_t i = pos; i < len; i++) {
++		switch (identifier[i]) {
++		case '/':
++			str_append(new_id, "%2f");
++			break;
++		case '%':
++			str_append(new_id, "%25");
++			break;
++		default:
++			str_append_c(new_id, identifier[i]);
++			break;
++		}
++	}
++	return str_c(new_id);
++}
++
+ static int
+ oauth2_jwt_header_process(struct json_tree *tree, const char **alg_r,
+ 			  const char **kid_r, const char **error_r)
+@@ -377,6 +405,8 @@ oauth2_jwt_body_process(const struct oauth2_settings *set, const char *alg,
+ 	const char *azp = get_field(tree, "azp");
+ 	if (azp == NULL)
+ 		azp = "default";
++	else
++		azp = escape_identifier(azp);
+ 
+ 	if (oauth2_validate_signature(set, azp, alg, kid, blobs, error_r) < 0)
+ 		return -1;
+@@ -429,32 +459,8 @@ int oauth2_try_parse_jwt(const struct oauth2_settings *set,
+ 	else if (*kid == '\0') {
+ 		*error_r = "'kid' field is empty";
+ 		return -1;
+-	}
+-
+-	size_t pos = strcspn(kid, "./%");
+-	if (pos < strlen(kid)) {
+-		/* sanitize kid, cannot allow dots or / in it, so we encode them
+-		 */
+-		string_t *new_kid = t_str_new(strlen(kid));
+-		/* put initial data */
+-		str_append_data(new_kid, kid, pos);
+-		for (const char *c = kid+pos; *c != '\0'; c++) {
+-			switch (*c) {
+-			case '.':
+-				str_append(new_kid, "%2e");
+-				break;
+-			case '/':
+-				str_append(new_kid, "%2f");
+-				break;
+-			case '%':
+-				str_append(new_kid, "%25");
+-				break;
+-			default:
+-				str_append_c(new_kid, *c);
+-				break;
+-			}
+-		}
+-		kid = str_c(new_kid);
++	} else {
++		kid = escape_identifier(kid);
+ 	}
+ 
+ 	/* parse body */
+diff --git a/src/lib-oauth2/test-oauth2-jwt.c b/src/lib-oauth2/test-oauth2-jwt.c
+index 4cfba64..1706a96 100644
+--- a/src/lib-oauth2/test-oauth2-jwt.c
++++ b/src/lib-oauth2/test-oauth2-jwt.c
+@@ -577,7 +577,7 @@ static void test_jwt_kid_escape(void)
+ 	 random_fill(ptr, 32);
+ 	 buffer_t *b64_key = t_base64_encode(0, SIZE_MAX,
+ 					     secret->data, secret->used);
+-	 save_key_to("HS256", "hello%2eworld%2f%25", str_c(b64_key));
++	 save_key_to("HS256", "hello.world%2f%25", str_c(b64_key));
+ 	/* make a token */
+ 	buffer_t *tokenbuf = create_jwt_token_kid("HS256", "hello.world/%");
+ 	/* sign it */
diff --git a/meta-networking/recipes-support/dovecot/dovecot_2.3.14.bb b/meta-networking/recipes-support/dovecot/dovecot_2.3.14.bb
index c1fa702eaa..14303b4c08 100644
--- a/meta-networking/recipes-support/dovecot/dovecot_2.3.14.bb
+++ b/meta-networking/recipes-support/dovecot/dovecot_2.3.14.bb
@@ -13,6 +13,7 @@  SRC_URI = "http://dovecot.org/releases/2.3/dovecot-${PV}.tar.gz \
            file://0001-m4-Check-for-libunwind-instead-of-libunwind-generic.patch \
            file://0001-auth-Fix-handling-passdbs-with-identical-driver-args.patch \
            file://0001-lib-smtp-smtp-server-connection-Fix-STARTTLS-command.patch \
+           file://CVE-2021-29157.patch \
            "
 
 SRC_URI[md5sum] = "2f03532cec3280ae45a101a7a55ccef5"