dovecot-2.0: auth: If userdb lookup returns tempfail, return rea...

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/b40ec803421e
changeset: 11019:b40ec803421e
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Mar 31 19:22:19 2010 +0300
description:
auth: If userdb lookup returns tempfail, return reason field (if any).

diffstat:

 src/auth/auth-master-connection.c |   6 +++
 src/auth/auth-request-handler.c   |   7 +++
 src/auth/auth-stream.c            |  53 ++++++++++++++++++++++----
 src/auth/auth-stream.h            |   3 +
 src/auth/auth-worker-client.c     |  21 ++++++++++
 src/auth/passdb-blocking.c        |   5 ++-
 src/auth/userdb-blocking.c        |  18 ++++++--
 7 files changed, 99 insertions(+), 14 deletions(-)

diffs (254 lines):

diff -r 2e08ce368bc0 -r b40ec803421e src/auth/auth-master-connection.c
--- a/src/auth/auth-master-connection.c	Wed Mar 31 19:21:09 2010 +0300
+++ b/src/auth/auth-master-connection.c	Wed Mar 31 19:22:19 2010 +0300
@@ -164,6 +164,7 @@
 	struct auth_master_connection *conn = auth_request->context;
 	struct auth_stream_reply *reply = auth_request->userdb_reply;
 	string_t *str;
+	const char *value;
 
 	if (auth_request->userdb_lookup_failed)
 		result = USERDB_RESULT_INTERNAL_FAILURE;
@@ -172,6 +173,11 @@
 	switch (result) {
 	case USERDB_RESULT_INTERNAL_FAILURE:
 		str_printfa(str, "FAIL\t%u", auth_request->id);
+		if (auth_request->userdb_lookup_failed) {
+			value = auth_stream_reply_find(reply, "reason");
+			if (value != NULL)
+				str_printfa(str, "\treason=%s", value);
+		}
 		break;
 	case USERDB_RESULT_USER_UNKNOWN:
 		str_printfa(str, "NOTFOUND\t%u", auth_request->id);
diff -r 2e08ce368bc0 -r b40ec803421e src/auth/auth-request-handler.c
--- a/src/auth/auth-request-handler.c	Wed Mar 31 19:21:09 2010 +0300
+++ b/src/auth/auth-request-handler.c	Wed Mar 31 19:22:19 2010 +0300
@@ -475,6 +475,7 @@
 {
         struct auth_request_handler *handler = request->context;
 	struct auth_stream_reply *reply;
+	const char *value;
 
 	i_assert(request->state == AUTH_REQUEST_STATE_USERDB);
 
@@ -488,6 +489,12 @@
 	case USERDB_RESULT_INTERNAL_FAILURE:
 		auth_stream_reply_add(reply, "FAIL", NULL);
 		auth_stream_reply_add(reply, NULL, dec2str(request->id));
+		if (request->userdb_lookup_failed) {
+			value = auth_stream_reply_find(request->userdb_reply,
+						       "reason");
+			if (value != NULL)
+				auth_stream_reply_add(reply, "reason", value);
+		}
 		break;
 	case USERDB_RESULT_USER_UNKNOWN:
 		auth_stream_reply_add(reply, "NOTFOUND", NULL);
diff -r 2e08ce368bc0 -r b40ec803421e src/auth/auth-stream.c
--- a/src/auth/auth-stream.c	Wed Mar 31 19:21:09 2010 +0300
+++ b/src/auth/auth-stream.c	Wed Mar 31 19:22:19 2010 +0300
@@ -40,7 +40,9 @@
 	}
 }
 
