changeset 3607:a2dd3d895e00 HEAD

Several fixes to make running from inetd working again
author Timo Sirainen <tss@iki.fi>
date Sat, 24 Sep 2005 15:25:25 +0300
parents 8a8352cda514
children b86d4c76efdf
files src/login-common/main.c src/master/login-process.c
diffstat 2 files changed, 52 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/login-common/main.c	Sat Sep 24 13:50:38 2005 +0300
+++ b/src/login-common/main.c	Sat Sep 24 15:25:25 2005 +0300
@@ -26,6 +26,7 @@
 unsigned int login_process_uid;
 struct auth_client *auth_client;
 
+static const char *process_name;
 static struct ioloop *ioloop;
 static struct io *io_listen, *io_ssl_listen;
 static int main_refcount;
@@ -134,9 +135,23 @@
                 clients_notify_auth_connected();
 }
 
-static void drop_privileges()
+static void drop_privileges(void)
 {
-	i_set_failure_internal();
+	const char *env;
+
+	if (!is_inetd)
+		i_set_failure_internal();
+	else {
+		/* log to syslog */
+		i_set_failure_syslog(process_name, LOG_NDELAY, LOG_MAIL);
+
+		/* if we don't chroot, we must chdir */
+		env = getenv("LOGIN_DIR");
+		if (env != NULL) {
+			if (chdir(env) < 0)
+				i_error("chdir(%s) failed: %m", env);
+		}
+	}
 
 	/* Initialize SSL proxy so it can read certificate and private
 	   key file. */
@@ -190,7 +205,7 @@
         closing_down = FALSE;
 	main_refcount = 0;
 
-	auth_client = auth_client_new((unsigned int)getpid());
+	auth_client = auth_client_new(login_process_uid);
         auth_client_set_connect_notify(auth_client, auth_connect_notify, NULL);
 	clients_init();
 
@@ -243,6 +258,7 @@
 {
 	const char *name, *group_name;
 	struct ip_addr ip, local_ip;
+	unsigned int local_port;
 	struct ssl_proxy *proxy = NULL;
 	struct client *client;
 	int i, fd = -1, master_fd = -1, ssl = FALSE;
@@ -260,9 +276,9 @@
 	if (is_inetd) {
 		/* running from inetd. create master process before
 		   dropping privileges. */
-		group_name = strrchr(argv[0], '/');
-		group_name = group_name == NULL ? argv[0] : group_name+1;
-		group_name = t_strcut(group_name, '-');
+		process_name = strrchr(argv[0], '/');
+		process_name = process_name == NULL ? argv[0] : process_name+1;
+		group_name = t_strcut(process_name, '-');
 
 		for (i = 1; i < argc; i++) {
 			if (strncmp(argv[i], "--group=", 8) == 0) {
@@ -286,20 +302,27 @@
 			i_fatal("%s can be started only through dovecot "
 				"master process, inetd or equilevant", argv[0]);
 		}
-		if (net_getsockname(1, &local_ip, NULL) < 0)
+		if (net_getsockname(1, &local_ip, &local_port) < 0) {
 			memset(&local_ip, 0, sizeof(local_ip));
+			local_port = 0;
+		}
 
 		fd = 1;
 		for (i = 1; i < argc; i++) {
-			if (strcmp(argv[i], "--ssl") == 0) {
-				fd = ssl_proxy_new(fd, &ip, &proxy);
-				if (fd == -1)
-					return 1;
+			if (strcmp(argv[i], "--ssl") == 0)
 				ssl = TRUE;
-			} else if (strncmp(argv[i], "--group=", 8) != 0)
+			else if (strncmp(argv[i], "--group=", 8) != 0)
 				i_fatal("Unknown parameter: %s", argv[i]);
 		}
 
+		/* hardcoded imaps and pop3s ports to be SSL by default */
+		if (local_port == 993 || local_port == 995 || ssl) {
+			ssl = TRUE;
+			fd = ssl_proxy_new(fd, &ip, &proxy);
+			if (fd == -1)
+				return 1;
+		}
+
 		master_init(master_fd, FALSE);
 		closing_down = TRUE;
 
--- a/src/master/login-process.c	Sat Sep 24 13:50:38 2005 +0300
+++ b/src/master/login-process.c	Sat Sep 24 15:25:25 2005 +0300
@@ -192,13 +192,13 @@
 		i_error("login: Server name wasn't sent");
 	else {
 		name = t_strndup(buf, len);
-		proto = strchr(buf, '/');
+		proto = strchr(name, '/');
 		if (proto == NULL) {
-			i_error("login: Missing protocol from server name '%s'",
-				name);
-			return FALSE;
+			proto = name;
+			name = "default";
+		} else {
+			name = t_strdup_until(name, proto++);
 		}
-		name = t_strdup_until(buf, proto++);
 
 		if (strcmp(proto, "imap") == 0)
 			protocol = MAIL_PROTOCOL_IMAP;
@@ -632,7 +632,7 @@
 {
 	extern char **environ;
 	char **env;
-	size_t len;
+	ssize_t len;
 	int ret = 0;
 
 	/* this will clear our environment. luckily we don't need it. */
@@ -641,13 +641,23 @@
 	for (env = environ; *env != NULL; env++) {
 		len = strlen(*env);
 
-		if (o_stream_send(p->output, *env, len) != (ssize_t)len ||
+		if (o_stream_send(p->output, *env, len) != len ||
 		    o_stream_send(p->output, "\n", 1) != 1) {
 			ret = -1;
 			break;
 		}
 	}
 
+	if (!p->group->set->login_chroot) {
+		/* if we're not chrooting, we need to tell login process
+		   where its base directory is */
+		const char *str = t_strdup_printf("LOGIN_DIR=%s\n",
+						  p->group->set->login_dir);
+		len = strlen(str);
+		if (o_stream_send(p->output, str, len) != len)
+			ret = -1;
+	}
+
 	if (ret == 0 && o_stream_send(p->output, "\n", 1) != 1)
 		ret = -1;