changeset 810:30f6811f4952 HEAD

Instead of just trusting randomness of authentication cookies between auth<->master<->login process IPC, master now doesn't accept any cookies from login process which weren't created by it (identified by PID). When login process dies, all it's pending cookies are also removed, so I can't see even a theoretical possiblity anymore for exploited login process to authenticate as someone else. Also fixed some int -> unsigned int.
author Timo Sirainen <tss@iki.fi>
date Fri, 20 Dec 2002 01:56:23 +0200
parents 27554afad17e
children 664de3231e33
files src/auth/auth-digest-md5.c src/auth/auth-interface.h src/auth/auth-plain.c src/auth/auth.c src/auth/auth.h src/auth/cookie.c src/auth/cookie.h src/auth/login-connection.c src/auth/main.c src/auth/master.c src/login/auth-connection.c src/login/auth-connection.h src/login/client-authenticate.c src/login/common.h src/login/main.c src/login/master.c src/login/master.h src/master/auth-process.c src/master/auth-process.h src/master/common.h src/master/login-process.c src/master/main.c src/master/master-interface.h src/master/settings.c src/master/settings.h
diffstat 25 files changed, 209 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/auth-digest-md5.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/auth-digest-md5.c	Fri Dec 20 01:56:23 2002 +0200
@@ -575,7 +575,8 @@
 	pool_unref(((AuthData *) cookie->context)->pool);
 }
 
