[dovecot-cvs] dovecot/src/master auth-process.c,1.38,1.39 common.h,1.13,1.14 login-process.c,1.36,1.37 mail-process.c,1.10,1.11 main.c,1.40,1.41 master-login-interface.h,1.3,1.4

cras at procontrol.fi cras at procontrol.fi
Tue Mar 4 06:02:59 EET 2003


Update of /home/cvs/dovecot/src/master
In directory danu:/tmp/cvs-serv14529/master

Modified Files:
	auth-process.c common.h login-process.c mail-process.c main.c 
	master-login-interface.h 
Log Message:
Somewhat working code to support loading Dovecot from inetd and such. It
still needs possibility to specify which login process to use, and LOGIN and
AUTHENTICATE commands shouldn't be allowed before we're connected to auth
process.



Index: auth-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/auth-process.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- auth-process.c	4 Mar 2003 02:18:09 -0000	1.38
+++ auth-process.c	4 Mar 2003 04:02:56 -0000	1.39
@@ -274,6 +274,7 @@
 
 	if (pid != 0) {
 		/* master */
+		net_set_nonblock(fd[0], TRUE);
 		fd_close_on_exec(fd[0], TRUE);
 		auth_process_new(pid, fd[0], group);
 		(void)close(fd[1]);
@@ -292,7 +293,7 @@
 	if (dup2(null_fd, 1) < 0)
 		i_fatal("login: dup2(1) failed: %m");
 
-	clean_child_process();
+	child_process_init_env();
 
 	/* move login communication handle to 3. do it last so we can be
 	   sure it's not closed afterwards. */
@@ -304,8 +305,7 @@
 	for (i = 0; i <= 3; i++)
 		fd_close_on_exec(i, FALSE);
 
-	/* setup access environment - needs to be done after
-	   clean_child_process() since it clears environment */
+	/* setup access environment */
 	restrict_access_set_env(group->set->user, pwd->pw_uid, pwd->pw_gid,
 				group->set->chroot);
 

Index: common.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/common.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- common.h	30 Jan 2003 19:01:40 -0000	1.13
+++ common.h	4 Mar 2003 04:02:56 -0000	1.14
@@ -30,7 +30,10 @@
 
 extern struct ioloop *ioloop;
 extern struct hash_table *pids;
-extern int null_fd, mail_fd[FD_MAX];
+extern int null_fd, mail_fd[FD_MAX], inetd_login_fd;
+
+#define IS_INETD() \
+	(inetd_login_fd != -1)
 
 /* processes */
 #define PID_GET_PROCESS_TYPE(pid) \
@@ -42,7 +45,7 @@
 #define PID_REMOVE_PROCESS_TYPE(pid) \
 	hash_remove(pids, POINTER_CAST(pid))
 
-void clean_child_process(void);
+void child_process_init_env(void);
 
 /* misc */
 #define VALIDATE_STR(str) \

Index: login-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/login-process.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- login-process.c	23 Feb 2003 19:49:20 -0000	1.36
+++ login-process.c	4 Mar 2003 04:02:56 -0000	1.37
@@ -58,8 +58,9 @@
 	struct ip_addr ip;
 };
 
-static unsigned int auth_id_counter;
+static unsigned int auth_id_counter, login_pid_counter;
 static struct timeout *to;
+static struct io *io_listen;
 
 static struct hash_table *processes;
 static struct login_group *login_groups;
@@ -220,7 +221,8 @@
 {
 	struct login_process *p;
 
-	PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN);
+	i_assert(pid != 0);
+	i_assert(group != NULL);
 
 	p = i_new(struct login_process, 1);
 	p->group = group;
@@ -233,7 +235,9 @@
 					 sizeof(struct master_login_reply)*10,
 					 IO_PRIORITY_DEFAULT, FALSE);
 
+	PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN);
 	hash_insert(processes, POINTER_CAST(pid), p);
+
 	p->group->processes++;
 	p->group->listening_processes++;
 	return p;
@@ -276,7 +280,8 @@
 		login_process_remove_from_lists(p);
 
 	p->group->processes--;
-	hash_remove(processes, POINTER_CAST(p->pid));
+	if (p->pid != 0)
+		hash_remove(processes, POINTER_CAST(p->pid));
 
 	login_process_unref(p);
 }
@@ -290,6 +295,44 @@
 	i_free(p);
 }
 
