Mercurial > dovecot > core-2.2
changeset 10924:91ae9577aca9 HEAD
auth worker: Verify that both client and server see the same passdb/userdb IDs.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 16 Mar 2010 18:26:25 +0200 |
parents | bf26a6ec3389 |
children | 0a469d9f1ea4 |
files | src/auth/auth-worker-client.c src/auth/auth-worker-client.h src/auth/auth-worker-server.c src/auth/passdb.c src/auth/passdb.h src/auth/userdb.c src/auth/userdb.h |
diffstat | 7 files changed, 118 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- 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 {
--- 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;
--- 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; }
--- 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;
--- 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);
--- 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;
--- 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);