client-common.c revision e59faf65ce864fe95dc00f5d52b8323cdbd0608a
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "login-common.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "hostpid.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "llist.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "istream.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "ostream.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "process-title.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "str.h"
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#include "str-sanitize.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "safe-memset.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "var-expand.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "master-service.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "master-auth.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "auth-client.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "login-proxy.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "ssl-proxy.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include "client-common.h"
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch#include <stdlib.h>
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstruct client *clients = NULL, *last_client = NULL;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstatic unsigned int clients_count = 0;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstatic void client_idle_disconnect_timeout(struct client *client)
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch{
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client_send_line(client, CLIENT_CMD_REPLY_BYE,
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch "Disconnected for inactivity.");
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client_destroy(client, "Disconnected: Inactivity");
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch}
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstatic void client_open_streams(struct client *client)
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch{
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->input =
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch i_stream_create_fd(client->fd, LOGIN_MAX_INBUF_SIZE, FALSE);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->output =
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch o_stream_create_fd(client->fd, LOGIN_MAX_OUTBUF_SIZE, FALSE);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch}
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschstruct client *
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Boschclient_create(int fd, bool ssl, pool_t pool,
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch const struct login_settings *set, void **other_sets,
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch const struct ip_addr *local_ip, const struct ip_addr *remote_ip)
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch{
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch struct client *client;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch i_assert(fd != -1);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client = client_vfuncs.alloc(pool);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->v = client_vfuncs;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch if (client->v.auth_send_challenge == NULL)
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->v.auth_send_challenge = client_auth_send_challenge;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch if (client->v.auth_parse_response == NULL)
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->v.auth_parse_response = client_auth_parse_response;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->created = ioloop_time;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->refcount = 1;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->pool = pool;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->set = set;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->local_ip = *local_ip;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->ip = *remote_ip;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->fd = fd;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->tls = ssl;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->trusted = client_is_trusted(client);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->secured = ssl || client->trusted ||
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch net_ip_compare(remote_ip, local_ip);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch if (last_client == NULL)
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch last_client = client;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch DLLIST_PREPEND(&clients, client);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch clients_count++;
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->to_idle_disconnect =
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch timeout_add(CLIENT_LOGIN_IDLE_TIMEOUT_MSECS,
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client_idle_disconnect_timeout, client);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client_open_streams(client);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch client->v.create(client, other_sets);
62ed3307fb8a4a038a32a5181c503f1b645bf946Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (auth_client_is_connected(auth_client))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->v.send_greeting(client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch else
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_set_auth_waiting(client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch login_refresh_proctitle();
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return client;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschvoid client_destroy(struct client *client, const char *reason)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch if (client->destroyed)
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->destroyed = TRUE;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!client->login_success && reason != NULL) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch reason = t_strconcat(reason, " ",
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_get_extra_disconnect_reason(client), NULL);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch }
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch if (reason != NULL)
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch client_log(client, reason);
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch if (last_client == client)
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch last_client = client->prev;
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch DLLIST_REMOVE(&clients, client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->input != NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_stream_close(client->input);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->output != NULL)
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch o_stream_close(client->output);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->master_tag != 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(client->auth_request == NULL);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(client->authenticating);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(client->refcount > 1);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->authenticating = FALSE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch master_auth_request_abort(master_auth, client->master_tag);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->refcount--;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else if (client->auth_request != NULL) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(client->authenticating);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch sasl_server_auth_abort(client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(!client->authenticating);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->io != NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch io_remove(&client->io);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->to_idle_disconnect != NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch timeout_remove(&client->to_idle_disconnect);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->to_auth_waiting != NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch timeout_remove(&client->to_auth_waiting);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->auth_response != NULL)
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch str_free(&client->auth_response);
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch if (client->fd != -1) {
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch net_disconnect(client->fd);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->fd = -1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch if (client->proxy_password != NULL) {
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch safe_memset(client->proxy_password, 0,
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch strlen(client->proxy_password));
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch i_free_and_null(client->proxy_password);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_free_and_null(client->proxy_user);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_free_and_null(client->proxy_master_user);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->login_proxy != NULL)
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen login_proxy_free(&client->login_proxy);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->ssl_proxy != NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ssl_proxy_free(&client->ssl_proxy);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->v.destroy(client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client_unref(&client) &&
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch master_service_get_service_count(master_service) == 1) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* as soon as this connection is done with proxying
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch (or whatever), the process will die. there's no need for
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch authentication anymore, so close the connection. */
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen if (auth_client != NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch auth_client_deinit(&auth_client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch login_refresh_proctitle();
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschvoid client_destroy_success(struct client *client, const char *reason)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
89e040049336e69c43fec09dcbdfd0f2ae5efd51Martti Rannanjärvi client->login_success = TRUE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_destroy(client, reason);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschvoid client_destroy_internal_failure(struct client *client)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch "Internal login failure. "
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch "Refer to server log for more information.");
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch client_destroy(client, "Internal login failure");
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch}
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Boschvoid client_ref(struct client *client)
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch{
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch client->refcount++;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschbool client_unref(struct client **_client)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct client *client = *_client;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch i_assert(client->refcount > 0);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (--client->refcount > 0)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return TRUE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch *_client = NULL;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(client->destroyed);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(client->ssl_proxy == NULL);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(client->login_proxy == NULL);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->input != NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_stream_unref(&client->input);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->output != NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch o_stream_unref(&client->output);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_free(client->virtual_user);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_free(client->auth_mech_name);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch pool_unref(&client->pool);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_assert(clients_count > 0);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch clients_count--;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch master_service_client_connection_destroyed(master_service);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch login_refresh_proctitle();
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return FALSE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschvoid client_destroy_oldest(void)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch struct client *client;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch if (last_client == NULL) {
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch /* we have no clients */
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch return;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch }
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch /* destroy the last client that hasn't successfully authenticated yet.
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch this is usually the last client, but don't kill it if it's just
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch waiting for master to finish its job. */
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch for (client = last_client; client != NULL; client = client->prev) {
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch if (client->master_tag == 0)
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch break;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch }
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch if (client == NULL)
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch client = last_client;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch client_destroy(client, "Disconnected: Connection queue full");
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch}
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Boschvoid clients_destroy_all(void)
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch{
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch struct client *client, *next;
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (client = clients; client != NULL; client = next) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch next = client->next;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_destroy(client, "Disconnected: Shutting down");
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Boschstatic void client_start_tls(struct client *client)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int fd_ssl;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_ref(client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!client_unref(&client) || client->destroyed)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch fd_ssl = ssl_proxy_alloc(client->fd, &client->ip,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->set, &client->ssl_proxy);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (fd_ssl == -1) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_send_line(client, CLIENT_CMD_REPLY_BYE,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch "TLS initialization failed.");
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_destroy(client,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch "Disconnected: TLS initialization failed.");
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch ssl_proxy_set_client(client->ssl_proxy, client);
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch ssl_proxy_start(client->ssl_proxy);
32f28ff765ef6983af0df78ebc5289b478abf3feStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->starttls = TRUE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->tls = TRUE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->secured = TRUE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch login_refresh_proctitle();
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->fd = fd_ssl;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->io = io_add(client->fd, IO_READ, client_input, client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_stream_unref(&client->input);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch o_stream_unref(&client->output);
72fc989c43a0dc94ec2f114b5e221beeab45519bTimo Sirainen client_open_streams(client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client->v.starttls(client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int client_output_starttls(struct client *client)
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch int ret;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if ((ret = o_stream_flush(client->output)) < 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_destroy(client, "Disconnected");
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return 1;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch if (ret > 0) {
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch o_stream_unset_flush_callback(client->output);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_start_tls(client);
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch }
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch return 1;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch}
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Boschvoid client_cmd_starttls(struct client *client)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch if (client->tls) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_send_line(client, CLIENT_CMD_REPLY_BAD,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch "TLS is already active.");
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch }
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen if (!ssl_initialized) {
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch client_send_line(client, CLIENT_CMD_REPLY_BAD,
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch "TLS support isn't enabled.");
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch return;
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch }
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* remove input handler, SSL proxy gives us a new fd. we also have to
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch remove it in case we have to wait for buffer to be flushed */
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch if (client->io != NULL)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch io_remove(&client->io);
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch client_send_line(client, CLIENT_CMD_REPLY_OK,
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch "Begin TLS negotiation now.");
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch /* uncork the old fd */
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch o_stream_uncork(client->output);
b4167b174b4eeebceaf80e240635e601f0a9860cStephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (o_stream_flush(client->output) <= 0) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* the buffer has to be flushed */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch o_stream_set_flush_pending(client->output, TRUE);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch o_stream_set_flush_callback(client->output,
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch client_output_starttls, client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else {
0e702716169a158b87d08e21d1a128eb99e23fa1Phil Carmody client_start_tls(client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschunsigned int clients_get_count(void)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return clients_count;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic const struct var_expand_table *
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschget_var_expand_table(struct client *client)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch static struct var_expand_table static_tab[] = {
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen { 'u', NULL, "user" },
0e702716169a158b87d08e21d1a128eb99e23fa1Phil Carmody { 'n', NULL, "username" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'd', NULL, "domain" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 's', NULL, "service" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'h', NULL, "home" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'l', NULL, "lip" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'r', NULL, "rip" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'p', NULL, "pid" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'm', NULL, "mech" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'a', NULL, "lport" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'b', NULL, "rport" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'c', NULL, "secured" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'k', NULL, "ssl_security" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 'e', NULL, "mail_pid" },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { '\0', NULL, NULL }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch };
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct var_expand_table *tab;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int i;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab = t_malloc(sizeof(static_tab));
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch memcpy(tab, static_tab, sizeof(static_tab));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (client->virtual_user != NULL) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[0].value = client->virtual_user;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[1].value = t_strcut(client->virtual_user, '@');
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[2].value = strchr(client->virtual_user, '@');
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (tab[2].value != NULL) tab[2].value++;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (i = 0; i < 3; i++)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[i].value = str_sanitize(tab[i].value, 80);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[3].value = login_protocol;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[4].value = getenv("HOME");
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[5].value = net_ip2addr(&client->local_ip);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[6].value = net_ip2addr(&client->ip);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[7].value = my_pid;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[8].value = client->auth_mech_name == NULL ? NULL :
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[9].value = dec2str(client->local_port);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[10].value = dec2str(client->remote_port);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (!client->tls) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[11].value = client->secured ? "secured" : NULL;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[12].value = "";
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch } else {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const char *ssl_state =
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ssl_proxy_is_handshaked(client->ssl_proxy) ?
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch "TLS" : "TLS handshaking";
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const char *ssl_error =
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ssl_proxy_get_last_error(client->ssl_proxy);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[11].value = ssl_error == NULL ? ssl_state :
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch t_strdup_printf("%s: %s", ssl_state, ssl_error);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch tab[12].value =
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch ssl_proxy_get_security_string(client->ssl_proxy);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch }
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch tab[13].value = dec2str(client->mail_pid);
7a545edbd1fca7a330bcb4a807002373ee18762aStephan Bosch return tab;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic bool have_key(const struct var_expand_table *table, const char *str)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch char key;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned int i;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch key = var_get_key(str);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch for (i = 0; table[i].key != '\0'; i++) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (table[i].key == key) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return table[i].value != NULL &&
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch table[i].value[0] != '\0';
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch }
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch }
b7e953d7eecd18f1d0de701cc181e8830d8167b1Stephan Bosch return FALSE;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch}
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic const char *
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschclient_get_log_str(struct client *client, const char *msg)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch{
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch static struct var_expand_table static_tab[3] = {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { 's', NULL, NULL },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { '$', NULL, NULL },
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch { '\0', NULL, NULL }
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch };
4d955db590c3d76a631dfc5d37bcdf578a43e55aStephan Bosch const struct var_expand_table *var_expand_table;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct var_expand_table *tab;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch const char *p;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch char *const *e;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch string_t *str;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch var_expand_table = get_var_expand_table(client);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
f3cf2f02155c4bac23fd50f0de96c0cae9c46478Stephan Bosch tab = t_malloc(sizeof(static_tab));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memcpy(tab, static_tab, sizeof(static_tab));
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch str = t_str_new(256);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch for (e = client->set->log_format_elements_split; *e != NULL; e++) {
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch for (p = *e; *p != '\0'; p++) {
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch if (*p != '%' || p[1] == '\0')
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch continue;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch p++;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch if (have_key(var_expand_table, p)) {
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch if (str_len(str) > 0)
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch str_append(str, ", ");
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch var_expand(str, *e, var_expand_table);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch break;
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch }
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch }
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch }
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch tab[0].value = t_strdup(str_c(str));
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch tab[1].value = msg;
14383bf2be0296954609df5afd3c63c6555815f9Stephan Bosch str_truncate(str, 0);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch var_expand(str, client->set->login_log_format, tab);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return str_c(str);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschvoid client_log(struct client *client, const char *msg)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch T_BEGIN {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch i_info("%s", client_get_log_str(client, msg));
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch } T_END;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschvoid client_log_err(struct client *client, const char *msg)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch T_BEGIN {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch i_error("%s", client_get_log_str(client, msg));
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch } T_END;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschbool client_is_trusted(struct client *client)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch const char *const *net;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch struct ip_addr net_ip;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch unsigned int bits;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (client->set->login_trusted_networks == NULL)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return FALSE;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch net = t_strsplit_spaces(client->set->login_trusted_networks, ", ");
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch for (; *net != NULL; net++) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (net_parse_range(*net, &net_ip, &bits) < 0) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch i_error("login_trusted_networks: "
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch "Invalid network '%s'", *net);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch break;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (net_is_in_network(&client->ip, &net_ip, bits))
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return TRUE;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return FALSE;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschconst char *client_get_extra_disconnect_reason(struct client *client)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (client->set->ssl_require_client_cert && client->ssl_proxy != NULL) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (ssl_proxy_has_broken_client_cert(client->ssl_proxy))
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return "(client sent an invalid cert)";
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (!ssl_proxy_has_valid_client_cert(client->ssl_proxy))
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return "(client didn't send a cert)";
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (client->auth_attempts == 0)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return "(no auth attempts)";
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* some auth attempts without SSL/TLS */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (client->auth_tried_disabled_plaintext)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return "(tried to use disabled plaintext auth)";
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (client->set->ssl_require_client_cert)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return "(cert required, client didn't start TLS)";
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (client->auth_tried_unsupported_mech)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return "(tried to use unsupported auth mechanism)";
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (client->auth_request != NULL && client->auth_attempts == 1)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return "(disconnected while authenticating)";
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (client->auth_try_aborted && client->auth_attempts == 1)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return "(aborted authentication)";
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return t_strdup_printf("(auth failed, %u attempts)",
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch client->auth_attempts);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschvoid client_send_line(struct client *client, enum client_cmd_reply reply,
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch const char *text)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch client->v.send_line(client, reply, text);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschvoid client_send_raw_data(struct client *client, const void *data, size_t size)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch ssize_t ret;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch ret = o_stream_send(client->output, data, size);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch if (ret < 0 || (size_t)ret != size) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* either disconnection or buffer full. in either case we want
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch this connection destroyed. however destroying it here might
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch break things if client is still tried to be accessed without
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch being referenced.. */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch i_stream_close(client->input);
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch }
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschvoid client_send_raw(struct client *client, const char *data)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch client_send_raw_data(client, data, strlen(data));
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch}
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Boschbool client_read(struct client *client)
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch{
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch switch (i_stream_read(client->input)) {
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch case -2:
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* buffer full */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch client_send_line(client, CLIENT_CMD_REPLY_BYE,
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch "Input buffer full, aborting");
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch client_destroy(client, "Disconnected: Input buffer full");
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return FALSE;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch case -1:
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* disconnected */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch client_destroy(client, "Disconnected");
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return FALSE;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch case 0:
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* nothing new read */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch return TRUE;
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch default:
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch /* something was read */
b0dfc8fc0dd5d08fe6a746e346dca6c737749d89Stephan Bosch timeout_reset(client->to_idle_disconnect);
d3b0b5d2389acc43c75b63d2960daf82cf1f8aa7Stephan Bosch return TRUE;
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch }
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch}
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Boschvoid client_input(struct client *client)
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch{
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch client->v.input(client);
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch}
8d2d2780c9e71581ff9c3e8bce527b492c295ec1Stephan Bosch