+static void login_process_init_env(struct login_group *group, pid_t pid)
+{
+	child_process_init_env();
+
+	/* setup access environment - needs to be done after
+	   clean_child_process() since it clears environment */
+	restrict_access_set_env(group->set->user,
+				group->set->uid, set->login_gid,
+				set->login_chroot ? set->login_dir : NULL);
+
+	env_put("DOVECOT_MASTER=1");
+
+	if (!set->ssl_disable) {
+		env_put(t_strconcat("SSL_CERT_FILE=",
+				    set->ssl_cert_file, NULL));
+		env_put(t_strconcat("SSL_KEY_FILE=", set->ssl_key_file, NULL));
+		env_put(t_strconcat("SSL_PARAM_FILE=",
+				    set->ssl_parameters_file, NULL));
+	}
+
+	if (set->disable_plaintext_auth)
+		env_put("DISABLE_PLAINTEXT_AUTH=1");
+	if (set->verbose_proctitle)
+		env_put("VERBOSE_PROCTITLE=1");
+	if (set->verbose_ssl)
+		env_put("VERBOSE_SSL=1");
+
+	if (group->set->process_per_connection) {
+		env_put("PROCESS_PER_CONNECTION=1");
+		env_put("MAX_LOGGING_USERS=1");
+	} else {
+		env_put(t_strdup_printf("MAX_LOGGING_USERS=%u",
+					group->set->max_logging_users));
+	}
+
+	env_put(t_strdup_printf("PROCESS_UID=%s", dec2str(pid)));
+}
+
 static pid_t create_login_process(struct login_group *group)
 {
 	static const char *argv[] = { NULL, NULL };
@@ -322,44 +365,32 @@
 
 	if (pid != 0) {
 		/* master */
+		net_set_nonblock(fd[0], TRUE);
 		fd_close_on_exec(fd[0], TRUE);
-		login_process_new(group, pid, fd[0]);
+		(void)login_process_new(group, pid, fd[0]);
 		(void)close(fd[1]);
 		return pid;
 	}
 
-	/* move communication handle */
-	if (dup2(fd[1], LOGIN_MASTER_SOCKET_FD) < 0)
-		i_fatal("login: dup2(master) failed: %m");
-	fd_close_on_exec(LOGIN_MASTER_SOCKET_FD, FALSE);
-
 	/* move the listen handle */
 	if (dup2(*group->listen_fd, LOGIN_LISTEN_FD) < 0)
 		i_fatal("login: dup2(listen_fd) failed: %m");
 	fd_close_on_exec(LOGIN_LISTEN_FD, FALSE);
 
 	/* move the SSL listen handle */
-	if (!set->ssl_disable) {
-		if (dup2(*group->ssl_listen_fd, LOGIN_SSL_LISTEN_FD) < 0)
-			i_fatal("login: dup2(ssl_listen_fd) failed: %m");
-	} else {
-		if (dup2(null_fd, LOGIN_SSL_LISTEN_FD) < 0)
-			i_fatal("login: dup2(ssl_listen_fd) failed: %m");
-	}
+	if (dup2(*group->ssl_listen_fd, LOGIN_SSL_LISTEN_FD) < 0)
+		i_fatal("login: dup2(ssl_listen_fd) failed: %m");
 	fd_close_on_exec(LOGIN_SSL_LISTEN_FD, FALSE);
 
-	/* listen_fds are closed by clean_child_process() */
+	/* move communication handle */
+	if (dup2(fd[1], LOGIN_MASTER_SOCKET_FD) < 0)
+		i_fatal("login: dup2(master) failed: %m");
+	fd_close_on_exec(LOGIN_MASTER_SOCKET_FD, FALSE);
 
 	(void)close(fd[0]);
 	(void)close(fd[1]);
 
-	clean_child_process();
-
-	/* setup access environment - needs to be done after
-	   clean_child_process() since it clears environment */
-	restrict_access_set_env(group->set->user,
-				group->set->uid, set->login_gid,
-				set->login_chroot ? set->login_dir : NULL);
+	login_process_init_env(group, getpid());
 
 	if (!set->login_chroot) {
 		/* no chrooting, but still change to the directory */
@@ -367,31 +398,6 @@
 			i_fatal("chdir(%s) failed: %m", set->login_dir);
 	}
 
-	if (!set->ssl_disable) {
-		env_put(t_strconcat("SSL_CERT_FILE=",
-				    set->ssl_cert_file, NULL));
-		env_put(t_strconcat("SSL_KEY_FILE=", set->ssl_key_file, NULL));
-		env_put(t_strconcat("SSL_PARAM_FILE=",
-				    set->ssl_parameters_file, NULL));
-	}
-
-	if (set->disable_plaintext_auth)
-		env_put("DISABLE_PLAINTEXT_AUTH=1");
-	if (set->verbose_proctitle)
-		env_put("VERBOSE_PROCTITLE=1");
-	if (set->verbose_ssl)
-		env_put("VERBOSE_SSL=1");
-
-	if (group->set->process_per_connection) {
-		env_put("PROCESS_PER_CONNECTION=1");
-		env_put("MAX_LOGGING_USERS=1");
-	} else {
-		env_put(t_strdup_printf("MAX_LOGGING_USERS=%u",
-					group->set->max_logging_users));
-	}
-
-	env_put(t_strdup_printf("PROCESS_UID=%s", dec2str(getpid())));
-
 	restrict_process_size(group->set->process_size, 0);
 
 	/* make sure we don't leak syslog fd, but do it last so that
@@ -483,18 +489,82 @@
 		login_group_start_missings(group);
 }
 
+static int login_process_send_env(struct login_process *p)
+{
+	extern char **environ;
+	char **env;
+	size_t len;
+	int ret = 0;
+
+	/* this will clear our environment. luckily we don't need it. */
+	login_process_init_env(p->group, p->pid);
+
+	for (env = environ; *env != NULL; env++) {
+		len = strlen(*env);
+
+		if (o_stream_send(p->output, *env, len) != (ssize_t)len ||
+		    o_stream_send(p->output, "\n", 1) != 1) {
+			ret = -1;
+			break;
+		}
+	}
+
+	if (ret == 0 && o_stream_send(p->output, "\n", 1) != 1)
+		ret = -1;
+
+	env_clean();
+	return ret;
+}
+
+static void inetd_login_accept(void *context __attr_unused__)
+{
+        struct login_process *p;
+	int fd;
+
+	fd = net_accept(inetd_login_fd, NULL, NULL);
+	if (fd < 0) {
+		if (fd < -1)
+			i_fatal("accept(inetd_login_fd) failed: %m");
+	} else {
+		net_set_nonblock(fd, TRUE);
+		fd_close_on_exec(fd, TRUE);
+
+		p = login_process_new(login_groups, ++login_pid_counter, fd);
+		p->initialized = TRUE;;
+
+		if (login_process_send_env(p) < 0) {
+			i_warning("Couldn't send environment to login process");
+			login_process_destroy(p);
+		}
+	}
+}
+
 void login_processes_init(void)
 {
-        auth_id_counter = 0;
+	auth_id_counter = 0;
+        login_pid_counter = 0;
 	login_groups = NULL;
 
 	processes = hash_create(default_pool, default_pool, 128, NULL, NULL);
-	to = timeout_add(1000, login_processes_start_missing, NULL);
+	if (!IS_INETD()) {
+		to = timeout_add(1000, login_processes_start_missing, NULL);
+		io_listen = NULL;
+	} else {
+		/* use the first login group for everyone */
+		login_group_create(set->logins);
+
+		to = NULL;
+		io_listen = io_add(inetd_login_fd, IO_READ,
+				   inetd_login_accept, NULL);
+	}
 }
 
 void login_processes_deinit(void)
 {
-	timeout_remove(to);
+	if (to != NULL)
+		timeout_remove(to);
+	if (io_listen != NULL)
+		io_remove(io_listen);
 
         login_processes_destroy_all();
 	hash_destroy(processes);

Index: mail-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/mail-process.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- mail-process.c	23 Feb 2003 21:06:58 -0000	1.10
+++ mail-process.c	4 Mar 2003 04:02:56 -0000	1.11
@@ -132,7 +132,7 @@
 		return TRUE;
 	}
 
