dovecot-2.2: Added support to perform token-based service proces...

dovecot at dovecot.org dovecot at dovecot.org
Fri Sep 14 21:49:59 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/aa6027a0a78e
changeset: 15049:aa6027a0a78e
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Fri Sep 14 21:48:45 2012 +0300
description:
Added support to perform token-based service process authentication.

Creates hidden SASL method DOVECOT-TOKEN. This method is not available on
the normal auth login socket and thus never presented to clients.

Creates new auth socket type 'tokenlogin'. This otherwise normal login
socket only offers authentication using the DOVECOT-TOKEN mechanism.

Creates new token-login directory in base_dir to separate token logins from
normal logins. This directory is otherwise completely identical to the
normal login dir, i.e. it contains sockets for the service backends, used
to chroot login processes to, etc.

Makes default login socket configurable.

Performs some minor changes to src/login-common to build very sparse
protocols, e.g. avoid the need to implement methods that are not needed.

diffstat:

 src/auth/Makefile.am                   |    3 +
 src/auth/auth-client-connection.c      |   15 ++-
 src/auth/auth-client-connection.h      |    3 +-
 src/auth/auth-master-connection.c      |    7 +-
 src/auth/auth-request-handler.c        |   95 ++++++++++++++---
 src/auth/auth-request-handler.h        |   12 +-
 src/auth/auth-request.c                |   16 ++
 src/auth/auth-request.h                |    3 +
 src/auth/auth-settings.c               |    4 +-
 src/auth/auth-token.c                  |  183 +++++++++++++++++++++++++++++++++
 src/auth/auth-token.h                  |   11 +
 src/auth/main.c                        |   22 +++-
 src/auth/mech-dovecot-token.c          |   86 +++++++++++++++
 src/auth/mech.h                        |    2 +
 src/imap/main.c                        |    1 +
 src/lib-master/master-login-auth.c     |    8 +-
 src/lib-master/master-login-auth.h     |    3 +-
 src/lib-master/master-login.c          |    3 +-
 src/lib-master/master-login.h          |    2 +
 src/lib-storage/mail-storage-service.c |    5 +-
 src/lib-storage/mail-user.h            |    2 +
 src/login-common/client-common-auth.c  |    2 +
 src/login-common/client-common.c       |    9 +-
 src/login-common/login-common.h        |    6 +
 src/login-common/main.c                |    5 +-
 src/master/master-settings.c           |   50 +++++---
 26 files changed, 494 insertions(+), 64 deletions(-)

diffs (truncated from 1091 to 300 lines):

diff -r b74e8de5f3d9 -r aa6027a0a78e src/auth/Makefile.am
--- a/src/auth/Makefile.am	Fri Sep 14 21:31:45 2012 +0300
+++ b/src/auth/Makefile.am	Fri Sep 14 21:48:45 2012 +0300
@@ -71,6 +71,7 @@
 	auth-request-handler.c \
 	auth-settings.c \
 	auth-stream.c \
+	auth-token.c \
 	auth-worker-client.c \
 	auth-worker-server.c \
 	db-checkpassword.c \
@@ -93,6 +94,7 @@
 	mech-rpa.c \
 	mech-apop.c \
 	mech-winbind.c \
+	mech-dovecot-token.c \
 	passdb.c \
 	passdb-blocking.c \
 	passdb-bsdauth.c \
@@ -136,6 +138,7 @@
 	auth-request-handler.h \
 	auth-settings.h \
 	auth-stream.h \
+	auth-token.h \
 	auth-worker-client.h \
 	auth-worker-server.h \
 	db-dict.h \
diff -r b74e8de5f3d9 -r aa6027a0a78e src/auth/auth-client-connection.c
--- a/src/auth/auth-client-connection.c	Fri Sep 14 21:31:45 2012 +0300
+++ b/src/auth/auth-client-connection.c	Fri Sep 14 21:48:45 2012 +0300
@@ -125,7 +125,7 @@
 	/* handshake complete, we can now actually start serving requests */
         conn->refcount++;
 	conn->request_handler =
