dovecot-2.0: auth: Identify clients using a 128bit random cookie...

dovecot at dovecot.org dovecot at dovecot.org
Thu Oct 15 01:25:38 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/aa30fc7d771a
changeset: 10059:aa30fc7d771a
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Oct 14 18:25:29 2009 -0400
description:
auth: Identify clients using a 128bit random cookie on top of the existing PID.
When master is finishing the login, it must give this cookie to REQUEST
command and it must match what auth process knows. This change makes it safe
to do client/master login without a dedicated master process.

diffstat:

10 files changed, 78 insertions(+), 10 deletions(-)
src/auth/auth-client-connection.c     |    7 ++++++-
src/auth/auth-client-connection.h     |    3 +++
src/auth/auth-master-connection.c     |   21 +++++++++++++++++----
src/lib-auth/auth-client.c            |    5 +++++
src/lib-auth/auth-client.h            |    1 +
src/lib-auth/auth-server-connection.c |   22 ++++++++++++++++++++++
src/lib-auth/auth-server-connection.h |    1 +
src/lib-master/master-interface.h     |    6 +++++-
src/login-common/sasl-server.c        |   10 +++++++++-
src/master/service-auth-source.c      |   12 +++++++++---

diffs (294 lines):

diff -r b81f4a4076de -r aa30fc7d771a src/auth/auth-client-connection.c
--- a/src/auth/auth-client-connection.c	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/auth/auth-client-connection.c	Wed Oct 14 18:25:29 2009 -0400
@@ -6,9 +6,11 @@
 #include "istream.h"
 #include "ostream.h"
 #include "network.h"
+#include "hex-binary.h"
 #include "hostpid.h"
 #include "str.h"
 #include "str-sanitize.h"
+#include "randgen.h"
 #include "safe-memset.h"
 #include "master-service.h"
 #include "auth-stream.h"
