dovecot-2.0: Added support for userdb lookup to fail with a reas...

dovecot at dovecot.org dovecot at dovecot.org
Wed Mar 31 19:22:29 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/2e08ce368bc0
changeset: 11018:2e08ce368bc0
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Mar 31 19:21:09 2010 +0300
description:
Added support for userdb lookup to fail with a reason (many API changes).

diffstat:

 doc/auth-protocol.txt                  |   7 +-
 src/doveadm/doveadm-auth.c             |  11 ++-
 src/doveadm/doveadm-mail.c             |   9 +-
 src/dsync/dsync.c                      |   8 +-
 src/imap/main.c                        |  82 +++++++++++++++++++--------
 src/lib-auth/auth-master.c             |  48 +++++++++++----
 src/lib-auth/auth-master.h             |   4 +-
 src/lib-master/master-auth.c           |   8 +--
 src/lib-master/master-auth.h           |   4 +
 src/lib-master/master-login-auth.c     |  39 ++++++++----
 src/lib-master/master-login-auth.h     |   2 +-
 src/lib-master/master-login.c          |  17 ++++-
 src/lib-master/master-login.h          |   6 +-
 src/lib-storage/mail-storage-service.c |  66 ++++++++++++++--------
 src/lib-storage/mail-storage-service.h |  11 +--
 src/lmtp/commands.c                    |  22 ++++---
 src/login-common/client-common-auth.c  |   5 +
 src/login-common/sasl-server.c         |  15 +++--
 src/login-common/sasl-server.h         |   1 +
 src/pop3/main.c                        |  12 +++-
 20 files changed, 253 insertions(+), 124 deletions(-)

diffs (truncated from 925 to 300 lines):

diff -r ce7ed594d99e -r 2e08ce368bc0 doc/auth-protocol.txt
--- a/doc/auth-protocol.txt	Wed Mar 31 19:18:01 2010 +0300
+++ b/doc/auth-protocol.txt	Wed Mar 31 19:21:09 2010 +0300
@@ -164,7 +164,7 @@
  M: "USER" TAB <id> TAB <userid> TAB service=<service> [TAB <parameters>]
 
  S: "NOTFOUND" TAB <id>
- S: "FAIL" TAB <id> TAB <error message>
+ S: "FAIL" TAB <id> [TAB <parameters>]
  S: "USER" TAB <id> TAB <userid> [TAB <parameters>]
 
 Master commands can request information about existing authentication
@@ -180,7 +180,10 @@
 
 FAIL reply means an internal error occurred. Usually either a configuration
 mistake or temporary error caused by lost resource (eg. database down).
-Also unknown request IDs are reported as FAILs.
+Also unknown request IDs are reported as FAILs. Currently the only
+specified parameter is "reason", which is used when user is wanted to be
+put into "temporarily disabled" state and the reason string will be shown
+to user on login or to LMTP RCPT TO reply.
 
 USER reply is sent if request succeeded. It can return parameters:
 
diff -r ce7ed594d99e -r 2e08ce368bc0 src/doveadm/doveadm-auth.c
--- a/src/doveadm/doveadm-auth.c	Wed Mar 31 19:18:01 2010 +0300
+++ b/src/doveadm/doveadm-auth.c	Wed Mar 31 19:21:09 2010 +0300
@@ -37,9 +37,14 @@
 	conn = auth_master_init(auth_socket_path, 0);
 	ret = auth_master_user_lookup(conn, input->username, &input->info,
 				      pool, &username, &fields);