-		auth_request_handler_create(auth_callback, conn,
+		auth_request_handler_create(conn->token_auth, auth_callback, conn,
 					    !conn->login_requests ? NULL :
 					    auth_master_request_callback);
 	auth_request_handler_set(conn->request_handler, conn->connect_uid, pid);
@@ -294,10 +294,11 @@
 }
 
 void auth_client_connection_create(struct auth *auth, int fd,
-				   bool login_requests)
+				   bool login_requests, bool token_auth)
 {
 	static unsigned int connect_uid_counter = 0;
 	struct auth_client_connection *conn;
+	const char *mechanisms;
 	string_t *str;
 
 	conn = i_new(struct auth_client_connection, 1);
@@ -305,6 +306,7 @@
 	conn->refcount = 1;
 	conn->connect_uid = ++connect_uid_counter;
 	conn->login_requests = login_requests;
+	conn->token_auth = token_auth;
 	random_fill(conn->cookie, sizeof(conn->cookie));
 
 	conn->fd = fd;
@@ -317,11 +319,18 @@
 
 	DLLIST_PREPEND(&auth_client_connections, conn);
 
+	if (token_auth) {
+		mechanisms = t_strconcat("MECH\t",
+			mech_dovecot_token.mech_name, "\n", NULL);
+	} else {
+		mechanisms = str_c(auth->reg->handshake);
+	}
+
 	str = t_str_new(128);
 	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(auth->reg->handshake), my_pid, conn->connect_uid);
+		    mechanisms, my_pid, conn->connect_uid);
 	binary_to_hex_append(str, conn->cookie, sizeof(conn->cookie));
 	str_append(str, "\nDONE\n");
 
diff -r b74e8de5f3d9 -r aa6027a0a78e src/auth/auth-client-connection.h
--- a/src/auth/auth-client-connection.h	Fri Sep 14 21:31:45 2012 +0300
+++ b/src/auth/auth-client-connection.h	Fri Sep 14 21:48:45 2012 +0300
@@ -20,10 +20,11 @@
 
 	unsigned int login_requests:1;
 	unsigned int version_received:1;
+	unsigned int token_auth:1;
 };
 
 void auth_client_connection_create(struct auth *auth, int fd,
-				   bool login_requests);
+				   bool login_requests, bool token_auth);
 void auth_client_connection_destroy(struct auth_client_connection **conn);
 
 struct auth_client_connection *
diff -r b74e8de5f3d9 -r aa6027a0a78e src/auth/auth-master-connection.c
--- a/src/auth/auth-master-connection.c	Fri Sep 14 21:31:45 2012 +0300
+++ b/src/auth/auth-master-connection.c	Fri Sep 14 21:48:45 2012 +0300
@@ -95,12 +95,12 @@
 master_input_request(struct auth_master_connection *conn, const char *args)
 {
 	struct auth_client_connection *client_conn;
-	const char *const *list;
+	const char *const *list, *const *params;
 	unsigned int id, client_pid, client_id;
 	uint8_t cookie[MASTER_AUTH_COOKIE_SIZE];
 	buffer_t buf;
 
-	/* <id> <client-pid> <client-id> <cookie> */
+	/* <id> <client-pid> <client-id> <cookie> [<parameters>] */
 	list = t_strsplit_tab(args);
 	if (str_array_length(list) < 4 ||
 	    str_to_uint(list[0], &id) < 0 ||
@@ -115,6 +115,7 @@
 		i_error("BUG: Master sent broken REQUEST cookie");
 		return FALSE;
 	}
+	params = list + 4;
 
 	client_conn = auth_client_connection_lookup(client_pid);
 	if (client_conn == NULL) {
@@ -128,7 +129,7 @@
 		o_stream_nsend_str(conn->output,
 				   t_strdup_printf("FAIL\t%u\n", id));
 	} else if (!auth_request_handler_master_request(
-			client_conn->request_handler, conn, id, client_id)) {
+			client_conn->request_handler, conn, id, client_id, params)) {
 		i_error("Master requested auth for non-login client %u",
 			client_pid);
 		o_stream_nsend_str(conn->output,
diff -r b74e8de5f3d9 -r aa6027a0a78e src/auth/auth-request-handler.c
--- a/src/auth/auth-request-handler.c	Fri Sep 14 21:31:45 2012 +0300
+++ b/src/auth/auth-request-handler.c	Fri Sep 14 21:48:45 2012 +0300
@@ -6,11 +6,13 @@
 #include "aqueue.h"
 #include "base64.h"
 #include "hash.h"
+#include "network.h"
 #include "str.h"
 #include "str-sanitize.h"
 #include "master-interface.h"
 #include "auth-penalty.h"
 #include "auth-request.h"
+#include "auth-token.h"
 #include "auth-master-connection.h"
 #include "auth-request-handler.h"
 
@@ -31,6 +33,7 @@
 	auth_request_callback_t *master_callback;
 
 	unsigned int destroyed:1;
+	unsigned int token_auth:1;
 };
 
 static ARRAY(struct auth_request *) auth_failures_arr;
@@ -41,8 +44,8 @@
 
 #undef auth_request_handler_create
 struct auth_request_handler *
-auth_request_handler_create(auth_request_callback_t *callback, void *context,
-			    auth_request_callback_t *master_callback)
+auth_request_handler_create(bool token_auth, auth_request_callback_t *callback,
+			    void *context, auth_request_callback_t *master_callback)
 {
 	struct auth_request_handler *handler;
 	pool_t pool;
@@ -56,6 +59,7 @@
 	handler->callback = callback;
 	handler->context = context;
 	handler->master_callback = master_callback;
+	handler->token_auth = token_auth;
 	return handler;
 }
 
@@ -461,13 +465,24 @@
 		return FALSE;
 	}
 
