]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dcrypt: Handle short reads in header correctly
authorAki Tuomi <aki.tuomi@dovecot.fi>
Wed, 3 Aug 2016 07:14:35 +0000 (10:14 +0300)
committerAki Tuomi <aki.tuomi@dovecot.fi>
Thu, 4 Aug 2016 11:51:59 +0000 (14:51 +0300)
src/lib-dcrypt/istream-decrypt.c

index 6df03b55571e017de0b90d3d02433b41f29138c9..67f34e0971e2b662e60bc4f86953d25fc9408b95 100644 (file)
@@ -646,7 +646,7 @@ i_stream_decrypt_read(struct istream_private *stream)
 
                /* if something is already decrypted, return as much of it as
                   we can */
-               if (dstream->buf->used > 0) {
+               if (dstream->initialized && dstream->buf->used > 0) {
                        size_t new_pos, bytes;
 
                        /* only return up to max_buffer_size bytes, even when buffer
@@ -708,15 +708,38 @@ i_stream_decrypt_read(struct istream_private *stream)
 
                if (!dstream->initialized) {
                        ssize_t hret;
+
+                       /* put the data in buffer */
+                       buffer_append(dstream->buf, data, size);
+
                        if ((hret=i_stream_decrypt_read_header
-                               (dstream, data, size)) <= 0) {
+                               (dstream, dstream->buf->data, dstream->buf->used)) <= 0) {
                                if (hret < 0 && stream->istream.stream_errno == 0) {
                                        /* assume temporary failure */
                                        stream->istream.stream_errno = EIO;
+                                       return -1;
                                }
-                               return hret;
+
+                               if (hret == 0 && stream->parent->eof) {
+                                       /* not encrypted by us */
+                                       stream->istream.stream_errno = EINVAL;
+                                       io_stream_set_error(&stream->iostream,
+                                               "Truncated header");
+                                       return -1;
+                               }
+                       }
+
+                       if (hret == 0) {
+                               /* see if we can get more data */
+                               i_stream_skip(stream->parent, size);
+                               continue;
+                       } else {
+                               /* clean up buffer */
+                               safe_memset(buffer_get_modifiable_data(dstream->buf, 0), 0, dstream->buf->used);
+                               buffer_set_used_size(dstream->buf, 0);
+                               i_stream_skip(stream->parent, hret);
                        }
-                       i_stream_skip(stream->parent, hret);
+
                        data = i_stream_get_data(stream->parent, &size);
                }
                decrypt_size = size;
@@ -826,7 +849,7 @@ struct decrypt_istream *i_stream_create_decrypt_common(struct istream *input)
        dstream->istream.istream.blocking = TRUE;
        dstream->istream.istream.seekable = FALSE;
 
-       dstream->buf = buffer_create_dynamic(default_pool, 128);
+       dstream->buf = buffer_create_dynamic(default_pool, 512);
 
        (void)i_stream_create(&dstream->istream, input,
                              i_stream_get_fd(input));