[dovecot-cvs] dovecot/src/auth auth-master-connection.c, 1.44, 1.45 auth-request-handler.c, 1.19, 1.20 auth-request.c, 1.74, 1.75 auth-request.h, 1.29, 1.30 auth-worker-client.c, 1.27, 1.28 userdb-blocking.c, 1.5, 1.6 userdb-ldap.c, 1.42, 1.43 userdb-passwd-file.c, 1.22, 1.23 userdb-passwd.c, 1.18, 1.19 userdb-prefetch.c, 1.3, 1.4 userdb-sql.c, 1.15, 1.16 userdb-static.c, 1.21, 1.22 userdb-vpopmail.c, 1.21, 1.22 userdb.h, 1.25, 1.26

tss at dovecot.org tss at dovecot.org
Sat Dec 9 15:11:51 UTC 2006


Update of /var/lib/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv9973

Modified Files:
	auth-master-connection.c auth-request-handler.c auth-request.c 
	auth-request.h auth-worker-client.c userdb-blocking.c 
	userdb-ldap.c userdb-passwd-file.c userdb-passwd.c 
	userdb-prefetch.c userdb-sql.c userdb-static.c 
	userdb-vpopmail.c userdb.h 
Log Message:
We treated internal userdb lookup errors as "user unknown" errors. In such
situations this caused deliver to think the user didn't exist and the mail
get bounced.



Index: auth-master-connection.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-master-connection.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- auth-master-connection.c	12 Nov 2006 19:54:29 -0000	1.44
+++ auth-master-connection.c	9 Dec 2006 15:11:48 -0000	1.45
@@ -78,18 +78,25 @@
 }
 
 static void
