import dovecot-2.3.8-4.el8

This commit is contained in:
CentOS Sources 2020-09-10 18:25:29 +00:00 committed by Andrew Lukoshko
parent c380bcd304
commit 7e699f8952
8 changed files with 3350 additions and 14 deletions

View File

@ -1,11 +0,0 @@
diff -up dovecot-2.3.0.1/src/auth/mycrypt.c.libxcrypt dovecot-2.3.0.1/src/auth/mycrypt.c
--- dovecot-2.3.0.1/src/auth/mycrypt.c.libxcrypt 2018-02-28 15:28:58.000000000 +0100
+++ dovecot-2.3.0.1/src/auth/mycrypt.c 2018-03-27 10:57:38.447769201 +0200
@@ -14,6 +14,7 @@
# define _XPG6 /* Some Solaris versions require this, some break with this */
#endif
#include <unistd.h>
+#include <crypt.h>
#include "mycrypt.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
diff -up dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c.CVE_2020_12100ph dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c
--- dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c.CVE_2020_12100ph 2019-10-08 10:48:14.000000000 +0200
+++ dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/plugins/notify/ext-notify-common.c 2020-08-07 16:42:56.515389867 +0200
@@ -148,6 +148,7 @@ static int cmd_notify_extract_body_text
const char **body_text_r, size_t *body_size_r)
{
const struct sieve_extension *this_ext = renv->oprtn->ext;
+ const struct message_parser_settings parser_set = { .flags = 0 };
struct ext_notify_message_context *mctx;
struct mail *mail = renv->msgdata->mail;
struct message_parser_ctx *parser;
@@ -181,7 +182,7 @@ static int cmd_notify_extract_body_text
/* Initialize body decoder */
decoder = message_decoder_init(NULL, 0);
- parser = message_parser_init(mctx->pool, input, 0, 0);
+ parser = message_parser_init(mctx->pool, input, &parser_set);
is_text = TRUE;
save_body = FALSE;
while ( (ret=message_parser_parse_next_block(parser, &block)) > 0 ) {
diff -up dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c.CVE_2020_12100ph dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c
--- dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c.CVE_2020_12100ph 2019-10-08 10:48:14.000000000 +0200
+++ dovecot-2.3.8/dovecot-2.3-pigeonhole-0.5.8/src/lib-sieve/sieve-message.c 2020-08-07 16:42:56.516389854 +0200
@@ -1077,10 +1077,10 @@ static int sieve_message_parts_add_missi
struct sieve_message_context *msgctx = renv->msgctx;
pool_t pool = msgctx->context_pool;
struct mail *mail = sieve_message_get_mail(renv->msgctx);
- enum message_parser_flags mparser_flags =
- MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS;
- enum message_header_parser_flags hparser_flags =
- MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP;
+ struct message_parser_settings parser_set = {
+ .hdr_flags = MESSAGE_HEADER_PARSER_FLAG_SKIP_INITIAL_LWSP,
+ .flags = MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS,
+ };
ARRAY(struct sieve_message_header) headers;
struct sieve_message_part *body_part, *header_part, *last_part;
struct message_parser_ctx *parser;
@@ -1117,7 +1117,7 @@ static int sieve_message_parts_add_missi
if (iter_all) {
t_array_init(&headers, 64);
hdr_content = t_str_new(512);
- hparser_flags |= MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
+ parser_set.hdr_flags |= MESSAGE_HEADER_PARSER_FLAG_CLEAN_ONELINE;
} else {
i_zero(&headers);
}
@@ -1129,7 +1129,7 @@ static int sieve_message_parts_add_missi
//parser = message_parser_init_from_parts(parts, input,
// hparser_flags, mparser_flags);
parser = message_parser_init(pool_datastack_create(),
- input, hparser_flags, mparser_flags);
+ input, &parser_set);
while ( (ret=message_parser_parse_next_block
(parser, &block)) > 0 ) {
struct sieve_message_part **body_part_idx;

View File

@ -0,0 +1,224 @@
diff -up dovecot-2.3.8/src/lib-mail/message-decoder.c.CVE_2020_12100prereq dovecot-2.3.8/src/lib-mail/message-decoder.c
--- dovecot-2.3.8/src/lib-mail/message-decoder.c.CVE_2020_12100prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib-mail/message-decoder.c 2020-08-07 17:48:58.320126698 +0200
@@ -13,9 +13,6 @@
#include "message-header-decode.h"
#include "message-decoder.h"
-/* base64 takes max 4 bytes per character, q-p takes max 3. */
-#define MAX_ENCODING_BUF_SIZE 3
-
struct message_decoder_context {
enum message_decoder_flags flags;
normalizer_func_t *normalizer;
@@ -30,7 +27,7 @@ struct message_decoder_context {
size_t translation_size;
struct qp_decoder *qp;
- buffer_t *encoding_buf;
+ struct base64_decoder base64_decoder;
char *content_type, *content_charset;
enum message_cte message_cte;
@@ -53,7 +50,7 @@ message_decoder_init(normalizer_func_t *
ctx->normalizer = normalizer;
ctx->buf = buffer_create_dynamic(default_pool, 8192);
ctx->buf2 = buffer_create_dynamic(default_pool, 8192);
- ctx->encoding_buf = buffer_create_dynamic(default_pool, 128);
+ base64_decode_init(&ctx->base64_decoder, &base64_scheme, 0);
return ctx;
}
@@ -68,7 +65,6 @@ void message_decoder_deinit(struct messa
if (ctx->qp != NULL)
qp_decoder_deinit(&ctx->qp);
- buffer_free(&ctx->encoding_buf);
buffer_free(&ctx->buf);
buffer_free(&ctx->buf2);
i_free(ctx->charset_trans_charset);
@@ -273,14 +269,9 @@ static bool message_decode_body(struct m
struct message_block *input,
struct message_block *output)
{
- struct base64_decoder b64dec;
const unsigned char *data = NULL;
- size_t pos = 0, size = 0;
+ size_t pos, size = 0;
const char *error;
- int ret;
-
- if (ctx->encoding_buf->used != 0)
- buffer_append(ctx->encoding_buf, input->data, input->size);
switch (ctx->message_cte) {
case MESSAGE_CTE_UNKNOWN:
@@ -289,12 +280,10 @@ static bool message_decode_body(struct m
case MESSAGE_CTE_78BIT:
case MESSAGE_CTE_BINARY:
- i_assert(ctx->encoding_buf->used == 0);
data = input->data;
- size = pos = input->size;
+ size = input->size;
break;
case MESSAGE_CTE_QP: {
- i_assert(ctx->encoding_buf->used == 0);
buffer_set_used_size(ctx->buf, 0);
if (ctx->qp == NULL)
ctx->qp = qp_decoder_init(ctx->buf);
@@ -302,45 +291,24 @@ static bool message_decode_body(struct m
&pos, &error);
data = ctx->buf->data;
size = ctx->buf->used;
- /* eat away all input. qp-decoder buffers it internally. */
- pos = input->size;
break;
}
case MESSAGE_CTE_BASE64:
buffer_set_used_size(ctx->buf, 0);
- base64_decode_init(&b64dec, &base64_scheme, 0);
- if (ctx->encoding_buf->used != 0) {
- ret = base64_decode_more(&b64dec,
- ctx->encoding_buf->data,
- ctx->encoding_buf->used,
- &pos, ctx->buf);
- } else {
- ret = base64_decode_more(&b64dec,
- input->data, input->size,
- &pos, ctx->buf);
- }
- if (ret < 0 || base64_decode_finish(&b64dec) < 0) {
- /* corrupted base64 data, don't bother with
- the rest of it */
- return FALSE;
- }
- if (ret == 0) {
- /* end of base64 input */
- pos = input->size;
- buffer_set_used_size(ctx->encoding_buf, 0);
+ if (!base64_decode_is_finished(&ctx->base64_decoder)) {
+ if (base64_decode_more(&ctx->base64_decoder,
+ input->data, input->size,
+ &pos, ctx->buf) <= 0) {
+ /* ignore the rest of the input in this
+ MIME part */
+ (void)base64_decode_finish(&ctx->base64_decoder);
+ }
}
data = ctx->buf->data;
size = ctx->buf->used;
break;
}
- if (ctx->encoding_buf->used != 0)
- buffer_delete(ctx->encoding_buf, 0, pos);
- else if (pos != input->size) {
- buffer_append(ctx->encoding_buf,
- input->data + pos, input->size - pos);
- }
-
if (ctx->binary_input) {
output->data = data;
output->size = size;
@@ -402,10 +370,11 @@ void message_decoder_decode_reset(struct
{
const char *error;
+ base64_decode_reset(&ctx->base64_decoder);
+
if (ctx->qp != NULL)
(void)qp_decoder_finish(ctx->qp, &error);
i_free_and_null(ctx->content_type);
i_free_and_null(ctx->content_charset);
ctx->message_cte = MESSAGE_CTE_78BIT;
- buffer_set_used_size(ctx->encoding_buf, 0);
}
diff -up dovecot-2.3.8/src/lib-mail/test-message-decoder.c.CVE_2020_12100prereq dovecot-2.3.8/src/lib-mail/test-message-decoder.c
--- dovecot-2.3.8/src/lib-mail/test-message-decoder.c.CVE_2020_12100prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/lib-mail/test-message-decoder.c 2020-08-07 17:50:04.612248484 +0200
@@ -1,7 +1,8 @@
/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
-#include "buffer.h"
+#include "str.h"
+#include "istream.h"
#include "charset-utf8.h"
#include "message-parser.h"
#include "message-header-decode.h"
@@ -82,6 +83,66 @@ static void test_message_decoder(void)
test_end();
}
+static void test_message_decoder_multipart(void)
+{
+ static const char test_message_input[] =
+ "Content-Type: multipart/mixed; boundary=foo\n"
+ "\n"
+ "--foo\n"
+ "Content-Transfer-Encoding: quoted-printable\n"
+ "Content-Type: text/plain; charset=utf-8\n"
+ "\n"
+ "p=C3=A4iv=C3=A4=C3=A4\n"
+ "\n"
+ "--foo\n"
+ "Content-Transfer-Encoding: base64\n"
+ "Content-Type: text/plain; charset=utf-8\n"
+ "\n"
+ "ecO2dMOkIHZhYW4uCg== ignored\n"
+ "--foo\n"
+ "Content-Transfer-Encoding: base64\n"
+ "Content-Type: text/plain; charset=utf-8\n"
+ "\n"
+ "?garbage\n"
+ "--foo--\n";
+ struct message_parser_ctx *parser;
+ struct message_decoder_context *decoder;
+ struct message_part *parts;
+ struct message_block input, output;
+ struct istream *istream;
+ string_t *str_out = t_str_new(20);
+ int ret;
+
+ test_begin("message decoder multipart");
+
+ istream = test_istream_create(test_message_input);
+ parser = message_parser_init(pool_datastack_create(), istream, 0, 0);
+ decoder = message_decoder_init(NULL, 0);
+
+ test_istream_set_allow_eof(istream, FALSE);
+ for (size_t i = 0; i < sizeof(test_message_input); i++) {
+ if (i == sizeof(test_message_input)-1)
+ test_istream_set_allow_eof(istream, TRUE);
+ test_istream_set_size(istream, i);
+ while ((ret = message_parser_parse_next_block(parser, &input)) > 0) {
+ if (message_decoder_decode_next_block(decoder, &input, &output) &&
+ output.hdr == NULL && output.size > 0)
+ str_append_data(str_out, output.data, output.size);
+ }
+ if (i == sizeof(test_message_input)-1)
+ test_assert(ret == -1);
+ else
+ test_assert(ret == 0);
+ }
+ /* NOTE: qp-decoder decoder changes \n into \r\n */
+ test_assert_strcmp(str_c(str_out), "p\xC3\xA4iv\xC3\xA4\xC3\xA4\r\ny\xC3\xB6t\xC3\xA4 vaan.\n");
+
+ message_decoder_deinit(&decoder);
+ message_parser_deinit(&parser, &parts);
+ i_stream_unref(&istream);
+ test_end();
+}
+
static void test_message_decoder_current_content_type(void)
{
struct message_decoder_context *ctx;
@@ -149,6 +210,7 @@ int main(void)
{
static void (*const test_functions[])(void) = {
test_message_decoder,
+ test_message_decoder_multipart,
test_message_decoder_current_content_type,
NULL
};

View File

@ -0,0 +1,34 @@
From 1c6405d3026e5ceae3d214d63945bba85251af4c Mon Sep 17 00:00:00 2001
From: Aki Tuomi <aki.tuomi@open-xchange.com>
Date: Mon, 18 May 2020 12:33:39 +0300
Subject: [PATCH 2/3] lib-ntlm: Check buffer length on responses
Add missing check for buffer length.
If this is not checked, it is possible to send message which
causes read past buffer bug.
Broken in c7480644202e5451fbed448508ea29a25cffc99c
---
src/lib-ntlm/ntlm-message.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/lib-ntlm/ntlm-message.c b/src/lib-ntlm/ntlm-message.c
index 160b9f918c..a29413b47e 100644
--- a/src/lib-ntlm/ntlm-message.c
+++ b/src/lib-ntlm/ntlm-message.c
@@ -184,6 +184,11 @@ static bool ntlmssp_check_buffer(const struct ntlmssp_buffer *buffer,
if (length == 0 && space == 0)
return TRUE;
+ if (length > data_size) {
+ *error = "buffer length out of bounds";
+ return FALSE;
+ }
+
if (offset >= data_size) {
*error = "buffer offset out of bounds";
return FALSE;
--
2.11.0

View File

@ -0,0 +1,234 @@
From bd9d2fe7da833f0e4705a8280efc56930371806b Mon Sep 17 00:00:00 2001
From: Aki Tuomi <aki.tuomi@open-xchange.com>
Date: Wed, 6 May 2020 13:40:36 +0300
Subject: [PATCH 1/3] auth: mech-rpa - Fail on zero len buffer
---
src/auth/mech-rpa.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/auth/mech-rpa.c b/src/auth/mech-rpa.c
index 08298ebdd6..2de8705b4f 100644
--- a/src/auth/mech-rpa.c
+++ b/src/auth/mech-rpa.c
@@ -224,7 +224,7 @@ rpa_read_buffer(pool_t pool, const unsigned char **data,
return 0;
len = *p++;
- if (p + len > end)
+ if (p + len > end || len == 0)
return 0;
*buffer = p_malloc(pool, len);
--
2.11.0
From 98c39fd633adf9b1d11a7bad58ef0784a25042e6 Mon Sep 17 00:00:00 2001
From: Aki Tuomi <aki.tuomi@open-xchange.com>
Date: Mon, 18 May 2020 13:08:45 +0300
Subject: [PATCH 3/3] auth: test-mech - Add tests for RPA and NTLM bug
---
src/auth/test-mech.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff -up dovecot-2.3.8/src/auth/test-mech.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/test-mech.c
--- dovecot-2.3.8/src/auth/test-mech.c.CVE_2020_12674prereq 2020-08-07 20:46:56.095295825 +0200
+++ dovecot-2.3.8/src/auth/test-mech.c 2020-08-07 20:47:08.742124304 +0200
@@ -0,0 +1,196 @@
+/* Copyright (c) 2020 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "auth.h"
+#include "str.h"
+#include "auth-common.h"
+#include "auth-request.h"
+#include "auth-request-handler-private.h"
+#include "auth-settings.h"
+#include "otp.h"
+#include "mech-otp-skey-common.h"
+#include "settings-parser.h"
+#include "password-scheme.h"
+#include "test-common.h"
+#include "test-auth.h"
+#include "auth-token.h"
+
+#include <unistd.h>
+#include <time.h>
+
+#define UCHAR_LEN(str) (const unsigned char *)(str), sizeof(str)-1
+
+extern const struct mech_module mech_oauthbearer;
+extern const struct mech_module mech_otp;
+extern const struct mech_module mech_ntlm;
+extern const struct mech_module mech_rpa;
+
+static struct auth_settings set;
+static struct mechanisms_register *mech_reg;
+
+struct test_case {
+ const struct mech_module *mech;
+ const unsigned char *in;
+ size_t len;
+ const char *username;
+ const char *expect_error;
+ bool success;
+ bool set_username_before_test;
+ bool set_cert_username;
+};
+
+static void
+verify_plain_continue_mock_callback(struct auth_request *request,
+ verify_plain_callback_t *callback)
+{
+ request->passdb_success = TRUE;
+ callback(PASSDB_RESULT_OK, request);
+}
+
+static void
+request_handler_reply_mock_callback(struct auth_request *request,
+ enum auth_client_result result,
+ const void *auth_reply ATTR_UNUSED,
+ size_t reply_size ATTR_UNUSED)
+{
+ request->failed = result != AUTH_CLIENT_RESULT_SUCCESS;
+
+ if (request->passdb_result == PASSDB_RESULT_OK)
+ request->failed = FALSE;
+ else if (request->mech == &mech_otp) {
+ if (null_strcmp(request->user, "otp_phase_2") == 0)
+ request->failed = FALSE;
+ } else if (request->mech == &mech_oauthbearer) {
+ }
+};
+
+static void
+request_handler_reply_continue_mock_callback(struct auth_request *request,
+ const void *reply,
+ size_t reply_size)
+{
+ request->context = p_strndup(request->pool, reply, reply_size);
+}
+
+static void
+auth_client_request_mock_callback(const char *reply ATTR_UNUSED,
+ struct auth_client_connection *conn ATTR_UNUSED)
+{
+}
+
+static void test_mechs_init(void)
+{
+ const char *const services[] = {NULL};
+ process_start_time = time(NULL);
+
+ /* Copy default settings */
+ set = *(struct auth_settings *) auth_setting_parser_info.defaults;
+ global_auth_settings = &set;
+ global_auth_settings->base_dir = ".";
+ memset((&set)->username_chars_map, 1, sizeof((&set)->username_chars_map));
+ set.username_format = "";
+
+ t_array_init(&set.passdbs, 2);
+ struct auth_passdb_settings *mock_set = t_new(struct auth_passdb_settings, 1);
+ *mock_set = mock_passdb_set;
+ array_push_back(&set.passdbs, &mock_set);
+ mock_set = t_new(struct auth_passdb_settings, 1);
+ *mock_set = mock_passdb_set;
+ mock_set->master = TRUE;
+ array_push_back(&set.passdbs, &mock_set);
+ t_array_init(&set.userdbs, 1);
+
+ /* Disable stats */
+ set.stats = FALSE;
+
+ /* For tests of digest-md5. */
+ set.realms_arr = t_strsplit_spaces("example.com ", " ");
+ /* For tests of mech-anonymous. */
+ set.anonymous_username = "anonuser";
+
+ mech_init(global_auth_settings);
+ mech_reg = mech_register_init(global_auth_settings);
+ passdbs_init();
+ userdbs_init();
+ passdb_mock_mod_init();
+ password_schemes_init();
+
+ auths_preinit(&set, pool_datastack_create(), mech_reg, services);
+ auths_init();
+ auth_token_init();
+}
+
+
+static void test_rpa(void)
+{
+ test_mechs_init();
+ static struct auth_request_handler handler = {
+ .callback = auth_client_request_mock_callback,
+ .reply_callback = request_handler_reply_mock_callback,
+ .reply_continue_callback = request_handler_reply_continue_mock_callback,
+ .verify_plain_continue_callback = verify_plain_continue_mock_callback,
+ };
+
+ const struct mech_module *mech = &mech_rpa;
+ test_begin("test rpa");
+ struct auth_request *req = mech->auth_new();
+ global_auth_settings->realms_arr = t_strsplit("example.com", " ");
+ req->set = global_auth_settings;
+ req->service = "login";
+ req->handler = &handler;
+ req->mech_event = event_create(NULL);
+ req->event = event_create(NULL);
+ req->mech = mech;
+ req->state = AUTH_REQUEST_STATE_MECH_CONTINUE;
+ auth_request_state_count[AUTH_REQUEST_STATE_MECH_CONTINUE] = 1;
+ mech->auth_initial(req, UCHAR_LEN("\x60\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x73\x01\x01\x01\x00\x04\x00\x00\x01"));
+ mech->auth_continue(req, UCHAR_LEN("\x60\x11\x06\x09\x60\x86\x48\x01\x86\xf8\x73\x01\x01\x00\x03A@A\x00"));
+ test_assert(req->failed == TRUE);
+ test_assert(req->passdb_success == FALSE);
+ event_unref(&req->mech_event);
+ event_unref(&req->event);
+ mech->auth_free(req);
+ test_end();
+}
+
+static void test_ntlm(void)
+{
+ static struct auth_request_handler handler = {
+ .callback = auth_client_request_mock_callback,
+ .reply_callback = request_handler_reply_mock_callback,
+ .reply_continue_callback = request_handler_reply_continue_mock_callback,
+ .verify_plain_continue_callback = verify_plain_continue_mock_callback,
+ };
+
+ const struct mech_module *mech = &mech_ntlm;
+ test_begin("test ntlm");
+ struct auth_request *req = mech->auth_new();
+ global_auth_settings->realms_arr = t_strsplit("example.com", " ");
+ req->set = global_auth_settings;
+ req->service = "login";
+ req->handler = &handler;
+ req->mech_event = event_create(NULL);
+ req->event = event_create(NULL);
+ req->mech = mech;
+ req->state = AUTH_REQUEST_STATE_MECH_CONTINUE;
+ auth_request_state_count[AUTH_REQUEST_STATE_MECH_CONTINUE] = 1;
+ mech->auth_initial(req, UCHAR_LEN("NTLMSSP\x00\x01\x00\x00\x00\x00\x02\x00\x00""AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
+ mech->auth_continue(req, UCHAR_LEN("NTLMSSP\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""AA\x00\x00\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00""orange""\x00"));
+ test_assert(req->failed == TRUE);
+ test_assert(req->passdb_success == FALSE);
+ event_unref(&req->mech_event);
+ event_unref(&req->event);
+ mech->auth_free(req);
+ test_end();
+}
+
+int main(void)
+{
+ static void (*const test_functions[])(void) = {
+ test_rpa,
+ test_ntlm,
+ NULL
+ };
+
+ return test_run(test_functions);
+}

View File

@ -0,0 +1,345 @@
diff -up dovecot-2.3.8/src/auth/Makefile.am.CVE_2020_12674prereq dovecot-2.3.8/src/auth/Makefile.am
--- dovecot-2.3.8/src/auth/Makefile.am.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/Makefile.am 2020-08-07 20:46:56.095295825 +0200
@@ -38,6 +38,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib-oauth2 \
-I$(top_srcdir)/src/lib-ssl-iostream \
-I$(top_srcdir)/src/lib-lua \
+ -I$(top_srcdir)/src/lib-dcrypt \
-DAUTH_MODULE_DIR=\""$(auth_moduledir)"\" \
-DPKG_LIBEXECDIR=\""$(pkglibexecdir)"\" \
-DPKG_RUNDIR=\""$(rundir)"\" \
@@ -248,7 +249,8 @@ libstats_auth_la_SOURCES = auth-stats.c
test_programs = \
test-libpassword \
test-auth-cache \
- test-auth
+ test-auth \
+ test-mech
noinst_PROGRAMS = $(test_programs)
@@ -288,6 +290,13 @@ test_auth_SOURCES = \
test_auth_LDADD = $(test_libs) $(auth_libs) $(AUTH_LIBS)
test_auth_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs)
+test_mech_SOURCES = \
+ test-mock.c \
+ test-mech.c
+
+test_mech_LDADD = $(test_libs) $(auth_libs) $(AUTH_LIBS)
+test_mech_DEPENDENCIES = $(pkglibexec_PROGRAMS) $(test_libs)
+
check-local:
for bin in $(test_programs); do \
if ! $(RUN_TEST) ./$$bin; then exit 1; fi; \
diff -up dovecot-2.3.8/src/auth/passdb.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/passdb.h
--- dovecot-2.3.8/src/auth/passdb.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/passdb.h 2020-08-07 20:35:16.295684287 +0200
@@ -24,6 +24,8 @@ enum passdb_result {
typedef void verify_plain_callback_t(enum passdb_result result,
struct auth_request *request);
+typedef void verify_plain_continue_callback_t(struct auth_request *request,
+ verify_plain_callback_t *callback);
typedef void lookup_credentials_callback_t(enum passdb_result result,
const unsigned char *credentials,
size_t size,
diff -up dovecot-2.3.8/src/auth/auth-request-handler-private.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request-handler-private.h
--- dovecot-2.3.8/src/auth/auth-request-handler-private.h.CVE_2020_12674prereq 2020-08-07 20:35:16.295684287 +0200
+++ dovecot-2.3.8/src/auth/auth-request-handler-private.h 2020-08-07 20:35:16.295684287 +0200
@@ -0,0 +1,27 @@
+#ifndef AUTH_REQUEST_HANDLER_PRIVATE_H
+#define AUTH_REQUEST_HANDLER_PRIVATE_H
+
+struct auth_request;
+struct auth_client_connection;
+
+struct auth_request_handler {
+ int refcount;
+ pool_t pool;
+ HASH_TABLE(void *, struct auth_request *) requests;
+
+ unsigned int connect_uid, client_pid;
+
+ auth_client_request_callback_t *callback;
+ struct auth_client_connection *conn;
+
+ auth_master_request_callback_t *master_callback;
+ auth_request_handler_reply_callback_t *reply_callback;
+ auth_request_handler_reply_continue_callback_t *reply_continue_callback;
+ verify_plain_continue_callback_t *verify_plain_continue_callback;
+
+ bool destroyed:1;
+ bool token_auth:1;
+};
+
+
+#endif
diff -up dovecot-2.3.8/src/auth/auth-request-handler.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request-handler.h
--- dovecot-2.3.8/src/auth/auth-request-handler.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/auth-request-handler.h 2020-08-07 20:35:16.295684287 +0200
@@ -17,6 +17,17 @@ auth_client_request_callback_t(const cha
typedef void
auth_master_request_callback_t(const char *reply, struct auth_master_connection *conn);
+typedef void
+auth_request_handler_reply_callback_t(struct auth_request *request,
+ enum auth_client_result result,
+ const void *auth_reply,
+ size_t reply_size);
+typedef void
+auth_request_handler_reply_continue_callback_t(struct auth_request *request,
+ const void *reply,
+ size_t reply_size);
+
+
struct auth_request_handler *
auth_request_handler_create(bool token_auth, auth_client_request_callback_t *callback,
struct auth_client_connection *conn,
diff -up dovecot-2.3.8/src/auth/test-mock.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/test-mock.c
--- dovecot-2.3.8/src/auth/test-mock.c.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/test-mock.c 2020-08-07 20:35:16.296684273 +0200
@@ -28,14 +28,22 @@ static void passdb_mock_verify_plain(str
callback(PASSDB_RESULT_OK, request);
}
+static void passdb_mock_lookup_credentials(struct auth_request *request,
+ lookup_credentials_callback_t *callback)
+{
+ passdb_handle_credentials(PASSDB_RESULT_OK, "password", "PLAIN",
+ callback, request);
+}
+
static struct passdb_module_interface mock_interface = {
.name = "mock",
.init = passdb_mock_init,
.deinit = passdb_mock_deinit,
.verify_plain = passdb_mock_verify_plain,
+ .lookup_credentials = passdb_mock_lookup_credentials,
};
-static struct auth_passdb_settings set = {
+struct auth_passdb_settings mock_passdb_set = {
.name = "mock",
.driver = "mock",
.args = "",
@@ -95,7 +103,7 @@ void passdb_mock_mod_deinit(void)
struct auth_passdb *passdb_mock(void)
{
struct auth_passdb *ret = i_new(struct auth_passdb, 1);
- ret->set = &set;
+ ret->set = &mock_passdb_set;
ret->passdb = mock_passdb_mod;
return ret;
}
diff -up dovecot-2.3.8/src/auth/test-auth.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/test-auth.h
--- dovecot-2.3.8/src/auth/test-auth.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/test-auth.h 2020-08-07 20:35:16.296684273 +0200
@@ -8,6 +8,8 @@
struct auth_passdb;
+extern struct auth_passdb_settings mock_passdb_set;
+
void test_auth_request_var_expand(void);
void test_db_dict_parse_cache_key(void);
void test_username_filter(void);
diff -up dovecot-2.3.8/src/auth/auth-request.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request.c
--- dovecot-2.3.8/src/auth/auth-request.c.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/auth-request.c 2020-08-07 20:35:16.295684287 +0200
@@ -16,6 +16,7 @@
#include "auth-cache.h"
#include "auth-request.h"
#include "auth-request-handler.h"
+#include "auth-request-handler-private.h"
#include "auth-request-stats.h"
#include "auth-client-connection.h"
#include "auth-master-connection.h"
@@ -67,9 +68,6 @@ static void
auth_request_userdb_import(struct auth_request *request, const char *args);
static
-void auth_request_verify_plain_continue(struct auth_request *request,
- verify_plain_callback_t *callback);
-static
void auth_request_lookup_credentials_policy_continue(struct auth_request *request,
lookup_credentials_callback_t *callback);
static
@@ -307,10 +307,12 @@ void auth_request_success_continue(struct auth_policy_check_ctx *ctx)
return;
}
- stats = auth_request_stats_get(request);
- stats->auth_success_count++;
- if (request->master_user != NULL)
- stats->auth_master_success_count++;
+ if (request->set->stats) {
+ stats = auth_request_stats_get(request);
+ stats->auth_success_count++;
+ if (request->master_user != NULL)
+ stats->auth_master_success_count++;
+ }
auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
auth_request_refresh_last_access(request);
@@ -324,8 +326,10 @@ void auth_request_fail(struct auth_request *request)
i_assert(request->state == AUTH_REQUEST_STATE_MECH_CONTINUE);
- stats = auth_request_stats_get(request);
- stats->auth_failure_count++;
+ if (request->set->stats) {
+ stats = auth_request_stats_get(request);
+ stats->auth_failure_count++;
+ }
auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
auth_request_refresh_last_access(request);
@@ -1233,7 +1231,7 @@ void auth_request_policy_penalty_finish(
switch(ctx->type) {
case AUTH_POLICY_CHECK_TYPE_PLAIN:
- auth_request_verify_plain_continue(ctx->request, ctx->callback_plain);
+ ctx->request->handler->verify_plain_continue_callback(ctx->request, ctx->callback_plain);
return;
case AUTH_POLICY_CHECK_TYPE_LOOKUP:
auth_request_lookup_credentials_policy_continue(ctx->request, ctx->callback_lookup);
@@ -1284,7 +1282,8 @@ void auth_request_verify_plain(struct au
request->user_changed_by_lookup = FALSE;
if (request->policy_processed || !request->set->policy_check_before_auth) {
- auth_request_verify_plain_continue(request, callback);
+ request->handler->verify_plain_continue_callback(request,
+ callback);
} else {
ctx = p_new(request->pool, struct auth_policy_check_ctx, 1);
ctx->request = request;
@@ -1294,10 +1293,9 @@ void auth_request_verify_plain(struct au
}
}
-static
-void auth_request_verify_plain_continue(struct auth_request *request,
- verify_plain_callback_t *callback) {
-
+void auth_request_default_verify_plain_continue(struct auth_request *request,
+ verify_plain_callback_t *callback)
+{
struct auth_passdb *passdb;
enum passdb_result result;
const char *cache_key, *error;
diff -up dovecot-2.3.8/src/auth/auth-request-handler.c.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request-handler.c
--- dovecot-2.3.8/src/auth/auth-request-handler.c.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/auth-request-handler.c 2020-08-07 20:35:16.295684287 +0200
@@ -17,32 +17,28 @@
#include "auth-client-connection.h"
#include "auth-master-connection.h"
#include "auth-request-handler.h"
+#include "auth-request-handler-private.h"
#include "auth-policy.h"
#define AUTH_FAILURE_DELAY_CHECK_MSECS 500
-
-struct auth_request_handler {
- int refcount;
- pool_t pool;
- HASH_TABLE(void *, struct auth_request *) requests;
-
- unsigned int connect_uid, client_pid;
-
- auth_client_request_callback_t *callback;
- struct auth_client_connection *conn;
-
- auth_master_request_callback_t *master_callback;
-
- bool destroyed:1;
- bool token_auth:1;
-};
-
static ARRAY(struct auth_request *) auth_failures_arr;
static struct aqueue *auth_failures;
static struct timeout *to_auth_failures;
static void auth_failure_timeout(void *context) ATTR_NULL(1);
+
+static void
+auth_request_handler_default_reply_callback(struct auth_request *request,
+ enum auth_client_result result,
+ const void *auth_reply,
+ size_t reply_size);
+
+static void
+auth_request_handler_default_reply_continue(struct auth_request *request,
+ const void *reply,
+ size_t reply_size);
+
struct auth_request_handler *
auth_request_handler_create(bool token_auth, auth_client_request_callback_t *callback,
struct auth_client_connection *conn,
@@ -61,6 +57,12 @@ auth_request_handler_create(bool token_a
handler->conn = conn;
handler->master_callback = master_callback;
handler->token_auth = token_auth;
+ handler->reply_callback =
+ auth_request_handler_default_reply_callback;
+ handler->reply_continue_callback =
+ auth_request_handler_default_reply_continue;
+ handler->verify_plain_continue_callback =
+ auth_request_default_verify_plain_continue;
return handler;
}
@@ -355,6 +363,16 @@ void auth_request_handler_reply(struct a
enum auth_client_result result,
const void *auth_reply, size_t reply_size)
{
+ struct auth_request_handler *handler = request->handler;
+ handler->reply_callback(request, result, auth_reply, reply_size);
+}
+
+static void
+auth_request_handler_default_reply_callback(struct auth_request *request,
+ enum auth_client_result result,
+ const void *auth_reply,
+ size_t reply_size)
+{
struct auth_request_handler *handler = request->handler;
string_t *str;
int ret;
@@ -407,6 +425,14 @@ void auth_request_handler_reply(struct a
void auth_request_handler_reply_continue(struct auth_request *request,
const void *reply, size_t reply_size)
{
+ request->handler->reply_continue_callback(request, reply, reply_size);
+}
+
+static void
+auth_request_handler_default_reply_continue(struct auth_request *request,
+ const void *reply,
+ size_t reply_size)
+{
auth_request_handler_reply(request, AUTH_CLIENT_RESULT_CONTINUE,
reply, reply_size);
}
@@ -703,6 +729,7 @@ static void auth_str_append_userdb_extra
auth_str_add_keyvalue(dest, "master_user",
request->master_user);
}
+ auth_str_add_keyvalue(dest, "auth_mech", request->mech->mech_name);
if (*request->set->anonymous_username != '\0' &&
strcmp(request->user, request->set->anonymous_username) == 0) {
/* this is an anonymous login, either via ANONYMOUS
diff -up dovecot-2.3.8/src/auth/auth-request.h.CVE_2020_12674prereq dovecot-2.3.8/src/auth/auth-request.h
--- dovecot-2.3.8/src/auth/auth-request.h.CVE_2020_12674prereq 2019-10-08 10:46:18.000000000 +0200
+++ dovecot-2.3.8/src/auth/auth-request.h 2020-08-07 20:35:16.295684287 +0200
@@ -295,6 +295,8 @@ void auth_request_set_credentials(struct
set_credentials_callback_t *callback);
void auth_request_userdb_callback(enum userdb_result result,
struct auth_request *request);
+void auth_request_default_verify_plain_continue(struct auth_request *request,
+ verify_plain_callback_t *callback);
void auth_request_refresh_last_access(struct auth_request *request);
void auth_str_append(string_t *dest, const char *key, const char *value);

View File

@ -5,7 +5,7 @@ Name: dovecot
Epoch: 1
Version: 2.3.8
%global prever %{nil}
Release: 3%{?dist}
Release: 4%{?dist}
#dovecot itself is MIT, a few sources are PD, pigeonhole is LGPLv2
License: MIT and LGPLv2
Group: System Environment/Daemons
@ -32,7 +32,6 @@ Patch6: dovecot-2.1.10-waitonline.patch
Patch8: dovecot-2.2.20-initbysystemd.patch
Patch9: dovecot-2.2.22-systemd_w_protectsystem.patch
Patch10: dovecot-2.3.0.1-libxcrypt.patch
# sent upstream, rhbz#1630380
Patch11: dovecot-2.2.36-aclfix.patch
@ -48,6 +47,14 @@ Patch14: dovecot-2.3.6-opensslhmac.patch
Patch15: dovecot-2.3.10-smtppre.patch
Patch16: dovecot-2.3.10-CVE_2020_10957,10958,10967.patch
# from upstream, for dovecot <= 2.3.10.1
Patch17: dovecot-2.3.8-CVE_2020_12100prereq.patch
Patch18: dovecot-2.3.8-CVE_2020_12100.patch
Patch19: dovecot-2.3.8-CVE_2020_12100ph.patch
Patch20: dovecot-2.3.8-CVE_2020_12673.patch
Patch21: dovecot-2.3.8-CVE_2020_12674prereq.patch
Patch22: dovecot-2.3.8-CVE_2020_12674.patch
Source15: prestartscript
BuildRequires: openssl-devel, pam-devel, zlib-devel, bzip2-devel, libcap-devel
@ -148,12 +155,17 @@ This package provides the development files for dovecot.
%patch6 -p1 -b .waitonline
%patch8 -p1 -b .initbysystemd
%patch9 -p1 -b .systemd_w_protectsystem
#%patch10 -p1 -b .libxcrypt
%patch11 -p1 -b .aclfix
%patch13 -p1 -b .bigkey
%patch14 -p1 -b .opensslhmac
%patch15 -p1 -b .smtppre
%patch16 -p1 -b .CVE_2020_10957,10958,10967
%patch17 -p1 -b .CVE_2020_12100prereq
%patch18 -p1 -b .CVE_2020_12100
%patch19 -p1 -b .CVE_2020_12100ph
%patch20 -p1 -b .CVE_2020_12673
%patch21 -p1 -b .CVE_2020_12674prereq
%patch22 -p1 -b .CVE_2020_12674
pushd dovecot-2*3-pigeonhole-%{pigeonholever}
popd
@ -513,6 +525,11 @@ make check
%{_libdir}/%{name}/dict/libdriver_pgsql.so
%changelog
* Fri Aug 07 2020 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.8-4
- fix CVE-2020-12100 resource exhaustion via deeply nested MIME parts (#1866756)
- fix CVE-2020-12673 out of bound reads in dovecot NTLM implementation (#1866761)
- fix CVE-2020-12674 crash due to assert in RPA implementation (#1866768)
* Mon Jun 01 2020 Michal Hlavinka <mhlavink@redhat.com> - 1:2.3.8-3
- fix CVE-2020-10957 dovecot: malformed NOOP commands leads to DoS (#1840354)
- fix CVE-2020-10958 dovecot: command followed by sufficient number of newlines