Debian Patches
Status for dovecot/1:2.4.1+dfsg1-6+deb13u7
| Patch | Description | Author | Forwarded | Bugs | Origin | Last update |
|---|---|---|---|---|---|---|
| 0001-lib-imap-urlauth-Fix-leaking-uninitialized-memory-in.patch | lib-imap-urlauth: Fix leaking uninitialized memory into client error message imap_urlauth_fetch_parsed() called imap_msgpart_url_open_mailbox() with client_error_r and then, on the ret==0 (mailbox-not-found) branch, formatted a separate uninitialized local "error" pointer with t_strdup_printf("Invalid URLAUTH: %s", error). The %s read process stack memory until a NUL byte and sent it to the authenticated IMAP client inside the "* NO Failed to fetch URLAUTH ..." response. Broken by bb193c273e63ffa42c5c0b51ecd8860398e3beab |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-06 | ||
| 0001-lib-Add-str_equals_timing_safe.patch | [PATCH 1/2] lib: Add str_equals_timing_safe() Constant-time string comparison that avoids the length leak in str_equals_timing_almost_safe(). Compares HMAC-SHA256 digests of the inputs (keyed with hash_iv) rather than the strings themselves, so neither the contents nor the length of either input affects timing in a way an attacker can exploit. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-28 | ||
| 0002-doveadm-Avoid-leaking-doveadm_password-or-doveadm_ap.patch | [PATCH 2/2] doveadm: Avoid leaking doveadm_password or doveadm_api_key lengths | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-28 | ||
| CVE-2026-27855-3.patch | [PATCH 23/24] auth: Initialize set_credentials event properly Fixes update_query |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-03-09 | ||
| CVE-2026-27855-4.patch | [PATCH 24/24] auth: passdb-sql - Require update_query to be set when used | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-03-11 | ||
| CVE-2026-27856-1.patch | [PATCH 16/24] doveadm: client-connection - Use timing safe credential check | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-03-04 | ||
| CVE-2026-27856-2.patch | [PATCH 17/24] doveadm: Use datastack for temporary b64 value There is no need to allocate it from connection pool. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-03-04 | ||
| CVE-2026-27856-3.patch | [PATCH 18/24] doveadm: client-connection - Get API key from per-connection settings | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-03-04 | ||
| CVE-2026-27857-1.patch | [PATCH 1/2] plugins: imap-filter-sieve: imap-filter-sieve - Adjust to imap_parser_create() API change | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-03-06 | ||
| CVE-2026-27857-2.patch | [PATCH 12/24] lib-imap, global: Add params parameter to imap_parser_create() | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-03-06 | ||
| CVE-2026-27857-3.patch | [PATCH 13/24] lib-imap: Add imap_parser_params.list_count_limit | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-03-06 | ||
| CVE-2026-27857-4.patch | [PATCH 14/24] imap-login: Limit the number of open IMAP parser lists This prevents attackers from using a large number of '(' in a command to grow memory usage excessively. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-03-06 | ||
| CVE-2026-27857-5.patch | [PATCH 15/24] global: Use const for struct imap_parser_params params | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-03-02 | ||
| CVE-2026-27858.patch | [PATCH 2/2] managesieve-login: Verify AUTHENTICATE initial response size isn't too large This prevents DoSing the managesieve-login by sending an excessively large initial response size, which causes a huge memory allocation. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-03-02 | ||
| CVE-2026-27859.patch | [PATCH 03/24] lib-mail: Limit the number of RFC2231 parameters that can be parsed This avoids excessive CPU usage especially in result_append(). |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-24 | ||
| CVE-2026-27851.patch | lib-var-expand: Reset safe state when transfer is unset Otherwise unsafe content is treated safe. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-03-29 | ||
| CVE-2026-40016.patch | lib-sieve: Enforce CPU time limit within :contains and :matches matcher loops The naive O(N*M) substring search in mcht-contains.c and the naive find loop in mcht-matches.c can run for hours on a large value (e.g. a message body), completely bypassing sieve_max_cpu_time because that limit was only checked between bytecode operations. Expose the active CPU limit via sieve_runtime_cpu_limit_exceeded() and poll it every 4096 inner iterations. When the limit is hit the match returns SIEVE_EXEC_RESOURCE_LIMIT, matching the existing behavior at the bytecode boundary. This is a minimal safety net ahead of switching the matchers to algorithms that do not require it. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-19 | ||
| CVE-2026-33603.patch | login-common: Only accept base64 in sasl | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-04-08 | ||
| CVE-2026-40020-1.patch | [PATCH 1/3] acl: Add acl_id_is_valid() Returns TRUE if the ACL identifier string is at most ACL_ID_MAX_LEN (1024) bytes long, contains no control characters and is valid UTF-8. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-22 | ||
| CVE-2026-40020-2.patch | [PATCH 2/3] imap-acl: Fail if ACL identifier is invalid Reject invalid identifiers early in imap_acl_identifier_parse() using acl_id_is_valid(). This prevents CR/LF injection and rejects identifiers that are too long, contain control characters or are not valid UTF-8. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-22 | ||
| CVE-2026-40020-3.patch | [PATCH 3/3] acl: Assert-crash if ACL identifier is invalid before writing it It should have been checked earlier already. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-22 | ||
| CVE-2026-42006.patch | lib-imap: Fix imap_parser_params.list_count_limit to actually work The previous fix in d0f67b52914565a35f3817335ab9633cb291513c was accidentally limiting the number of ')', not the number of '('. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-27 | ||
| lib-mail-istream-header-filter-Fix-potential-assert-.patch | lib-mail: istream-header-filter - Fix potential assert-crash In some situations multiple snapshots were created, which broke the logic of using a single snapshot_pending boolean. Changed it to refcount. Fixes: |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-09-02 | ||
| skip-rfc-subdir.patch | Don't try to build doc/rfc subdir components | Noah Meyerhans <noahm@debian.org> | not-needed | 2020-05-21 | ||
| 0001-lda-Fix-using-USER-environment-if-d-hasn-t-been-spec.patch | lda: Fix using USER environment if -d hasn't been specified This became broken at some point. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-05-26 | ||
| 0002-lda-Default-mail_home-HOME-environment-if-not-using-.patch | lda: Default mail_home=$HOME environment if not using userdb lookup The previous code to do this was removed by e57d5b9002f910c095ee5b55821395fcf1da016a |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-05-26 | ||
| Use-_FORTIFY_SOURCE-level-3.patch | Use _FORTIFY_SOURCE level 3 | Christian Göttsche <cgzones@googlemail.com> | not-needed | 2022-12-22 | ||
| fit-32-bit-test-integers.patch | =================================================================== | no | ||||
| bug1104549-gssapi-regression.patch | Fix GSSAPI regression Dovecot 2.4 introduced a regression that broke GSSAPI authentication for some clients. This patch contains a fix provided by the upstream maintainers. |
no | debian | https://dovecot.org/mailman3/archives/list/dovecot@dovecot.org/message/O54EAGLIXXHMOH7BQCCKHHB3Z32HDWVR/ | 2025-05-02 | |
| fix-man-errors.patch | Fix groff errors in upstream manpages | Noah Meyerhans <noahm@debian.org> | no | 2025-05-02 | ||
| bug1106784_Fix-LDAP-SASL-auth-support.patch | Fix LDAP SASL auth support 961275fdb54878fdfa4ee1b9f1a4f00e82bf4a83 moved code without creating a way to have HAVE_LDAP_SASL defined there. Copy the preprocessor block from src/auth/db-ldap.c to fix this. |
Jakob Haufe <sur5r@sur5r.net> | no | 2025-05-25 | ||
| auth__Use_AUTH_CACHE_KEY_USER_instead_of_per-database.patch | auth: Use AUTH_CACHE_KEY_USER instead of per-database constants Fixes cache key issue where users would end up overwriting each other in cache due to cache key being essentially static string because we no longer support %u. Forgotten in 2e298e7ee98b6df61cf85117f000290d60a473b8 |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2025-07-25 | ||
| auth__Terminate_properly_auth_oauth2_post_setting_defines.patch | auth: Terminate properly auth_oauth2_post_setting_defines list Fixes: |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-05-15 | ||
| lib-sieve_sieve-script_c_sieve_script_create_common_Correctly_handle_errors.patch | lib-sieve/sieve-script.c: sieve_script_create_common: Correctly handle errors. Fixes null pointer deref (e.g. in case of absent file). |
Alexander Gerasiov <a@gerasiov.net> | no | 2025-09-23 | ||
| bug1121000_dovecot-ldap_Crash_if_iterate_filter_is_set_but_iterate_fields_is_not_set.patch | auth: ldap - Fix crash if users are iterated, but userdb_ldap_iterate_fields is not set | Timo Sirainen <timo.sirainen@open-xchange.com> | no | debian | 2025-11-06 | |
| 0001-trash-Use-mailbox-event-in-trash_try_mailbox-for-set.patch | trash: Use mailbox event in trash_try_mailbox() for settings | Aki Tuomi <aki.tuomi@open-xchange.com> | no | debian | 2026-01-09 | |
| acl-Fix-crash-when-group-ACLs-are-used-but-user-s-ac.patch | acl: Fix crash when group ACLs are used, but user's acl_groups is empty | Marco Bettini <marco.bettini@open-xchange.com> | no | debian | 2025-08-28 | |
| CVE-2025-59028.patch | [PATCH 01/24] auth: Don't disconnect auth client when invalid base64 SASL input is received The base64 input comes from untrusted client. It shouldn't cause the auth client to disconnect, which causes other concurrent logins to be aborted. Broken by 1486c30e191ff079bfa78e7950173bb33d8073d9 |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-11-04 | ||
| CVE-2025-59031.patch | [PATCH 02/24] fts: Remove decode2text.sh The script is flawed and not fit for production use, should recommend writing your own script, or using Apache Tika. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-01-08 | ||
| CVE-2025-59032.patch | managesieve-login: Fix crash when command didn't finish on the first call | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-12-22 | ||
| CVE-2026-24031-27860-1.patch | [PATCH 04/24] auth: Make struct settings_get_params params const | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-25 | ||
| CVE-2026-24031-27860-2.patch | [PATCH 05/24] auth: passdb/userdb ldap - Fix escaping ldap filter, base and bind_userdn Broken by c2ccdab8d09dec65753ee42366f48d53d7f47cfd |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-20 | ||
| CVE-2026-24031-27860-3.patch | [PATCH 06/24] lib-settings: settings_get_params() - Fix using provided escape_func This fixes auth-sql and auth-ldap to actually do escaping. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-23 | ||
| CVE-2026-24031-27860-4.patch | [PATCH 07/24] auth: test-auth - Run Lua unit tests even when building Lua as plugin | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-23 | ||
| CVE-2026-24031-27860-5.patch | [PATCH 08/24] auth: Rewrite ldap_escape() with a unit test | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-23 | ||
| CVE-2026-24031-27860-6.patch | [PATCH 09/24] auth: passdb sql - Fix escaping for set_credentials() This was only used by OTP SASL mechanism after successful authentication, so it practically couldn't be used for SQL injections. Broken by ef0c63b690e6ef9fbd53cb815dfab50d1667ba3a |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-24 | ||
| CVE-2026-24031-27860-7.patch | [PATCH 10/24] auth: userdb sql - Fix escaping for user iteration This is mostly a non-issue, since userdb iteration doesn't take any untrusted input. Broken by ef0c63b690e6ef9fbd53cb815dfab50d1667ba3a |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-24 | ||
| CVE-2026-24031-27860-8.patch | [PATCH 11/24] lib-var-expand: Add "safe" filter to prevent escaping output For example ldap_base = %{passdb:next_dn | safe} to avoid escaping the DN. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-25 | ||
| CVE-2026-27855-1.patch | [PATCH 21/24] auth: cache - Use translated username in auth_cache_remove() | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-03-09 | ||
| CVE-2026-27855-2.patch | [PATCH 22/24] auth: Move passdb event lifecycle handling to auth_request_passdb_event_(begin|end) | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-03-11 | ||
| 0001-imap-Restrict-COMPRESS-to-DEFLATE-only.patch | [PATCH 1/3] imap: Restrict COMPRESS to DEFLATE only cmd_compress() and the imap-login proxy side channel looked up any registered compression handler by name, so a client could request e.g. COMPRESS ZSTD even though only COMPRESS=DEFLATE is advertised (RFC 4978). Non-DEFLATE algorithms can require far more memory to decompress (a zstd decoder alone can hold a 16+ MB window per connection versus ~40 KB for inflate). This matters now that imap-login handles COMPRESS for proxied login process into its vsz_limit and crash it, affecting all clients on that process. Only accept DEFLATE on both the backend and the login proxy path. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-07-04 | ||
| 0002-doveadm-compress-connect-Don-t-hang-when-server-reje.patch | [PATCH 2/3] doveadm: compress-connect - Don't hang when server rejects COMPRESS After sending a COMPRESS command the client stopped reading stdin and waited for the server's reply, but it only resumed on an "OK Begin compression" reply. If the server rejected COMPRESS (e.g. a NO reply for an unsupported mechanism), compress_waiting was never cleared: the client waited forever for an OK that never came while the server waited for the next command, deadlocking the session. Remember the COMPRESS command tag and treat any tagged reply to it that isn't the compression-start reply as a rejection, resuming the pipelined input. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-07-06 | ||
| 0003-doveadm-compress-Delay-failing-if-used-COMPRESS-algo.patch | [PATCH 3/3] doveadm compress: Delay failing if used COMPRESS algorithm is not supported locally This command is used in CI tests to verify the server rejects non-DEFLATE algorithm. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-07-07 | ||
| 0001-lib-storage-Allow-NULL-path-in-mailbox_list_mkdir_ro.patch | [PATCH 1/2] lib-storage: Allow NULL path in mailbox_list_mkdir_root() When path is NULL, look up the root directory path of the given type via mailbox_list_get_root_path() and create that. If there is no path of the requested type, nothing is done. This avoids open-coding the common get_root_path() + mkdir_root() pair at call sites. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-23 | ||
| 0002-lib-storage-Simplify-mailbox_mkdir-using-mailbox_lis.patch | [PATCH 2/2] lib-storage: Simplify mailbox_mkdir() using mailbox_list_mkdir_root(NULL) mailbox_mkdir() looked up the root path via mailbox_list_get_root_forced() only to pass it straight to mailbox_list_mkdir_root(). Let mkdir_root() resolve the root itself by passing path=NULL, dropping the local variable. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-23 | ||
| 0001-lib-sieve-sieve-storage-Add-is_personal-bit.patch | lib-sieve: sieve-storage - Add is_personal bit Simpler than evaluating the type and personal storage is created only through sieve_storage_create_personal(). This mimics the bit for default storage. |
Stephan Bosch <stephan.bosch@open-xchange.com> | no | 2025-11-25 | ||
| 0001-lib-sieve-sieve-storage-Fix-panic-caused-by-flawed-d.patch | lib-sieve: sieve-storage - Fix panic caused by flawed detection of personal storage type Recent commit d82c2e624e4a9c364a6fa58fad0938ae5578660c added the is_personal flag, but it is assigned too late. Fix this issue by assigning this flag in the earliest allocation function. This issue commonly surfaces when people forget to set an appropriate type for a script storage definition, in which case the "personal" type is the default. Panic was: (sieve_file_storage_active_read_link): assertion failed: (fstorage->active_path != NULL) |
Stephan Bosch <stephan.bosch@open-xchange.com> | no | 2026-03-04 | ||
| 0001-lib-sieve-Add-per-user-sieve-rusage-file-for-cumulat.patch | [PATCH 1/7] lib-sieve: Add per-user sieve-rusage file for cumulative CPU tracking Cumulative resource usage was previously stored in each compiled Sieve binary's (.svbin) header. Because the binary file is keyed by script name, a user could reset their CPU budget by uploading the same script under a different name (PUTSCRIPT newname + SETACTIVE newname), RENAMESCRIPT, or DELETESCRIPT followed by PUTSCRIPT under another name. Each such operation produced a fresh .svbin with zero counter, allowing the sieve_max_cpu_time limit to be bypassed indefinitely. Track cumulative CPU per user instead, in <INBOX-namespace-root>/sieve-rusage. The file persists across all script renames, deletions, and re-uploads, since it is not tied to any particular script name. Tracking is enabled only for personal storages where the user's INBOX namespace has a filesystem path; admin/default storages are unaffected here. The on-disk format is a single ASCII line: V1 <flags> <cpu-secs> <update-time> CPU time is rounded up to whole seconds when persisted; sub-second precision is preserved only for the in-memory accumulation within a single execution. The file is updated by writing a new copy via file_dotlock_open_mode() and replacing the original via file_dotlock_replace(). Concurrent writers are serialized through the dotlock; readers do not need a lock because the rename is atomic. The .svbin header still carries its original resource_usage struct as the active fallback when no per-user file is available; a follow-up commit drops that path. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-05 | ||
| 0002-lib-sieve-Drop-binary-header-resource-usage-tracking.patch | [PATCH 2/7] lib-sieve: Drop binary-header resource usage tracking With the per-user sieve-rusage file now authoritative for personal storages, the .svbin header no longer needs to carry CPU usage. Admin storages (sieve_before/after, default location) cannot be re-uploaded by the user, so cross-run tracking is unnecessary there; the runtime sieve_max_cpu_time check still enforces the per-execution limit. Move the in-memory cumulative carry-over from sbin->header.resource_usage to a dedicated sbin->persisted_rusage substruct. The on-disk header struct now solely represents the wire format and is zeroed on every save; the in-memory carry-over no longer overloads it. Drop the now-dead "resource usage" section from sieve_binary_dumper_run() (the on-disk fields are always zero, so the section never produced output). |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-05 | ||
| 0003-lib-sieve-Rename-on-disk-header-rusage-fields-to-unu.patch | [PATCH 3/7] lib-sieve: Rename on-disk header rusage fields to unused_* The .svbin header's resource_usage fields no longer carry data: they are zeroed on save and discarded on load. Cumulative CPU tracking lives in the per-user sieve-rusage file, and the in-memory carry-over lives in sbin->persisted_rusage. Flatten the nested resource_usage struct and rename the fields to unused_update_time and unused_cpu_time_msecs so it is obvious the fields are kept only for on-disk format compatibility. The memory layout of struct sieve_binary_header is unchanged. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-03 | ||
| 0004-lib-sieve-Switch-sieve_max_cpu_time-enforcement-to-t.patch | [PATCH 4/7] lib-sieve: Switch sieve_max_cpu_time enforcement to time-decayed re-enable When a user's cumulative CPU time exceeded sieve_max_cpu_time, the script was permanently disabled. SIEVE_BINARY_FLAG_RESOURCE_LIMIT was set in the binary header on first overrun and was never cleared by the resource_usage_timeout decay (which only zeroed the cpu_time field), so sieve_binary_check_executable() refused execution forever unless the binary was recompiled or an admin manually wiped the file. Replace the sticky-flag model with one driven purely by the persisted cumulative cpu_time, decayed by resource_usage_timeout: - Drop SIEVE_BINARY_FLAG_RESOURCE_LIMIT and the enum that defined it; nothing reads sbin->header.flags anymore. - sieve_binary_check_executable() and sieve_binary_check_resource_usage() call sieve_resource_usage_is_excessive() on the current cumulative cpu_time. Raising sieve_max_cpu_time now correctly re-enables a previously over-limit user without further intervention. - Gate per-user file persistence on the per-run delta, not the cumulative total. A refused-without-running attempt has a zero delta, skips the file write, and leaves update_time at the moment work was actually consumed. After resource_usage_timeout seconds of inactivity (or only-trivial deliveries) the next load decays the cpu_time to zero and the user is allowed to run again. The on-disk per-user sieve-rusage file format becomes: V1 <cpu-secs> <update-time> |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-05 | ||
| 0005-lib-sieve-file-storage-Remove-orphan-compiled-binari.patch | [PATCH 5/7] lib-sieve: file storage: Remove orphan compiled binaries on delete and rename DELETESCRIPT and RENAMESCRIPT only operated on the .sieve file and left the matching compiled binary (.svbin) on disk. The orphan was never referenced again under that name, so it accumulated as wasted disk space until something else (manual cleanup, account removal) removed it. Unlink fscript->bin_path alongside the .sieve operation. The unlink is DELETE/RENAME. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-05 | ||
| 0006-lib-sieve-Log-a-warning-when-cumulative-CPU-exceeds-.patch | [PATCH 6/7] lib-sieve: Log a warning when cumulative CPU exceeds the limit sieve_binary_record_resource_usage() returned FALSE when the script's cumulative CPU time crossed sieve_max_cpu_time, but the only log line on that path was a debug-level "Updated cumulative resource usage" emitted on every recording, with no signal at the actual disable transition. Operators had to infer the disable from later "Failed to open script ... (cumulative resource limit exceeded)" errors on subsequent deliveries. Emit a warning at the transition point, including the cumulative CPU usage that triggered it. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-03 | ||
| 0007-lib-sieve-Log-an-info-line-when-opening-a-CPU-disabl.patch | [PATCH 7/7] lib-sieve: Log an info line when opening a CPU-disabled script sieve_binary_check_executable() blocks execution when a script's persisted cumulative CPU usage already exceeds sieve_max_cpu_time, but only logged the block at debug level. With cumulative tracking now sticky across redeliveries via the per-user sieve-rusage file, the script can stay blocked indefinitely until the resource_usage_timeout decay or admin intervention; operators benefit from a per-attempt record of that block at info level. Promote the existing debug log to e_info and include the cumulative CPU usage. The caller continues to emit its own error message on the failed open (lda-sieve, imap-sieve, imap-filter-sieve plugin paths). |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-03 | ||
| 0008-lib-sieve-Reduce-CPU-limit-check-interval-in-contain.patch | lib-sieve: Reduce CPU limit check interval in :contains and :matches matchers Reduce the interval to 64 so worst-case work between checks is ~64 MiB. cpu_limit_exceeded() is a signal-counter comparison with no syscall, so the higher call frequency has no measurable cost. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-05-25 | ||
| 0001-imap-login-Add-comments-to-internal-ID-command-param.patch | imap-login: Add comments to internal ID command parameter handling | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-02 | ||
| 0001-imap-login-Fix-excessive-memory-growth-with-pre-logi.patch | imap-login: Fix excessive memory growth with pre-login ID command The pre-login ID parser reset the per-argument line and list limits after every argument, so nothing bounded the number of key/value pairs. Each external key grew log_reply and added a distinct event field (a linear scan, making it O(N^2)), allowing a pre-auth CPU/memory amplification. Account at most 30 pairs (per RFC 2971) into the logging and client_id bookkeeping. Internal x-* parameter handlers still run for pairs beyond the limit, since a trusted proxy may legitimately forward more fields. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-07-04 | ||
| 0001-lib-lda-mail-deliver-Autocreate-delivery-mailbox-via.patch | [PATCH 1/2] lib-lda: mail-deliver - Autocreate delivery mailbox via explicit mailbox_create() Instead of relying on MAILBOX_FLAG_AUTO_CREATE to have mailbox_open() implicitly create the target, open it and, on MAIL_ERROR_NOTFOUND, create it explicitly when lda_mailbox_autocreate is enabled. This makes the creation go through the normal mailbox_create() path (including ACL checks) and removes one of the two users of the autocreate mailbox flags. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-11 | ||
| 0002-lib-storage-Remove-MAILBOX_FLAG_AUTO_CREATE-and-MAIL.patch | [PATCH 2/2] lib-storage: Remove MAILBOX_FLAG_AUTO_CREATE and MAILBOX_FLAG_AUTO_SUBSCRIBE These flags were set only by mail delivery (lib-lda) and Sieve fileinto (Pigeonhole), both of which now create the target mailbox explicitly with mailbox_create(). Nothing sets the flags anymore, so remove them and drop the flag checks from mailbox_is_autocreated() and mailbox_is_autosubscribed(). As a result mailbox_is_autocreated() reflects only mailboxes that virtually already exist (the user's INBOX and admin-configured "auto" mailboxes), so the ACL plugin again enforces the CREATE right for delivery-autocreated mailboxes in shared and public namespaces. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-11 | ||
| 0001-lib-sieve-actions-Split-mailbox-creation-into-sieve_.patch | [PATCH 1/2] lib-sieve: actions - Split mailbox creation into sieve_act_store_create_mailbox() Pure refactoring with no functional change: move the mailbox_create() / subscribe / reopen sequence out of the "mailbox" extension's :create side effect (seff_mailbox_create_pre_execute) into a new reusable sieve_act_store_create_mailbox() helper. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-11 | ||
| 0002-lib-sieve-actions-Create-fileinto-mailbox-without-th.patch | [PATCH 2/2] lib-sieve: actions - Create fileinto mailbox without the autocreate flag Stop setting MAILBOX_FLAG_AUTO_CREATE/SUBSCRIBE in act_store. Instead, on mailbox_open() returning MAIL_ERROR_NOTFOUND, create the mailbox explicitly with sieve_act_store_create_mailbox() when autocreation is enabled (the :create side effect already creates it explicitly). This makes the creation go through the normal ACL CREATE gate, so a fileinto (with lda_mailbox_autocreate=yes) or fileinto :create can no longer create a mailbox in a shared or public namespace that the user lacks the CREATE right for. A permission failure to create the mailbox is classified by sieve_act_store_create_error_status(): for a user's personal script it is a permanent failure (implicit keep), while for a global (administrator-defined) script it is deferred (temporary failure), so the administrator notices the script is behaving in a way they did not intend. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-11 | ||
| 0001-lib-i_close_fd-Document-that-it-preserves-errno.patch | [PATCH 1/5] lib: i_close_fd*() - Document that it preserves errno | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-03 | ||
| 0002-lib-path-util-Add-t_openat_safe-for-jailed-openat-re.patch | [PATCH 2/5] lib: path-util - Add t_openat_safe() for jailed openat() resolution Add a helper that opens a path relative to a directory fd while refusing any resolution that escapes that directory. Each component is opened with O_NOFOLLOW so symlinks are detected explicitly rather than transparently followed; symlinks are then resolved manually and only honoured when their (recursively resolved) target also stays beneath the base fd. Absolute symlink targets, leading '/', and '..' past the base are rejected with errno=ELOOP. Symlink chains are bounded by PATH_UTIL_OPENAT_SAFE_MAX_SYMLINKS hops. Anchoring resolution at a caller-held base_fd makes the lookup TOCTOU-safe even when intermediate path components are mutated on disk concurrently: the kernel resolves all openat() lookups relative to the original directory inode that base_fd refers to, so an attacker mutating path components on the filesystem cannot redirect resolution. This is the portable counterpart to Linux's openat2() with RESOLVE_BENEATH and is intended for callers that need to safely look up files under a user-writable directory (e.g. a Sieve script storage directory). |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-04 | ||
| 0003-lib-Add-t_openat_safe_dir.patch | [PATCH 3/5] lib: Add t_openat_safe_dir() | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-03 | ||
| 0004-acl-dovecot-acl-list-is-never-supposed-to-be-a-symli.patch | [PATCH 4/5] acl: dovecot-acl-list is never supposed to be a symlink - use O_NOFOLLOW flag | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-03 | ||
| 0005-lib-Add-comments-about-memory-allocations-and-string.patch | [PATCH 5/5] lib: Add comments about memory allocations and string functions preserving errno | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-03 | ||
| 0001-lib-sieve-storage-file-Refuse-symlinks-escaping-pers.patch | [PATCH 1/2] lib-sieve: storage: file - Refuse symlinks escaping personal storage directory Pigeonhole's file storage followed any symlink encountered while resolving a script path, including symlinks in personal (user-writable) storage whose target lay outside the storage directory. In some non-recommended configurations a user could exploit this through the include extension: an "include :personal name;" lookup of ~/sieve/name.sieve transparently followed a user-placed to e.g. another user's file readable by the mail process, leaking its contents (or causing it to be parsed as Sieve). Normally this shouldn't be possible, because sieve processes shouldn't have any more privileges to read files than the local system user creating the symlink. Open the canonical (realpath'd) personal storage directory at storage init time and keep an O_DIRECTORY|O_CLOEXEC fd to it. Resolve script content reads through this fd by routing sieve_file_script_get_stream() via a new sieve_file_storage_open_safe() wrapper around t_openat_safe(), which: - opens each path component with O_NOFOLLOW so symlinks are detected explicitly rather than transparently followed; - follows symlinks only when their (recursively resolved) target stays beneath dir_fd, refusing absolute targets and `..` past the storage root with ELOOP; - caps the symlink-hop count to bound resolution time. Anchoring at dir_fd makes the lookup TOCTOU-safe even when intermediate path components are mutated on disk concurrently: resolution stays relative to the original directory inode and the safe walker still rejects any target that leaves it. Apply the protection only when storage->is_personal is set; admin-managed global storage is trusted and may legitimately use cross-boundary symlinks. Single-file storages (is_file=TRUE) keep dir_fd at -1 and fall back to the existing open path. Also guard the dir_fd open with S_ISDIR() to handle the autodetect quirk where storage_path can refer to a regular file even when is_file is FALSE. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-04 | ||
| 0002-lib-sieve-storage-file-Validate-script-stat-path-thr.patch | [PATCH 2/2] lib-sieve: storage: file - Validate script stat path through dir_fd Extend the symlink-escape protection added in the previous commit to the stat performed by sieve_file_script_open(): an "include :personal" lookup or any other indirect path that triggers sieve_file_script_stat() also needs to refuse a symlink whose target leaves the personal storage directory, otherwise the existence check succeeds and the file is opened later via the safe path with an unhelpful "permission denied". Add sieve_file_script_stat_safe(), which uses fstatat(AT_SYMLINK_NOFOLLOW) to obtain the entry's own stat (lnk_st) and then, only if the entry is a symlink, opens it through sieve_file_storage_open_safe() to validate the target stays inside dir_fd and to fetch the resolved target's stat (st) via fstat(). Non-symlink entries skip the open entirely. Use the new helper in sieve_file_script_open() whenever fstorage->dir_fd is available, falling back to the unsafe lstat+stat variant for non-personal or single-file storages. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-04 | ||
| 0004-lib-compression-test-Add-zero-len-frame-test-for-all.patch | [PATCH 4/4] lib-compression: test - Add zero-len frame test for all handlers Verify that successive empty compressed frames produce a clean EOF across all compression algorithms. lz4 is limited to one frame as it uses a custom single-stream format without concatenation support. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-06-12 | ||
| 0003-lib-compression-istream-zstd-Guard-against-no-progre.patch | [PATCH 3/4] lib-compression: istream-zstd - Guard against no-progress loop in read If ZSTD_decompressStream() returns with neither input consumed nor output produced, the read loop would spin indefinitely. Add a check after each call: if input.pos is unchanged and output.pos is zero, treat it as a corrupt stream (EIO). |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-06-12 | ||
| 0001-lib-compression-istream-lz4-Ensure-uncompressed-chun.patch | lib-compression: istream-lz4 - Ensure uncompressed chunk size is not 0 | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-02-23 | ||
| 0001-lib-compression-istream-lz4-Try-again-if-no-data-was.patch | lib-compression: istream-lz4 - Try again if no data was decompressed | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-02-23 | ||
| 0001-lib-compression-Don-t-calculate-crc32-if-using-zlib-.patch | lib-compression: Don't calculate crc32 if using zlib in deflate mode | Michael M Slusarz <michael.slusarz@open-xchange.com> | no | 2025-10-04 | ||
| 0001-lib-compression-istream-zlib-Use-container_of-macro.patch | lib-compression: istream-zlib - Use container_of() macro | Stephan Bosch <stephan.bosch@open-xchange.com> | no | 2023-11-14 | ||
| 0001-global-Fix-spelling.patch | =================================================================== | no | ||||
| 0001-lib-compression-wrap-_read-in-for-loop-reindent-only.patch | [PATCH 1/4] lib-compression: wrap *_read() in for(;;) loop (reindent only) Prepare for the next commit: wrap the body of i_stream_lz4_read(), i_stream_bzlib_read(), and i_stream_zlib_read() in a for(;;) loop. No logic change; all paths still return on the first iteration. Separating the indent churn makes the actual fix easier to review. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-06-10 | ||
| 0002-lib-compression-Iterate-instead-of-recursing-on-zero.patch | [PATCH 2/4] lib-compression: Iterate instead of recursing on zero-output decompress chunks istream-lz4, istream-zlib and istream-bzlib each retried a read that produced no output by tail-calling their own read function. A crafted compressed stream can contain an unbounded number of chunks/steps that each decompress to zero bytes - e.g. an lz4 stream of single-byte chunks that each decode to nothing - so an attacker controlling the compressed data can drive recursion depth proportional to the chunk count. Tail-call optimization is not guaranteed, so this can exhaust the stack and crash the process reading the stream. Replace the recursive calls with continue inside the for(;;) loop introduced in the previous commit, keeping stack usage O(1). Add a regression test that feeds istream-lz4 a stream of 100000 empty chunks and reads it in a single call. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-06-10 | ||
| 0001-lib-sql-sql-api-Implement-async-calls-for-drivers-th.patch | lib-sql: sql-api - Implement async calls for drivers that can't Changes the behaviour of asynchronous functions to be truly asynchronous even if the underlying driver isn't capable of doing this. Implemented by adding immediate timeouts to call the callbacks after returning from the synchronous function and ending up back to ioloop. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2025-10-06 | ||
| 0001-lib-sql-Add-sql_result_new_error-helper.patch | lib-sql: Add sql_result_new_error() helper | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-05-29 | ||
| 0002-lib-sql-Extract-sql_query_callback_delayed-helper.patch | [PATCH 2/6] lib-sql: Extract sql_query_callback_delayed() helper | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-05-29 | ||
| 0003-lib-sql-Add-sql_commit_schedule_delayed-helper.patch | [PATCH 3/6] lib-sql: Add sql_commit_schedule_delayed() helper | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-06-02 | ||
| 0004-lib-var-expand-Change-escape-func-signature-to-retur.patch | [PATCH 4/6] lib-var-expand: Change escape func signature to return int with error_r Wire error propagation in var_expand_program_execute_one_real() so a failing escape function causes the expansion to return -1. Update all implementations (passdb-sql, userdb-sql, db-ldap, dict-ldap, auth-request-var-expand) and replace the unsafe auth_request_escape_func_t cast in auth-request-var-expand.c with a proper bridge wrapper. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-05-21 | ||
| 0001-lib-sql-driver-sqlite-Use-sqlite3_snprintf-to-quote-.patch | lib-sql: driver-sqlite - Use sqlite3_snprintf() to quote values This does it the sqlite3 way. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2025-11-07 | ||
| 0001-lib-sql-Use-strchr-based-while-loop-to-fill-template.patch | lib-sql: Use strchr() based while loop to fill template This is much faster than going one byte at a time. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2025-08-18 | ||
| 0005-lib-sql-Make-escape_string-return-int-with-error_r-f.patch | [PATCH 5/6] lib-sql: Make escape_string return int with error_r, fail instead of unsafe fallback Change escape_string driver vfunc and sql_escape_string() to return int with separate error_r output parameter. On failure (e.g. not connected), return -1 instead of falling back to unsafe escaping. Move escaping from sql_statement_bind_str() to sql_statement_get_query() so errors can be propagated to callers. Add failed_error field to sql_transaction_context for deferred error reporting at commit time. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-05-29 | ||
| 0006-auth-passdb_sql-connect-before-expanding-query-varia.patch | [PATCH 6/6] auth: passdb_sql: connect before expanding query variables sql_lookup_pass() calls settings_get_params() with an SQL escape func that requires a live connection. If the DB is disconnected, the error propagated as "Failed to parse configuration" instead of a DB connectivity error. Call sql_connect() first; fail with "Not connected to database" directly if it returns -1. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-05-29 | ||
| 0007-lib-sql-Run-sql-statement-queries-in-their-own-data-.patch | lib-sql: Run sql statement queries in their own data stack frame | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-06-11 | ||
| 0001-auth-db-oauth2-Reduce-nesting-in-token_in_scope-via-.patch | [PATCH 1/4] auth: db-oauth2: Reduce nesting in token_in_scope via early return | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-06-03 | ||
| 0002-auth-db-oauth2-Fix-scope-check-to-require-all-config.patch | [PATCH 2/4] auth: db-oauth2: Fix scope check to require all configured scopes Switch token-in-scope check to AND semantics: all configured scopes must be present in the token. Behaviour now matches the JWT path. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-06-03 | ||
| 0003-auth-db-oauth2-Add-oauth2_audience-setting-deprecate.patch | [PATCH 3/4] auth: db-oauth2: Add oauth2_audience setting, deprecate aud-as-scope fallback Add a dedicated oauth2_audience setting checked against the token's aud claim (RFC 7519 section 4.1.3) using the same tab-split AND-semantics as oauth2_scope. Emit a deprecation warning when the existing aud fallback in db_oauth2_token_in_scope() is triggered so operators know to migrate. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-05-29 | ||
| 0001-lib-mail-ostream-dot-Optimize-stream-writing.patch | lib-mail: ostream-dot - Optimize stream writing Use i_memcspn() to figure out how much we can skip. |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-01-26 | ||
| 0001-lib-mail-o_stream_dot_sendv-Use-I_MIN.patch | [PATCH 1/4] lib-mail: o_stream_dot_sendv() - Use I_MIN() | Marco Bettini <marco.bettini@open-xchange.com> | no | 2026-04-10 | ||
| 0002-lib-mail-o_stream_dot_sendv-Fix-boundary-off-by-one.patch | [PATCH 2/4] lib-mail: o_stream_dot_sendv() - Fix boundary off by one | Marco Bettini <marco.bettini@open-xchange.com> | no | 2026-04-20 | ||
| 0003-lib-mail-o_stream_dot_sendv-Use-enumeration-to-defin.patch | [PATCH 3/4] lib-mail: o_stream_dot_sendv() - Use enumeration to define the items to inject | Marco Bettini <marco.bettini@open-xchange.com> | no | 2026-04-10 | ||
| 0001-lib-test-Add-test_assert_memcmp.patch | lib-test: Add test_assert_memcmp*() | Stephan Bosch <stephan.bosch@open-xchange.com> | no | 2025-07-25 | ||
| 0001-lib-test-Require-both-lengths-in-test_assert_memcmp.patch | lib-test: Require both lengths in test_assert_memcmp() | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-01-27 | ||
| 0004-lib-mail-o_stream_dot_sendv-Do-not-send-unguarded-.-.patch | [PATCH 4/4] lib-mail: o_stream_dot_sendv() - Do not send unguarded '.' after bare '\r' | Marco Bettini <marco.bettini@open-xchange.com> | no | 2026-04-08 | ||
| 0001-lib-imap-imap-match-Fix-excessive-CPU-usage-caused-b.patch | lib-imap: imap-match - Fix excessive CPU usage caused by backtracking Backport the NFA/non-backtracking algorithm from 2684624… while retaining the byte-oriented matcher semantics of 2.4.1. Original commit message: Replace the recursive backtracking matcher with a Thompson-style NFA simulation over grapheme clusters. Each grapheme cluster of the compressed pattern becomes one state: LITERAL, PERCENT (consume any number of non-separator clusters) or STAR (consume any number of clusters including separators). A virtual ACCEPT position sits at index n_states. Simulation tracks the set of active positions in a bitmap. Epsilon-closure (skipping a PERCENT or STAR without consuming) is a single forward pass because the NFA is The resulting match is O(n_data * n_pattern) regardless of pattern shape, with no recursion and no backtracking, so there is no way for a malicious pattern or mailbox name to trigger exponential CPU, excessive stack depth, or unbounded memory. IMAP_MATCH_YES / NO / CHILDREN / PARENT semantics are preserved: - YES: ACCEPT reachable after consuming all data. - PARENT: ACCEPT was active at some point while the next data grapheme cluster was the separator. - CHILDREN: some active non-ACCEPT state remains after consuming all data, and either the data ends with a separator or an active state can still consume a separator (precomputed as sep_accept[]). Inboxcase handling (case-insensitive comparison for the INBOX prefix of data) and grapheme-cluster comparison are unchanged - the existing match_gc logic is reused inline as literal_matches(). pattern_compress() and pattern_is_inboxcase() are unchanged. |
Noah Meyerhans <noahm@debian.org> | no | 2026-09-10 | ||
| 0001-lib-mail-Reset-charset-translation-buffer-between-MI.patch | [PATCH 01/14] lib-mail: Reset charset translation buffer between MIME parts If MIME part ended with an incomplete charset translation, the buffer was kept for the next MIME part. This could have produced garbage in the next MIME part, or a crash. Fixes: |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-02-28 | ||
| 0002-imap-Stream-BODYSTRUCTURE-to-client-without-ostream-.patch | [PATCH 02/14] imap: Stream BODYSTRUCTURE to client without ostream memory duplication For huge BODYSTRUCTURE responses (messages with many MIME parts), o_stream_send_str() caused the ostream to copy the entire string into its ring buffer when the stream was corked, doubling memory usage. Use the same o_stream_set_max_buffer_size(0) + o_stream_send_istream() pattern as fetch_stream_continue() so the ostream buffer stays at 0 bytes and the I/O loop handles flow control via WAIT_OUTPUT. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-17 | ||
| 0003-imap-Stream-ENVELOPE-to-client-without-ostream-memor.patch | [PATCH 03/14] imap: Stream ENVELOPE to client without ostream memory duplication Same fix as for BODYSTRUCTURE: avoid copying the envelope string into the ostream ring buffer by using o_stream_set_max_buffer_size(0) + o_stream_send_istream() with a continuation handler. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-17 | ||
| 0004-lib-mail-message-parser-from-parts-Enforce-50-MB-all.patch | [PATCH 04/14] lib-mail: message-parser-from-parts: Enforce 50 MB all-headers-max-size limit The preparsed (from-parts) header parser was not tracking all_headers_total_size and never called message_parse_header_lower_limit(), so the cumulative 50 MB header size limit was never applied when re-parsing a message using cached part structure. Fix by mirroring the same tracking that message-parser.c does in its parse_next_header_block(): update all_headers_total_size for each parsed header line, and call message_parse_header_lower_limit() with the remaining budget when initialising the per-part header parser. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-16 | ||
| 0005-lib-mail-Add-count-field-to-struct-message_address_l.patch | [PATCH 05/14] lib-mail: Add count field to struct message_address_list Add a count field and increment it in add_address() so callers can read the number of parsed addresses directly from the list struct without walking the linked list. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-17 | ||
| 0006-lib-storage-mbox-Explicitly-disable-the-header-block.patch | [PATCH 06/14] lib-storage/mbox: Explicitly disable the header block size limit mbox_sync_parse_next_mail() appends each header's raw bytes into ctx->header and writes them back when rewriting the mbox file. The default MESSAGE_HEADER_BLOCK_DEFAULT_MAX_SIZE limit (10 MB) must not apply here: any truncation would corrupt the mbox on rewrite. Similarly, mbox_sync_parse_match_mail() feeds full raw header bytes into the MD5 verifier. Today the per-chunk hdr->value delivered by message_parse_header_next() is not clamped cumulatively, so the limit only bites on full_value and unknown headers pass through intact. That is about to change - a subsequent commit will clamp hdr->value cumulatively. Explicitly setting SIZE_MAX here locks in the intent and prevents a regression. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-19 | ||
| 0007-lib-mail-istream-header-filter-Use-container_of-for-.patch | [PATCH 07/14] lib-mail: istream-header-filter - Use container_of() for struct casts Replace the C-style downcasts from struct istream_private/iostream_private to struct header_filter_istream with container_of(), matching the convention used by other istream implementations in tree. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-20 | ||
| 0008-lib-mail-Make-istream-header-filter-s-per-header-siz.patch | [PATCH 08/14] lib-mail: Make istream-header-filter's per-header size limit configurable Until now the internal message_header_parser_ctx used the default MESSAGE_HEADER_BLOCK_DEFAULT_MAX_SIZE (10 MB) cap. In practice that cap only bounded hdr->full_value; per-chunk hdr->value was delivered in full regardless. A subsequent change to message_parse_header_next() will clamp hdr->value cumulatively as well, and at that point the 10 MB default would silently truncate data for callers like mbox-save that stream raw header bytes to storage. Default the filter to SIZE_MAX (unlimited) to preserve the effective behavior and add i_stream_header_filter_set_max_header_block_size() so callers that genuinely want a cap (index_mail_get_header_stream()) can opt in. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-19 | ||
| 0009-lib-storage-Cap-per-header-size-in-index_mail_get_he.patch | [PATCH 09/14] lib-storage: Cap per-header size in index_mail_get_header_stream() Apply MESSAGE_HEADER_BLOCK_DEFAULT_MAX_SIZE (10 MB) to the header-filter istream used for populating the header cache. A pathological single header (for example a To: with millions of addresses) otherwise grows mail->header_data and the cache write buffer in lockstep with the raw header size, which can push the imap process over vsz_limit on FETCH ENVELOPE / BODYSTRUCTURE. On its own this change does not yet bound hdr->value delivery; that requires the upcoming change to message_parse_header_next() to clamp per-chunk value_len cumulatively. Setting the limit here now lets that follow-up take effect without further touching this file. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-19 | ||
| 0010-lib-mail-Clamp-hdr-value-cumulatively-against-header.patch | [PATCH 10/14] lib-mail: Clamp hdr->value cumulatively against header_block_max_size Until now header_block_max_size only bounded hdr->full_value via value_buf. Continued chunks returned to the caller via hdr->value were left at the raw chunk size, so a caller that consumed hdr->value per chunk without ever requesting use_full_value (e.g. the header-cache path in index_mail_parse_header()) could accumulate the full raw header size. A pathological To: with millions of addresses could grow mail->header_data and the cache write buffer to tens of megabytes each, driving the imap process over vsz_limit on FETCH ENVELOPE. Reinterpret header_block_total_size as the running sum of line_value_size across all chunks of all headers, and clamp each new chunk against the remaining header_block_max_size budget. Propagate the clamped size to line->value_len in the two continued-line branches that previously left it untouched. value_buf is bounded implicitly since every append uses line_value_size. The up-front per-chunk clamp (line->value_len = MIN(value_len, max_size)) is now subsumed by the cumulative clamp and has been removed. Update the truncation tests that were documenting the old "value_len stays at raw chunk size" behavior. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-20 | ||
| 0011-lib-mail-Introduce-struct-message_part_data_limits-a.patch | [PATCH 11/14] lib-mail: Introduce struct message_part_data_limits and thread it through parsers Add an empty struct message_part_data_limits and pass it by pointer through message_part_data_parse_from_header() and message_part_envelope_parse_from_header(). No behaviour change: the struct has no fields yet and no limits are applied. Subsequent commits add the individual limit fields and enforcement. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-17 | ||
| 0012-lib-mail-Limit-total-address-count-per-message-to-10.patch | [PATCH 12/14] lib-mail: Limit total address count per message to 100 000 A message with millions of addresses across all its envelope headers can exhaust memory when parsed (each struct message_address is ~100 bytes regardless of whether the raw address is only a few bytes long). Add remaining_addresses to struct message_part_data_limits, initialised to MESSAGE_PART_DATA_MAX_TOTAL_ADDRESSES (100 000). Pass the remaining budget as max_addresses to message_address_parse_full() so parsing stops at the limit, then deduct the actual count parsed from the budget. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-17 | ||
| 0013-lib-mail-Limit-total-Content-Language-tag-count-per-.patch | [PATCH 13/14] lib-mail: Limit total Content-Language tag count per message to 100 000 A multipart message with many MIME parts each containing many language tags can exhaust memory: the per-part RFC 2231 parser had no cumulative limit. Add remaining_language_tags to struct message_part_data_limits, initialised to MESSAGE_PART_DATA_MAX_TOTAL_LANGUAGE_TAGS (100 000). Break out of the tag-parsing loop in parse_content_language() once the budget reaches zero. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-17 | ||
| 0014-lib-mail-Limit-total-MIME-parameter-count-per-messag.patch | [PATCH 14/14] lib-mail: Limit total MIME parameter count per message to 200 000 Content-Type and Content-Disposition parameters are both parsed through parse_mime_parameters(). A message with many MIME parts each having many parameters can accumulate millions of struct message_part_param entries. Add remaining_mime_params to struct message_part_data_limits (combined budget for both Content-Type and Content-Disposition), initialised to MESSAGE_PART_DATA_MAX_TOTAL_MIME_PARAMS (200 000). Cap params_count to the remaining budget before allocating and deduct accordingly. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-17 | ||
| 0001-lib-storage-thread-Avoid-excessive-data-stack-growth.patch | [PATCH 1/3] lib-storage: thread - Avoid excessive data stack growth with many References msgids | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-13 | ||
| 0002-lib-storage-thread-Limit-References-header-msgid-cou.patch | [PATCH 2/3] lib-storage: thread - Limit References: header msgid count to prevent O(N^2) CPU usage Cap per-message References ingestion at MAIL_THREAD_REFERENCES_MAX (1000) in mail_thread_map_add_mail(). Without this limit a single crafted email with N unique Message-IDs triggers N(N-1)/2 ancestor traversals in thread_node_has_ancestor(), allowing unauthenticated DoS via mail delivery. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-16 | ||
| 0003-lib-storage-thread-Limit-ancestor-chain-traversal-de.patch | [PATCH 3/3] lib-storage: thread - Limit ancestor chain traversal depth to prevent O(N^2) CPU usage The per-message References limit (MAIL_THREAD_REFERENCES_MAX) prevents a single crafted message from causing O(N^2) traversals in thread_node_has_ancestor(). However, multiple crafted messages each containing 1000 References entries can build an arbitrarily deep ancestor chain across the mailbox, causing the same quadratic blowup spread over many messages: processing email k costs O(k * MAIL_THREAD_REFERENCES_MAX) steps, giving O(M^2 * MAIL_THREAD_REFERENCES_MAX) total for M emails. Fix this by limiting the traversal depth in thread_node_has_ancestor() to MAIL_THREAD_REFERENCES_MAX steps. When the limit is reached the link is dropped, bounding per-email work to O(MAIL_THREAD_REFERENCES_MAX^2) regardless of how deep the chain was built by prior messages. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-17 | ||
| 0001-lib-sieve-sieve-binary-code-Fix-single-byte-oob-stac.patch | lib-sieve: sieve-binary-code - Fix single byte oob stack buffer write in sieve_binary_emit_integer() | Stephan Bosch <stephan.bosch@open-xchange.com> | no | 2026-04-10 | ||
| 0001-lib-managesieve-managesieve-parser-Fix-handling-of-l.patch | [PATCH 1/2] lib-managesieve: managesieve-parser - Fix handling of lone CR character | Stephan Bosch <stephan.bosch@open-xchange.com> | no | 2026-04-11 | ||
| 0002-managesieve-login-client_skip_line-Discard-data-when.patch | [PATCH 2/2] managesieve-login: client_skip_line() - Discard data when newline is not found Without this, data without a newline (e.g., from a lone CR protocol violation detected by the parser) stays in the buffer indefinitely. This prevents the server from ever detecting client disconnect, causing a deadlock where both sides wait for the other. The post-login server-side client_skip_line() in managesieve-client.c already handles this correctly by always calling i_stream_skip(). |
Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-05-25 | ||
| 0001-imap-hibernate-Fix-out-of-bounds-read-when-parsing-D.patch | [PATCH 1/2] imap-hibernate: Fix out-of-bounds read when parsing DONE command tag The tag-skipping loop was missing a size>0 guard, so a malformed DONE command with no space/CR/tab terminator after the tag would read one byte past the end of the buffer. Also add a \0 check to stop on embedded null bytes, which are not valid tag characters. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-16 | ||
| 0002-imap-hibernate-Use-imap-parser-API-for-parsing-DONE-.patch | [PATCH 2/2] imap-hibernate: Use imap-parser API for parsing DONE command Replace the ad-hoc DONE/IDLE tokenizer with imap-parser.h: use imap_parser_read_tag() to read the tag and imap_parser_read_word() to read the DONE and IDLE keywords. This delegates bounds checks and character validation to the shared parser. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-22 | ||
| 0001-lib-Add-XXH64-hash-implementation.patch | [PATCH 01/12] lib: Add XXH64 hash implementation Adds a streaming XXH64 (non-cryptographic) hash with init/loop/result API, a one-shot xxh64_data(), and an xxh64_to_32() XOR-fold inline. Registered in hash_methods[] for use via the generic hash_method API. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-13 | ||
| 0001-lib-xxh64-fix-byte-ordering-bug-on-big-endian-system.patch | lib: xxh64: fix byte ordering bug on big-endian systems Convert from little-endian to host byte order where necessary. Background at https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1146449 |
Noah Meyerhans <noahm@debian.org> | no | 2026-09-01 | ||
| 0002-lib-Replace-str_hash-strcase_hash-with-xxh64.patch | [PATCH 02/12] lib: Replace str_hash/strcase_hash with xxh64 Replaces the old ASU-derived shift-and-XOR hash with xxh64_to_32(), which provides better distribution and avalanche properties. strcase_hash feeds each i_toupper()'d byte through the streaming API. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-13 | ||
| 0003-lib-Add-str_stable_hash.patch | [PATCH 03/12] lib: Add str_stable_hash() For now this is the same as str_hash(), but this is changed in a following commit. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-13 | ||
| 0004-lib-Key-str_hash-strcase_hash-with-a-random-seed-to-.patch | [PATCH 04/12] lib: Key str_hash/strcase_hash with a random seed to prevent HashDoS hash_init() fills a process-wide uint64_t hash_iv via random_fill() at lib_init() time (after random_init()). str_hash() and strcase_hash() pass hash_iv as the xxh64 seed so an attacker cannot predict bucket placement and manufacture collision chains. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-13 | ||
| 0005-lib-index-mail-index-strmap-Fix-OOB-read-from-trunca.patch | [PATCH 05/12] lib-index: mail-index-strmap - Fix OOB read from truncated record size | Aki Tuomi <aki.tuomi@open-xchange.com> | no | 2026-08-17 | ||
| 0006-lib-index-Rename-crc32-variables-parameters-to-hash-.patch | [PATCH 06/12] lib-index: Rename crc32 variables/parameters to hash in strmap Pure rename - no functional change. The stored 32-bit value is still produced by crc32_str_nonzero(); only the identifiers change to prepare for swapping the hash algorithm in the next commit. recs_crc32 -> recs_hash, hash_key.crc32 -> hash_key.hash, crc32_r -> hash_r, local crc32 -> hash, *crc32 -> *hashes. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-13 | ||
| 0007-lib-index-Add-keyed-xxh64-strmap-format-v2-gated-by-.patch | [PATCH 07/12] lib-index: Add keyed xxh64 strmap format v2, gated by config version The on-disk hash stored in the strmap file is now optionally a keyed xxh64_to_32() with a per-file random 64-bit IV stored in the file header. This replaces the previous plain crc32_str_nonzero() output and hardens the strmap against deliberately-collided message-id hashes. The v1 (crc32) format remains fully readable and writable so older configurations keep working without forced rebuilds. On-disk: - v1 header is 8 bytes: version, 3 unused, uid_validity (unchanged). - v2 header is 16 bytes: version, compat_flags, 2 unused, uid_validity, hash_iv. The first 8 bytes of v2 align with v1 byte-for-byte, so the open path reads 8 bytes, dispatches on version, and reads the trailing 8 bytes only for v2. Runtime: - strmap->enable_xxh64 selects the format used when creating a new file (or recreating one whose uid_validity has changed). - view->format_version follows the on-disk file when one exists; for fresh files it follows the strmap-wide preference. - Renumber recreate_write() preserves view->format_version, so we never silently migrate an existing file across the threshold while it is still in use - the migration only happens at open time. - When enable_xxh64 is TRUE and the on-disk file is v1, open treats it as a version mismatch: the file is unlinked and the next sync's recreate_write() produces a v2 file. Below the threshold v1 stays v1 indefinitely. - strmap_hash_str() dispatches per-view, so v1 files keep using crc32 hashes and v2 files use keyed xxh64 even in mixed setups. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-30 | ||
| 0008-doveadm-Fix-ubsan-unsigned-integer-overflow-error.patch | [PATCH 08/12] doveadm: Fix ubsan unsigned integer overflow error | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-16 | ||
| 0009-config-Assume-dovecot_config_version-0.0.0-is-the-sa.patch | [PATCH 09/12] config: Assume dovecot_config_version=0.0.0 is the same as the latest version It's used for git builds. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-09-29 | ||
| 0010-lib-master-Move-config_version_find-from-src-config-.patch | [PATCH 10/12] lib-master: Move config_version_find() from src/config/config-parser.c Rename to dovecot_config_version_find() and expose it via master-service-settings.h so non-config callers (e.g. the upcoming dovecot_storage_version validation in master_service_settings_check()) can share the same supported-versions list. No behaviour change. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-01 | ||
| 0011-lib-lib-master-Move-version_-to-lib-version.-ch.patch | [PATCH 11/12] lib, lib-master: Move version_*() to lib/version.[ch] | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-10-05 | ||
| 0012-config-doveconf-dF-Add-dovecot_storage_version.patch | [PATCH 12/12] config: doveconf -dF - Add dovecot_storage_version | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-04-09 | ||
| 0001-lib-sieve-util-edit-mail-Fix-writing-to-freed-memory.patch | [PATCH 1/3] lib-sieve: util: edit-mail - Fix writing to freed memory | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-14 | ||
| 0002-lib-sieve-util-test-edit-mail-Adjust-to-changes-in-d.patch | [PATCH 2/3] lib-sieve: util: test-edit-mail - Adjust to changes in dovecot core lib-test | Stephan Bosch <stephan.bosch@open-xchange.com> | no | 2025-10-29 | ||
| 0003-lib-sieve-edit_mail_headers_parse-Fix-info-leak-via-.patch | [PATCH 3/3] lib-sieve: edit_mail_headers_parse() - Fix info leak via NUL-truncated header copy i_strndup() stops at the first NUL byte, so embedded NULs caused field->data to be shorter than field->size. This left stale heap data readable past the copied content when callers treat data+body_offset as a string. Adds a test-edit-mail unit test and a sieve testsuite case that both exercise edit_mail_headers_parse() with a NUL byte embedded in a header value. The unit test memcmp-verifies that the bytes after the NUL are preserved; the sieve test triggers an invalid heap read detectable by valgrind under the old code. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-01 | ||
| 0001-login-common-client-common-Add-client_disconnect-vfu.patch | [PATCH 1/5] login-common: client-common - Add client_disconnect() vfunc | Stephan Bosch <stephan.bosch@open-xchange.com> | no | 2025-11-28 | ||
| 0002-submission-login-client-Fix-panic-occurring-at-mail_.patch | [PATCH 2/5] submission-login: client - Fix panic occurring at mail_max_userip_connections limit transgression Panic was: Fixed by making sure the underlying smtp-server connection is always closed before the connection FD is closed. |
Stephan Bosch <stephan.bosch@open-xchange.com> | no | 2025-11-28 | ||
| 0003-lib-smtp-smtp-server-Expose-smtp_server_connection_r.patch | [PATCH 3/5] lib-smtp: smtp-server - Expose smtp_server_connection_reply_immediate The function already existed internally as a way to write a reply directly to the output stream, bypassing the per-command reply queue. Make it part of the public API so callers that need a reply on the wire before tearing the connection down (where queued replies would otherwise be aborted) can use it. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-07 | ||
| 0004-submission-login-client-authenticate-Reply-421-4.7.0.patch | [PATCH 4/5] submission-login: client-authenticate - Reply 421 4.7.0 on mail_max_userip_connections Until now the connection limit was reported via the same 454 4.7.0 reply that is used for generic temporary authentication failures. That makes proxies (including Dovecot's own submission proxy) treat the rejection as a transient auth error and retry, which is futile when the limit is hit and only obscures the actual cause in the proxy log. Reply with 421 4.7.0 instead. RFC 5321 Section 4.2.1 specifies 421 as "service shutting down, closing transmission channel", which is the right signal for "do not retry on this connection". The 421 + 4.7.0 combination is unique among the 421 replies emitted by submission and is used by the submission proxy to recognize this specifically as a connection-limit reply rather than a generic 421 internal/shutdown. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-07 | ||
| 0001-commin-Rename-LOGIN_PROXY_FAILURE_TYPE_AUTH-to-LOGIN.patch | *-commin: Rename LOGIN_PROXY_FAILURE_TYPE_AUTH to LOGIN_PROXY_FAILURE_TYPE_AUTH_REPLIED | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-07-18 | ||
| 0001-managesieve-login-Adjust-to-core-s-login_proxy_failu.patch | =================================================================== | no | ||||
| 0001-login-common-login-Add-proxy_dest_connection_limit-e.patch | login-common, *-login: Add proxy_dest_connection_limit error_code to proxy_session_finished If IMAP backend returns with [LIMIT] or POP3 backend returns with [IN-USE], use this error code rather than the generic proxy_dest_auth_failed. Error messages are also updated. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-12-03 | ||
| 0005-submission-login-submission-proxy-Recognize-421-4.7..patch | [PATCH 5/5] submission-login: submission-proxy - Recognize 421 4.7.0 as connection-limit reply When the backend signals that the user's connection limit has been reached, do not classify the response as a generic temporary authentication failure (which causes the proxy to reconnect). Map it instead to LOGIN_PROXY_FAILURE_TYPE_AUTH_LIMIT_REACHED_REPLIED, which suppresses retries and reports the failure as proxy_dest_connection_limit in the login_aborted event/log line. This mirrors what imap-login does for the [LIMIT] response code and pop3-login for [IN-USE]. Other 421 replies (typically server shutdown / fatal error) are mapped to LOGIN_PROXY_FAILURE_TYPE_AUTH_REPLIED rather than AUTH_TEMPFAIL: 421 means "closing transmission channel" (RFC 5321 Section 4.2.1), so a reconnect on the same destination is unlikely to help and should not happen automatically. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-07 | ||
| 0001-managesieve-login-Support-LOGIN_PROXY_FAILURE_TYPE_A.patch | =================================================================== | no | ||||
| 0001-login-Add-LOGIN_PROXY_FAILURE_TYPE_AUTH_NOT_REPLIED.patch | *-login: Add LOGIN_PROXY_FAILURE_TYPE_AUTH_NOT_REPLIED | Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-07-18 | ||
| 0001-dsync-Avoid-potentially-excessive-data-stack-growth-.patch | [PATCH 1/2] dsync: Avoid potentially excessive data stack growth for mailbox attribute sending The attribute value can be large. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-03-24 | ||
| 0002-dsync-Fix-escaping-mail-or-attribute-value-that-begi.patch | [PATCH 2/2] dsync: Fix escaping mail or attribute value that begins with a "." line Such a mail or attribute would have escaped the value parameter and the rest of the value would have been processed as dsync stream commands. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-03-24 | ||
| 0001-imap-Extract-side-channel-ostream-creation-into-help.patch | [PATCH 1/5] imap: Extract side-channel ostream creation into helper Add client_create_side_channel_output() and use it in cmd_compress() in place of the inline channel-creation code. The helper will also be used by the imap state import path to recreate the side channel after unhibernation. No functional change. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-01 | ||
| 0002-imap-Recreate-multiplex-ostream-side-channel-after-u.patch | [PATCH 2/5] imap: Recreate multiplex ostream side channel after unhibernation This will be needed by the following changes to send dict_reset commands via the side channel. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-01 | ||
| 0003-lib-compression-Add-o_stream_deflate_reset_dict.patch | [PATCH 3/5] lib-compression: Add o_stream_deflate_reset_dict() New public function that locates the deflate ostream in the parent chain (transparently handles rawlog wrappers) and schedules a Z_FULL_FLUSH on the next uncork/flush. Z_FULL_FLUSH emits all buffered data and then resets the deflate dictionary, so subsequent compressed output cannot reference data from before the call. Adds a pending_dict_reset flag to struct zlib_ostream. The flag persists through partial flush retries and is cleared only once the full flush loop completes. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-16 | ||
| 0004-imap-login-Add-dict_reset-side-channel-command-to-im.patch | [PATCH 4/5] imap-login: Add dict_reset side-channel command to imap-proxy When imap_compress_on_proxy is enabled, DEFLATE compression runs inside the imap-login process. The imap backend process cannot call o_stream_deflate_reset_dict() directly on a remote stream, so this adds a new side-channel command "dict_reset" that the backend can send to trigger the dictionary reset on the proxy side. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-16 | ||
| 0005-imap-Add-imap_compress_on_proxy-hidden-setting.patch | [PATCH 5/6] imap: Add imap_compress_on_proxy hidden setting Keep it disabled by default for now. Once we're sure COMPRESS on proxy works properly we'll enable it again. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2025-06-04 | ||
| 0006-imap-Reset-DEFLATE-dictionary-after-every-tagged-rep.patch | [PATCH 6/6] imap: Reset DEFLATE dictionary after every tagged reply Prevents CRIME-style cross-command compression oracle attacks (CVE-class: compression side-channel). Without this fix an observer who can inject chosen plaintext into one IMAP command's response can measure the compressed size of a subsequent command's response and determine whether the secret content matches the injected plaintext. After each tagged response line is sent, the DEFLATE compression dictionary is reset via Z_FULL_FLUSH so that the compression history from one command cannot influence the compressed size of the next. For direct compression (imap_compress_on_proxy=no) the reset is applied to the local ostream. For proxy-mode compression (imap_compress_on_proxy=yes) a "dict_reset" command is sent over the multiplex side channel to the imap-login process. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-04-16 | ||
| 0001-submission-Fix-settings-leak-on-error-paths-in-clien.patch | [PATCH 1/2] submission: Fix settings leak on error paths in client_create_from_input() | Markus Valentin <markus.valentin@open-xchange.com> | no | 2026-04-23 | ||
| 0002-auth-Fix-prefixing-forward_fields-without-a-value-fr.patch | [PATCH 2/2] auth: Fix prefixing forward_fields without a value from client Bare tokens (without '=') were not prefixed, only key=value pairs were. In practice this affected forward_fields, where a bare token such as 'nopassword' would land in extra_fields unprefixed instead of as 'forward_nopassword', allowing injection of internal auth control fields. |
Markus Valentin <markus.valentin@open-xchange.com> | no | 2026-04-23 | ||
| 0001-login-common-Fix-crash-when-XCLIENT-FORWARD-base64-c.patch | [PATCH 1/2] login-common: Fix crash when XCLIENT FORWARD= base64 contains NUL byte Sending "XCLIENT FORWARD=AA==" (base64 for a single NUL byte) followed by a regular login crashed pop3-login (and other login services) with: Panic: file ../../src/lib/array.h: line 275 (array_idx_i): assertion failed: (idx < array->buffer->used / array->element_size) p_strsplit_tabescaped() truncates at the first NUL, so an all-NUL payload produced an empty fields list. forward_fields was still created (but empty), and the later array_front() call in sasl_server_auth_begin() then panicked on the empty array. Reject empty payloads and payloads containing NUL bytes during base64 decode, so the array is never created in this case. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-03 | ||
| 0002-login-common-Avoid-array_front-panic-on-empty-forwar.patch | [PATCH 2/2] login-common: Avoid array_front() panic on empty forward_fields array sasl_server_auth_request_info_fill() and proxy_redirect_reauth() NUL-terminate the forward_fields array via array_append_zero() + array_pop_back() and then call array_front() to hand the C array to the auth client. array_front() asserts when the array is empty, so a created-but-empty forward_fields array crashes login. The empty-array case is no longer reachable from client_forward_decode_base64() after the previous commit, but guard defensively here as well: any future caller that creates the array without populating it should not be able to panic the process. |
Timo Sirainen <timo.sirainen@open-xchange.com> | no | 2026-05-03 |
All known versions for source package 'dovecot'
- 1:2.4.5+dfsg1-3 (sid)
- 1:2.4.5+dfsg1-2 (forky)
- 1:2.4.1+dfsg1-6+deb13u7 (trixie-security)
- 1:2.4.1+dfsg1-6+deb13u6 (trixie)
- 1:2.3.21.1+dfsg1-1~bpo12+1 (bookworm-backports)
- 1:2.3.19.1+dfsg1-2.1+deb12u6 (bookworm-security, bookworm)