-user_callback(struct auth_stream_reply *reply,
+user_callback(enum userdb_result result,
+	      struct auth_stream_reply *reply,
 	      struct auth_request *auth_request)
 {
 	struct auth_master_connection *conn = auth_request->context;
 	string_t *str;
 
 	str = t_str_new(128);
-	if (reply == NULL)
+	switch (result) {
+	case USERDB_RESULT_INTERNAL_FAILURE:
+		str_printfa(str, "FAIL\t%u", auth_request->id);
+		break;
+	case USERDB_RESULT_USER_UNKNOWN:
 		str_printfa(str, "NOTFOUND\t%u", auth_request->id);
-	else {
+		break;
+	case USERDB_RESULT_OK:
 		str_printfa(str, "USER\t%u\t", auth_request->id);
 		str_append(str, auth_stream_reply_export(reply));
+		break;
 	}
 
 	if (conn->listener->auth->verbose_debug)

Index: auth-request-handler.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-request-handler.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- auth-request-handler.c	7 Nov 2006 13:59:31 -0000	1.19
+++ auth-request-handler.c	9 Dec 2006 15:11:48 -0000	1.20
@@ -396,7 +396,8 @@
 	return TRUE;
 }
 
-static void userdb_callback(struct auth_stream_reply *reply,
+static void userdb_callback(enum userdb_result result,
+			    struct auth_stream_reply *reply,
 			    struct auth_request *request)
 {
         struct auth_request_handler *handler = request->context;
@@ -407,15 +408,21 @@
 	request->state = AUTH_REQUEST_STATE_FINISHED;
 
 	str = t_str_new(256);
-	if (reply == NULL)
+	switch (result) {
+	case USERDB_RESULT_INTERNAL_FAILURE:
+		str_printfa(str, "FAIL\t%u", request->id);
+		break;
+	case USERDB_RESULT_USER_UNKNOWN:
 		str_printfa(str, "NOTFOUND\t%u", request->id);
-	else {
+		break;
+	case USERDB_RESULT_OK:
 		if (request->master_user != NULL) {
 			auth_stream_reply_add(reply, "master_user",
 					      request->master_user);
 		}
 		str_printfa(str, "USER\t%u\t", request->id);
 		str_append(str, auth_stream_reply_export(reply));
+		break;
 	}
 	handler->master_callback(str_c(str), request->master);
 

Index: auth-request.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-request.c,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -d -r1.74 -r1.75
--- auth-request.c	3 Dec 2006 19:23:33 -0000	1.74
+++ auth-request.c	9 Dec 2006 15:11:48 -0000	1.75
@@ -564,24 +564,34 @@
 	}
 }
 
-void auth_request_userdb_callback(struct auth_stream_reply *reply,
+void auth_request_userdb_callback(enum userdb_result result,
+				  struct auth_stream_reply *reply,
 				  struct auth_request *request)
 {
-	if (reply == NULL && request->userdb->next != NULL) {
+	if (result != USERDB_RESULT_OK && request->userdb->next != NULL) {
 		/* try next userdb. */
+		if (result == USERDB_RESULT_INTERNAL_FAILURE)
+			request->userdb_internal_failure = TRUE;
+
 		request->userdb = request->userdb->next;
 		auth_request_lookup_user(request,
 					 request->private_callback.userdb);
 		return;
 	}
 
-	if (reply == NULL && request->client_pid != 0) {
-		/* this was actual login attempt */
+	if (request->userdb_internal_failure && result != USERDB_RESULT_OK) {
+		/* one of the userdb lookups failed. the user might have been
+		   in there, so this is an internal failure */
+		result = USERDB_RESULT_INTERNAL_FAILURE;
+	} else if (result == USERDB_RESULT_USER_UNKNOWN &&
+		   request->client_pid != 0) {
+		/* this was an actual login attempt, the user should
+		   have been found. */
 		auth_request_log_error(request, "userdb",
 				       "user not found from userdb");
 	}
 
-        request->private_callback.userdb(reply, request);
+        request->private_callback.userdb(result, reply, request);
 }
 
 void auth_request_lookup_user(struct auth_request *request,

Index: auth-request.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-request.h,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- auth-request.h	8 Nov 2006 20:22:08 -0000	1.29
+++ auth-request.h	9 Dec 2006 15:11:48 -0000	1.30
@@ -72,6 +72,7 @@
 	unsigned int passdb_failure:1;
 	unsigned int internal_failure:1;
 	unsigned int passdb_internal_failure:1;
+	unsigned int userdb_internal_failure:1;
 	unsigned int delayed_failure:1;
 	unsigned int accept_input:1;
 	unsigned int no_failure_delay:1;
@@ -154,7 +155,8 @@
 				  enum passdb_credentials credentials,
 				  const char *data,
 				  set_credentials_callback_t *callback);
-void auth_request_userdb_callback(struct auth_stream_reply *reply,
+void auth_request_userdb_callback(enum userdb_result result,
+				  struct auth_stream_reply *reply,
 				  struct auth_request *request);
 
 #endif

Index: auth-worker-client.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-worker-client.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- auth-worker-client.c	8 Nov 2006 20:22:08 -0000	1.27
+++ auth-worker-client.c	9 Dec 2006 15:11:48 -0000	1.28
@@ -298,16 +298,27 @@
 }
 
 static void
-lookup_user_callback(struct auth_stream_reply *reply,
+lookup_user_callback(enum userdb_result result,
+		     struct auth_stream_reply *reply,
 		     struct auth_request *auth_request)
 {
 	struct auth_worker_client *client = auth_request->context;
 	string_t *str;
 
-	str = t_str_new(64);
+	str = t_str_new(128);
 	str_printfa(str, "%u\t", auth_request->id);
-	if (reply != NULL)
+	switch (result) {
+	case USERDB_RESULT_INTERNAL_FAILURE:
+		str_append(str, "FAIL\t");
+		break;
+	case USERDB_RESULT_USER_UNKNOWN:
+		str_append(str, "NOTFOUND\t");
+		break;
+	case USERDB_RESULT_OK:
+		str_append(str, "OK\t");
 		str_append(str, auth_stream_reply_export(reply));
+		break;
+	}
 	str_append_c(str, '\n');
 
 	o_stream_send(client->output, str_data(str), str_len(str));

Index: userdb-blocking.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-blocking.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- userdb-blocking.c	24 Sep 2005 10:49:55 -0000	1.5
+++ userdb-blocking.c	9 Dec 2006 15:11:48 -0000	1.6
@@ -10,16 +10,23 @@
 
 static void user_callback(struct auth_request *request, const char *reply)
 {
-	struct auth_stream_reply *stream_reply;
+	struct auth_stream_reply *stream_reply = NULL;
+	enum userdb_result result;
 
-	if (*reply == '\0')
-		stream_reply = NULL;
-	else {
+	if (strncmp(reply, "FAIL\t", 5) == 0)
+		result = USERDB_RESULT_INTERNAL_FAILURE;
+	else if (strncmp(reply, "NOTFOUND\t", 9) == 0)
+		result = USERDB_RESULT_USER_UNKNOWN;
+	else if (strncmp(reply, "OK\t", 3) == 0) {
+		result = USERDB_RESULT_OK;
 		stream_reply = auth_stream_reply_init(request);
 		auth_stream_reply_import(stream_reply, reply);
+	} else {
+		result = USERDB_RESULT_INTERNAL_FAILURE;
+		i_error("BUG: auth-worker sent invalid user reply");
 	}
 
-        auth_request_userdb_callback(stream_reply, request);
+        auth_request_userdb_callback(result, stream_reply, request);
 }
 
 void userdb_blocking_lookup(struct auth_request *request)

Index: userdb-ldap.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-ldap.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- userdb-ldap.c	4 Nov 2006 20:22:31 -0000	1.42
+++ userdb-ldap.c	9 Dec 2006 15:11:48 -0000	1.43
@@ -138,32 +138,36 @@
 	struct auth_request *auth_request = urequest->auth_request;
 	LDAPMessage *entry;
 	struct auth_stream_reply *reply = NULL;
+	enum userdb_result result = USERDB_RESULT_INTERNAL_FAILURE;
 	int ret;
 
 	ret = ldap_result2error(conn->ld, res, 0);
 	if (ret != LDAP_SUCCESS) {
 		auth_request_log_error(auth_request, "ldap",
 			"ldap_search() failed: %s", ldap_err2string(ret));
-		urequest->userdb_callback(NULL, auth_request);
+		urequest->userdb_callback(result, NULL, auth_request);
 		return;
 	}
 
 	entry = res == NULL ? NULL : ldap_first_entry(conn->ld, res);
 	if (entry == NULL) {
 		if (res != NULL) {
+			result = USERDB_RESULT_USER_UNKNOWN;
 			auth_request_log_error(auth_request, "ldap",
 					       "Authenticated user not found");
 		}
 	} else {
 		reply = ldap_query_get_result(conn, entry, auth_request);
-		if (ldap_next_entry(conn->ld, entry) != NULL) {
+		if (ldap_next_entry(conn->ld, entry) == NULL)
+			result = USERDB_RESULT_OK;
+		else {
 			auth_request_log_error(auth_request, "ldap",
 				"Multiple replies found for user");
 			reply = NULL;
 		}
 	}
 
-	urequest->userdb_callback(reply, auth_request);
+	urequest->userdb_callback(result, reply, auth_request);
 	auth_request_unref(&auth_request);
 }
 

Index: userdb-passwd-file.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-passwd-file.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- userdb-passwd-file.c	20 Feb 2006 16:31:46 -0000	1.22
+++ userdb-passwd-file.c	9 Dec 2006 15:11:48 -0000	1.23
@@ -31,7 +31,7 @@
 
 	pu = db_passwd_file_lookup(module->pwf, auth_request);
 	if (pu == NULL) {
-		callback(NULL, auth_request);
+		callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request);
 		return;
 	}
 
@@ -65,7 +65,7 @@
 		t_pop();
 	}
 
-	callback(reply, auth_request);
+	callback(USERDB_RESULT_OK, reply, auth_request);
 }
 
 static struct userdb_module *

Index: userdb-passwd.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-passwd.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- userdb-passwd.c	16 Oct 2005 14:34:39 -0000	1.18
+++ userdb-passwd.c	9 Dec 2006 15:11:48 -0000	1.19
@@ -17,7 +17,7 @@
 	pw = getpwnam(auth_request->user);
 	if (pw == NULL) {
 		auth_request_log_info(auth_request, "passwd", "unknown user");
-		callback(NULL, auth_request);
+		callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request);
 		return;
 	}
 
@@ -36,7 +36,7 @@
 	auth_stream_reply_add(reply, "gid", dec2str(pw->pw_gid));
 	auth_stream_reply_add(reply, "home", pw->pw_dir);
 
-	callback(reply, auth_request);
+	callback(USERDB_RESULT_OK, reply, auth_request);
 }
 
 struct userdb_module_interface userdb_passwd = {

Index: userdb-prefetch.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-prefetch.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- userdb-prefetch.c	9 Apr 2006 13:54:46 -0000	1.3
+++ userdb-prefetch.c	9 Dec 2006 15:11:48 -0000	1.4
@@ -29,7 +29,7 @@
 			auth_request_log_info(auth_request, "prefetch",
 				"passdb didn't return userdb entries");
 		}
-		callback(NULL, auth_request);
+		callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request);
 		return;
 	}
 
@@ -84,7 +84,7 @@
 	}
 
 	if (uid == (uid_t)-1 || gid == (gid_t)-1)
-		callback(NULL, auth_request);
+		callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request);
 	else {
 		struct auth_stream_reply *reply;
 
@@ -92,7 +92,7 @@
 		   exported they are already in escaped form in the string. */
 		reply = auth_stream_reply_init(auth_request);
 		auth_stream_reply_import(reply, str_c(str));
-		callback(reply, auth_request);
+		callback(USERDB_RESULT_OK, reply, auth_request);
 	}
 	t_pop();
 }

