main.c revision a8c5a86d183db25a57bf193c06b41e092ec2e151
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz/* Copyright (c) 2002-2014 Dovecot authors, see the included COPYING file */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "login-common.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "ioloop.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "randgen.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "process-title.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "restrict-access.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "restrict-process-size.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "master-auth.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "master-service.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "master-interface.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "client-common.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "access-lookup.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "anvil-client.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "auth-client.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "dsasl-client.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "master-service-ssl-settings.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "ssl-proxy.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include "login-proxy.h"
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include <stdlib.h>
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include <unistd.h>
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#include <syslog.h>
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz#define AUTH_CLIENT_IDLE_TIMEOUT_MSECS (1000*60)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstruct login_access_lookup {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct master_service_connection conn;
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz struct io *io;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz char **sockets, **next_socket;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz struct access_lookup *access;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz};
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzconst struct login_binary *login_binary;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstruct auth_client *auth_client;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstruct master_auth *master_auth;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzbool closing_down;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzstruct anvil_client *anvil;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzconst char *login_rawlog_dir = NULL;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzunsigned int initial_service_count;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzconst struct login_settings *global_login_settings;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzconst struct master_service_ssl_settings *global_ssl_settings;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzvoid **global_other_settings;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic struct timeout *auth_client_to;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic bool shutting_down = FALSE;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzstatic bool ssl_connections = FALSE;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic bool auth_connected_once = FALSE;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarzstatic void login_access_lookup_next(struct login_access_lookup *lookup);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzvoid login_refresh_proctitle(void)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct client *client = clients;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const char *addr;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (!global_login_settings->verbose_proctitle)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz if (clients_get_count() == 0) {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz process_title_set("");
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz } else if (clients_get_count() > 1 || client == NULL) {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz process_title_set(t_strdup_printf("[%u connections (%u TLS)]",
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz clients_get_count(), ssl_proxy_get_count()));
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz } else {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz addr = net_ip2addr(&client->ip);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz if (addr[0] != '\0') {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz process_title_set(t_strdup_printf(client->tls ?
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz "[%s TLS]" : "[%s]", addr));
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz } else {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz process_title_set(client->tls ? "[TLS]" : "");
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz }
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz }
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz}
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzstatic void auth_client_idle_timeout(struct auth_client *auth_client)
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz{
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz i_assert(clients == NULL);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz auth_client_disconnect(auth_client, "idle disconnect");
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz timeout_remove(&auth_client_to);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzvoid login_client_destroyed(void)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (clients == NULL && auth_client_to == NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz auth_client_to = timeout_add(AUTH_CLIENT_IDLE_TIMEOUT_MSECS,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz auth_client_idle_timeout,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz auth_client);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz}
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzstatic void login_die(void)
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz{
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz shutting_down = TRUE;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_proxy_kill_idle();
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (!auth_client_is_connected(auth_client)) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* we don't have auth client, and we might never get one */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz clients_destroy_all();
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzclient_connected_finish(const struct master_service_connection *conn)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct client *client;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct ssl_proxy *proxy;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct ip_addr local_ip;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const struct login_settings *set;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const struct master_service_ssl_settings *ssl_set;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz unsigned int local_port;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz pool_t pool;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz int fd_ssl;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz void **other_sets;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (net_getsockname(conn->fd, &local_ip, &local_port) < 0) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz memset(&local_ip, 0, sizeof(local_ip));
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz local_port = 0;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz pool = pool_alloconly_create("login client", 8*1024);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz set = login_settings_read(pool, &local_ip,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz &conn->remote_ip, NULL, &ssl_set, &other_sets);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (!ssl_connections && !conn->ssl) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client = client_create(conn->fd, FALSE, pool,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz set, ssl_set, other_sets,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz &local_ip, &conn->remote_ip);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz } else {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz fd_ssl = ssl_proxy_alloc(conn->fd, &conn->remote_ip, pool,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz set, ssl_set, &proxy);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (fd_ssl == -1) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz net_disconnect(conn->fd);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz pool_unref(&pool);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz master_service_client_connection_destroyed(master_service);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client = client_create(fd_ssl, TRUE, pool,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz set, ssl_set, other_sets,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz &local_ip, &conn->remote_ip);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->ssl_proxy = proxy;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz ssl_proxy_set_client(proxy, client);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz ssl_proxy_start(proxy);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->real_remote_port = client->remote_port = conn->remote_port;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->real_local_port = client->local_port = local_port;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (auth_client_to != NULL)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz timeout_remove(&auth_client_to);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void login_access_lookup_free(struct login_access_lookup *lookup)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
4ee5a85e75d520497bd43dbfcc6fc273f3e57ceaMichael Slusarz if (lookup->io != NULL)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz io_remove(&lookup->io);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz if (lookup->access != NULL)
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz access_lookup_destroy(&lookup->access);
4ee5a85e75d520497bd43dbfcc6fc273f3e57ceaMichael Slusarz if (lookup->conn.fd != -1) {
4ee5a85e75d520497bd43dbfcc6fc273f3e57ceaMichael Slusarz if (close(lookup->conn.fd) < 0)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_error("close(client) failed: %m");
4ee5a85e75d520497bd43dbfcc6fc273f3e57ceaMichael Slusarz master_service_client_connection_destroyed(master_service);
4ee5a85e75d520497bd43dbfcc6fc273f3e57ceaMichael Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz p_strsplit_free(default_pool, lookup->sockets);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_free(lookup);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void login_access_callback(bool success, void *context)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
4ee5a85e75d520497bd43dbfcc6fc273f3e57ceaMichael Slusarz struct login_access_lookup *lookup = context;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (!success) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_info("access(%s): Client refused (rip=%s)",
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz *lookup->next_socket,
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz net_ip2addr(&lookup->conn.remote_ip));
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz login_access_lookup_free(lookup);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz } else {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz lookup->next_socket++;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_access_lookup_next(lookup);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void login_access_lookup_next(struct login_access_lookup *lookup)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz if (*lookup->next_socket == NULL) {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz /* last one */
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz if (lookup->io != NULL)
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz io_remove(&lookup->io);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client_connected_finish(&lookup->conn);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lookup->conn.fd = -1;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_access_lookup_free(lookup);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lookup->access = access_lookup(*lookup->next_socket, lookup->conn.fd,
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz login_binary->protocol,
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz login_access_callback, lookup);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz if (lookup->access == NULL)
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz login_access_lookup_free(lookup);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void client_input_error(struct login_access_lookup *lookup)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz char c;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz int ret;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz ret = recv(lookup->conn.fd, &c, 1, MSG_PEEK);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (ret <= 0) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_info("access(%s): Client disconnected during lookup (rip=%s)",
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz *lookup->next_socket,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz net_ip2addr(&lookup->conn.remote_ip));
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_access_lookup_free(lookup);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz } else {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* actual input. stop listening until lookup is done. */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz io_remove(&lookup->io);
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void client_connected(struct master_service_connection *conn)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const char *access_sockets =
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz global_login_settings->login_access_sockets;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz struct login_access_lookup *lookup;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz master_service_client_connection_accept(conn);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (conn->remote_ip.family != 0) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* log the connection's IP address in case we crash. it's of
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz course possible that another earlier client causes the
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz crash, but this is better than nothing. */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_set_failure_send_ip(&conn->remote_ip);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* make sure we're connected (or attempting to connect) to auth */
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz auth_client_connect(auth_client);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (*access_sockets == '\0') {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* no access checks */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client_connected_finish(conn);
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz return;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lookup = i_new(struct login_access_lookup, 1);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lookup->conn = *conn;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lookup->io = io_add(conn->fd, IO_READ, client_input_error, lookup);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz lookup->sockets = p_strsplit_spaces(default_pool, access_sockets, " ");
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz lookup->next_socket = lookup->sockets;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_access_lookup_next(lookup);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void auth_connect_notify(struct auth_client *client ATTR_UNUSED,
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz bool connected, void *context ATTR_UNUSED)
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (connected) {
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz auth_connected_once = TRUE;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz clients_notify_auth_connected();
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz } else if (shutting_down)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz clients_destroy_all();
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz else if (!auth_connected_once) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* auth disconnected without having ever succeeded, so the
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz auth process is probably misconfigured. no point in
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz keeping the client connections hanging. */
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz clients_destroy_all_reason("Disconnected: Auth process broken");
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic bool anvil_reconnect_callback(void)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz /* we got disconnected from anvil. we can't reconnect to it since we're
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz chrooted, so just die after we've finished handling the current
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz connections. */
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz master_service_stop_new_connections(master_service);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz return FALSE;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarzstatic void main_preinit(bool allow_core_dumps)
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz unsigned int max_fds;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz random_init();
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* Initialize SSL proxy so it can read certificate and private
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz key file. */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz ssl_proxy_init();
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz dsasl_clients_init();
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* set the number of fds we want to use. it may get increased or
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz decreased. leave a couple of extra fds for auth sockets and such.
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz worst case each connection can use:
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz - 1 for client
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz - 1 for login proxy
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz - 2 for client-side ssl proxy
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz - 2 for server-side ssl proxy (with login proxy)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz max_fds = MASTER_LISTEN_FD_FIRST + 16 +
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz master_service_get_socket_count(master_service) +
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz master_service_get_client_limit(master_service)*6;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz restrict_fd_limit(max_fds);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz io_loop_set_max_fd_count(current_ioloop, max_fds);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_assert(strcmp(global_ssl_settings->ssl, "no") == 0 ||
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz ssl_initialized);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (global_login_settings->mail_max_userip_connections > 0) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz anvil = anvil_client_init("anvil", anvil_reconnect_callback, 0);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (anvil_client_connect(anvil, TRUE) < 0)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_fatal("Couldn't connect to anvil");
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz restrict_access_by_env(NULL, TRUE);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (allow_core_dumps)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz restrict_access_allow_coredumps(TRUE);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz initial_service_count = master_service_get_service_count(master_service);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (restrict_access_get_current_chroot() == NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (chdir("login") < 0)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_fatal("chdir(login) failed: %m");
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (login_rawlog_dir != NULL &&
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz access(login_rawlog_dir, W_OK | X_OK) < 0) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz i_error("access(%s, wx) failed: %m - disabling rawlog",
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_rawlog_dir);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_rawlog_dir = NULL;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz }
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarzstatic void main_init(const char *login_socket)
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* make sure we can't fork() */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz restrict_process_count(1);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz master_service_set_avail_overflow_callback(master_service,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client_destroy_oldest);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz master_service_set_die_callback(master_service, login_die);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz auth_client = auth_client_init(login_socket, (unsigned int)getpid(),
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz FALSE);
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz auth_client_set_connect_notify(auth_client, auth_connect_notify, NULL);
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz master_auth = master_auth_init(master_service, login_binary->protocol);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_binary->init();
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_proxy_init("proxy-notify");
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz}
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz
da2423165d31474f5384833fdaa6dc4c0cee28f4Timo Sirainenstatic void main_deinit(void)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz{
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz ssl_proxy_deinit();
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz login_proxy_deinit();
login_binary->deinit();
auth_client_deinit(&auth_client);
master_auth_deinit(&master_auth);
if (anvil != NULL)
anvil_client_deinit(&anvil);
if (auth_client_to != NULL)
timeout_remove(&auth_client_to);
dsasl_clients_deinit();
login_settings_deinit();
}
int login_binary_run(const struct login_binary *binary,
int argc, char *argv[])
{
enum master_service_flags service_flags =
MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN |
MASTER_SERVICE_FLAG_TRACK_LOGIN_STATE |
MASTER_SERVICE_FLAG_USE_SSL_SETTINGS |
MASTER_SERVICE_FLAG_NO_SSL_INIT;
pool_t set_pool;
bool allow_core_dumps = FALSE;
const char *login_socket;
int c;
login_binary = binary;
login_socket = binary->default_login_socket != NULL ?
binary->default_login_socket : LOGIN_DEFAULT_SOCKET;
master_service = master_service_init(login_binary->process_name,
service_flags, &argc, &argv,
"DR:S");
master_service_init_log(master_service, t_strconcat(
login_binary->process_name, ": ", NULL));
while ((c = master_getopt(master_service)) > 0) {
switch (c) {
case 'D':
allow_core_dumps = TRUE;
break;
case 'R':
login_rawlog_dir = optarg;
break;
case 'S':
ssl_connections = TRUE;
break;
default:
return FATAL_DEFAULT;
}
}
if (argv[optind] != NULL)
login_socket = argv[optind];
login_binary->preinit();
set_pool = pool_alloconly_create("global login settings", 4096);
global_login_settings =
login_settings_read(set_pool, NULL, NULL, NULL,
&global_ssl_settings,
&global_other_settings);
main_preinit(allow_core_dumps);
master_service_init_finish(master_service);
main_init(login_socket);
master_service_run(master_service, client_connected);
main_deinit();
pool_unref(&set_pool);
master_service_deinit(&master_service);
return 0;
}