dovecot-2.0: lib-master: When finishing auth, don't send REQUEST...

dovecot at dovecot.org dovecot at dovecot.org
Mon Sep 20 19:50:35 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/16330c0c8ef4
changeset: 12137:16330c0c8ef4
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Sep 20 17:50:29 2010 +0100
description:
lib-master: When finishing auth, don't send REQUEST if auth process has restarted.
This avoids unnecessary "Master requested auth for nonexistent client" errors
when auth process restarts (crashes).

diffstat:

 src/lib-master/master-login-auth.c |  109 +++++++++++++++++++++++++++++-------
 1 files changed, 88 insertions(+), 21 deletions(-)

diffs (192 lines):

diff -r 26e88084bbc0 -r 16330c0c8ef4 src/lib-master/master-login-auth.c
--- a/src/lib-master/master-login-auth.c	Mon Sep 20 16:06:17 2010 +0100
+++ b/src/lib-master/master-login-auth.c	Mon Sep 20 17:50:29 2010 +0100
@@ -23,6 +23,11 @@
 	unsigned int id;
 	time_t create_stamp;
 
+	pid_t auth_pid;
+	unsigned int auth_id;
+	unsigned int client_pid;
+	uint8_t cookie[MASTER_AUTH_COOKIE_SIZE];
+
 	master_login_auth_request_callback_t *callback;
 	void *context;
 };
@@ -43,10 +48,14 @@
 	/* linked list of requests, ordered by create_stamp */
 	struct master_login_auth_request *request_head, *request_tail;
 
+	pid_t auth_server_pid;
+
 	unsigned int version_received:1;
+	unsigned int spid_received:1;
 };
 
 static void master_login_auth_set_timeout(struct master_login_auth *auth);
+static void master_login_auth_send_all_requests(struct master_login_auth *auth);
 
 struct master_login_auth *master_login_auth_init(const char *auth_socket_path)
 {
@@ -156,27 +165,35 @@
 	}
 }
 
+static void
+master_login_auth_request_remove(struct master_login_auth *auth,
+				 struct master_login_auth_request *request)
+{
+	bool update_timeout;
+
+	update_timeout = request->prev == NULL;
+
+	hash_table_remove(auth->requests, POINTER_CAST(request->id));
+	DLLIST2_REMOVE(&auth->request_head, &auth->request_tail, request);
+
+	if (update_timeout) {
+		timeout_remove(&auth->to);
+		master_login_auth_set_timeout(auth);
+	}
+}
+
 static struct master_login_auth_request *
 master_login_auth_lookup_request(struct master_login_auth *auth,
 				 unsigned int id)
 {
 	struct master_login_auth_request *request;
-	bool update_timeout;
 
 	request = hash_table_lookup(auth->requests, POINTER_CAST(id));
 	if (request == NULL) {
 		i_error("Auth server sent reply with unknown ID %u", id);
 		return NULL;
 	}
-	update_timeout = request->prev == NULL;
-
-	hash_table_remove(auth->requests, POINTER_CAST(id));
-	DLLIST2_REMOVE(&auth->request_head, &auth->request_tail, request);
-
-	if (update_timeout) {
-		timeout_remove(&auth->to);
-		master_login_auth_set_timeout(auth);
-	}
+	master_login_auth_request_remove(auth, request);
 	return request;
 }
 
@@ -291,6 +308,21 @@
 		}
 		auth->version_received = TRUE;
 	}
+	if (!auth->spid_received) {
+		line = i_stream_next_line(auth->input);
+		if (line == NULL)
+			return;
+
+		if (strncmp(line, "SPID\t", 5) != 0 ||
+		    str_to_pid(line + 5, &auth->auth_server_pid) < 0) {
+			i_error("Authentication server didn't "
+				"send valid SPID as expected: %s", line);
+			master_login_auth_disconnect(auth);
+			return;
+		}
+		auth->spid_received = TRUE;
+		master_login_auth_send_all_requests(auth);
+	}
 
 	auth->refcount++;
 	while ((line = i_stream_next_line(auth->input)) != NULL) {
@@ -331,6 +363,41 @@
 	return 0;
 }
 
+static void
+master_login_auth_send_request(struct master_login_auth *auth,
+			       struct master_login_auth_request *req)
+{
+	string_t *str;
+
+	i_assert(auth->spid_received);
+
+	if (auth->auth_server_pid != req->auth_pid) {
+		/* auth server was restarted. don't even attempt a login. */
+		master_login_auth_request_remove(auth, req);
+		req->callback(NULL, MASTER_AUTH_ERRMSG_INTERNAL_FAILURE,
+			      req->context);
+		i_free(req);
+		return;
+	}
+
+	str = t_str_new(128);
+	str_printfa(str, "REQUEST\t%u\t%u\t%u\t", req->id,
+		    req->client_pid, req->auth_id);
+	binary_to_hex_append(str, req->cookie, sizeof(req->cookie));
+	str_append_c(str, '\n');
+	o_stream_send(auth->output, str_data(str), str_len(str));
+}
+
+static void master_login_auth_send_all_requests(struct master_login_auth *auth)
+{
+	struct master_login_auth_request *req, *next;
+
+	for (req = auth->request_head; req != NULL; req = next) {
+		next = req->next;
+		master_login_auth_send_request(auth, req);
+	}
+}
+
 void master_login_auth_request(struct master_login_auth *auth,
 			       const struct master_auth_request *req,
 			       master_login_auth_request_callback_t *callback,
@@ -338,33 +405,30 @@
 {
 	struct master_login_auth_request *login_req;
 	unsigned int id;
-	string_t *str;
 
-	str = t_str_new(128);
 	if (auth->fd == -1) {
 		if (master_login_auth_connect(auth) < 0) {
 			callback(NULL, MASTER_AUTH_ERRMSG_INTERNAL_FAILURE,
 				 context);
 			return;
 		}
-		str_printfa(str, "VERSION\t%u\t%u\n",
-			    AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
-			    AUTH_MASTER_PROTOCOL_MINOR_VERSION);
+		o_stream_send_str(auth->output,
+			t_strdup_printf("VERSION\t%u\t%u\n",
+					AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
+					AUTH_MASTER_PROTOCOL_MINOR_VERSION));
 	}
 
 	id = ++auth->id_counter;
 	if (id == 0)
 		id++;
 
-	str_printfa(str, "REQUEST\t%u\t%u\t%u\t", id,
-		    req->client_pid, req->auth_id);
-	binary_to_hex_append(str, req->cookie, sizeof(req->cookie));
-	str_append_c(str, '\n');
-	o_stream_send(auth->output, str_data(str), str_len(str));
-
 	login_req = i_new(struct master_login_auth_request, 1);
 	login_req->create_stamp = ioloop_time;
 	login_req->id = id;
+	login_req->auth_pid = req->auth_pid;
+	login_req->client_pid = req->client_pid;
+	login_req->auth_id = req->auth_id;
+	memcpy(login_req->cookie, req->cookie, sizeof(login_req->cookie));
 	login_req->callback = callback;
 	login_req->context = context;
 	hash_table_insert(auth->requests, POINTER_CAST(id), login_req);
@@ -372,6 +436,9 @@
 
 	if (auth->to == NULL)
 		master_login_auth_set_timeout(auth);
+
+	if (auth->spid_received)
+		master_login_auth_send_request(auth, login_req);
 }
 
 unsigned int master_login_auth_request_count(struct master_login_auth *auth)


More information about the dovecot-cvs mailing list