summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGyorgy Sarvari <skandigraun@gmail.com>2026-02-27 16:40:31 +0100
committerGyorgy Sarvari <skandigraun@gmail.com>2026-02-27 17:00:35 +0100
commit331ff3f94b22a65ae15a744cdeffd02771d8394f (patch)
treefccc2cf349db68d43f4d4d4a2887ee0e75e38d23
parent7fd8cd657fe0836020116fd1633fe15cdb646df4 (diff)
downloadmeta-openembedded-331ff3f94b22a65ae15a744cdeffd02771d8394f.tar.gz
dovecot: patch CVE-2021-29157
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>
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot/CVE-2021-29157.patch152
-rw-r--r--meta-networking/recipes-support/dovecot/dovecot_2.3.14.bb1
2 files changed, 153 insertions, 0 deletions
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 @@
1From 1ee6540ef6ffa8cefade0161f4dcd47d82a1d10b Mon Sep 17 00:00:00 2001
2From: Gyorgy Sarvari <skandigraun@gmail.com>
3Date: Fri, 27 Feb 2026 16:10:35 +0100
4Subject: [PATCH] Fix CVE-2021-29157
5
6CVE: CVE-2021-29157
7Upstream-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]
8Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
9---
10 src/lib-dict-extra/dict-fs.c | 29 ++++++++++++++++
11 src/lib-oauth2/oauth2-jwt.c | 58 ++++++++++++++++++--------------
12 src/lib-oauth2/test-oauth2-jwt.c | 2 +-
13 3 files changed, 62 insertions(+), 27 deletions(-)
14
15diff --git a/src/lib-dict-extra/dict-fs.c b/src/lib-dict-extra/dict-fs.c
16index 31af578..f39c86c 100644
17--- a/src/lib-dict-extra/dict-fs.c
18+++ b/src/lib-dict-extra/dict-fs.c
19@@ -68,8 +68,37 @@ static void fs_dict_deinit(struct dict *_dict)
20 i_free(dict);
21 }
22
23+/* Remove unsafe paths */
24+static const char *fs_dict_escape_key(const char *key)
25+{
26+ const char *ptr;
27+ string_t *new_key = NULL;
28+ /* we take the slow path always if we see potential
29+ need for escaping */
30+ while ((ptr = strstr(key, "/.")) != NULL) {
31+ /* move to the first dot */
32+ const char *ptr2 = ptr + 1;
33+ /* find position of non-dot */
34+ while (*ptr2 == '.') ptr2++;
35+ if (new_key == NULL)
36+ new_key = t_str_new(strlen(key));
37+ str_append_data(new_key, key, ptr - key);
38+ /* if ptr2 is / or end of string, escape */
39+ if (*ptr2 == '/' || *ptr2 == '\0')
40+ str_append(new_key, "/...");
41+ else
42+ str_append(new_key, "/.");
43+ key = ptr + 2;
44+ }
45+ if (new_key == NULL)
46+ return key;
47+ str_append(new_key, key);
48+ return str_c(new_key);
49+}
50+
51 static const char *fs_dict_get_full_key(struct fs_dict *dict, const char *key)
52 {
53+ key = fs_dict_escape_key(key);
54 if (str_begins(key, DICT_PATH_SHARED))
55 return key + strlen(DICT_PATH_SHARED);
56 else if (str_begins(key, DICT_PATH_PRIVATE)) {
57diff --git a/src/lib-oauth2/oauth2-jwt.c b/src/lib-oauth2/oauth2-jwt.c
58index 83b241c..8e43cf9 100644
59--- a/src/lib-oauth2/oauth2-jwt.c
60+++ b/src/lib-oauth2/oauth2-jwt.c
61@@ -277,6 +277,34 @@ oauth2_jwt_copy_fields(ARRAY_TYPE(oauth2_field) *fields, struct json_tree *tree)
62 }
63 }
64
65+/* Escapes '/' and '%' in identifier to %hex */
66+static const char *escape_identifier(const char *identifier)
67+{
68+ size_t pos = strcspn(identifier, "/%");
69+ /* nothing to escape */
70+ if (identifier[pos] == '\0')
71+ return identifier;
72+
73+ size_t len = strlen(identifier);
74+ string_t *new_id = t_str_new(len);
75+ str_append_data(new_id, identifier, pos);
76+
77+ for (size_t i = pos; i < len; i++) {
78+ switch (identifier[i]) {
79+ case '/':
80+ str_append(new_id, "%2f");
81+ break;
82+ case '%':
83+ str_append(new_id, "%25");
84+ break;
85+ default:
86+ str_append_c(new_id, identifier[i]);
87+ break;
88+ }
89+ }
90+ return str_c(new_id);
91+}
92+
93 static int
94 oauth2_jwt_header_process(struct json_tree *tree, const char **alg_r,
95 const char **kid_r, const char **error_r)
96@@ -377,6 +405,8 @@ oauth2_jwt_body_process(const struct oauth2_settings *set, const char *alg,
97 const char *azp = get_field(tree, "azp");
98 if (azp == NULL)
99 azp = "default";
100+ else
101+ azp = escape_identifier(azp);
102
103 if (oauth2_validate_signature(set, azp, alg, kid, blobs, error_r) < 0)
104 return -1;
105@@ -429,32 +459,8 @@ int oauth2_try_parse_jwt(const struct oauth2_settings *set,
106 else if (*kid == '\0') {
107 *error_r = "'kid' field is empty";
108 return -1;
109- }
110-
111- size_t pos = strcspn(kid, "./%");
112- if (pos < strlen(kid)) {
113- /* sanitize kid, cannot allow dots or / in it, so we encode them
114- */
115- string_t *new_kid = t_str_new(strlen(kid));
116- /* put initial data */
117- str_append_data(new_kid, kid, pos);
118- for (const char *c = kid+pos; *c != '\0'; c++) {
119- switch (*c) {
120- case '.':
121- str_append(new_kid, "%2e");
122- break;
123- case '/':
124- str_append(new_kid, "%2f");
125- break;
126- case '%':
127- str_append(new_kid, "%25");
128- break;
129- default:
130- str_append_c(new_kid, *c);
131- break;
132- }
133- }
134- kid = str_c(new_kid);
135+ } else {
136+ kid = escape_identifier(kid);
137 }
138
139 /* parse body */
140diff --git a/src/lib-oauth2/test-oauth2-jwt.c b/src/lib-oauth2/test-oauth2-jwt.c
141index 4cfba64..1706a96 100644
142--- a/src/lib-oauth2/test-oauth2-jwt.c
143+++ b/src/lib-oauth2/test-oauth2-jwt.c
144@@ -577,7 +577,7 @@ static void test_jwt_kid_escape(void)
145 random_fill(ptr, 32);
146 buffer_t *b64_key = t_base64_encode(0, SIZE_MAX,
147 secret->data, secret->used);
148- save_key_to("HS256", "hello%2eworld%2f%25", str_c(b64_key));
149+ save_key_to("HS256", "hello.world%2f%25", str_c(b64_key));
150 /* make a token */
151 buffer_t *tokenbuf = create_jwt_token_kid("HS256", "hello.world/%");
152 /* 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 \
13 file://0001-m4-Check-for-libunwind-instead-of-libunwind-generic.patch \ 13 file://0001-m4-Check-for-libunwind-instead-of-libunwind-generic.patch \
14 file://0001-auth-Fix-handling-passdbs-with-identical-driver-args.patch \ 14 file://0001-auth-Fix-handling-passdbs-with-identical-driver-args.patch \
15 file://0001-lib-smtp-smtp-server-connection-Fix-STARTTLS-command.patch \ 15 file://0001-lib-smtp-smtp-server-connection-Fix-STARTTLS-command.patch \
16 file://CVE-2021-29157.patch \
16 " 17 "
17 18
18SRC_URI[md5sum] = "2f03532cec3280ae45a101a7a55ccef5" 19SRC_URI[md5sum] = "2f03532cec3280ae45a101a7a55ccef5"