dovecot-2.0: auth worker: Verify that both client and server see...

dovecot at dovecot.org dovecot at dovecot.org
Tue Mar 16 18:26:28 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/91ae9577aca9
changeset: 10924:91ae9577aca9
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Mar 16 18:26:25 2010 +0200
description:
auth worker: Verify that both client and server see the same passdb/userdb IDs.

diffstat:

 src/auth/auth-worker-client.c |  52 ++++++++++++++++++++++++++
 src/auth/auth-worker-client.h |   2 +
 src/auth/auth-worker-server.c |  24 +++++++++++-
 src/auth/passdb.c             |  17 ++++++++
 src/auth/passdb.h             |   4 ++
 src/auth/userdb.c             |  17 ++++++++
 src/auth/userdb.h             |   3 +
 7 files changed, 118 insertions(+), 1 deletions(-)

diffs (233 lines):

diff -r bf26a6ec3389 -r 91ae9577aca9 src/auth/auth-worker-client.c
--- a/src/auth/auth-worker-client.c	Tue Mar 16 18:08:27 2010 +0200
+++ b/src/auth/auth-worker-client.c	Tue Mar 16 18:26:25 2010 +0200
@@ -6,6 +6,7 @@
 #include "network.h"
 #include "istream.h"
 #include "ostream.h"
+#include "hex-binary.h"
 #include "str.h"
 #include "master-service.h"
 #include "auth-request.h"
@@ -23,6 +24,9 @@
 	struct io *io;
 	struct istream *input;
 	struct ostream *output;
+
+	unsigned int version_received:1;
+	unsigned int dbhash_received:1;
 };
 
 struct auth_worker_list_context {
@@ -550,6 +554,24 @@
         return ret;
 }
 
+static bool auth_worker_verify_db_hash(const char *line)
+{
+	string_t *str;
+	unsigned char passdb_md5[MD5_RESULTLEN];
+	unsigned char userdb_md5[MD5_RESULTLEN];
+
+	passdbs_generate_md5(passdb_md5);
+	userdbs_generate_md5(userdb_md5);
+
+	str = t_str_new(128);
+	str_append(str, "DBHASH\t");
+	binary_to_hex_append(str, passdb_md5, sizeof(passdb_md5));
+	str_append_c(str, '\t');
+	binary_to_hex_append(str, userdb_md5, sizeof(userdb_md5));
+
+	return strcmp(line, str_c(str)) == 0;
+}
+
 static void auth_worker_input(struct auth_worker_client *client)
 {
 	char *line;
@@ -570,6 +592,36 @@
 		return;
 	}
 
+	if (!client->version_received) {
+		line = i_stream_next_line(client->input);
+		if (line == NULL)
+			return;
+
+		if (strncmp(line, "VERSION\tauth-worker\t", 20) != 0 ||
+		    atoi(t_strcut(line + 20, '\t')) !=
+		    AUTH_WORKER_PROTOCOL_MAJOR_VERSION) {
+			i_error("Auth worker not compatible with this server "
+				"(mixed old and new binaries?)");
+			auth_worker_client_destroy(&client);
+			return;
+		}
+		client->version_received = TRUE;
+	}
+	if (!client->dbhash_received) {
+		line = i_stream_next_line(client->input);
+		if (line == NULL)
+			return;
+
+		if (!auth_worker_verify_db_hash(line)) {
+			i_error("Auth worker sees different passdbs/userdbs "
+				"than auth server. Maybe config just changed "
+				"and this goes away automatically?");
+			auth_worker_client_destroy(&client);
+			return;
+		}
+		client->dbhash_received = TRUE;
+	}
+
         client->refcount++;
 	while ((line = i_stream_next_line(client->input)) != NULL) {
 		T_BEGIN {
diff -r bf26a6ec3389 -r 91ae9577aca9 src/auth/auth-worker-client.h
--- a/src/auth/auth-worker-client.h	Tue Mar 16 18:08:27 2010 +0200
+++ b/src/auth/auth-worker-client.h	Tue Mar 16 18:26:25 2010 +0200
@@ -1,6 +1,8 @@
 #ifndef AUTH_WORKER_CLIENT_H
 #define AUTH_WORKER_CLIENT_H
 
+#define AUTH_WORKER_PROTOCOL_MAJOR_VERSION 1
+#define AUTH_WORKER_PROTOCOL_MINOR_VERSION 0
 #define AUTH_WORKER_MAX_LINE_LENGTH 8192
 
 extern struct auth_worker_client *auth_worker_client;
diff -r bf26a6ec3389 -r 91ae9577aca9 src/auth/auth-worker-server.c
--- a/src/auth/auth-worker-server.c	Tue Mar 16 18:08:27 2010 +0200
+++ b/src/auth/auth-worker-server.c	Tue Mar 16 18:26:25 2010 +0200
@@ -119,6 +119,28 @@
 	auth_worker_request_send(conn, request);
 }
 
+static void auth_worker_send_handshake(struct auth_worker_connection *conn)
+{
+	string_t *str;
+	unsigned char passdb_md5[MD5_RESULTLEN];
+	unsigned char userdb_md5[MD5_RESULTLEN];
+
+	str = t_str_new(128);
+	str_printfa(str, "VERSION\tauth-worker\t%u\t%u\n",
+		    AUTH_WORKER_PROTOCOL_MAJOR_VERSION,
+		    AUTH_WORKER_PROTOCOL_MINOR_VERSION);
+
+	passdbs_generate_md5(passdb_md5);
+	userdbs_generate_md5(userdb_md5);
+	str_append(str, "DBHASH\t");
+	binary_to_hex_append(str, passdb_md5, sizeof(passdb_md5));
+	str_append_c(str, '\t');
+	binary_to_hex_append(str, userdb_md5, sizeof(userdb_md5));
+	str_append_c(str, '\n');
+
+	o_stream_send(conn->output, str_data(str), str_len(str));
+}
+
 static struct auth_worker_connection *auth_worker_create(void)
 {
 	struct auth_worker_connection *conn;
@@ -141,9 +163,9 @@
 	conn->io = io_add(fd, IO_READ, worker_input, conn);
 	conn->to = timeout_add(AUTH_WORKER_MAX_IDLE_SECS * 1000,
 			       auth_worker_idle_timeout, conn);
+	auth_worker_send_handshake(conn);
 
 	idle_count++;
-
 	array_append(&connections, &conn, 1);
 	return conn;
 }
diff -r bf26a6ec3389 -r 91ae9577aca9 src/auth/passdb.c
--- a/src/auth/passdb.c	Tue Mar 16 18:08:27 2010 +0200
+++ b/src/auth/passdb.c	Tue Mar 16 18:26:25 2010 +0200
@@ -232,6 +232,23 @@
 		passdb->iface.deinit(passdb);
 }
 
