Mercurial > dovecot > core-2.2
view src/login-common/main.c @ 9984:097588a7903c HEAD
lib-auth: Changed API to connect to only a single specified auth socket.
Login processes now always connect to socket called "auth".
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 07 Oct 2009 17:46:14 -0400 |
parents | 0d5d10a3273c |
children | 45cdc5539c93 |
line wrap: on
line source
/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */ #include "common.h" #include "ioloop.h" #include "randgen.h" #include "restrict-access.h" #include "restrict-process-size.h" #include "process-title.h" #include "master-auth.h" #include "master-service.h" #include "master-interface.h" #include "client-common.h" #include "auth-client.h" #include "ssl-proxy.h" #include "login-proxy.h" #include <stdlib.h> #include <unistd.h> #include <syslog.h> struct auth_client *auth_client; bool closing_down; int anvil_fd = -1; const struct login_settings *global_login_settings; static bool ssl_connections = FALSE; static void client_connected(const struct master_service_connection *conn) { struct client *client; struct ssl_proxy *proxy; struct ip_addr local_ip; const struct login_settings *set; unsigned int local_port; pool_t pool; int fd_ssl; if (net_getsockname(conn->fd, &local_ip, &local_port) < 0) { memset(&local_ip, 0, sizeof(local_ip)); local_port = 0; } pool = pool_alloconly_create("login client", 3*1024); set = login_settings_read(master_service, pool, &local_ip, &conn->remote_ip); if (!ssl_connections && !conn->ssl) { client = client_create(conn->fd, FALSE, pool, set, &local_ip, &conn->remote_ip); } else { fd_ssl = ssl_proxy_new(conn->fd, &conn->remote_ip, set, &proxy); if (fd_ssl == -1) { net_disconnect(conn->fd); pool_unref(&pool); return; } client = client_create(fd_ssl, TRUE, pool, set, &local_ip, &conn->remote_ip); client->ssl_proxy = proxy; ssl_proxy_set_client(proxy, client); } client->remote_port = conn->remote_port; client->local_port = local_port; } static void auth_connect_notify(struct auth_client *client ATTR_UNUSED, bool connected, void *context ATTR_UNUSED) { if (connected) clients_notify_auth_connected(); } static int anvil_connect(void) { #define ANVIL_HANDSHAKE "VERSION\tanvil\t1\t0\n" int i = 0, fd; while ((fd = net_connect_unix("anvil")) == -1) { if (errno != EAGAIN || ++i == 3) i_fatal("net_connect_unix(anvil) failed: %m"); sleep(1); } net_set_nonblock(fd, FALSE); if (write(fd, ANVIL_HANDSHAKE, strlen(ANVIL_HANDSHAKE)) < 0) i_fatal("write(anvil) failed: %m"); return fd; } static void main_preinit(void) { unsigned int max_fds; random_init(); /* Initialize SSL proxy so it can read certificate and private key file. */ ssl_proxy_init(); /* set the number of fds we want to use. it may get increased or decreased. leave a couple of extra fds for auth sockets and such. worst case each connection can use: - 1 for client - 1 for login proxy - 2 for client-side ssl proxy - 2 for server-side ssl proxy (with login proxy) */ max_fds = MASTER_LISTEN_FD_FIRST + 16 + master_service_get_socket_count(master_service) + master_service_get_client_limit(master_service)*6; restrict_fd_limit(max_fds); io_loop_set_max_fd_count(current_ioloop, max_fds); i_assert(strcmp(global_login_settings->ssl, "no") == 0 || ssl_initialized); if (global_login_settings->mail_max_userip_connections > 0) anvil_fd = anvil_connect(); restrict_access_by_env(NULL, TRUE); } static void main_init(void) { /* make sure we can't fork() */ restrict_process_size((unsigned int)-1, 1); if (restrict_access_get_current_chroot() == NULL) { if (chdir("login") < 0) i_fatal("chdir(login) failed: %m"); } master_service_set_avail_overflow_callback(master_service, client_destroy_oldest); auth_client = auth_client_init("auth", (unsigned int)getpid(), FALSE); auth_client_set_connect_notify(auth_client, auth_connect_notify, NULL); clients_init(); login_proxy_init(); master_auth_init(master_service); } static void main_deinit(void) { ssl_proxy_deinit(); login_proxy_deinit(); if (auth_client != NULL) auth_client_deinit(&auth_client); clients_deinit(); if (anvil_fd != -1) { if (close(anvil_fd) < 0) i_error("close(anvil) failed: %m"); } master_auth_deinit(master_service); } int main(int argc, char *argv[], char *envp[]) { const char *getopt_str; pool_t set_pool; int c; //FIXME:is_inetd = getenv("DOVECOT_MASTER") == NULL; master_service = master_service_init(login_process_name, MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN, argc, argv); master_service_init_log(master_service, t_strconcat( login_process_name, ": ", NULL)); getopt_str = t_strconcat("DS", master_service_getopt_string(), NULL); while ((c = getopt(argc, argv, getopt_str)) > 0) { switch (c) { case 'D': restrict_access_allow_coredumps(TRUE); break; case 'S': ssl_connections = TRUE; break; default: if (!master_service_parse_option(master_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", 4096); global_login_settings = login_settings_read(master_service, set_pool, NULL, NULL); /* main_preinit() needs to know the client limit, which is set by this. so call it first. */ master_service_init_finish(master_service); main_preinit(); main_init(); master_service_run(master_service, client_connected); main_deinit(); pool_unref(&set_pool); master_service_deinit(&master_service); return 0; }