mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-06-13 17:39:57 +00:00
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>
This commit is contained in:
@@ -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 */
|
||||||
@@ -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-m4-Check-for-libunwind-instead-of-libunwind-generic.patch \
|
||||||
file://0001-auth-Fix-handling-passdbs-with-identical-driver-args.patch \
|
file://0001-auth-Fix-handling-passdbs-with-identical-driver-args.patch \
|
||||||
file://0001-lib-smtp-smtp-server-connection-Fix-STARTTLS-command.patch \
|
file://0001-lib-smtp-smtp-server-connection-Fix-STARTTLS-command.patch \
|
||||||
|
file://CVE-2021-29157.patch \
|
||||||
"
|
"
|
||||||
|
|
||||||
SRC_URI[md5sum] = "2f03532cec3280ae45a101a7a55ccef5"
|
SRC_URI[md5sum] = "2f03532cec3280ae45a101a7a55ccef5"
|
||||||
|
|||||||
Reference in New Issue
Block a user