Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Please unblock package dovecot [ Reason ] Dovecot 1:2.3.13+dfsg1-2 includes two targeted security fixes and no other changes. The relevant section of debian/changelog is: dovecot (1:2.3.13+dfsg1-2) unstable; urgency=high * Import upstream fixes for security issues (Closes: #990566): - CVE-2021-29157: Path traversal issue allowing an attacker with access to the local filesystem can trick OAuth2 authentication into using an HS256 validation key from an attacker-controlled location - CVE-2021-33515: Sensitive information could be redirected to an attacker-controlled address because of a STARTTLS command injection bug in the submission service -- Noah Meyerhans <no...@debian.org> Tue, 20 Jul 2021 08:05:19 -0700 [ Impact ] We release bullseye with known security issues and will likely need to fix them in a subsequent point release. [ Tests ] I've done basic functionality testing. Additionally, the fixes are backported from upstream's changes and are already included in Ubuntu's security archive, so they've gotten reasonable test coverage at that level. I do not have reproducers for the security issues, so I have been unable to verify experimentally that the problems have been fixed. [ Risks ] Code changes are reasonably straightforward, and as mentioned are already deployed elsewhere. Further, they impact what I believe to be less common features of dovecot, meaning that even in the worst-case scenario, impact is likely to be limited to a small number of users. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing [ Other info ] n/a unblock dovecot/1:2.3.13+dfsg1-2
diff -Nru dovecot-2.3.13+dfsg1/debian/changelog dovecot-2.3.13+dfsg1/debian/changelog --- dovecot-2.3.13+dfsg1/debian/changelog 2021-01-25 23:38:17.000000000 +0000 +++ dovecot-2.3.13+dfsg1/debian/changelog 2021-07-20 15:05:19.000000000 +0000 @@ -1,3 +1,15 @@ +dovecot (1:2.3.13+dfsg1-2) unstable; urgency=high + + * Import upstream fixes for security issues (Closes: #990566): + - CVE-2021-29157: Path traversal issue allowing an attacker with + access to the local filesystem can trick OAuth2 authentication into + using an HS256 validation key from an attacker-controlled location + - CVE-2021-33515: Sensitive information could be redirected to an + attacker-controlled address because of a STARTTLS command injection + bug in the submission service + + -- Noah Meyerhans <no...@debian.org> Tue, 20 Jul 2021 08:05:19 -0700 + dovecot (1:2.3.13+dfsg1-1) unstable; urgency=medium [ Christian Göttsche ] diff -Nru dovecot-2.3.13+dfsg1/debian/patches/CVE-2021-29157.patch dovecot-2.3.13+dfsg1/debian/patches/CVE-2021-29157.patch --- dovecot-2.3.13+dfsg1/debian/patches/CVE-2021-29157.patch 1970-01-01 00:00:00.000000000 +0000 +++ dovecot-2.3.13+dfsg1/debian/patches/CVE-2021-29157.patch 2021-07-19 22:09:38.000000000 +0000 @@ -0,0 +1,134 @@ +Description: fix incorrectly escapes kid and azp fields in JWT tokens +Origin: https://launchpadlibrarian.net/544092180/dovecot_1%3A2.3.13+dfsg1-1ubuntu1_1%3A2.3.13+dfsg1-1ubuntu1.1.diff.gz + +--- a/src/lib-dict-extra/dict-fs.c ++++ b/src/lib-dict-extra/dict-fs.c +@@ -67,8 +67,37 @@ static void fs_dict_deinit(struct 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)) { +--- a/src/lib-oauth2/oauth2-jwt.c ++++ b/src/lib-oauth2/oauth2-jwt.c +@@ -250,6 +250,34 @@ oauth2_jwt_copy_fields(ARRAY_TYPE(oauth2 + } + } + ++/* 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) +@@ -349,6 +377,8 @@ oauth2_jwt_body_process(const struct oau + 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; +@@ -401,31 +431,8 @@ int oauth2_try_parse_jwt(const struct oa + 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 */ +--- a/src/lib-oauth2/test-oauth2-jwt.c ++++ b/src/lib-oauth2/test-oauth2-jwt.c +@@ -508,7 +508,7 @@ static void test_jwt_kid_escape(void) + void *ptr = buffer_append_space_unsafe(secret, 32); + 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 -Nru dovecot-2.3.13+dfsg1/debian/patches/CVE-2021-33515.patch dovecot-2.3.13+dfsg1/debian/patches/CVE-2021-33515.patch --- dovecot-2.3.13+dfsg1/debian/patches/CVE-2021-33515.patch 1970-01-01 00:00:00.000000000 +0000 +++ dovecot-2.3.13+dfsg1/debian/patches/CVE-2021-33515.patch 2021-07-19 22:05:12.000000000 +0000 @@ -0,0 +1,62 @@ +commit 321c339756f9b2b98fb7326359d1333adebb5295 +Author: Stephan Bosch <stephan.bo...@open-xchange.com> +Date: Sat May 22 00:16:38 2021 +0200 + + lib-smtp: smtp-server-connection - Fix STARTTLS command injection vulnerability. + + The input handler kept reading more commands even though the input was locked by + the STARTTLS command, thereby causing it to read the command pipelined beyond + STARTTLS. This causes a STARTTLS command injection vulerability. + +--- a/src/lib-smtp/smtp-server-cmd-starttls.c ++++ b/src/lib-smtp/smtp-server-cmd-starttls.c +@@ -37,6 +37,13 @@ static int cmd_starttls_start(struct smt + return -1; + } + ++ /* The command queue must be empty at this point. If anything were to be ++ queued somehow, this connection is vulnerable to STARTTLS command ++ insertion. ++ */ ++ i_assert(conn->command_queue_count == 0 && ++ conn->command_queue_head == NULL); ++ + /* RFC 3207, Section 4.2: + + Upon completion of the TLS handshake, the SMTP protocol is reset to +@@ -107,6 +114,13 @@ cmd_starttls_next(struct smtp_server_cmd + const struct smtp_server_callbacks *callbacks = conn->callbacks; + int ret; + ++ /* The command queue can only contain the STARTTLS command at this ++ point. If anything beyond the STARTTLS were queued somehow, this ++ connection is vulnerable to STARTTLS command insertion. ++ */ ++ i_assert(conn->command_queue_count == 1 && ++ conn->command_queue_tail == command); ++ + smtp_server_connection_set_state(conn, SMTP_SERVER_STATE_STARTTLS, + NULL); + +--- a/src/lib-smtp/smtp-server-connection.c ++++ b/src/lib-smtp/smtp-server-connection.c +@@ -440,7 +440,7 @@ smtp_server_connection_handle_input(stru + + /* Parse commands */ + ret = 1; +- while (!conn->closing && ret != 0) { ++ while (!conn->closing && !conn->input_locked && ret != 0) { + while ((ret = smtp_command_parse_next( + conn->smtp_parser, &cmd_name, &cmd_params, + &error_code, &error)) > 0) { +@@ -464,6 +464,10 @@ smtp_server_connection_handle_input(stru + + if (conn->disconnected) + return; ++ /* Last command locked the input; stop trying to read ++ more. */ ++ if (conn->input_locked) ++ break; + /* Client indicated it will close after this command; + stop trying to read more. */ + if (conn->closing) diff -Nru dovecot-2.3.13+dfsg1/debian/patches/series dovecot-2.3.13+dfsg1/debian/patches/series --- dovecot-2.3.13+dfsg1/debian/patches/series 2021-01-25 23:38:17.000000000 +0000 +++ dovecot-2.3.13+dfsg1/debian/patches/series 2021-07-19 22:05:12.000000000 +0000 @@ -16,3 +16,5 @@ Fix-32bit-sign-comparisons.patch Fix-32-bit-test-case.patch Improve-cross-compile-support.patch +CVE-2021-29157.patch +CVE-2021-33515.patch