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