dovecot-2.0: lib-auth: Added support for iterating through all u...

dovecot at dovecot.org dovecot at dovecot.org
Fri May 15 22:10:36 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/77d6b5eb0963
changeset: 9288:77d6b5eb0963
user:      Timo Sirainen <tss at iki.fi>
date:      Fri May 15 15:09:13 2009 -0400
description:
lib-auth: Added support for iterating through all users.

diffstat:

2 files changed, 194 insertions(+), 64 deletions(-)
src/lib-auth/auth-master.c |  251 ++++++++++++++++++++++++++++++++------------
src/lib-auth/auth-master.h |    7 +

diffs (truncated from 398 to 300 lines):

diff -r 6557ed6fc4e1 -r 77d6b5eb0963 src/lib-auth/auth-master.c
--- a/src/lib-auth/auth-master.c	Fri May 15 15:08:37 2009 -0400
+++ b/src/lib-auth/auth-master.c	Fri May 15 15:09:13 2009 -0400
@@ -21,6 +21,8 @@
 #define MAX_INBUF_SIZE 8192
 #define MAX_OUTBUF_SIZE 1024
 
+#define DEFAULT_USERDB_LOOKUP_PREFIX "userdb lookup"
+
 struct auth_master_connection {
 	char *auth_socket_path;
 
@@ -30,12 +32,13 @@ struct auth_master_connection {
 	struct istream *input;
 	struct ostream *output;
 	struct timeout *to;
+	const char *prefix;
 
 	unsigned int request_counter;
-	pool_t pool;
-	const char *user;
-	struct auth_user_reply *user_reply;
-	int return_value;
+
+	bool (*reply_callback)(const char *cmd, const char *const *args,
+			       void *context);
+	void *reply_context;
 
 	unsigned int debug:1;
 	unsigned int sent_handshake:1;
@@ -43,6 +46,23 @@ struct auth_master_connection {
 	unsigned int aborted:1;
 };
 
+struct auth_master_user_lookup_ctx {
+	struct auth_master_connection *conn;
+	pool_t pool;
+	const char *user;
+	struct auth_user_reply *user_reply;
+	int return_value;
+};
+
+struct auth_master_user_list_ctx {
+	struct auth_master_connection *conn;
+	pool_t pool;
+	ARRAY_TYPE(const_string) users;
+	const char *const *user_strings;
+	unsigned int idx, user_count;
+	bool failed;
+};
+
 static void auth_input(struct auth_master_connection *conn);
 
 struct auth_master_connection *
@@ -54,6 +74,7 @@ auth_master_init(const char *auth_socket
 	conn->auth_socket_path = i_strdup(auth_socket_path);
 	conn->fd = -1;
 	conn->debug = debug;
+	conn->prefix = DEFAULT_USERDB_LOOKUP_PREFIX;
 	return conn;
 }
 
@@ -87,19 +108,19 @@ static void auth_request_lookup_abort(st
 	conn->aborted = TRUE;
 }
 
-static void auth_parse_input(struct auth_master_connection *conn,
+static void auth_parse_input(struct auth_master_user_lookup_ctx *ctx,
 			     const char *const *args)
 {
-	struct auth_user_reply *reply = conn->user_reply;
+	struct auth_user_reply *reply = ctx->user_reply;
 
 	memset(reply, 0, sizeof(*reply));
 	reply->uid = (uid_t)-1;
 	reply->gid = (gid_t)-1;
-	p_array_init(&reply->extra_fields, conn->pool, 64);
-
-	reply->user = p_strdup(conn->pool, *args);
+	p_array_init(&reply->extra_fields, ctx->pool, 64);
+
+	reply->user = p_strdup(ctx->pool, *args);
 	for (args++; *args != NULL; args++) {
-		if (conn->debug)
+		if (ctx->conn->debug)
 			i_info("auth input: %s", *args);
 
 		if (strncmp(*args, "uid=", 4) == 0)
@@ -107,11 +128,11 @@ static void auth_parse_input(struct auth
 		else if (strncmp(*args, "gid=", 4) == 0)
 			reply->gid = strtoul(*args + 4, NULL, 10);
 		else if (strncmp(*args, "home=", 5) == 0)
-			reply->home = p_strdup(conn->pool, *args + 5);
+			reply->home = p_strdup(ctx->pool, *args + 5);
 		else if (strncmp(*args, "chroot=", 7) == 0)
-			reply->chroot = p_strdup(conn->pool, *args + 7);
+			reply->chroot = p_strdup(ctx->pool, *args + 7);
 		else {
-			const char *field = p_strdup(conn->pool, *args);
+			const char *field = p_strdup(ctx->pool, *args);
 			array_append(&reply->extra_fields, &field, 1);
 		}
 	}
@@ -126,9 +147,9 @@ static int auth_input_handshake(struct a
 		if (strcmp(tmp[0], "VERSION") == 0 &&
 		    tmp[1] != NULL && tmp[2] != NULL) {
 			if (strcmp(tmp[1], dec2str(AUTH_PROTOCOL_MAJOR)) != 0) {
-				i_error("userdb lookup(%s): "
+				i_error("userdb lookup: "
 					"Auth protocol version mismatch "
-					"(%s vs %d)", conn->user, tmp[1],
+					"(%s vs %d)", tmp[1],
 					AUTH_PROTOCOL_MAJOR);
 				auth_request_lookup_abort(conn);
 				return -1;
@@ -141,6 +162,29 @@ static int auth_input_handshake(struct a
 	return 0;
 }
 
+static bool auth_user_reply_callback(const char *cmd, const char *const *args,
+				     void *context)
+{
+	struct auth_master_user_lookup_ctx *ctx = context;
+
+	io_loop_stop(ctx->conn->ioloop);
+	if (strcmp(cmd, "USER") == 0) {
+		auth_parse_input(ctx, args);
+		ctx->return_value = 1;
+		return TRUE;
+	}
+	if (strcmp(cmd, "NOTFOUND") == 0) {
+		ctx->return_value = 0;
+		return TRUE;
+	}
+	if (strcmp(cmd, "FAIL") == 0) {
+		i_error("userdb lookup(%s) failed: %s", ctx->user,
+			*args != NULL ? *args : "Internal failure");
+		return TRUE;
+	}
+	return FALSE;
+}
+
 static void auth_input(struct auth_master_connection *conn)
 {
 	const char *line, *cmd, *const *args, *id, *wanted_id;
@@ -150,14 +194,14 @@ static void auth_input(struct auth_maste
 		return;
 	case -1:
 		/* disconnected */
-		i_error("userdb lookup(%s): Disconnected unexpectedly",
-			conn->user);
+		i_error("%s: Disconnected unexpectedly",
+			conn->prefix);
 		auth_request_lookup_abort(conn);
 		return;
 	case -2:
 		/* buffer full */
-		i_error("userdb lookup(%s): BUG: Received more than %d bytes",
-			conn->user, MAX_INBUF_SIZE);
+		i_error("%s: BUG: Received more than %d bytes",
+			conn->prefix, MAX_INBUF_SIZE);
 		auth_request_lookup_abort(conn);
 		return;
 	}
@@ -182,31 +226,16 @@ static void auth_input(struct auth_maste
 
 	wanted_id = dec2str(conn->request_counter);
 	if (strcmp(id, wanted_id) == 0) {
-		io_loop_stop(conn->ioloop);
-		if (strcmp(cmd, "USER") == 0) {
-			auth_parse_input(conn, args);
-			conn->return_value = 1;
+		if (conn->reply_callback(cmd, args, conn->reply_context))
 			return;
-		}
-		if (strcmp(cmd, "NOTFOUND") == 0) {
-			conn->return_value = 0;
-			return;
-		}
-		if (strcmp(cmd, "FAIL") == 0) {
-			i_error("userdb lookup(%s) failed: %s",
-				conn->user, *args != NULL ? *args :
-				"Internal failure");
-			return;
-		}
 	}
 	
 	if (strcmp(cmd, "CUID") == 0) {
-		i_error("userdb lookup(%s): %s is an auth client socket. "
+		i_error("%s: %s is an auth client socket. "
 			"It should be a master socket.",
-			conn->user, conn->auth_socket_path);
+			conn->prefix, conn->auth_socket_path);
 	} else {
-		i_error("userdb lookup(%s): BUG: Unexpected input: %s",
-			conn->user, line);
+		i_error("%s: BUG: Unexpected input: %s", conn->prefix, line);
 	}
 	auth_request_lookup_abort(conn);
 }
@@ -238,9 +267,9 @@ static void auth_request_timeout(struct 
 static void auth_request_timeout(struct auth_master_connection *conn)
 {
 	if (!conn->handshaked)
-		i_error("userdb lookup(%s): Connecting timed out", conn->user);
+		i_error("%s: Connecting timed out", conn->prefix);
 	else
-		i_error("userdb lookup(%s): Request timed out", conn->user);
+		i_error("%s: Request timed out", conn->prefix);
 	auth_request_lookup_abort(conn);
 }
 
@@ -293,17 +322,12 @@ static bool is_valid_string(const char *
 	return TRUE;
 }
 
-int auth_master_user_lookup(struct auth_master_connection *conn,
-			    const char *user, const char *service,
-			    pool_t pool, struct auth_user_reply *reply_r)
+static int auth_master_run_cmd(struct auth_master_connection *conn,
+			       const char *cmd)
 {
 	struct ioloop *prev_ioloop;
 	const char *str;
 
-	if (!is_valid_string(user) || !is_valid_string(service)) {
-		/* non-allowed characters, the user can't exist */
-		return 0;
-	}
 	if (conn->fd == -1) {
 		if (auth_master_connect(conn) < 0)
 			return -1;
@@ -311,14 +335,6 @@ int auth_master_user_lookup(struct auth_
 
 	prev_ioloop = current_ioloop;
 	auth_master_set_io(conn);
-	conn->return_value = -1;
-	conn->pool = pool;
-	conn->user = user;
-	conn->user_reply = reply_r;
-	if (++conn->request_counter == 0) {
-		/* avoid zero */
-		conn->request_counter++;
-	}
 
 	o_stream_cork(conn->output);
 	if (!conn->sent_handshake) {
@@ -328,9 +344,7 @@ int auth_master_user_lookup(struct auth_
 		conn->sent_handshake = TRUE;
 	}
 
-	str = t_strdup_printf("USER\t%u\t%s\tservice=%s\n",
-			      conn->request_counter, user, service);
-	o_stream_send_str(conn->output, str);
+	o_stream_send_str(conn->output, cmd);
 	o_stream_uncork(conn->output);
 
 	if (conn->output->stream_errno != 0) {
@@ -344,9 +358,118 @@ int auth_master_user_lookup(struct auth_
 	if (conn->aborted) {
 		conn->aborted = FALSE;
 		auth_connection_close(conn);
-	}
-	conn->user = NULL;
-	conn->pool = NULL;
-	conn->user_reply = NULL;
-	return conn->return_value;
-}
+		return -1;
+	}
+	return 0;
+}
+
+int auth_master_user_lookup(struct auth_master_connection *conn,
+			    const char *user, const char *service,
+			    pool_t pool, struct auth_user_reply *reply_r)
+{
+	struct auth_master_user_lookup_ctx ctx;
+	const char *str;
+
+	if (!is_valid_string(user) || !is_valid_string(service)) {
+		/* non-allowed characters, the user can't exist */
+		return 0;
+	}
+
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.conn = conn;
+	ctx.return_value = -1;
+	ctx.pool = pool;
+	ctx.user = user;
+	ctx.user_reply = reply_r;
+
+	if (++conn->request_counter == 0) {
+		/* avoid zero */
+		conn->request_counter++;
+	}
+
+	conn->reply_callback = auth_user_reply_callback;
+	conn->reply_context = &ctx;
+


More information about the dovecot-cvs mailing list