@@ -274,6 +276,7 @@ auth_client_connection_create(struct aut
 	conn->auth = auth;
 	conn->refcount = 1;
 	conn->connect_uid = ++connect_uid_counter;
+	random_fill(conn->cookie, sizeof(conn->cookie));
 
 	conn->fd = fd;
 	conn->input = i_stream_create_fd(fd, AUTH_CLIENT_MAX_LINE_LENGTH,
@@ -285,11 +288,13 @@ auth_client_connection_create(struct aut
 	array_append(&auth_client_connections, &conn, 1);
 
 	str = t_str_new(128);
-	str_printfa(str, "VERSION\t%u\t%u\n%sSPID\t%s\nCUID\t%u\nDONE\n",
+	str_printfa(str, "VERSION\t%u\t%u\n%sSPID\t%s\nCUID\t%u\nCOOKIE\t",
                     AUTH_CLIENT_PROTOCOL_MAJOR_VERSION,
                     AUTH_CLIENT_PROTOCOL_MINOR_VERSION,
 		    str_c(conn->auth->mech_handshake),
 		    my_pid, conn->connect_uid);
+	binary_to_hex_append(str, conn->cookie, sizeof(conn->cookie));
+	str_append(str, "\nDONE\n");
 
 	if (o_stream_send(conn->output, str_data(str), str_len(str)) < 0)
 		auth_client_connection_destroy(&conn);
diff -r b81f4a4076de -r aa30fc7d771a src/auth/auth-client-connection.h
--- a/src/auth/auth-client-connection.h	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/auth/auth-client-connection.h	Wed Oct 14 18:25:29 2009 -0400
@@ -1,5 +1,7 @@
 #ifndef AUTH_CLIENT_CONNECTION_H
 #define AUTH_CLIENT_CONNECTION_H
+
+#include "master-interface.h"
 
 struct auth_client_connection {
 	struct auth *auth;
@@ -12,6 +14,7 @@ struct auth_client_connection {
 
 	unsigned int pid;
 	unsigned int connect_uid;
+	uint8_t cookie[MASTER_AUTH_COOKIE_SIZE];
 	struct auth_request_handler *request_handler;
 
 	unsigned int version_received:1;
diff -r b81f4a4076de -r aa30fc7d771a src/auth/auth-master-connection.c
--- a/src/auth/auth-master-connection.c	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/auth/auth-master-connection.c	Wed Oct 14 18:25:29 2009 -0400
@@ -5,8 +5,9 @@
 #include "hash.h"
 #include "str.h"
 #include "strescape.h"
+#include "str-sanitize.h"
 #include "hostpid.h"
-#include "str-sanitize.h"
+#include "hex-binary.h"
 #include "ioloop.h"
 #include "network.h"
 #include "istream.h"
@@ -69,10 +70,12 @@ master_input_request(struct auth_master_
 	struct auth_client_connection *client_conn;
 	const char *const *list;
 	unsigned int id, client_pid, client_id;
-
-	/* <id> <client-pid> <client-id> */
+	uint8_t cookie[MASTER_AUTH_COOKIE_SIZE];
+	buffer_t buf;
+
+	/* <id> <client-pid> <client-id> <cookie> */
 	list = t_strsplit(args, "\t");
-	if (list[0] == NULL || list[1] == NULL || list[2] == NULL) {
+	if (str_array_length(list) < 4) {
 		i_error("BUG: Master sent broken REQUEST");
 		return FALSE;
 	}
@@ -80,10 +83,20 @@ master_input_request(struct auth_master_
 	id = (unsigned int)strtoul(list[0], NULL, 10);
 	client_pid = (unsigned int)strtoul(list[1], NULL, 10);
 	client_id = (unsigned int)strtoul(list[2], NULL, 10);
+	buffer_create_data(&buf, cookie, sizeof(cookie));
+	if (hex_to_binary(list[3], &buf) < 0) {
+		i_error("BUG: Master sent broken REQUEST cookie");
+		return FALSE;
+	}
 
 	client_conn = auth_client_connection_lookup(client_pid);
 	if (client_conn == NULL) {
 		i_error("Master requested auth for nonexisting client %u",
+			client_pid);
+		(void)o_stream_send_str(conn->output,
+					t_strdup_printf("NOTFOUND\t%u\n", id));
+	} else if (memcmp(client_conn->cookie, cookie, sizeof(cookie)) != 0) {
+		i_error("Master requested auth for client %u with invalid cookie",
 			client_pid);
 		(void)o_stream_send_str(conn->output,
 					t_strdup_printf("NOTFOUND\t%u\n", id));
diff -r b81f4a4076de -r aa30fc7d771a src/lib-auth/auth-client.c
--- a/src/lib-auth/auth-client.c	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/lib-auth/auth-client.c	Wed Oct 14 18:25:29 2009 -0400
@@ -70,3 +70,8 @@ void auth_client_get_connect_id(struct a
 	*server_pid_r = client->conn->server_pid;
 	*connect_uid_r = client->conn->connect_uid;
 }
+
+const char *auth_client_get_cookie(struct auth_client *client)
+{
+	return client->conn->cookie;
+}
diff -r b81f4a4076de -r aa30fc7d771a src/lib-auth/auth-client.h
--- a/src/lib-auth/auth-client.h	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/lib-auth/auth-client.h	Wed Oct 14 18:25:29 2009 -0400
@@ -68,6 +68,7 @@ void auth_client_get_connect_id(struct a
 void auth_client_get_connect_id(struct auth_client *client,
 				unsigned int *server_pid_r,
 				unsigned int *connect_uid_r);
+const char *auth_client_get_cookie(struct auth_client *client);
 
 /* Create a new authentication request. callback is called whenever something
    happens for the request. */
diff -r b81f4a4076de -r aa30fc7d771a src/lib-auth/auth-server-connection.c
--- a/src/lib-auth/auth-server-connection.c	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/lib-auth/auth-server-connection.c	Wed Oct 14 18:25:29 2009 -0400
@@ -84,8 +84,24 @@ auth_server_input_cuid(struct auth_serve
 		i_error("BUG: Authentication server already sent handshake");
 		return -1;
 	}
+	if (args[0] == NULL) {
+		i_error("BUG: Authentication server sent broken CUID line");
+		return -1;
+	}
 
 	conn->connect_uid = (unsigned int)strtoul(args[0], NULL, 10);
+	return 0;
+}
+
+static int
+auth_server_input_cookie(struct auth_server_connection *conn,
+			 const char *const *args)
+{
+	if (conn->cookie != NULL) {
+		i_error("BUG: Authentication server already sent cookie");
+		return -1;
+	}
+	conn->cookie = p_strdup(conn->pool, args[0]);
 	return 0;
 }
 
@@ -93,6 +109,10 @@ static int auth_server_input_done(struct
 {
 	if (array_count(&conn->available_auth_mechs) == 0) {
 		i_error("BUG: Authentication server returned no mechanisms");
+		return -1;
+	}
+	if (conn->cookie == NULL) {
+		i_error("BUG: Authentication server didn't send a cookie");
 		return -1;
 	}
 
@@ -197,6 +217,8 @@ auth_server_connection_input_line(struct
 		return auth_server_input_spid(conn, args + 1);
 	else if (strcmp(args[0], "CUID") == 0)
 		return auth_server_input_cuid(conn, args + 1);
+	else if (strcmp(args[0], "COOKIE") == 0)
+		return auth_server_input_cookie(conn, args + 1);
 	else if (strcmp(args[0], "DONE") == 0)
 		return auth_server_input_done(conn);
 	else {
diff -r b81f4a4076de -r aa30fc7d771a src/lib-auth/auth-server-connection.h
--- a/src/lib-auth/auth-server-connection.h	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/lib-auth/auth-server-connection.h	Wed Oct 14 18:25:29 2009 -0400
@@ -15,6 +15,7 @@ struct auth_server_connection {
 
 	unsigned int server_pid;
 	unsigned int connect_uid;
+	char *cookie;
 
 	ARRAY_DEFINE(available_auth_mechs, struct auth_mech_desc);
 
diff -r b81f4a4076de -r aa30fc7d771a src/lib-master/master-interface.h
--- a/src/lib-master/master-interface.h	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/lib-master/master-interface.h	Wed Oct 14 18:25:29 2009 -0400
@@ -34,15 +34,19 @@ struct log_service_handshake {
    to make sure there's space to transfer the command tag  */
 #define MASTER_AUTH_MAX_DATA_SIZE (1024*2)
 
+/* Authentication client process's cookie size */
+#define MASTER_AUTH_COOKIE_SIZE (128/8)
+
 /* Authentication request. File descriptor may be sent along with the
    request. */
 struct master_auth_request {
 	/* Request tag. Reply is sent back using same tag. */
 	unsigned int tag;
 
-	/* Authentication process and authentication ID. */
+	/* Authentication process, authentication ID and auth cookie. */
 	pid_t auth_pid;
 	unsigned int auth_id;
+	uint8_t cookie[MASTER_AUTH_COOKIE_SIZE];
 
 	/* Local and remote IPs of the connection. The file descriptor
 	   itself may be a local socketpair. */
diff -r b81f4a4076de -r aa30fc7d771a src/login-common/sasl-server.c
--- a/src/login-common/sasl-server.c	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/login-common/sasl-server.c	Wed Oct 14 18:25:29 2009 -0400
@@ -3,6 +3,7 @@
 #include "common.h"
 #include "base64.h"
 #include "buffer.h"
+#include "hex-binary.h"
 #include "istream.h"
 #include "write-full.h"
 #include "strescape.h"
@@ -102,8 +103,11 @@ master_send_request(struct client *clien
 {
 	struct master_auth_request req;
 	const unsigned char *data;
+	const char *cookie;
 	size_t size;
 	buffer_t *buf;
+
+	buf = buffer_create_dynamic(pool_datastack_create(), 256);
 
 	memset(&req, 0, sizeof(req));
 	req.auth_pid = auth_client_request_get_server_pid(request);
@@ -111,7 +115,11 @@ master_send_request(struct client *clien
 	req.local_ip = client->local_ip;
 	req.remote_ip = client->ip;
 
-	buf = buffer_create_dynamic(pool_datastack_create(), 256);
+	cookie = auth_client_get_cookie(auth_client);
+	if (hex_to_binary(cookie, buf) == 0 && buf->used == sizeof(req.cookie))
+		memcpy(req.cookie, buf->data, sizeof(req.cookie));
+
+	buffer_set_used_size(buf, 0);
 	buffer_append(buf, client->master_data_prefix,
 		      client->master_data_prefix_len);
 
diff -r b81f4a4076de -r aa30fc7d771a src/master/service-auth-source.c
--- a/src/master/service-auth-source.c	Wed Oct 14 16:35:16 2009 -0400
+++ b/src/master/service-auth-source.c	Wed Oct 14 18:25:29 2009 -0400
@@ -3,6 +3,7 @@
 #include "common.h"
 #include "hash.h"
 #include "str.h"
+#include "hex-binary.h"
 #include "ioloop.h"
 #include "ostream.h"
 #include "fdpass.h"
@@ -85,7 +86,8 @@ static unsigned int
 static unsigned int
 auth_server_send_request(struct service_process_auth_server *server_process,
 			 struct service_process_auth_source *source_process,
-			 unsigned int auth_id)
+			 unsigned int auth_id,
+			 const uint8_t cookie[MASTER_AUTH_COOKIE_SIZE])
 {
 	unsigned int tag = 0;
 	string_t *str;
@@ -104,8 +106,11 @@ auth_server_send_request(struct service_
 		str_truncate(str, 0);
 	}
 
-	str_printfa(str, "REQUEST\t%u\t%s\t%u\n",
+	str_printfa(str, "REQUEST\t%u\t%s\t%u\t",
 		    tag, dec2str(source_process->process.pid), auth_id);
+	binary_to_hex_append(str, cookie, MASTER_AUTH_COOKIE_SIZE);
+	str_append_c(str, '\n');
+
 	o_stream_send(server_process->auth_output, str_data(str), str_len(str));
 	return tag;
 }
@@ -241,7 +246,8 @@ service_process_auth_source_input(struct
 	auth_req->data_size = req.data_size;
 	memcpy(auth_req->data, data, req.data_size);
 
-	tag = auth_server_send_request(auth_process, process, req.auth_id);
+	tag = auth_server_send_request(auth_process, process, req.auth_id,
+				       req.cookie);
 
 	service_process_ref(&process->process);
 	hash_table_insert(auth_process->auth_requests,


More information about the dovecot-cvs mailing list