main.c revision 97db4761382024093f441e4bc78ba8b6a056504d
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen#include "common.h"
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen#include "ioloop.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "randgen.h"
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen#include "restrict-access.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "restrict-process-size.h"
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen#include "process-title.h"
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen#include "master-auth.h"
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen#include "master-service.h"
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen#include "master-interface.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "client-common.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "auth-client.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "ssl-proxy.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "login-proxy.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include <stdlib.h>
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen#include <unistd.h>
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include <syslog.h>
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstruct auth_client *auth_client;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenbool closing_down;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenint anvil_fd = -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstruct master_service *service;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenconst struct login_settings *global_login_settings;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic bool ssl_connections = FALSE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic void client_connected(const struct master_service_connection *conn)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct client *client;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct ssl_proxy *proxy;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct ip_addr local_ip;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const struct login_settings *set;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen unsigned int local_port;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool_t pool;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen int fd_ssl;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (net_getsockname(conn->fd, &local_ip, &local_port) < 0) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen memset(&local_ip, 0, sizeof(local_ip));
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen local_port = 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool = pool_alloconly_create("login client", 1024);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen set = login_settings_read(service, pool, &local_ip, &conn->remote_ip);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (!ssl_connections && !conn->ssl) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen client = client_create(conn->fd, FALSE, pool, set, &local_ip,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen &conn->remote_ip);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } else {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen fd_ssl = ssl_proxy_new(conn->fd, &conn->remote_ip, set, &proxy);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (fd_ssl == -1) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen net_disconnect(conn->fd);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool_unref(&pool);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen client = client_create(fd_ssl, TRUE, pool, set,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen &local_ip, &conn->remote_ip);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen client->proxying = TRUE;
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen client->proxy = proxy;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen client->remote_port = conn->remote_port;
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen client->local_port = local_port;
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen}
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenstatic void auth_connect_notify(struct auth_client *client ATTR_UNUSED,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen bool connected, void *context ATTR_UNUSED)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (connected)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen clients_notify_auth_connected();
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic int anvil_connect(void)
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen{
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen#define ANVIL_HANDSHAKE "VERSION\t1\t0\n"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen int fd;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen fd = net_connect_unix("anvil");
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (fd < 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen i_fatal("net_connect_unix(anvil) failed: %m");
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen net_set_nonblock(fd, FALSE);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen if (write(fd, ANVIL_HANDSHAKE, strlen(ANVIL_HANDSHAKE)) < 0)
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen i_fatal("write(anvil) failed: %m");
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen return fd;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen}
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainenstatic void main_preinit(void)
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen{
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen unsigned int max_fds;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen random_init();
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen /* Initialize SSL proxy so it can read certificate and private
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen key file. */
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen ssl_proxy_init();
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen /* set the number of fds we want to use. it may get increased or
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen decreased. leave a couple of extra fds for auth sockets and such.
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen normal connections each use one fd, but SSL connections use two */
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen max_fds = MASTER_LISTEN_FD_FIRST + 16 +
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen master_service_get_socket_count(service) +
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen global_login_settings->login_max_connections*2;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen restrict_fd_limit(max_fds);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen io_loop_set_max_fd_count(current_ioloop, max_fds);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen i_assert(strcmp(global_login_settings->ssl, "no") == 0 ||
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen ssl_initialized);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen if (global_login_settings->mail_max_userip_connections > 0)
2c50ccaa9adb7df8cb49a240909fce732da57bedTimo Sirainen anvil_fd = anvil_connect();
e3e5ca6aec3efe6ef7419f411d934a5350f06df9Timo Sirainen
e3e5ca6aec3efe6ef7419f411d934a5350f06df9Timo Sirainen restrict_access_by_env(NULL, TRUE);
e3e5ca6aec3efe6ef7419f411d934a5350f06df9Timo Sirainen}
e3e5ca6aec3efe6ef7419f411d934a5350f06df9Timo Sirainen
e3e5ca6aec3efe6ef7419f411d934a5350f06df9Timo Sirainenstatic void main_init(void)
e3e5ca6aec3efe6ef7419f411d934a5350f06df9Timo Sirainen{
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen /* make sure we can't fork() */
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen restrict_process_size((unsigned int)-1, 1);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen if (restrict_access_get_current_chroot() == NULL) {
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen if (chdir("login") < 0)
2c50ccaa9adb7df8cb49a240909fce732da57bedTimo Sirainen i_fatal("chdir(login) failed: %m");
2c50ccaa9adb7df8cb49a240909fce732da57bedTimo Sirainen }
2c50ccaa9adb7df8cb49a240909fce732da57bedTimo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen auth_client = auth_client_new((unsigned int)getpid());
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen auth_client_set_connect_notify(auth_client, auth_connect_notify, NULL);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen clients_init();
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen master_auth_init(service);
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic void main_deinit(void)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ssl_proxy_deinit();
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen login_proxy_deinit();
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
1554bed8d2b4e4286c10f7d6bcf716b246bd5bafTimo Sirainen if (auth_client != NULL)
1554bed8d2b4e4286c10f7d6bcf716b246bd5bafTimo Sirainen auth_client_free(&auth_client);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen clients_deinit();
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen if (anvil_fd != -1) {
2c50ccaa9adb7df8cb49a240909fce732da57bedTimo Sirainen if (close(anvil_fd) < 0)
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen i_error("close(anvil) failed: %m");
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen }
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen master_auth_deinit(service);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen}
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainenint main(int argc, char *argv[], char *envp[])
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen{
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen const char *getopt_str;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen pool_t set_pool;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen int c;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen //FIXME:is_inetd = getenv("DOVECOT_MASTER") == NULL;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
90e39174d397567c101dbf694761371af3682928Timo Sirainen service = master_service_init(login_process_name,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN,
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen argc, argv);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen master_service_init_log(service, t_strconcat(login_process_name, ": ",
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen NULL), 0);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen getopt_str = t_strconcat("DS", master_service_getopt_string(), NULL);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen while ((c = getopt(argc, argv, getopt_str)) > 0) {
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen switch (c) {
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen case 'D':
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen restrict_access_allow_coredumps(TRUE);
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen break;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen case 'S':
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen ssl_connections = TRUE;
e8762c2b4914db7997fa9eb644a91586952d1876Timo Sirainen break;
default:
if (!master_service_parse_option(service, c, optarg))
exit(FATAL_DEFAULT);
break;
}
}
#if 0
if (is_inetd) {
/* running from inetd. create master process before
dropping privileges. */
master_fd = master_connect(t_strcut(login_process_name, '-'));
}
#endif
process_title_init(argv, envp);
set_pool = pool_alloconly_create("global login settings", 1024);
global_login_settings =
login_settings_read(service, set_pool, NULL, NULL);
main_preinit();
master_service_init_finish(service);
main_init();
master_service_run(service, client_connected);
main_deinit();
pool_unref(&set_pool);
master_service_deinit(&service);
return 0;
}