1From 7bad6a24160e34bce8f10e73dbbf9e5fbbcd1904 Mon Sep 17 00:00:00 2001
2From: Timo Sirainen <timo.sirainen@open-xchange.com>
3Date: Mon, 9 May 2022 15:23:33 +0300
4Subject: [PATCH] auth: Fix handling passdbs with identical driver/args but
5 different mechanisms/username_filter
6
7The passdb was wrongly deduplicated in this situation, causing wrong
8mechanisms or username_filter setting to be used. This would be a rather
9unlikely configuration though.
10
11Fixed by moving mechanisms and username_filter from struct passdb_module
12to struct auth_passdb, which is where they should have been in the first
13place.
14
15Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
16---
17 src/auth/auth-request.c |  6 +++---
18 src/auth/auth.c         | 18 ++++++++++++++++++
19 src/auth/auth.h         |  5 +++++
20 src/auth/passdb.c       | 15 ++-------------
21 src/auth/passdb.h       |  4 ----
22 5 files changed, 28 insertions(+), 20 deletions(-)
23
24diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c
25index cd08b1fa02..0ca29f3674 100644
26--- a/src/auth/auth-request.c
27+++ b/src/auth/auth-request.c
28@@ -534,8 +534,8 @@ auth_request_want_skip_passdb(struct auth_request *request,
29 			      struct auth_passdb *passdb)
30 {
31 	/* if mechanism is not supported, skip */
32-	const char *const *mechs = passdb->passdb->mechanisms;
33-	const char *const *username_filter = passdb->passdb->username_filter;
34+	const char *const *mechs = passdb->mechanisms;
35+	const char *const *username_filter = passdb->username_filter;
36 	const char *username;
37
38 	username = request->fields.user;
39@@ -548,7 +548,7 @@ auth_request_want_skip_passdb(struct auth_request *request,
40 		return TRUE;
41 	}
42
43-	if (passdb->passdb->username_filter != NULL &&
44+	if (passdb->username_filter != NULL &&
45 	    !auth_request_username_accepted(username_filter, username)) {
46 		auth_request_log_debug(request,
47 				       request->mech != NULL ? AUTH_SUBSYS_MECH
48diff --git a/src/auth/auth.c b/src/auth/auth.c
49index f2f3fda20c..9f6c4ba60c 100644
50--- a/src/auth/auth.c
51+++ b/src/auth/auth.c
52@@ -99,6 +99,24 @@ auth_passdb_preinit(struct auth *auth, const struct auth_passdb_settings *set,
53 	auth_passdb->override_fields_tmpl =
54 		passdb_template_build(auth->pool, set->override_fields);
55
56+	if (*set->mechanisms == '\0') {
57+		auth_passdb->mechanisms = NULL;
58+	} else if (strcasecmp(set->mechanisms, "none") == 0) {
59+		auth_passdb->mechanisms = (const char *const[]){ NULL };
60+	} else {
61+		auth_passdb->mechanisms =
62+			(const char *const *)p_strsplit_spaces(auth->pool,
63+				set->mechanisms, " ,");
64+	}
65+
66+	if (*set->username_filter == '\0') {
67+		auth_passdb->username_filter = NULL;
68+	} else {
69+		auth_passdb->username_filter =
70+			(const char *const *)p_strsplit_spaces(auth->pool,
71+				set->username_filter, " ,");
72+	}
73+
74 	/* for backwards compatibility: */
75 	if (set->pass)
76 		auth_passdb->result_success = AUTH_DB_RULE_CONTINUE;
77diff --git a/src/auth/auth.h b/src/auth/auth.h
78index f700e29d5c..460a179765 100644
79--- a/src/auth/auth.h
80+++ b/src/auth/auth.h
81@@ -41,6 +41,11 @@ struct auth_passdb {
82 	struct passdb_template *default_fields_tmpl;
83 	struct passdb_template *override_fields_tmpl;
84
85+	/* Supported authentication mechanisms, NULL is all, {NULL} is none */
86+	const char *const *mechanisms;
87+	/* Username filter, NULL is no filter */
88+	const char *const *username_filter;
89+
90 	enum auth_passdb_skip skip;
91 	enum auth_db_rule result_success;
92 	enum auth_db_rule result_failure;
93diff --git a/src/auth/passdb.c b/src/auth/passdb.c
94index eb4ac8ae82..f5eed1af4f 100644
95--- a/src/auth/passdb.c
96+++ b/src/auth/passdb.c
97@@ -224,19 +224,8 @@ passdb_preinit(pool_t pool, const struct auth_passdb_settings *set)
98 	passdb->id = ++auth_passdb_id;
99 	passdb->iface = *iface;
100 	passdb->args = p_strdup(pool, set->args);
101-	if (*set->mechanisms == '\0') {
102-		passdb->mechanisms = NULL;
103-	} else if (strcasecmp(set->mechanisms, "none") == 0) {
104-		passdb->mechanisms = (const char *const[]){NULL};
105-	} else {
106-		passdb->mechanisms = (const char* const*)p_strsplit_spaces(pool, set->mechanisms, " ,");
107-	}
108-
109-	if (*set->username_filter == '\0') {
110-		passdb->username_filter = NULL;
111-	} else {
112-		passdb->username_filter = (const char* const*)p_strsplit_spaces(pool, set->username_filter, " ,");
113-	}
114+	/* NOTE: if anything else than driver & args are added here,
115+	   passdb_find() also needs to be updated. */
116 	array_push_back(&passdb_modules, &passdb);
117 	return passdb;
118 }
119diff --git a/src/auth/passdb.h b/src/auth/passdb.h
120index 2e95328e5c..e466a9fdb6 100644
121--- a/src/auth/passdb.h
122+++ b/src/auth/passdb.h
123@@ -63,10 +63,6 @@ struct passdb_module {
124 	/* Default password scheme for this module.
125 	   If default_cache_key is set, must not be NULL. */
126 	const char *default_pass_scheme;
127-	/* Supported authentication mechanisms, NULL is all, [NULL] is none*/
128-	const char *const *mechanisms;
129-	/* Username filter, NULL is no filter */
130-	const char *const *username_filter;
131
132 	/* If blocking is set to TRUE, use child processes to access
133 	   this passdb. */
134--
1352.30.2
136
137