changeset 5371:fdcea7e3cf0c HEAD

If doing a plain userdb lookup with userdb static, verify the user's existence from passdb first, unless allow_all_users=yes
author Timo Sirainen <tss@iki.fi>
date Wed, 21 Mar 2007 22:12:59 +0200
parents c1d53e221cb2
children 56cb17817e06
files dovecot-example.conf src/auth/auth-master-connection.c src/auth/userdb-static.c
diffstat 3 files changed, 85 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Wed Mar 21 22:06:19 2007 +0200
+++ b/dovecot-example.conf	Wed Mar 21 22:12:59 2007 +0200
@@ -909,6 +909,13 @@
     #
     #  args = uid=500 gid=500 home=/var/mail/%u
     #
+    # If you use deliver, it needs to look up users only from the userdb. This
+    # of course doesn't work with static because there is no list of users.
+    # Normally static userdb handles this by doing a passdb lookup. This works
+    # with most passdbs, with PAM being the most notable exception. If you do
+    # the user verification another way, you can add allow_all_users=yes to
+    # the args in which case the passdb lookup is skipped.
+    #
     #args =
   #}
 
--- a/src/auth/auth-master-connection.c	Wed Mar 21 22:06:19 2007 +0200
+++ b/src/auth/auth-master-connection.c	Wed Mar 21 22:12:59 2007 +0200
@@ -142,6 +142,7 @@
 		return FALSE;
 	}
 
+	auth_request->state = AUTH_REQUEST_STATE_USERDB;
 	auth_request_lookup_user(auth_request, user_callback);
 	return TRUE;
 }
--- a/src/auth/userdb-static.c	Wed Mar 21 22:06:19 2007 +0200
+++ b/src/auth/userdb-static.c	Wed Mar 21 22:12:59 2007 +0200
@@ -11,14 +11,21 @@
 
 #include <stdlib.h>
 
+struct static_context {
+	userdb_callback_t *callback, *old_callback;
+	void *old_context;
+};
+
 struct static_userdb_module {
 	struct userdb_module module;
 
 	ARRAY_DEFINE(template, const char *);
+
+	unsigned int allow_all_users:1;
 };
 
-static void static_lookup(struct auth_request *auth_request,
-			  userdb_callback_t *callback)
+static void static_lookup_real(struct auth_request *auth_request,
+			       userdb_callback_t *callback)
 {
 	struct userdb_module *_module = auth_request->userdb->userdb;
 	struct static_userdb_module *module =
@@ -53,6 +60,70 @@
 	t_pop();
 }
 
+static void
+static_credentials_callback(enum passdb_result result,
+			    const char *password __attr_unused__,
+			    struct auth_request *auth_request)
+{
+	struct static_context *ctx = auth_request->context;
+
+	auth_request->private_callback.userdb = ctx->old_callback;
+	auth_request->context = ctx->old_context;
+	auth_request->state = AUTH_REQUEST_STATE_USERDB;
+
+	switch (result) {
+	case PASSDB_RESULT_OK:
+		static_lookup_real(auth_request, ctx->callback);
+		break;
+	case PASSDB_RESULT_USER_UNKNOWN:
+	case PASSDB_RESULT_USER_DISABLED:
+	case PASSDB_RESULT_PASS_EXPIRED:
+		ctx->callback(USERDB_RESULT_USER_UNKNOWN, NULL, auth_request);
+		break;
+	case PASSDB_RESULT_SCHEME_NOT_AVAILABLE:
+		auth_request_log_error(auth_request, "static",
+			"passdb doesn't support lookups, "
+			"can't verify user's existence");
+		/* fall through */
+	default:
+		ctx->callback(USERDB_RESULT_INTERNAL_FAILURE,
+			      NULL, auth_request);
+		break;
+	}
+
+	i_free(ctx);
+}
+
+static void static_lookup(struct auth_request *auth_request,
+			  userdb_callback_t *callback)
+{
+	struct userdb_module *_module = auth_request->userdb->userdb;
+	struct static_userdb_module *module =
+		(struct static_userdb_module *)_module;
+	struct static_context *ctx;
+
+	if (!auth_request->successful && !module->allow_all_users) {
+		/* this is a userdb-only lookup. we need to know if this
+		   users exists or not. use a passdb lookup to do that.
+		   if the passdb doesn't support returning credentials, this
+		   will of course fail.. */
+		ctx = i_new(struct static_context, 1);
+		ctx->old_callback = auth_request->private_callback.userdb;
+		ctx->old_context = auth_request->context;
+		ctx->callback = callback;
+
+		i_assert(auth_request->state == AUTH_REQUEST_STATE_USERDB);
+		auth_request->state = AUTH_REQUEST_STATE_MECH_CONTINUE;
+
+		auth_request->context = ctx;
+		auth_request_lookup_credentials(auth_request,
+						PASSDB_CREDENTIALS_CRYPT,
+						static_credentials_callback);
+	} else {
+		static_lookup_real(auth_request, callback);
+	}
+}
+
 static struct userdb_module *
 static_preinit(struct auth_userdb *auth_userdb, const char *args)
 {
@@ -94,6 +165,10 @@
 					value);
 			}
 			value = dec2str(gid);
+		} else if (strcmp(key, "allow_all_users") == 0) {
+			module->allow_all_users = value == NULL ||
+				strcasecmp(value, "yes") == 0;
+			continue;
 		} else if (*key == '\0') {
 			i_fatal("Status userdb: Empty key (=%s)", value);
 		}