-static void auth_digest_md5_init(AuthInitRequestData *request,
+static void auth_digest_md5_init(unsigned int login_pid,
+				 AuthInitRequestData *request,
 				 AuthCallback callback, void *context)
 {
 	CookieData *cookie;
@@ -591,6 +592,7 @@
 	auth->qop = QOP_AUTH;
 
 	cookie = p_new(pool, CookieData, 1);
+	cookie->login_pid = login_pid;
 	cookie->auth_fill_reply = auth_digest_md5_fill_reply;
 	cookie->auth_continue = auth_digest_md5_continue;
 	cookie->free = auth_digest_md5_free;
--- a/src/auth/auth-interface.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/auth-interface.h	Fri Dec 20 01:56:23 2002 +0200
@@ -34,16 +34,21 @@
 
 /* Initialization reply, sent after client is connected */
 typedef struct {
-	int auth_process; /* unique auth process identifier */
+	unsigned int auth_process; /* unique auth process identifier */
 	AuthMethod auth_methods; /* valid authentication methods */
 } AuthInitData;
 
+/* Initialization handshake from client. */
+typedef struct {
+	unsigned int pid; /* unique identifier for client process */
+} ClientAuthInitData;
+
 /* New authentication request */
 typedef struct {
 	AuthRequestType type; /* AUTH_REQUEST_INIT */
 
 	AuthMethod method;
-	int id; /* AuthReplyData.id will contain this value */
+	unsigned int id; /* AuthReplyData.id will contain this value */
 } AuthInitRequestData;
 
 /* Continued authentication request */
@@ -51,7 +56,7 @@
 	AuthRequestType type; /* AUTH_REQUEST_CONTINUE */
 
 	unsigned char cookie[AUTH_COOKIE_SIZE];
-	int id; /* AuthReplyData.id will contain this value */
+	unsigned int id; /* AuthReplyData.id will contain this value */
 
 	size_t data_size;
 	/* unsigned char data[]; */
@@ -59,7 +64,7 @@
 
 /* Reply to authentication */
 typedef struct {
-	int id;
+	unsigned int id;
 	unsigned char cookie[AUTH_COOKIE_SIZE];
 	AuthResult result;
 
@@ -69,13 +74,14 @@
 
 /* Request data associated to cookie */
 typedef struct {
-	int id;
+	unsigned int id;
+	unsigned int login_pid;
 	unsigned char cookie[AUTH_COOKIE_SIZE];
 } AuthCookieRequestData;
 
 /* Reply to cookie request */
 typedef struct {
-	int id;
+	unsigned int id;
 	int success; /* FALSE if cookie wasn't found */
 
 	char system_user[AUTH_MAX_USER_LEN]; /* system user, if available */
--- a/src/auth/auth-plain.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/auth-plain.c	Fri Dec 20 01:56:23 2002 +0200
@@ -80,13 +80,15 @@
 	i_free(cookie);
 }
 
-static void auth_plain_init(AuthInitRequestData *request,
+static void auth_plain_init(unsigned int login_pid,
+			    AuthInitRequestData *request,
 			    AuthCallback callback, void *context)
 {
 	CookieData *cookie;
 	AuthReplyData reply;
 
 	cookie = i_new(CookieData, 1);
+	cookie->login_pid = login_pid;
 	cookie->auth_fill_reply = auth_plain_fill_reply;
 	cookie->auth_continue = auth_plain_continue;
 	cookie->free = auth_plain_free;
--- a/src/auth/auth.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/auth.c	Fri Dec 20 01:56:23 2002 +0200
@@ -54,7 +54,8 @@
 	}
 }
 
-void auth_init_request(AuthInitRequestData *request,
+void auth_init_request(unsigned int login_pid,
+		       AuthInitRequestData *request,
 		       AuthCallback callback, void *context)
 {
 	AuthModuleList *list;
@@ -70,7 +71,8 @@
 
 	for (list = auth_modules; list != NULL; list = list->next) {
 		if (list->module.method == request->method) {
-			list->module.init(request, callback, context);
+			list->module.init(login_pid, request,
+					  callback, context);
 			return;
 		}
 	}
@@ -78,7 +80,8 @@
 	i_unreached();
 }
 
-void auth_continue_request(AuthContinuedRequestData *request,
+void auth_continue_request(unsigned int login_pid,
+			   AuthContinuedRequestData *request,
 			   const unsigned char *data,
 			   AuthCallback callback, void *context)
 {
@@ -89,9 +92,11 @@
 		/* timeouted cookie */
 		failure_reply.id = request->id;
 		callback(&failure_reply, NULL, context);
+	} else if (cookie_data->login_pid != login_pid) {
+		i_error("BUG: imap-login requested cookie it didn't own");
 	} else {
-		cookie_data->auth_continue(cookie_data, request, data,
-					   callback, context);
+		cookie_data->auth_continue(cookie_data, request,
+					   data, callback, context);
 	}
 }
 
--- a/src/auth/auth.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/auth.h	Fri Dec 20 01:56:23 2002 +0200
@@ -9,7 +9,8 @@
 typedef struct {
 	AuthMethod method;
 
-	void (*init)(AuthInitRequestData *request,
+	void (*init)(unsigned int login_pid,
+		     AuthInitRequestData *request,
 		     AuthCallback callback, void *context);
 } AuthModule;
 
@@ -19,9 +20,11 @@
 void auth_register_module(AuthModule *module);
 void auth_unregister_module(AuthModule *module);
 
-void auth_init_request(AuthInitRequestData *request,
+void auth_init_request(unsigned int login_pid,
+		       AuthInitRequestData *request,
 		       AuthCallback callback, void *context);
-void auth_continue_request(AuthContinuedRequestData *request,
+void auth_continue_request(unsigned int login_pid,
+			   AuthContinuedRequestData *request,
 			   const unsigned char *data,
 			   AuthCallback callback, void *context);
 
--- a/src/auth/cookie.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/cookie.c	Fri Dec 20 01:56:23 2002 +0200
@@ -84,6 +84,7 @@
 
 	hash_remove(cookies, cookie);
 
+	/* FIXME: slow */
 	list = NULL;
 	for (pos = &oldest_cookie; *pos != NULL; pos = &(*pos)->next) {
 		if (cookie_cmp((*pos)->data->cookie, cookie) == 0) {
@@ -112,16 +113,34 @@
 	cookie_destroy(cookie, TRUE);
 }
 
-CookieData *cookie_lookup_and_remove(unsigned char cookie[AUTH_COOKIE_SIZE])
+CookieData *cookie_lookup_and_remove(unsigned int login_pid,
+				     unsigned char cookie[AUTH_COOKIE_SIZE])
 {
 	CookieData *data;
 
 	data = hash_lookup(cookies, cookie);
-	if (data != NULL)
-		cookie_destroy(cookie, FALSE);
+	if (data != NULL) {
+		if (data->login_pid != login_pid)
+			data = NULL;
+		else
+			cookie_destroy(cookie, FALSE);
+	}
 	return data;
 }
 
+void cookies_remove_login_pid(unsigned int login_pid)
+{
+	CookieList *list, *next;
+
+	/* FIXME: slow */
+	for (list = oldest_cookie; list != NULL; list = next) {
+		next = list->next;
+
+		if (list->data->login_pid == login_pid)
+			cookie_destroy(list->data->cookie, TRUE);
+	}
+}
+
 static void cookie_timeout(void *context __attr_unused__,
 			   Timeout timeout __attr_unused__)
 {
--- a/src/auth/cookie.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/cookie.h	Fri Dec 20 01:56:23 2002 +0200
@@ -6,6 +6,7 @@
 typedef struct _CookieData CookieData;
 
 struct _CookieData {
+	unsigned int login_pid;
 	unsigned char cookie[AUTH_COOKIE_SIZE];
 
 	/* continue authentication */
@@ -32,7 +33,11 @@
 /* Removes and frees the cookie */
 void cookie_remove(unsigned char cookie[AUTH_COOKIE_SIZE]);
 /* Looks up the cookie and removes it, you have to free the returned data. */
-CookieData *cookie_lookup_and_remove(unsigned char cookie[AUTH_COOKIE_SIZE]);
+CookieData *cookie_lookup_and_remove(unsigned int login_pid,
+				     unsigned char cookie[AUTH_COOKIE_SIZE]);
+
+/* Remove all cookies created by a login process. */
+void cookies_remove_login_pid(unsigned int login_pid);
 
 void cookies_init(void);
 void cookies_deinit(void);
--- a/src/auth/login-connection.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/login-connection.c	Fri Dec 20 01:56:23 2002 +0200
@@ -6,6 +6,7 @@
 #include "ostream.h"
 #include "network.h"
 #include "safe-memset.h"
+#include "cookie.h"
 #include "login-connection.h"
 
 #include <stdlib.h>
@@ -23,7 +24,9 @@
 	IO io;
 	IStream *input;
 	OStream *output;
-        AuthRequestType type;
+
+	unsigned int pid;
+	AuthRequestType type;
 };
 
 static AuthInitData auth_init_data;
@@ -44,27 +47,49 @@
 	}
 }
 
-static void login_input(void *context, int fd __attr_unused__,
-			IO io __attr_unused__)
+static LoginConnection *login_find_pid(unsigned int pid)
 {
-	LoginConnection *conn  = context;
+	LoginConnection *conn;
+
+	for (conn = connections; conn != NULL; conn = conn->next) {
+		if (conn->pid == pid)
+			return conn;
+	}
+
+	return NULL;
+}
+
+static void login_input_handshake(LoginConnection *conn)
+{
+        ClientAuthInitData rec;
         unsigned char *data;
 	size_t size;
 
-	switch (i_stream_read(conn->input)) {
-	case 0:
-		return;
-	case -1:
-		/* disconnected */
-		login_connection_destroy(conn);
+	data = i_stream_get_modifyable_data(conn->input, &size);
+	if (size < sizeof(ClientAuthInitData))
 		return;
-	case -2:
-		/* buffer full */
-		i_error("BUG: imap-login sent us more than %d bytes of data",
-			(int)MAX_INBUF_SIZE);
+
+	/* Don't just cast because of alignment issues. */
+	memcpy(&rec, data, sizeof(rec));
+	i_stream_skip(conn->input, sizeof(rec));
+
+	if (rec.pid == 0) {
+		i_error("BUG: imap-login said it's PID 0");
 		login_connection_destroy(conn);
-		return;
+	} else if (login_find_pid(rec.pid) != NULL) {
+		/* well, it might have just reconnected very fast .. although
+		   there's not much reason for it. */
+		i_error("BUG: imap-login gave a PID of existing connection");
+		login_connection_destroy(conn);
+	} else {
+		conn->pid = rec.pid;
 	}
+}
+
+static void login_input_request(LoginConnection *conn)
+{
+        unsigned char *data;
+	size_t size;
 
 	data = i_stream_get_modifyable_data(conn->input, &size);
 	if (size < sizeof(AuthRequestType))
@@ -87,7 +112,7 @@
 		i_stream_skip(conn->input, sizeof(request));
 
 		/* we have a full init request */
-		auth_init_request(&request, request_callback, conn);
+		auth_init_request(conn->pid, &request, request_callback, conn);
 		conn->type = AUTH_REQUEST_NONE;
 	} else if (conn->type == AUTH_REQUEST_CONTINUE) {
                 AuthContinuedRequestData request;
@@ -102,7 +127,8 @@
 		i_stream_skip(conn->input, sizeof(request) + request.data_size);
 
 		/* we have a full continued request */
-		auth_continue_request(&request, data + sizeof(request),
+		auth_continue_request(conn->pid, &request,
+				      data + sizeof(request),
 				      request_callback, conn);
 		conn->type = AUTH_REQUEST_NONE;
 
@@ -116,6 +142,32 @@
 	}
 }
 
+static void login_input(void *context, int fd __attr_unused__,
+			IO io __attr_unused__)
+{
+	LoginConnection *conn  = context;
+
+	switch (i_stream_read(conn->input)) {
+	case 0:
+		return;
+	case -1:
+		/* disconnected */
+		login_connection_destroy(conn);
+		return;
+	case -2:
+		/* buffer full */
+		i_error("BUG: imap-login sent us more than %d bytes of data",
+			(int)MAX_INBUF_SIZE);
+		login_connection_destroy(conn);
+		return;
+	}
+
+	if (conn->pid == 0)
+		login_input_handshake(conn);
+	else
+		login_input_request(conn);
+}
+
 LoginConnection *login_connection_create(int fd)
 {
 	LoginConnection *conn;
@@ -153,6 +205,8 @@
 		}
 	}
 
+	cookies_remove_login_pid(conn->pid);
+
 	i_stream_unref(conn->input);
 	o_stream_unref(conn->output);
 
--- a/src/auth/main.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/main.c	Fri Dec 20 01:56:23 2002 +0200
@@ -71,7 +71,8 @@
 	master_init();
 	userinfo_init();
 
-	io_listen = io_add(LOGIN_LISTEN_FD, IO_READ, auth_accept, NULL);
+	io_listen = io_add_priority(LOGIN_LISTEN_FD, IO_PRIORITY_LOW,
+				    IO_READ, auth_accept, NULL);
 }
 
 static void main_deinit(void)
--- a/src/auth/master.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/auth/master.c	Fri Dec 20 01:56:23 2002 +0200
@@ -23,7 +23,7 @@
 	CookieData *cookie;
         AuthCookieReplyData *reply, temp_reply;
 
-	cookie = cookie_lookup_and_remove(request->cookie);
+	cookie = cookie_lookup_and_remove(request->login_pid, request->cookie);
 	if (cookie == NULL)
 		reply = &failure_reply;
 	else {
--- a/src/login/auth-connection.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/login/auth-connection.c	Fri Dec 20 01:56:23 2002 +0200
@@ -25,7 +25,7 @@
 	IStream *input;
 	OStream *output;
 
-	int auth_process;
+	unsigned int auth_process;
 	AuthMethod available_auth_methods;
         AuthReplyData in_reply;
 
@@ -38,10 +38,11 @@
 AuthMethod available_auth_methods;
 
 static int auth_reconnect;
-static int request_id_counter;
+static unsigned int request_id_counter;
 static AuthConnection *auth_connections;
 static Timeout to;
 
+static void auth_connection_destroy(AuthConnection *conn);
 static void auth_input(void *context, int fd, IO io);
 static void auth_connect_missing(void);
 
@@ -59,7 +60,8 @@
 
 static AuthConnection *auth_connection_new(const char *path)
 {
-        AuthConnection *conn;
+	AuthConnection *conn;
+        ClientAuthInitData init_data;
 	int fd;
 
 	fd = net_connect_unix(path);
@@ -81,6 +83,14 @@
 
 	conn->next = auth_connections;
 	auth_connections = conn;
+
+	/* send our handshake */
+	memset(&init_data, 0, sizeof(init_data));
+	init_data.pid = login_process_uid;
+	if (o_stream_send(conn->output, &init_data, sizeof(init_data)) < 0) {
+                auth_connection_destroy(conn);
+		return NULL;
+	}
 	return conn;
 }
 
--- a/src/login/auth-connection.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/login/auth-connection.h	Fri Dec 20 01:56:23 2002 +0200
@@ -5,7 +5,7 @@
 
 /* If result == AUTH_RESULT_INTERNAL_FAILURE, request may be NULL and
    reply_data_size contains the error message. */
-typedef void (*AuthCallback)(AuthRequest *request, int auth_process,
+typedef void (*AuthCallback)(AuthRequest *request, unsigned int auth_process,
 			     AuthResult result, const unsigned char *reply_data,
 			     size_t reply_data_size, void *context);
 
@@ -13,7 +13,7 @@
         AuthMethod method;
         AuthConnection *conn;
 
-	int id;
+	unsigned int id;
 	unsigned char cookie[AUTH_COOKIE_SIZE];
 
 	AuthCallback callback;
--- a/src/login/client-authenticate.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/login/client-authenticate.c	Fri Dec 20 01:56:23 2002 +0200
@@ -123,7 +123,7 @@
 	t_pop();
 }
 
-static int auth_callback(AuthRequest *request, int auth_process,
+static int auth_callback(AuthRequest *request, unsigned int auth_process,
 			 AuthResult result, const unsigned char *reply_data,
 			 size_t reply_data_size, void *context)
 {
@@ -167,7 +167,7 @@
 	}
 }
 
-static void login_callback(AuthRequest *request, int auth_process,
+static void login_callback(AuthRequest *request, unsigned int auth_process,
 			   AuthResult result, const unsigned char *reply_data,
 			   size_t reply_data_size, void *context)
 {
@@ -219,8 +219,8 @@
 	}
 }
 
-static void authenticate_callback(AuthRequest *request, int auth_process,
-				  AuthResult result,
+static void authenticate_callback(AuthRequest *request,
+				  unsigned int auth_process, AuthResult result,
 				  const unsigned char *reply_data,
 				  size_t reply_data_size, void *context)
 {
--- a/src/login/common.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/login/common.h	Fri Dec 20 01:56:23 2002 +0200
@@ -9,6 +9,7 @@
 
 extern int disable_plaintext_auth, process_per_connection, verbose_proctitle;
 extern unsigned int max_logging_users;
+extern unsigned int login_process_uid;
 
 void main_ref(void);
 void main_unref(void);
--- a/src/login/main.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/login/main.c	Fri Dec 20 01:56:23 2002 +0200
@@ -17,6 +17,7 @@
 
 int disable_plaintext_auth, process_per_connection, verbose_proctitle;
 unsigned int max_logging_users;
+unsigned int login_process_uid;
 
 static IOLoop ioloop;
 static IO io_imap, io_imaps;
@@ -153,6 +154,13 @@
 	value = getenv("MAX_LOGGING_USERS");
 	max_logging_users = value == NULL ? 0 : strtoul(value, NULL, 10);
 
+	value = getenv("PROCESS_UID");
+	if (value == NULL)
+		i_fatal("BUG: PROCESS_UID environment not given");
+        login_process_uid = strtoul(value, NULL, 10);
+	if (login_process_uid == 0)
+		i_fatal("BUG: PROCESS_UID environment is 0");
+
         closing_down = FALSE;
 	main_refcount = 0;
 
--- a/src/login/master.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/login/master.c	Fri Dec 20 01:56:23 2002 +0200
@@ -14,7 +14,7 @@
 struct _WaitingRequest {
 	WaitingRequest *next;
 
-	int id;
+	unsigned int id;
 	MasterCallback callback;
 	void *context;
 };
@@ -25,7 +25,8 @@
 static unsigned int master_pos;
 static char master_buf[sizeof(MasterReply)];
 
-static void push_request(int id, MasterCallback callback, void *context)
+static void push_request(unsigned int id, MasterCallback callback,
+			 void *context)
 {
 	WaitingRequest *req;
 
@@ -63,7 +64,8 @@
 	i_free(req);
 }
 
-void master_request_imap(int fd, int auth_process, const char *login_tag,
+void master_request_imap(int fd, unsigned int auth_process,
+			 const char *login_tag,
 			 unsigned char cookie[AUTH_COOKIE_SIZE], IPADDR *ip,
 			 MasterCallback callback, void *context)
 {
--- a/src/login/master.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/login/master.h	Fri Dec 20 01:56:23 2002 +0200
@@ -6,7 +6,8 @@
 typedef void (*MasterCallback)(MasterReplyResult result, void *context);
 
 /* Request IMAP process for given cookie. */
-void master_request_imap(int fd, int auth_process,  const char *login_tag,
+void master_request_imap(int fd, unsigned int auth_process,
+			 const char *login_tag,
 			 unsigned char cookie[AUTH_COOKIE_SIZE], IPADDR *ip,
 			 MasterCallback callback, void *context);
 
--- a/src/master/auth-process.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/master/auth-process.c	Fri Dec 20 01:56:23 2002 +0200
@@ -35,7 +35,7 @@
 
 struct _WaitingRequest {
         WaitingRequest *next;
-	int id;
+	unsigned int id;
 
 	AuthCallback callback;
 	void *context;
@@ -46,7 +46,7 @@
 
 static void auth_process_destroy(AuthProcess *p);
 
-static void push_request(AuthProcess *process, int id,
+static void push_request(AuthProcess *process, unsigned int id,
 			 AuthCallback callback, void *context)
 {
 	WaitingRequest *req;
@@ -275,25 +275,27 @@
 	return -1;
 }
 
-AuthProcess *auth_process_find(int id)
+AuthProcess *auth_process_find(unsigned int id)
 {
 	AuthProcess *p;
 
 	for (p = processes; p != NULL; p = p->next) {
-		if (p->pid == id)
+		if ((unsigned int)p->pid == id)
 			return p;
 	}
 
 	return NULL;
 }
 
-void auth_process_request(AuthProcess *process, int id,
+void auth_process_request(unsigned int login_pid,
+			  AuthProcess *process, unsigned int id,
 			  unsigned char cookie[AUTH_COOKIE_SIZE],
 			  AuthCallback callback, void *context)
 {
 	AuthCookieRequestData req;
 
 	req.id = id;
+	req.login_pid = login_pid;
 	memcpy(req.cookie, cookie, AUTH_COOKIE_SIZE);
 
 	if (o_stream_send(process->output, &req, sizeof(req)) < 0)
@@ -302,10 +304,10 @@
 	push_request(process, id, callback, context);
 }
 
-static int auth_process_get_count(const char *name)
+static unsigned int auth_process_get_count(const char *name)
 {
 	AuthProcess *p;
-	int count = 0;
+	unsigned int count = 0;
 
 	for (p = processes; p != NULL; p = p->next) {
 		if (strcmp(p->name, name) == 0)
@@ -330,7 +332,7 @@
 					 Timeout timeout __attr_unused__)
 {
 	AuthConfig *config;
-	int count;
+	unsigned int count;
 
         config = auth_processes_config;
 	for (; config != NULL; config = config->next) {
--- a/src/master/auth-process.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/master/auth-process.h	Fri Dec 20 01:56:23 2002 +0200
@@ -8,10 +8,11 @@
 typedef struct _AuthProcess AuthProcess;
 
 /* Find process for given id */
-AuthProcess *auth_process_find(int id);
+AuthProcess *auth_process_find(unsigned int id);
 
 /* Request information about given cookie */
-void auth_process_request(AuthProcess *process, int id,
+void auth_process_request(unsigned int login_pid,
+			  AuthProcess *process, unsigned int id,
 			  unsigned char cookie[AUTH_COOKIE_SIZE],
 			  AuthCallback callback, void *context);
 
--- a/src/master/common.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/master/common.h	Fri Dec 20 01:56:23 2002 +0200
@@ -44,6 +44,6 @@
 /* misc */
 #define VALIDATE_STR(str) \
 	validate_str(str, sizeof(str))
-int validate_str(const char *str, int max_len);
+int validate_str(const char *str, size_t max_len);
 
 #endif
--- a/src/master/login-process.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/master/login-process.c	Fri Dec 20 01:56:23 2002 +0200
@@ -32,15 +32,15 @@
 
 typedef struct {
 	LoginProcess *process;
-	int login_id;
-	int auth_id;
+	unsigned int login_id;
+	unsigned int auth_id;
 	int fd;
 
 	IPADDR ip;
 	char login_tag[LOGIN_TAG_SIZE];
 } LoginAuthRequest;
 
-static int auth_id_counter;
+static unsigned int auth_id_counter;
 static Timeout to;
 
 static HashTable *processes;
@@ -163,8 +163,8 @@
 			req.auth_process);
 		auth_callback(NULL, authreq);
 	} else {
-		auth_process_request(auth_process, authreq->auth_id, req.cookie,
-				     auth_callback, authreq);
+		auth_process_request(p->pid, auth_process, authreq->auth_id,
+				     req.cookie, auth_callback, authreq);
 	}
 }
 
@@ -321,10 +321,12 @@
 		env_put("PROCESS_PER_CONNECTION=1");
 		env_put("MAX_LOGGING_USERS=1");
 	} else {
-		env_put(t_strdup_printf("MAX_LOGGING_USERS=%d",
+		env_put(t_strdup_printf("MAX_LOGGING_USERS=%u",
 					set_max_logging_users));
 	}
 
+	env_put(t_strdup_printf("PROCESS_UID=%s", dec2str(getpid())));
+
 	restrict_process_size(set_login_process_size);
 
 	/* make sure we don't leak syslog fd, but do it last so that
--- a/src/master/main.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/master/main.c	Fri Dec 20 01:56:23 2002 +0200
@@ -34,9 +34,9 @@
 HashTable *pids;
 int null_fd, imap_fd, imaps_fd;
 
-int validate_str(const char *str, int max_len)
+int validate_str(const char *str, size_t max_len)
 {
-	int i;
+	size_t i;
 
 	for (i = 0; i < max_len; i++) {
 		if (str[i] == '\0')
@@ -125,8 +125,8 @@
 			if (status != 0) {
 				login_process_abormal_exit(pid);
 				msg = get_exit_status_message(status);
-				if (msg != NULL)
-					msg = t_strconcat(" (", msg, ")", NULL);
+				msg = msg == NULL ? "" :
+					t_strconcat(" (", msg, ")", NULL);
 				i_error("child %s (%s) returned error %d%s",
 					dec2str(pid), process_type_name,
 					status, msg);
--- a/src/master/master-interface.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/master/master-interface.h	Fri Dec 20 01:56:23 2002 +0200
@@ -17,9 +17,9 @@
 } MasterReplyResult;
 
 typedef struct {
-	int id;
+	unsigned int id;
 
-	int auth_process;
+	unsigned int auth_process;
 	unsigned char cookie[AUTH_COOKIE_SIZE];
 
 	IPADDR ip;
@@ -27,7 +27,7 @@
 } MasterRequest;
 
 typedef struct {
-	int id;
+	unsigned int id;
         MasterReplyResult result;
 } MasterReply;
 
--- a/src/master/settings.c	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/master/settings.c	Fri Dec 20 01:56:23 2002 +0200
@@ -368,14 +368,20 @@
 	}
 
 	if (strcmp(key, "auth_count") == 0) {
-		if (!sscanf(value, "%i", &auth->count))
+		int num;
+
+		if (!sscanf(value, "%i", &num) || num < 0)
 			return t_strconcat("Invalid number: ", value, NULL);
+                auth->count = num;
 		return NULL;
 	}
 
 	if (strcmp(key, "auth_process_size") == 0) {
-		if (!sscanf(value, "%i", &auth->process_size))
+		int num;
+
+		if (!sscanf(value, "%i", &num) || num < 0)
 			return t_strconcat("Invalid number: ", value, NULL);
+                auth->process_size = num;
 		return NULL;
 	}
 
--- a/src/master/settings.h	Thu Dec 19 03:53:19 2002 +0200
+++ b/src/master/settings.h	Fri Dec 20 01:56:23 2002 +0200
@@ -72,7 +72,7 @@
 	char *user;
 	char *chroot;
 
-	int count;
+	unsigned int count;
 	unsigned int process_size;
 };