-void auth_stream_reply_remove(struct auth_stream_reply *reply, const char *key)
+static bool
+auth_stream_reply_find_area(struct auth_stream_reply *reply, const char *key,
+			    unsigned int *idx_r, unsigned int *len_r)
 {
 	const char *str = str_c(reply->str);
 	unsigned int i, start, key_len = strlen(key);
@@ -49,21 +51,56 @@
 	while (str[i] != '\0') {
 		start = i;
 		for (; str[i] != '\0'; i++) {
-			if (str[i] == '\t') {
-				i++;
+			if (str[i] == '\t')
 				break;
-			}
 		}
 
 		if (strncmp(str+start, key, key_len) == 0 &&
 		    (str[start+key_len] == '=' ||
 		     str[start+key_len] == '\t' ||
 		     str[start+key_len] == '\0')) {
-			str_delete(reply->str, start, i-start);
-			if (str_len(reply->str) == start && start > 0)
-				str_delete(reply->str, start - 1, 1);
-			break;
+			*idx_r = start;
+			*len_r = i - start;
+			return TRUE;
 		}
+		if (str[i] == '\t')
+			i++;
+	}
+	return FALSE;
+}
+
+void auth_stream_reply_remove(struct auth_stream_reply *reply, const char *key)
+{
+	unsigned int idx, len;
+
+	if (!auth_stream_reply_find_area(reply, key, &idx, &len))
+		return;
+
+	if (str_len(reply->str) < idx + len) {
+		/* remove also trailing tab */
+		len++;
+	} else if (str_len(reply->str) == idx + len && idx > 0) {
+		/* removing last item, remove preceding tab */
+		len++;
+		idx--;
+	}
+
+	str_delete(reply->str, idx, len);
+}
+
+const char *auth_stream_reply_find(struct auth_stream_reply *reply,
+				   const char *key)
+{
+	unsigned int idx, len, keylen;
+
+	if (!auth_stream_reply_find_area(reply, key, &idx, &len))
+		return NULL;
+	else {
+		keylen = strlen(key);
+		i_assert(len > keylen);
+		idx += keylen + 1;
+		len -= keylen + 1;
+		return t_strndup(str_c(reply->str) + idx, len);
 	}
 }
 
diff -r 2e08ce368bc0 -r b40ec803421e src/auth/auth-stream.h
--- a/src/auth/auth-stream.h	Wed Mar 31 19:21:09 2010 +0300
+++ b/src/auth/auth-stream.h	Wed Mar 31 19:22:19 2010 +0300
@@ -9,6 +9,9 @@
 void auth_stream_reply_reset(struct auth_stream_reply *reply);
 void auth_stream_reply_remove(struct auth_stream_reply *reply, const char *key);
 
+const char *auth_stream_reply_find(struct auth_stream_reply *reply,
+				   const char *key);
+
 void auth_stream_reply_import(struct auth_stream_reply *reply, const char *str);
 const char *auth_stream_reply_export(struct auth_stream_reply *reply);
 bool auth_stream_is_empty(struct auth_stream_reply *reply);
diff -r 2e08ce368bc0 -r b40ec803421e src/auth/auth-worker-client.c
--- a/src/auth/auth-worker-client.c	Wed Mar 31 19:21:09 2010 +0300
+++ b/src/auth/auth-worker-client.c	Wed Mar 31 19:22:19 2010 +0300
@@ -98,6 +98,7 @@
 	struct auth_worker_client *client = request->context;
 	struct auth_stream_reply *reply;
 	string_t *str;
+	const char *value;
 
 	if (request->passdb_failure && result == PASSDB_RESULT_OK)
 		result = PASSDB_RESULT_PASSWORD_MISMATCH;
@@ -127,6 +128,13 @@
 				auth_stream_reply_export(request->extra_cache_fields);
 			auth_stream_reply_import(reply, fields);
 		}
+	} else if (request->userdb_lookup_failed) {
+		value = auth_stream_reply_find(request->extra_fields, "reason");
+		if (value != NULL) {
+			auth_stream_reply_add(reply, NULL, "");
+			auth_stream_reply_add(reply, NULL, "");
+			auth_stream_reply_add(reply, "reason", value);
+		}
 	}
 	str = auth_stream_reply_get_str(reply);
 	str_append_c(str, '\n');
@@ -200,6 +208,7 @@
 	struct auth_worker_client *client = request->context;
 	struct auth_stream_reply *reply;
 	string_t *str;
+	const char *value;
 
 	if (request->passdb_failure && result == PASSDB_RESULT_OK)
 		result = PASSDB_RESULT_PASSWORD_MISMATCH;