+void passdbs_generate_md5(unsigned char md5[MD5_RESULTLEN])
+{
+	struct md5_context ctx;
+	struct passdb_module *const *passdbs;
+	unsigned int i, count;
+
+	md5_init(&ctx);
+	passdbs = array_get(&passdb_modules, &count);
+	for (i = 0; i < count; i++) {
+		md5_update(&ctx, &passdbs[i]->id, sizeof(passdbs[i]->id));
+		md5_update(&ctx, passdbs[i]->iface.name,
+			   strlen(passdbs[i]->iface.name));
+		md5_update(&ctx, passdbs[i]->args, strlen(passdbs[i]->args));
+	}
+	md5_final(&ctx, md5);
+}
+
 extern struct passdb_module_interface passdb_passwd;
 extern struct passdb_module_interface passdb_bsdauth;
 extern struct passdb_module_interface passdb_shadow;
diff -r bf26a6ec3389 -r 91ae9577aca9 src/auth/passdb.h
--- a/src/auth/passdb.h	Tue Mar 16 18:08:27 2010 +0200
+++ b/src/auth/passdb.h	Tue Mar 16 18:26:25 2010 +0200
@@ -1,6 +1,8 @@
 #ifndef PASSDB_H
 #define PASSDB_H
 
+#include "md5.h"
+
 #define IS_VALID_PASSWD(pass) \
 	((pass)[0] != '\0' && (pass)[0] != '*' && (pass)[0] != '!')
 
@@ -93,6 +95,8 @@
 void passdb_register_module(struct passdb_module_interface *iface);
 void passdb_unregister_module(struct passdb_module_interface *iface);
 
+void passdbs_generate_md5(unsigned char md5[MD5_RESULTLEN]);
+
 void passdbs_init(void);
 void passdbs_deinit(void);
 
diff -r bf26a6ec3389 -r 91ae9577aca9 src/auth/userdb.c
--- a/src/auth/userdb.c	Tue Mar 16 18:08:27 2010 +0200
+++ b/src/auth/userdb.c	Tue Mar 16 18:26:25 2010 +0200
@@ -181,6 +181,23 @@
 		userdb->iface->deinit(userdb);
 }
 
+void userdbs_generate_md5(unsigned char md5[MD5_RESULTLEN])
+{
+	struct md5_context ctx;
+	struct userdb_module *const *userdbs;
+	unsigned int i, count;
+
+	md5_init(&ctx);
+	userdbs = array_get(&userdb_modules, &count);
+	for (i = 0; i < count; i++) {
+		md5_update(&ctx, &userdbs[i]->id, sizeof(userdbs[i]->id));
+		md5_update(&ctx, userdbs[i]->iface->name,
+			   strlen(userdbs[i]->iface->name));
+		md5_update(&ctx, userdbs[i]->args, strlen(userdbs[i]->args));
+	}
+	md5_final(&ctx, md5);
+}
+
 extern struct userdb_module_interface userdb_prefetch;
 extern struct userdb_module_interface userdb_static;
 extern struct userdb_module_interface userdb_passwd;
diff -r bf26a6ec3389 -r 91ae9577aca9 src/auth/userdb.h
--- a/src/auth/userdb.h	Tue Mar 16 18:08:27 2010 +0200
+++ b/src/auth/userdb.h	Tue Mar 16 18:26:25 2010 +0200
@@ -1,6 +1,7 @@
 #ifndef USERDB_H
 #define USERDB_H
 
+#include "md5.h"
 #include "auth-stream.h"
 
 struct auth;
@@ -71,6 +72,8 @@
 void userdb_register_module(struct userdb_module_interface *iface);
 void userdb_unregister_module(struct userdb_module_interface *iface);
 
+void userdbs_generate_md5(unsigned char md5[MD5_RESULTLEN]);
+
 void userdbs_init(void);
 void userdbs_deinit(void);
 


More information about the dovecot-cvs mailing list