main.c revision 89a126810703c666309310d0f3189e9834d70b5b
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "ioloop.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib-signals.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "randgen.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "restrict-access.h"
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen#include "restrict-process-size.h"
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen#include "process-title.h"
15b9759df8e4f6fb00c115353827a2aebbebfebcTimo Sirainen#include "fd-close-on-exec.h"
15b9759df8e4f6fb00c115353827a2aebbebfebcTimo Sirainen#include "master.h"
15b9759df8e4f6fb00c115353827a2aebbebfebcTimo Sirainen#include "client-common.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "auth-client.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "ssl-proxy.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "login-proxy.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include <stdlib.h>
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include <unistd.h>
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include <syslog.h>
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenbool disable_plaintext_auth, process_per_connection, greeting_capability;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenbool verbose_proctitle, verbose_ssl, verbose_auth;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenconst char *greeting, *log_format;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenconst char *const *log_format_elements;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainenunsigned int max_connections;
0a3b01714dadf97dcc7439ad4eeba690ab044966Timo Sirainenunsigned int login_process_uid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct auth_client *auth_client;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenbool closing_down;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic const char *process_name;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct ioloop *ioloop;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int main_refcount;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainenstatic bool is_inetd, listening;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic ARRAY_DEFINE(listen_ios, struct io *);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic unsigned int listen_count, ssl_listen_count;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenvoid main_ref(void)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen main_refcount++;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen}
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenvoid main_unref(void)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (--main_refcount == 0) {
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen /* nothing to do, quit */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen io_loop_stop(ioloop);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen } else if (closing_down && clients_get_count() == 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* last login finished, close all communications
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen to master process */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen master_close();
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* we might still be proxying. close the connection to
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen dovecot-auth, since it's not needed anymore. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (auth_client != NULL)
e8490a52a1bc71bc53034e68f464435684ad810fTimo Sirainen auth_client_free(&auth_client);
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. */
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen if (auth_client != NULL)
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen auth_client_reconnect(auth_client);
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic void sig_die(int signo, void *context ATTR_UNUSED)
ab0155cbec1286e1cd00a0e01d78e0f3ca34cea6Timo Sirainen{
ab0155cbec1286e1cd00a0e01d78e0f3ca34cea6Timo Sirainen /* warn about being killed because of some signal, except SIGINT (^C)
ab0155cbec1286e1cd00a0e01d78e0f3ca34cea6Timo Sirainen which is too common at least while testing :) */
ab0155cbec1286e1cd00a0e01d78e0f3ca34cea6Timo Sirainen if (signo != SIGINT)
ab0155cbec1286e1cd00a0e01d78e0f3ca34cea6Timo Sirainen i_warning("Killed with signal %d", signo);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen io_loop_stop(ioloop);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic void login_accept(void *context)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int listen_fd = POINTER_CAST_TO(context, int);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct ip_addr remote_ip, local_ip;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int remote_port, local_port;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct client *client;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int fd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen fd = net_accept(listen_fd, &remote_ip, &remote_port);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (fd < 0) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (fd < -1)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen i_error("accept() failed: %m");
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen return;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen if (net_getsockname(fd, &local_ip, &local_port) < 0) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen memset(&local_ip, 0, sizeof(local_ip));
4b41116563110d00330896a568eff1078c382827Timo Sirainen local_port = 0;
4b41116563110d00330896a568eff1078c382827Timo Sirainen }
4b41116563110d00330896a568eff1078c382827Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen client = client_create(fd, FALSE, &local_ip, &remote_ip);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen client->remote_port = remote_port;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen client->local_port = local_port;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (process_per_connection) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen closing_down = TRUE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen main_listen_stop();
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen}
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void login_accept_ssl(void *context)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen int listen_fd = POINTER_CAST_TO(context, int);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen struct ip_addr remote_ip, local_ip;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen unsigned int remote_port, local_port;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen struct client *client;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen struct ssl_proxy *proxy;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen int fd, fd_ssl;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd = net_accept(listen_fd, &remote_ip, &remote_port);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fd < 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (fd < -1)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_error("accept() failed: %m");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (net_getsockname(fd, &local_ip, &local_port) < 0) {
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen memset(&local_ip, 0, sizeof(local_ip));
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen local_port = 0;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fd_ssl = ssl_proxy_new(fd, &remote_ip, &proxy);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (fd_ssl == -1)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen net_disconnect(fd);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client = client_create(fd_ssl, TRUE, &local_ip, &remote_ip);
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen client->proxy = proxy;
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen client->remote_port = remote_port;
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen client->local_port = local_port;
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen if (process_per_connection) {
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen closing_down = TRUE;
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen main_listen_stop();
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen }
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen}
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainenvoid main_listen_start(void)
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen{
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen struct io *io;
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen unsigned int i, current_count;
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen int cur_fd;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
c13f3df87bc8ec1fb279fc0ffa6e8517f74dc07cTimo Sirainen if (listening)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (closing_down) {
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 return;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen current_count = ssl_proxy_get_count() + login_proxy_get_count();
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (current_count >= max_connections) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* can't accept any more connections until existing proxies
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen get destroyed */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen cur_fd = LOGIN_MASTER_SOCKET_FD + 1;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_array_init(&listen_ios, listen_count + ssl_listen_count);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen for (i = 0; i < listen_count; i++, cur_fd++) {
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen io = io_add(cur_fd, IO_READ, login_accept,
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen POINTER_CAST(cur_fd));
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen array_append(&listen_ios, &io, 1);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen }
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen for (i = 0; i < ssl_listen_count; i++, cur_fd++) {
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen io = io_add(cur_fd, IO_READ, login_accept_ssl,
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen POINTER_CAST(cur_fd));
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen array_append(&listen_ios, &io, 1);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen listening = TRUE;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
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}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenvoid main_listen_stop(void)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
a12399903f415a7e14c2816cffa2f7a09dcbb097Timo Sirainen struct io **ios;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen unsigned int i, count;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen int cur_fd;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (!listening)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen ios = array_get_modifiable(&listen_ios, &count);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen for (i = 0; i < count; i++)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen io_remove(&ios[i]);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen array_free(&listen_ios);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen if (closing_down) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen cur_fd = LOGIN_MASTER_SOCKET_FD + 1;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen for (i = 0; i < count; i++, cur_fd++) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen if (close(cur_fd) < 0) {
87460b08cb97b31cde640d4975a6aa2c1d0e7226Timo Sirainen i_fatal("close(listener %d) failed: %m",
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen cur_fd);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen listening = FALSE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (io_loop_is_running(ioloop)) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen master_notify_state_change(clients_get_count() == 0 ?
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen LOGIN_STATE_FULL_LOGINS :
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen LOGIN_STATE_FULL_PRELOGINS);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenvoid connection_queue_add(unsigned int connection_count)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen unsigned int current_count;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (process_per_connection)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen current_count = clients_get_count() + ssl_proxy_get_count() +
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen login_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. */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen main_listen_stop();
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (current_count >= max_connections) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* already reached max. users count, kill few of the
e4c90f0b88e40a8f92b8f5e1f1a3ea701e5c965cTimo Sirainen oldest connections.
defb12ecd360df672ffb2f4dbf4d1218a0a9549cTimo Sirainen
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 Sirainen client_destroy_oldest();
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void auth_connect_notify(struct auth_client *client ATTR_UNUSED,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen bool connected, void *context ATTR_UNUSED)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (connected)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen clients_notify_auth_connected();
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void drop_privileges(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const char *env;
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen if (!is_inetd)
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen i_set_failure_internal();
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen else {
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen /* log to syslog */
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen env = getenv("SYSLOG_FACILITY");
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i_set_failure_syslog(process_name, LOG_NDELAY,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen env == NULL ? LOG_MAIL : atoi(env));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen /* if we don't chroot, we must chdir */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen env = getenv("LOGIN_DIR");
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen if (env != NULL) {
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen if (chdir(env) < 0)
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen i_error("chdir(%s) failed: %m", env);
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen }
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen /* Initialize SSL proxy so it can read certificate and private
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen key file. */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen random_init();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen ssl_proxy_init();
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* Refuse to run as root - we should never need it and it's
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen dangerous with SSL. */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen restrict_access_by_env(TRUE);
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* make sure we can't fork() */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen restrict_process_size((unsigned int)-1, 1);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen}
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void main_init(void)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const char *value;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen value = getenv("DOVECOT_VERSION");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (value != NULL && strcmp(value, PACKAGE_VERSION) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("Dovecot version mismatch: "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Master is v%s, login is v"PACKAGE_VERSION" "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "(if you don't care, set version_ignore=yes)", value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_init();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lib_signals_ignore(SIGPIPE, TRUE);
b3b4f3875850099c9292ad74d08bb385c3988f8fTimo Sirainen
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;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen verbose_ssl = getenv("VERBOSE_SSL") != NULL;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen verbose_auth = getenv("VERBOSE_AUTH") != NULL;
b3b4f3875850099c9292ad74d08bb385c3988f8fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen value = getenv("MAX_CONNECTIONS");
max_connections = value == NULL ? 1 : strtoul(value, NULL, 10);
greeting = getenv("GREETING");
if (greeting == NULL)
greeting = PACKAGE" ready.";
greeting_capability = getenv("GREETING_CAPABILITY") != NULL;
value = getenv("LOG_FORMAT_ELEMENTS");
if (value == NULL)
value = "user=<%u> method=%m rip=%r lip=%l %c : %$";
log_format_elements = t_strsplit(value, " ");
log_format = getenv("LOG_FORMAT");
if (log_format == NULL)
log_format = "%$: %s";
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");
/* capability default is set in imap/pop3-login */
value = getenv("CAPABILITY_STRING");
if (value != NULL && *value != '\0')
capability_string = value;
closing_down = FALSE;
main_refcount = 0;
auth_client = auth_client_new(login_process_uid);
auth_client_set_connect_notify(auth_client, auth_connect_notify, NULL);
clients_init();
value = getenv("LISTEN_FDS");
listen_count = value == NULL ? 0 : atoi(value);
value = getenv("SSL_LISTEN_FDS");
ssl_listen_count = value == NULL ? 0 : atoi(value);
if (!ssl_initialized && ssl_listen_count > 0) {
/* this shouldn't happen, master should have
disabled the ssl socket.. */
i_fatal("BUG: SSL initialization parameters not given "
"while they should have been");
}
if (!is_inetd) {
master_init(LOGIN_MASTER_SOCKET_FD);
main_listen_start();
}
}
static void main_deinit(void)
{
closing_down = TRUE;
main_listen_stop();
ssl_proxy_deinit();
login_proxy_deinit();
if (auth_client != NULL)
auth_client_free(&auth_client);
clients_deinit();
master_deinit();
lib_signals_deinit();
closelog();
}
int main(int argc ATTR_UNUSED, char *argv[], char *envp[])
{
const char *group_name;
struct ip_addr remote_ip, local_ip;
unsigned int remote_port, local_port;
struct ssl_proxy *proxy = NULL;
struct client *client;
int i, fd = -1, master_fd = -1;
bool ssl = FALSE;
is_inetd = getenv("DOVECOT_MASTER") == NULL;
#ifdef DEBUG
if (!is_inetd && getenv("GDB") == NULL) {
const char *env;
i = LOGIN_MASTER_SOCKET_FD + 1;
env = getenv("LISTEN_FDS");
if (env != NULL) i += atoi(env);
env = getenv("SSL_LISTEN_FDS");
if (env != NULL) i += atoi(env);
fd_debug_verify_leaks(i + 1, 1024);
}
#endif
/* clear all allocated memory before freeing it. this makes the login
processes pretty safe to reuse for new connections since the
attacker won't be able to find anything interesting from the
memory. */
default_pool = system_clean_pool;
data_stack_set_clean_after_pop(TRUE);
/* NOTE: we start rooted, so keep the code minimal until
restrict_access_by_env() is called */
lib_init();
if (is_inetd) {
/* running from inetd. create master process before
dropping privileges. */
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) {
group_name = argv[1]+8;
break;
}
}
master_fd = master_connect(group_name);
}
drop_privileges();
process_title_init(argv, envp);
ioloop = io_loop_create();
main_init();
if (is_inetd) {
if (net_getpeername(1, &remote_ip, &remote_port) < 0) {
i_fatal("%s can be started only through dovecot "
"master process, inetd or equilevant", argv[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)
ssl = TRUE;
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, &remote_ip, &proxy);
if (fd == -1)
return 1;
}
master_init(master_fd);
closing_down = TRUE;
if (fd != -1) {
client = client_create(fd, ssl, &local_ip, &remote_ip);
client->proxy = proxy;
client->remote_port = remote_port;
client->local_port = local_port;
}
}
io_loop_run(ioloop);
main_deinit();
io_loop_destroy(&ioloop);
lib_deinit();
return 0;
}