-	clean_child_process();
+	child_process_init_env();
 
 	/* move the client socket into stdin and stdout fds */
 	fd_close_on_exec(socket, FALSE);

Index: main.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/main.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- main.c	4 Mar 2003 02:18:09 -0000	1.40
+++ main.c	4 Mar 2003 04:02:56 -0000	1.41
@@ -33,7 +33,7 @@
 
 struct ioloop *ioloop;
 struct hash_table *pids;
-int null_fd, mail_fd[FD_MAX];
+int null_fd, mail_fd[FD_MAX], inetd_login_fd;
 
 int validate_str(const char *str, size_t max_len)
 {
@@ -47,7 +47,7 @@
 	return FALSE;
 }
 
-void clean_child_process(void)
+void child_process_init_env(void)
 {
 	/* remove all environment, we don't need them */
 	env_clean();
@@ -216,7 +216,7 @@
 	return ip;
 }
 
-static void open_fds(void)
+static void listen_protocols(void)
 {
 	struct ip_addr *imap_ip, *imaps_ip, *pop3_ip, *pop3s_ip, *ip;
 	const char *const *proto;
@@ -243,15 +243,6 @@
 	if (pop3s_ip == NULL && set->pop3s_listen == NULL)
 		pop3s_ip = pop3_ip;
 
-	/* initialize fds */
-	null_fd = open("/dev/null", O_RDONLY);
-	if (null_fd == -1)
-		i_fatal("Can't open /dev/null: %m");
-	fd_close_on_exec(null_fd, TRUE);
-
-	for (i = 0; i < FD_MAX; i++)
-		mail_fd[i] = -1;
-
 	/* register wanted protocols */
 	for (proto = t_strsplit(set->protocols, " "); *proto != NULL; proto++) {
 		if (strcasecmp(*proto, "imap") == 0) {
@@ -286,6 +277,29 @@
 			fd_close_on_exec(mail_fd[i], TRUE);
 		}
 	}
+}
+
+static void open_fds(void)
+{
+	int i;
+
+	/* initialize fds. */
+	null_fd = open("/dev/null", O_RDONLY);
+	if (null_fd == -1)
+		i_fatal("Can't open /dev/null: %m");
+	fd_close_on_exec(null_fd, TRUE);
+
+	/* make sure all fds between 0..3 are used. */
+	while (null_fd < 4) {
+		null_fd = dup(null_fd);
+		fd_close_on_exec(null_fd, TRUE);
+	}
+
+	for (i = 0; i < FD_MAX; i++)
+		mail_fd[i] = -1;
+
+	if (!IS_INETD())
+		listen_protocols();
 
 	/* close stdin and stdout. close stderr unless we're logging
 	   into /dev/stderr. */
@@ -299,7 +313,7 @@
 	    (set->info_log_path == NULL ||
 	     strcmp(set->info_log_path, "/dev/stderr") != 0)) {
 		if (dup2(null_fd, 2) < 0)
-			i_fatal("dup(0) failed: %m");
+			i_fatal("dup2(2) failed: %m");
 	}
 }
 