-	mech = mech_module_find(list[1]);
-	if (mech == NULL) {
-		/* unsupported mechanism */
-		i_error("BUG: Authentication client %u requested unsupported "
-			"authentication mechanism %s", handler->client_pid,
-			str_sanitize(list[1], MAX_MECH_NAME_LEN));
-		return FALSE;
+	if (handler->token_auth) {
+		mech = &mech_dovecot_token;
+		if (strcmp(list[1], mech->mech_name) != 0) {
+			/* unsupported mechanism */
+			i_error("BUG: Authentication client %u requested invalid "
+				"authentication mechanism %s (DOVECOT-TOKEN required)",
+				handler->client_pid, str_sanitize(list[1], MAX_MECH_NAME_LEN));
+			return FALSE;
+		}
+	} else {		 
+		mech = mech_module_find(list[1]);
+		if (mech == NULL) {
+			/* unsupported mechanism */
+			i_error("BUG: Authentication client %u requested unsupported "
+				"authentication mechanism %s", handler->client_pid,
+				str_sanitize(list[1], MAX_MECH_NAME_LEN));
+			return FALSE;
+		}
 	}
 
 	request = auth_request_new(mech);
@@ -664,8 +679,19 @@
 			auth_stream_reply_add(request->userdb_reply,
 					      "anonymous", NULL);
 		}
+
 		auth_stream_reply_import(reply,
 			auth_stream_reply_export(request->userdb_reply));
+
+		/* generate auth_token when master service provided session_pid */
+		if (request->session_pid != (pid_t)-1) {
+			const char *auth_token =
+				auth_token_get(request->service,
+					       dec2str(request->session_pid),
+					       request->user,
+					       request->session_id);
+			auth_stream_reply_add(reply, "auth_token", auth_token);
+		}
 		break;
 	}
 	handler->master_callback(reply, request->master);
@@ -675,13 +701,27 @@
         auth_request_handler_unref(&handler);
 }
 
+static bool
+auth_master_request_failed(struct auth_request_handler *handler,
+			   struct auth_master_connection *master,
+			   struct auth_stream_reply *reply, unsigned int id)
+{
+	auth_stream_reply_add(reply, "FAIL", NULL);
+	auth_stream_reply_add(reply, NULL, dec2str(id));
+	if (handler->master_callback == NULL)
+		return FALSE;
+	handler->master_callback(reply, master);
+	return TRUE;
+}
+
 bool auth_request_handler_master_request(struct auth_request_handler *handler,
 					 struct auth_master_connection *master,
-					 unsigned int id,
-					 unsigned int client_id)
+					 unsigned int id, unsigned int client_id,
+					 const char *const *params)
 {
 	struct auth_request *request;
 	struct auth_stream_reply *reply;
+	struct net_unix_cred cred;
 
 	reply = auth_stream_reply_init(pool_datastack_create());
 
@@ -689,17 +729,38 @@
 	if (request == NULL) {
 		i_error("Master request %u.%u not found",
 			handler->client_pid, client_id);
-		auth_stream_reply_add(reply, "FAIL", NULL);
-		auth_stream_reply_add(reply, NULL, dec2str(id));
-		if (handler->master_callback == NULL)
-			return FALSE;
-		handler->master_callback(reply, master);
-		return TRUE;
+		return auth_master_request_failed(handler, master, reply, id);
 	}
 
 	auth_request_ref(request);
 	auth_request_handler_remove(handler, request);
 
+	for (; *params != NULL; params++) {
+		const char *name, *param = strchr(*params, '=');
+
+		if (param == NULL) {
+			name = *params;
+			param = "";
+		} else {
+			name = t_strdup_until(*params, param);
+			param++;
+		}
+
+		(void)auth_request_import_master(request, name, param);
+	}
+
+	/* verify session pid if specified and possible */
+	if (request->session_pid != (pid_t)-1 &&
+	    net_getunixcred(master->fd, &cred) == 0 &&
+	    cred.pid != (pid_t)-1 && request->session_pid != cred.pid) {
+		i_error("Session pid %ld provided by master for request %u.%u "
+			"did not match peer credentials (pid=%ld, uid=%ld)",
+			(long)request->session_pid,
+			handler->client_pid, client_id,
+			(long)cred.pid, (long)cred.uid);
+		return auth_master_request_failed(handler, master, reply, id);
+	}
+
 	if (request->state != AUTH_REQUEST_STATE_FINISHED ||


More information about the dovecot-cvs mailing list