@@ -211,6 +220,12 @@
 		auth_stream_reply_add(reply, "FAIL", NULL);
 		auth_stream_reply_add(reply, NULL,
 				      t_strdup_printf("%d", result));
+		value = auth_stream_reply_find(request->extra_fields, "reason");
+		if (request->userdb_lookup_failed && value != NULL) {
+			auth_stream_reply_add(reply, NULL, "");
+			auth_stream_reply_add(reply, NULL, "");
+			auth_stream_reply_add(reply, "reason", value);
+		}
 	} else {
 		auth_stream_reply_add(reply, "OK", NULL);
 		auth_stream_reply_add(reply, NULL, request->user);
@@ -356,6 +371,7 @@
 	struct auth_worker_client *client = auth_request->context;
 	struct auth_stream_reply *reply = auth_request->userdb_reply;
 	string_t *str;
+	const char *value;
 
 	if (auth_request->userdb_lookup_failed)
 		result = USERDB_RESULT_INTERNAL_FAILURE;
@@ -365,6 +381,11 @@
 	switch (result) {
 	case USERDB_RESULT_INTERNAL_FAILURE:
 		str_append(str, "FAIL\t");
+		if (auth_request->userdb_lookup_failed) {
+			value = auth_stream_reply_find(reply, "reason");
+			if (value != NULL)
+				str_printfa(str, "reason=%s", value);
+		}
 		break;
 	case USERDB_RESULT_USER_UNKNOWN:
 		str_append(str, "NOTFOUND\t");
diff -r 2e08ce368bc0 -r b40ec803421e src/auth/passdb-blocking.c
--- a/src/auth/passdb-blocking.c	Wed Mar 31 19:21:09 2010 +0300
+++ b/src/auth/passdb-blocking.c	Wed Mar 31 19:22:19 2010 +0300
@@ -48,7 +48,10 @@
 			/* internal failure most likely */
 			return ret;
 		} else if (args[3] != NULL) {
-			auth_request_set_field(request, "user", args[2], NULL);
+			if (*args[2] != '\0') {
+				auth_request_set_field(request, "user",
+						       args[2], NULL);
+			}
 			auth_worker_reply_parse_args(request, args + 3);
 			return ret;
 		}
diff -r 2e08ce368bc0 -r b40ec803421e src/auth/userdb-blocking.c
--- a/src/auth/userdb-blocking.c	Wed Mar 31 19:21:09 2010 +0300
+++ b/src/auth/userdb-blocking.c	Wed Mar 31 19:22:19 2010 +0300
@@ -19,18 +19,26 @@
 {
 	struct auth_request *request = context;
 	enum userdb_result result;
+	const char *args;
 
-	if (strncmp(reply, "FAIL\t", 5) == 0)
+	if (strncmp(reply, "FAIL\t", 5) == 0) {
 		result = USERDB_RESULT_INTERNAL_FAILURE;
-	else if (strncmp(reply, "NOTFOUND\t", 9) == 0)
+		args = reply + 5;
+	} else if (strncmp(reply, "NOTFOUND\t", 9) == 0) {
 		result = USERDB_RESULT_USER_UNKNOWN;
-	else if (strncmp(reply, "OK\t", 3) == 0) {
+		args = reply + 9;
+	} else if (strncmp(reply, "OK\t", 3) == 0) {
 		result = USERDB_RESULT_OK;
-		request->userdb_reply = auth_stream_reply_init(request->pool);
-		auth_stream_reply_import(request->userdb_reply, reply + 3);
+		args = reply + 3;
 	} else {
 		result = USERDB_RESULT_INTERNAL_FAILURE;
 		i_error("BUG: auth-worker sent invalid user reply");
+		args = "";
+	}
+
+	if (*args != '\0') {
+		request->userdb_reply = auth_stream_reply_init(request->pool);
+		auth_stream_reply_import(request->userdb_reply, args);
 	}
 
         auth_request_userdb_callback(result, request);


More information about the dovecot-cvs mailing list