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