changeset 2765:428bba43a387 HEAD

Authentication OK and FAIL replies can now contain extra fields from passdb. Implemented this for sql passdb. Special fields are "nologin" (user can't actually login) and "nodelay" (don't delay failure replies).
author Timo Sirainen <tss@iki.fi>
date Mon, 18 Oct 2004 04:00:42 +0300
parents 3cc4ebb5f42d
children 26a091f3add6
files src/auth/auth-client-connection.c src/auth/mech.c src/auth/mech.h src/auth/passdb-sql.c
diffstat 4 files changed, 78 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/auth-client-connection.c	Mon Oct 18 02:36:08 2004 +0300
+++ b/src/auth/auth-client-connection.c	Mon Oct 18 04:00:42 2004 +0300
@@ -73,13 +73,20 @@
 			str_append(str, "\tresp=");
 			base64_encode(reply, reply_size, str);
 		}
+		if (request->extra_fields) {
+			str_append_c(str, '\t');
+			str_append(str, request->extra_fields);
+		}
 		break;
 	case AUTH_CLIENT_RESULT_FAILURE:
 		str = t_str_new(128);
 		str_printfa(str, "FAIL\t%u", request->id);
-		if (reply != NULL) {
+		str_append_c(str, '\t');
+		if (reply != NULL)
+			str_append(str, reply);
+		if (request->extra_fields) {
 			str_append_c(str, '\t');
-			str_append(str, reply);
+			str_append(str, request->extra_fields);
 		}
 		break;
 	}
--- a/src/auth/mech.c	Mon Oct 18 02:36:08 2004 +0300
+++ b/src/auth/mech.c	Mon Oct 18 04:00:42 2004 +0300
@@ -116,6 +116,15 @@
 		      const void *data, size_t data_size, int success)
 {
 	if (!success) {
+		if (request->no_failure_delay) {
+			/* passdb specifically requested to to delay the
+			   reply. */
+			request->callback(request, AUTH_CLIENT_RESULT_FAILURE,
+					  NULL, 0);
+			auth_request_destroy(request);
+			return;
+		}
+
 		/* failure. don't announce it immediately to avoid
 		   a) timing attacks, b) flooding */
 		if (auth_failures_buf->used > 0) {
@@ -134,7 +143,7 @@
 				  data, data_size);
 	}
 
-	if (request->conn == NULL ||
+	if (request->no_login || request->conn == NULL ||
 	    AUTH_MASTER_IS_DUMMY(request->conn->master)) {
 		/* we don't have master process, the request is no longer
 		   needed */
--- a/src/auth/mech.h	Mon Oct 18 02:36:08 2004 +0300
+++ b/src/auth/mech.h	Mon Oct 18 04:00:42 2004 +0300
@@ -22,6 +22,7 @@
 
 	pool_t pool;
 	char *user;
+	const char *extra_fields;
 
 	struct mech_module *mech;
 	struct auth_client_connection *conn;
@@ -34,6 +35,8 @@
 	mech_callback_t *callback;
 
 	unsigned int accept_input:1;
+	unsigned int no_failure_delay:1;
+	unsigned int no_login:1;
 	/* ... mechanism specific data ... */
 };
 
--- a/src/auth/passdb-sql.c	Mon Oct 18 02:36:08 2004 +0300
+++ b/src/auth/passdb-sql.c	Mon Oct 18 04:00:42 2004 +0300
@@ -29,12 +29,60 @@
 
 static struct sql_connection *passdb_sql_conn;
 
+static void result_save_extra_fields(struct sql_result *result,
+				     struct auth_request *auth_request)
+{
+	unsigned int i, fields_count;
+	const char *name, *value;
+	string_t *str;
+
+	fields_count = sql_result_get_fields_count(result);
+	if (fields_count == 1)
+		return;
+
+	str = NULL;
+	for (i = 0; i < fields_count; i++) {
+		name = sql_result_get_field_name(result, i);
+		value = sql_result_get_field_value(result, i);
+
+		if (strcmp(name, "password") == 0)
+			continue;
+
+		if (strcmp(name, "nodelay") == 0) {
+			/* don't delay replying to client of the failure */
+			auth_request->no_failure_delay = *value == 'Y';
+			continue;
+		}
+
+		if (str == NULL)
+			str = str_new(auth_request->pool, 64);
+
+		if (strcmp(name, "nologin") == 0) {
+			if (*value == 'Y') {
+				/* user can't actually login - don't keep this
+				   reply for master */
+				auth_request->no_login = TRUE;
+				if (str_len(str) > 0)
+					str_append_c(str, '\t');
+				str_append(str, name);
+			}
+		} else {
+			if (str_len(str) > 0)
+				str_append_c(str, '\t');
+			str_printfa(str, "%s=%s", name, value);
+		}
+	}
+
+	if (str != NULL)
+		auth_request->extra_fields = str_c(str);
+}
+
 static void sql_query_callback(struct sql_result *result, void *context)
 {
 	struct passdb_sql_request *sql_request = context;
 	struct auth_request *auth_request = sql_request->auth_request;
 	const char *user, *password, *scheme;
-	int ret;
+	int ret, idx;
 
 	user = auth_request->user;
 	password = NULL;
@@ -49,16 +97,15 @@
 			i_info("sql(%s): Unknown user",
 			       get_log_prefix(auth_request));
 		}
+	} else if ((idx = sql_result_find_field(result, "password")) < 0) {
+		i_error("sql(%s): Password query didn't return password",
+			get_log_prefix(auth_request));
 	} else {
-		password = sql_result_find_field_value(result, "password");
-		if (password != NULL)
-			password = t_strdup(password);
-		else {
-			i_error("sql(%s): Password query didn't return "
-				"password, or it was NULL",
-				get_log_prefix(auth_request));
-		}
+		password = t_strdup(sql_result_get_field_value(result, idx));
+                result_save_extra_fields(result, auth_request);
+	}
 
+	if (ret > 0) {
 		/* make sure there was only one row returned */
 		if (sql_result_next_row(result) > 0) {
 			i_error("sql(%s): Password query returned multiple "