-	if (ret < 0)
-		i_fatal("userdb lookup failed");
-	else if (ret == 0) {
+	if (ret < 0) {
+		if (fields[0] == NULL)
+			i_fatal("userdb lookup failed for %s", input->username);
+		else {
+			i_fatal("userdb lookup failed for %s: %s",
+				input->username, fields[0]);
+		}
+	} else if (ret == 0) {
 		printf("userdb lookup: user %s doesn't exist\n",
 		       input->username);
 	} else {
diff -r ce7ed594d99e -r 2e08ce368bc0 src/doveadm/doveadm-mail.c
--- a/src/doveadm/doveadm-mail.c	Wed Mar 31 19:18:01 2010 +0300
+++ b/src/doveadm/doveadm-mail.c	Wed Mar 31 19:21:09 2010 +0300
@@ -99,11 +99,12 @@
 		return ret;
 	}
 
-	if (mail_storage_service_next(storage_service, service_user,
-				      &mail_user, &error) < 0) {
-		*error_r = t_strdup_printf("User init failed: %s", error);
+	ret = mail_storage_service_next(storage_service, service_user,
+					&mail_user);
+	if (ret < 0) {
+		*error_r = "User init failed";
 		mail_storage_service_user_free(&service_user);
-		return -2;
+		return ret;
 	}
 
 	cmd(mail_user, args);
diff -r ce7ed594d99e -r 2e08ce368bc0 src/dsync/dsync.c
--- a/src/dsync/dsync.c	Wed Mar 31 19:18:01 2010 +0300
+++ b/src/dsync/dsync.c	Wed Mar 31 19:21:09 2010 +0300
@@ -147,8 +147,8 @@
 					&service_user, &error) <= 0)
 		i_fatal("User lookup failed: %s", error);
 	if (mail_storage_service_next(storage_service, service_user,
-				      &mail_user, &error) < 0)
-		i_fatal("User init failed: %s", error);
+				      &mail_user) < 0)
+		i_fatal("User init failed");
 
 	if (mirror_cmd != NULL) {
 		/* user initialization may exec doveconf, so do our forking
@@ -170,8 +170,8 @@
 		if (settings_parse_line(set_parser, set_line) < 0)
 			i_unreached();
 		if (mail_storage_service_next(storage_service, service_user,
-					      &mail_user2, &error) < 0)
-			i_fatal("User init failed: %s", error);
+					      &mail_user2) < 0)
+			i_fatal("User init failed");
 
 		worker2 = dsync_worker_init_local(mail_user2, alt_char);
 
diff -r ce7ed594d99e -r 2e08ce368bc0 src/imap/main.c
--- a/src/imap/main.c	Wed Mar 31 19:18:01 2010 +0300
+++ b/src/imap/main.c	Wed Mar 31 19:21:09 2010 +0300
@@ -15,6 +15,7 @@
 #include "master-login.h"
 #include "mail-user.h"
 #include "mail-storage-service.h"
+#include "imap-resp-code.h"
 #include "imap-commands.h"
 #include "imap-fetch.h"
 
@@ -104,52 +105,72 @@
 	}
 }
 
+struct client_input {
+	const char *tag;
+
+	const unsigned char *input;
+	unsigned int input_size;
+	bool send_untagged_capability;
+};
+
+static void
+client_parse_input(const unsigned char *data, unsigned int len,
+		   struct client_input *input_r)
+{
+	unsigned int taglen;
+
+	i_assert(len > 0);
+
+	memset(input_r, 0, sizeof(*input_r));
+
+	if (data[0] == '1')
+		input_r->send_untagged_capability = TRUE;
+	data++; len--;
+
+	input_r->tag = t_strndup(data, len);
+	taglen = strlen(input_r->tag) + 1;
+
+	if (len > taglen) {
+		input_r->input = data + taglen;
+		input_r->input_size = len - taglen;
+	}
+}
+
 static void client_add_input(struct client *client, const buffer_t *buf)
 {
 	struct ostream *output;
-	const char *tag;
-	unsigned int data_pos;
-	bool send_untagged_capability = FALSE;
+	struct client_input input;
 
 	if (buf != NULL && buf->used > 0) {
-		tag = t_strndup(buf->data, buf->used);
-		switch (*tag) {
-		case '0':
-			tag++;
-			break;
-		case '1':
-			send_untagged_capability = TRUE;
-			tag++;
-			break;
-		}
-		data_pos = strlen(tag) + 1;
-		if (data_pos > buf->used &&
-		    !i_stream_add_data(client->input,
-				       CONST_PTR_OFFSET(buf->data, data_pos),
-				       buf->used - data_pos))
+		client_parse_input(buf->data, buf->used, &input);
+		if (input.input_size > 0 &&
+		    !i_stream_add_data(client->input, input.input,
+				       input.input_size))
 			i_panic("Couldn't add client input to stream");
 	} else {
 		/* IMAPLOGINTAG environment is compatible with mailfront */
-		tag = getenv("IMAPLOGINTAG");
+		memset(&input, 0, sizeof(input));
+		input.tag = getenv("IMAPLOGINTAG");
 	}
 
 	output = client->output;
 	o_stream_ref(output);
 	o_stream_cork(output);
