main.c revision 89a126810703c666309310d0f3189e9834d70b5b
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenbool disable_plaintext_auth, process_per_connection, greeting_capability;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenbool verbose_proctitle, verbose_ssl, verbose_auth;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenconst char *const *log_format_elements;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic const char *process_name;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic unsigned int listen_count, ssl_listen_count;
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen /* nothing to do, quit */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen } else if (closing_down && clients_get_count() == 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* last login finished, close all communications
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen to master process */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* we might still be proxying. close the connection to
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen dovecot-auth, since it's not needed anymore. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else if (clients_get_count() == 0) {
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen /* make sure we clear all the memory used by the
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen authentication connections. also this makes sure that if
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen this connection's authentication was finished but the master
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen login wasn't, the next connection won't be able to log in
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen as this user by finishing the master login. */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic void sig_die(int signo, void *context ATTR_UNUSED)
ab0155cbec1286e1cd00a0e01d78e0f3ca34cea6Timo Sirainen /* warn about being killed because of some signal, except SIGINT (^C)
ab0155cbec1286e1cd00a0e01d78e0f3ca34cea6Timo Sirainen which is too common at least while testing :) */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int listen_fd = POINTER_CAST_TO(context, int);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen fd = net_accept(listen_fd, &remote_ip, &remote_port);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (net_getsockname(fd, &local_ip, &local_port) < 0) {
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen client = client_create(fd, FALSE, &local_ip, &remote_ip);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen int listen_fd = POINTER_CAST_TO(context, int);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd = net_accept(listen_fd, &remote_ip, &remote_port);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (net_getsockname(fd, &local_ip, &local_port) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd_ssl = ssl_proxy_new(fd, &remote_ip, &proxy);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client = client_create(fd_ssl, TRUE, &local_ip, &remote_ip);
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen unsigned int i, current_count;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* typically happens only with
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen login_process_per_connection=yes after client logs in */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen master_notify_state_change(LOGIN_STATE_FULL_LOGINS);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen current_count = ssl_proxy_get_count() + login_proxy_get_count();
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* can't accept any more connections until existing proxies
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen get destroyed */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_array_init(&listen_ios, listen_count + ssl_listen_count);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen for (i = 0; i < listen_count; i++, cur_fd++) {
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen for (i = 0; i < ssl_listen_count; i++, cur_fd++) {
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen io = io_add(cur_fd, IO_READ, login_accept_ssl,
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen /* the initial notification tells master that we're ok. if we die
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen before sending it, the master should shutdown itself. */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen master_notify_state_change(LOGIN_STATE_LISTENING);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen unsigned int i, count;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen ios = array_get_modifiable(&listen_ios, &count);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen for (i = 0; i < count; i++)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen master_notify_state_change(clients_get_count() == 0 ?
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenvoid connection_queue_add(unsigned int connection_count)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen current_count = clients_get_count() + ssl_proxy_get_count() +
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (current_count + connection_count + 1 >= max_connections) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* after this client we've reached max users count,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen so stop listening for more. reserve +1 extra for SSL
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen connections. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* already reached max. users count, kill few of the
e4c90f0b88e40a8f92b8f5e1f1a3ea701e5c965cTimo Sirainen oldest connections.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen this happens when we've maxed out the login process
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen count and master has told us to start listening for
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen new connections even though we're full. */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void auth_connect_notify(struct auth_client *client ATTR_UNUSED,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void drop_privileges(void)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const char *env;
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen /* log to syslog */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i_set_failure_syslog(process_name, LOG_NDELAY,
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen /* if we don't chroot, we must chdir */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen /* Initialize SSL proxy so it can read certificate and private
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* Refuse to run as root - we should never need it and it's
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen dangerous with SSL. */
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* make sure we can't fork() */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void main_init(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (value != NULL && strcmp(value, PACKAGE_VERSION) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "(if you don't care, set version_ignore=yes)", value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen disable_plaintext_auth = getenv("DISABLE_PLAINTEXT_AUTH") != NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen process_per_connection = getenv("PROCESS_PER_CONNECTION") != NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen verbose_proctitle = getenv("VERBOSE_PROCTITLE") != NULL;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen verbose_auth = getenv("VERBOSE_AUTH") != NULL;
if (login_process_uid == 0)
/* capability default is set in imap/pop3-login */
main_refcount = 0;
clients_init();
if (!is_inetd) {
static void main_deinit(void)
closelog();
const char *group_name;
#ifdef DEBUG
const char *env;
lib_init();
if (is_inetd) {
main_init();
if (is_inetd) {
local_port = 0;
main_deinit();
lib_deinit();