Blame SOURCES/dovecot-2.3.8-CVE_2020_12674.patch

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