-	if (tag == NULL) {
+	if (input.tag == NULL) {
 		client_send_line(client, t_strconcat(
 			"* PREAUTH [CAPABILITY ",
 			str_c(client->capability_string), "] "
 			"Logged in as ", client->user->username, NULL));
-	} else if (send_untagged_capability) {
+	} else if (input.send_untagged_capability) {
 		/* client doesn't seem to understand tagged capabilities. send
 		   untagged instead and hope that it works. */
 		client_send_line(client, t_strconcat("* CAPABILITY ",
 			str_c(client->capability_string), NULL));
-		client_send_line(client, t_strconcat(tag, " OK Logged in", NULL));
+		client_send_line(client,
+				 t_strconcat(input.tag, " OK Logged in", NULL));
 	} else {
 		client_send_line(client, t_strconcat(
-			tag, " OK [CAPABILITY ",
+			input.tag, " OK [CAPABILITY ",
 			str_c(client->capability_string), "] Logged in", NULL));
 	}
 	(void)client_handle_input(client);
@@ -241,6 +262,18 @@
 	}
 }
 
+static void login_client_failed(const struct master_login_client *client,
+				const char *errormsg)
+{
+	struct client_input input;
+	const char *msg;
+
+	client_parse_input(client->data, client->auth_req.data_size, &input);
+	msg = t_strdup_printf("%s NO ["IMAP_RESP_CODE_UNAVAILABLE"] %s\r\n",
+			      input.tag, errormsg);
+	(void)write(client->fd, msg, strlen(msg));
+}
+
 static void client_connected(const struct master_service_connection *conn)
 {
 	if (master_login == NULL) {
@@ -315,7 +348,8 @@
 	} else {
 		master_login = master_login_init(master_service, "auth-master",
 						 postlogin_socket_path,
-						 login_client_connected);
+						 login_client_connected,
+						 login_client_failed);
 		io_loop_set_running(current_ioloop);
 	}
 
diff -r ce7ed594d99e -r 2e08ce368bc0 src/lib-auth/auth-master.c
--- a/src/lib-auth/auth-master.c	Wed Mar 31 19:18:01 2010 +0300
+++ b/src/lib-auth/auth-master.c	Wed Mar 31 19:21:09 2010 +0300
@@ -50,6 +50,7 @@
 
 struct auth_master_lookup_ctx {
 	struct auth_master_connection *conn;
+	const char *user;
 	const char *expected_reply;
 	int return_value;
 
@@ -135,19 +136,21 @@
 	return 0;
 }
 
-static int parse_reply(struct auth_master_connection *conn,
-		       const char *cmd, const char *const *args,
-		       const char *expected_reply)
+static int parse_reply(const char *cmd, const char *const *args,
+		       const char *expected_reply, const char *user, bool debug)
 {
-	io_loop_stop(conn->ioloop);
-
 	if (strcmp(cmd, expected_reply) == 0)
 		return 1;
 	if (strcmp(cmd, "NOTFOUND") == 0)
 		return 0;
 	if (strcmp(cmd, "FAIL") == 0) {
-		i_error("Lookup failed: %s",
-			*args != NULL ? *args : "Internal failure");
+		if (*args == NULL) {
+			i_error("user %s: Auth %s lookup failed",
+				user, expected_reply);
+		} else if (debug) {
+			i_debug("user %s: Auth %s lookup returned temporary failure: %s",
+				user, expected_reply, *args);
+		}
 		return -1;
 	}
 	i_error("Unknown reply: %s", cmd);
@@ -159,17 +162,31 @@
 {
 	struct auth_master_lookup_ctx *ctx = context;
 	unsigned int i, len;
+	bool debug = (ctx->conn->flags & AUTH_MASTER_FLAG_DEBUG) != 0;
+
+	io_loop_stop(ctx->conn->ioloop);
 
 	ctx->return_value =
-		parse_reply(ctx->conn, cmd, args, ctx->expected_reply);
-	if (ctx->return_value > 0) {
-		len = str_array_length(args);
+		parse_reply(cmd, args, ctx->expected_reply, ctx->user, debug);
+
+	len = str_array_length(args);
+	if (ctx->return_value >= 0) {
 		ctx->fields = p_new(ctx->pool, const char *, len + 1);
 		for (i = 0; i < len; i++)
 			ctx->fields[i] = p_strdup(ctx->pool, args[i]);
-		if ((ctx->conn->flags & AUTH_MASTER_FLAG_DEBUG) != 0)
-			i_debug("auth input: %s", t_strarray_join(args, " "));
+	} else {
+		/* put the reason string into first field */
+		ctx->fields = p_new(ctx->pool, const char *, 2);
+		for (i = 0; i < len; i++) {
+			if (strncmp(args[i], "reason=", 7) == 0) {
+				ctx->fields[0] =
+					p_strdup(ctx->pool, args[i] + 7);
+				break;
+			}
+		}
 	}
+	if (debug)
+		i_debug("auth input: %s", t_strarray_join(args, " "));


More information about the dovecot-cvs mailing list