Index: userdb-sql.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-sql.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- userdb-sql.c	31 May 2006 11:03:53 -0000	1.15
+++ userdb-sql.c	9 Dec 2006 15:11:48 -0000	1.16
@@ -78,24 +78,29 @@
 	return reply;
 }
 
-static void sql_query_callback(struct sql_result *result, void *context)
+static void sql_query_callback(struct sql_result *sql_result, void *context)
 {
 	struct userdb_sql_request *sql_request = context;
 	struct auth_request *auth_request = sql_request->auth_request;
 	struct auth_stream_reply *reply = NULL;
+	enum userdb_result result = USERDB_RESULT_INTERNAL_FAILURE;
 	int ret;
 
-	ret = sql_result_next_row(result);
+	ret = sql_result_next_row(sql_result);
 	if (ret < 0) {
 		auth_request_log_error(auth_request, "sql",
-			"User query failed: %s", sql_result_get_error(result));
+				       "User query failed: %s",
+				       sql_result_get_error(sql_result));
 	} else if (ret == 0) {
+		result = USERDB_RESULT_USER_UNKNOWN;
 		auth_request_log_info(auth_request, "sql", "User not found");
 	} else {
-                reply = sql_query_get_result(result, auth_request);
+		reply = sql_query_get_result(sql_result, auth_request);
+		if (reply != NULL)
+			result = USERDB_RESULT_OK;
 	}
 
