]> dgit.raspbian.org Git - dovecot.git/commitdiff
[PATCH 6/6] imap: Reset DEFLATE dictionary after every tagged reply
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 16 Apr 2026 15:38:53 +0000 (17:38 +0200)
committerNoah Meyerhans <noahm@debian.org>
Wed, 16 Sep 2026 19:06:35 +0000 (15:06 -0400)
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.

Gbp-Pq: Name 0006-imap-Reset-DEFLATE-dictionary-after-every-tagged-rep.patch

src/imap/imap-client.c

index 3de93917937ca35b26dc85183f9a25d9010b1b3f..8d4a5aab042c6da3b8929b19970eca4a1304a113 100644 (file)
@@ -12,6 +12,7 @@
 #include "istream-concat.h"
 #include "ostream.h"
 #include "ostream-multiplex.h"
+#include "ostream-zlib.h"
 #include "time-util.h"
 #include "settings.h"
 #include "master-service.h"
@@ -712,6 +713,22 @@ client_default_send_tagline(struct client_command_context *cmd, const char *data
        } T_END;
 
        client->last_output = ioloop_time;
+
+       /* Reset the DEFLATE compression dictionary after every tagged reply so
+          that cross-command compression correlation attacks (CRIME-style) are
+          not possible.  For proxy-mode compression the reset is forwarded to
+          the imap-login process via the side channel; for direct compression
+          it is applied to the local ostream immediately. */
+       if (client->compress_handler != NULL) {
+               if (client->multiplex_output != NULL &&
+                   client->set->imap_compress_on_proxy) {
+                       i_assert(client->side_channel_output != NULL);
+                       o_stream_nsend_str(client->side_channel_output,
+                                          "dict_reset\n");
+               } else {
+                       o_stream_deflate_reset_dict(client->output);
+               }
+       }
 }
 
 static int