@@ -357,8 +371,10 @@
 		i_error("close(null_fd) failed: %m");
 
 	for (i = 0; i < FD_MAX; i++) {
-		if (close(mail_fd[i]) < 0)
-			i_error("close(mail_fd[%d]) failed: %m", i);
+		if (mail_fd[i] != -1) {
+			if (close(mail_fd[i]) < 0)
+				i_error("close(mail_fd[%d]) failed: %m", i);
+		}
 	}
 
 	hash_destroy(pids);
@@ -393,6 +409,7 @@
 
 	lib_init();
 
+        inetd_login_fd = -1;
 	for (i = 1; i < argc; i++) {
 		if (strcmp(argv[i], "-F") == 0) {
 			/* foreground */
@@ -402,6 +419,13 @@
 			i++;
 			if (i == argc) i_fatal("Missing config file argument");
 			configfile = argv[i];
+		} else if (strcmp(argv[i], "--inetd") == 0) {
+			/* starting through inetd. */
+			inetd_login_fd = dup(0);
+			if (inetd_login_fd == -1)
+				i_fatal("dup(0) failed: %m");
+			fd_close_on_exec(inetd_login_fd, TRUE);
+			foreground = TRUE;
 		} else if (strcmp(argv[i], "--version") == 0) {
 			printf("%s\n", VERSION);
 			return 0;
@@ -415,6 +439,9 @@
 	master_settings_init();
 	master_settings_read(configfile);
 	open_fds();
+
+	/* we don't need any environment */
+	env_clean();
 
 	if (!foreground)
 		daemonize();

Index: master-login-interface.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/master-login-interface.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- master-login-interface.h	8 Feb 2003 15:42:46 -0000	1.3
+++ master-login-interface.h	4 Mar 2003 04:02:56 -0000	1.4
@@ -3,9 +3,9 @@
 
 #include "network.h"
 
-#define LOGIN_MASTER_SOCKET_FD 0
-#define LOGIN_LISTEN_FD 1
-#define LOGIN_SSL_LISTEN_FD 3
+#define LOGIN_LISTEN_FD 0
+#define LOGIN_SSL_LISTEN_FD 1
+#define LOGIN_MASTER_SOCKET_FD 3
 
 struct master_login_request {
 	unsigned int tag;




More information about the dovecot-cvs mailing list