-	sql_request->callback(reply, auth_request);
+	sql_request->callback(result, reply, auth_request);
 	auth_request_unref(&auth_request);
 	i_free(sql_request);
 }

Index: userdb-static.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-static.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- userdb-static.c	10 Sep 2006 12:48:12 -0000	1.21
+++ userdb-static.c	9 Dec 2006 15:11:48 -0000	1.22
@@ -49,7 +49,7 @@
 		auth_stream_reply_add(reply, args[i], value);
 	}
 
-	callback(reply, auth_request);
+	callback(USERDB_RESULT_OK, reply, auth_request);
 	t_pop();
 }
 

Index: userdb-vpopmail.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb-vpopmail.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- userdb-vpopmail.c	22 Jan 2006 13:55:20 -0000	1.21
+++ userdb-vpopmail.c	9 Dec 2006 15:11:48 -0000	1.22
@@ -50,7 +50,7 @@
 
 	vpw = vpopmail_lookup_vqp(auth_request, vpop_user, vpop_domain);
 	if (vpw == NULL) {
-		callback(NULL, auth_request);
+		callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request);
 		return;
 	}
 
@@ -59,7 +59,7 @@
 	if (vget_assign(vpop_domain, NULL, 0, &uid, &gid) == NULL) {
 		auth_request_log_info(auth_request, "vpopmail",
 				      "vget_assign(%s) failed", vpop_domain);
-		callback(NULL, auth_request);
+		callback(USERDB_RESULT_INTERNAL_FAILURE, NULL, auth_request);
 		return;
 	}
 
@@ -72,14 +72,16 @@
 			auth_request_log_error(auth_request, "vpopmail",
 					       "make_user_dir(%s, %s) failed",
 					       vpop_user, vpop_domain);
-			callback(NULL, auth_request);
+			callback(USERDB_RESULT_INTERNAL_FAILURE,
+				 NULL, auth_request);
 			return;
 		}
 
 		/* get the user again so pw_dir is visible */
 		vpw = vauth_getpw(vpop_user, vpop_domain);
 		if (vpw == NULL) {
-			callback(NULL, auth_request);
+			callback(USERDB_RESULT_INTERNAL_FAILURE,
+				 NULL, auth_request);
 			return;
 		}
 	}
@@ -90,7 +92,7 @@
 	auth_stream_reply_add(reply, "gid", dec2str(gid));
 	auth_stream_reply_add(reply, "home", vpw->pw_dir);
 
-	callback(reply, auth_request);
+	callback(USERDB_RESULT_OK, reply, auth_request);
 }
 
 struct userdb_module_interface userdb_vpopmail = {

Index: userdb.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- userdb.h	13 Jan 2006 20:25:57 -0000	1.25
+++ userdb.h	9 Dec 2006 15:11:48 -0000	1.26
@@ -5,7 +5,15 @@
 
 struct auth_request;
 
-typedef void userdb_callback_t(struct auth_stream_reply *reply,
+enum userdb_result {
+	USERDB_RESULT_INTERNAL_FAILURE = -1,
+	USERDB_RESULT_USER_UNKNOWN = -2,
+
+	USERDB_RESULT_OK = 1
+};
+
+typedef void userdb_callback_t(enum userdb_result result,
+			       struct auth_stream_reply *reply,
 			       struct auth_request *request);
 
 struct userdb_module {



More information about the dovecot-cvs mailing list