From: Timo Sirainen Date: Wed, 17 Aug 2016 14:20:21 +0000 (+0300) Subject: lib-dcrypt: Fixed accessing out-of-bounds data in istream. X-Git-Tag: 2.3.0.rc1~3131 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a84b413ef72378bbe235a13846fe6a84899eaedc;p=thirdparty%2Fdovecot%2Fcore.git lib-dcrypt: Fixed accessing out-of-bounds data in istream. Also some small cleanups to make it clearer what's actually happening. --- diff --git a/src/lib-dcrypt/istream-decrypt.c b/src/lib-dcrypt/istream-decrypt.c index a514b24d7d..c5807c2436 100644 --- a/src/lib-dcrypt/istream-decrypt.c +++ b/src/lib-dcrypt/istream-decrypt.c @@ -54,13 +54,13 @@ ssize_t i_stream_decrypt_read_header_v1(struct decrypt_istream *stream, const unsigned char *data, size_t mlen) { const char *error = NULL; - size_t hdr_len = 0; + size_t keydata_len = 0; uint16_t len; int ec, i = 0; const unsigned char *digest_pos = NULL, *key_digest_pos = NULL, *key_ct_pos = NULL; - size_t pos = 9; + size_t pos = sizeof(IOSTREAM_CRYPT_MAGIC); size_t digest_len = 0; size_t key_ct_len = 0; size_t key_digest_size = 0; @@ -69,9 +69,10 @@ ssize_t i_stream_decrypt_read_header_v1(struct decrypt_istream *stream, buffer_t *secret = buffer_create_dynamic(pool_datastack_create(), 256); buffer_t *key = buffer_create_dynamic(pool_datastack_create(), 256); - hdr_len = ((data[0] << 8) | data[1]) + 12; - - if (mlen < hdr_len - pos) { + if (mlen < 2) + return 0; + keydata_len = (data[0] << 8) | data[1]; + if (mlen-2 < keydata_len) { /* try to read more */ return 0; } @@ -79,12 +80,14 @@ ssize_t i_stream_decrypt_read_header_v1(struct decrypt_istream *stream, data+=2; mlen-=2; - memcpy(&len, data, 2); - - while(i < 4 && mlen > 2 && (len = ntohs(len)) <= (mlen - 2) && len > 0) { + while (i < 4 && mlen > 2) { + memcpy(&len, data, 2); + len = ntohs(len); data += 2; mlen -= 2; pos += 2; + if (len == 0 || len > mlen) + break; switch(i++) { case 0: @@ -109,7 +112,6 @@ ssize_t i_stream_decrypt_read_header_v1(struct decrypt_istream *stream, pos += len; data += len; mlen -= len; - memcpy(&len, data, 2); } if (i < 4) { @@ -227,7 +229,7 @@ ssize_t i_stream_decrypt_read_header_v1(struct decrypt_istream *stream, stream->initialized = TRUE; /* now we are ready to decrypt stream */ - return hdr_len; + return sizeof(IOSTREAM_CRYPT_MAGIC) + 1 + 2 + keydata_len; } static bool get_msb32(const unsigned char **_data, const unsigned char *end, uint32_t *num_r) diff --git a/src/lib-dcrypt/ostream-encrypt.c b/src/lib-dcrypt/ostream-encrypt.c index 84919d32d8..ae661a9e73 100644 --- a/src/lib-dcrypt/ostream-encrypt.c +++ b/src/lib-dcrypt/ostream-encrypt.c @@ -84,7 +84,7 @@ int o_stream_encrypt_send_header_v1(struct encrypt_ostream *stream) /* version */ c = 1; buffer_append(values, &c, 1); - /* header length including this and data written so far */ + /* key data length */ s = htons(stream->key_data_len); buffer_append(values, &s, 2); /* then write key data */