client-common.c revision 5f5870385cff47efd2f58e7892f251cf13761528
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
fca7aa88ab19375aba5a8fd9d4100ea885dccb68Timo Sirainenstruct client *clients = NULL, *last_client = NULL;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic unsigned int clients_count = 0;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic void client_idle_disconnect_timeout(struct client *client)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_BYE,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Disconnected for inactivity.");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client_destroy(client, "Disconnected: Inactivity");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic void client_open_streams(struct client *client)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen i_stream_create_fd(client->fd, LOGIN_MAX_INBUF_SIZE, FALSE);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen o_stream_create_fd(client->fd, LOGIN_MAX_OUTBUF_SIZE, FALSE);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen if (iostream_rawlog_create(login_rawlog_dir, &client->input,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen const struct login_settings *set, void **other_sets,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen const struct ip_addr *local_ip, const struct ip_addr *remote_ip)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client = login_binary->client_vfuncs->alloc(pool);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client->v.auth_send_challenge = client_auth_send_challenge;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client->v.auth_parse_response = client_auth_parse_response;
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenvoid client_destroy(struct client *client, const char *reason)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen if (!client->login_success && reason != NULL) {
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client_get_extra_disconnect_reason(client), NULL);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen master_auth_request_abort(master_auth, client->master_tag);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen if (client_unref(&client) && initial_service_count == 1) {
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen /* as soon as this connection is done with proxying
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen (or whatever), the process will die. there's no need for
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen authentication anymore, so close the connection.
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen do this only with initial service_count=1, in case there
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen are other clients with pending authentications */
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen auth_client_disconnect(auth_client, "unnecessary connection");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenvoid client_destroy_success(struct client *client, const char *reason)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenvoid client_destroy_internal_failure(struct client *client)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Internal login failure. "
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Refer to server log for more information.");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Internal login failure (pid=%s id=%u)",
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen master_service_client_connection_destroyed(master_service);
e9fdf11b707cbff4686d742a74c261eda4a4a92aTimo Sirainen /* we have no clients */
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen /* destroy the last client that hasn't successfully authenticated yet.
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen this is usually the last client, but don't kill it if it's just
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen waiting for master to finish its job. */
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen for (client = last_client; client != NULL; client = client->prev) {
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client_destroy(client, "Disconnected: Connection queue full");
e9fdf11b707cbff4686d742a74c261eda4a4a92aTimo Sirainen for (client = clients; client != NULL; client = next) {
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client_destroy(client, "Disconnected: Shutting down");
e9fdf11b707cbff4686d742a74c261eda4a4a92aTimo Sirainenstatic void client_start_tls(struct client *client)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen if (!client_unref(&client) || client->destroyed)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen fd_ssl = ssl_proxy_alloc(client->fd, &client->ip,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_BYE,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "TLS initialization failed.");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Disconnected: TLS initialization failed.");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen ssl_proxy_set_client(client->ssl_proxy, client);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic int client_output_starttls(struct client *client)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen if ((ret = o_stream_flush(client->output)) < 0) {
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen o_stream_unset_flush_callback(client->output);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenvoid client_cmd_starttls(struct client *client)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_BAD,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "TLS is already active.");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_BAD,
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "TLS support isn't enabled.");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen /* remove input handler, SSL proxy gives us a new fd. we also have to
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen remove it in case we have to wait for buffer to be flushed */
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen "Begin TLS negotiation now.");
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen /* uncork the old fd */
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen /* the buffer has to be flushed */
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen o_stream_set_flush_pending(client->output, TRUE);
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenunsigned int clients_get_count(void)
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainenstatic const struct var_expand_table *
7313101ef0723c7b210e7b7bb5eb11d0d73d1b4dTimo Sirainen static struct var_expand_table static_tab[] = {
const char *ssl_state =
const char *ssl_error =
return tab;
char key;
return FALSE;
return TRUE;
return FALSE;
T_BEGIN {
} T_END;
T_BEGIN {
} T_END;
T_BEGIN {
} T_END;
const char *const *net;
unsigned int bits;
return FALSE;
return TRUE;
return FALSE;
return t_strdup_printf(
const char *text)
return FALSE;
return FALSE;
return TRUE;
return TRUE;