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