client-common.c revision 12c6ef6f1268ed4d5b63709bb4215c481b4f078c
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstruct client *clients = NULL, *last_client = NULL;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic unsigned int clients_count = 0;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic void client_idle_disconnect_timeout(struct client *client)
bbadd5331f534017cf62d5183003b3d9fdad079eTimo Sirainen client_notify_disconnect(client, CLIENT_DISCONNECT_TIMEOUT,
bbadd5331f534017cf62d5183003b3d9fdad079eTimo Sirainen "Disconnected for inactivity.");
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen client_destroy(client, "Disconnected: Inactivity");
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic void client_open_streams(struct client *client)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen i_stream_create_fd(client->fd, LOGIN_MAX_INBUF_SIZE, FALSE);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen o_stream_create_fd(client->fd, LOGIN_MAX_OUTBUF_SIZE, FALSE);
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen if (iostream_rawlog_create(login_rawlog_dir, &client->input,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenstatic bool client_is_trusted(struct client *client)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen const char *const *net;
51fb710488efa419a2964335c30451c62b9633b1Timo Sirainen unsigned int bits;
93a7d1ee4b518b5c85f9721dc6539e4dab6aae00Timo Sirainen if (client->set->login_trusted_networks == NULL)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen net = t_strsplit_spaces(client->set->login_trusted_networks, ", ");
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (net_parse_range(*net, &net_ip, &bits) < 0) {
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen if (net_is_in_network(&client->ip, &net_ip, bits))
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen const struct login_settings *set, void **other_sets,
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen const struct ip_addr *local_ip, const struct ip_addr *remote_ip)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen client = login_binary->client_vfuncs->alloc(pool);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen client->v.auth_send_challenge = client_auth_send_challenge;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen client->v.auth_parse_response = client_auth_parse_response;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainenvoid client_destroy(struct client *client, const char *reason)
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen if (!client->login_success && reason != NULL) {
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen client_get_extra_disconnect_reason(client), NULL);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen master_auth_request_abort(master_auth, client->master_tag);
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen if (client_unref(&client) && initial_service_count == 1) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* as soon as this connection is done with proxying
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen (or whatever), the process will die. there's no need for
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen authentication anymore, so close the connection.
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen do this only with initial service_count=1, in case there
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen are other clients with pending authentications */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen auth_client_disconnect(auth_client, "unnecessary connection");
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid client_destroy_success(struct client *client, const char *reason)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenvoid client_destroy_internal_failure(struct client *client)
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen client_notify_disconnect(client, CLIENT_DISCONNECT_INTERNAL_ERROR,
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainen "Internal login failure. "
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainen "Refer to server log for more information.");
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen "Internal login failure (pid=%s id=%u)",
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainen master_service_client_connection_destroyed(master_service);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* we have no clients */
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen /* destroy the last client that hasn't successfully authenticated yet.
1da01eaa962be13cee75771064e2256b1a82d90aTimo Sirainen this is usually the last client, but don't kill it if it's just
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen waiting for master to finish its job. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (client = last_client; client != NULL; client = client->prev) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen client_notify_disconnect(client, CLIENT_DISCONNECT_RESOURCE_CONSTRAINT,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen "Connection queue full");
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen client_destroy(client, "Disconnected: Connection queue full");
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen for (client = clients; client != NULL; client = next) {
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen CLIENT_DISCONNECT_SYSTEM_SHUTDOWN, "Shutting down.");
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen client_destroy(client, "Disconnected: Shutting down");
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainenstatic void client_start_tls(struct client *client)
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen if (!client_unref(&client) || client->destroyed)
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen fd_ssl = ssl_proxy_alloc(client->fd, &client->ip,
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen "TLS initialization failed.");
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen "Disconnected: TLS initialization failed.");
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen ssl_proxy_set_client(client->ssl_proxy, client);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainenstatic int client_output_starttls(struct client *client)
6bd263caf006edc75205f446fa0283c6f364941bTimo Sirainen if ((ret = o_stream_flush(client->output)) < 0) {
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen o_stream_unset_flush_callback(client->output);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainenvoid client_cmd_starttls(struct client *client)
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen client->v.notify_starttls(client, FALSE, "TLS is already active.");
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen client->v.notify_starttls(client, FALSE, "TLS support isn't enabled.");
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen /* remove input handler, SSL proxy gives us a new fd. we also have to
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen remove it in case we have to wait for buffer to be flushed */
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen client->v.notify_starttls(client, TRUE, "Begin TLS negotiation now.");
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen /* uncork the old fd */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen /* the buffer has to be flushed */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen o_stream_set_flush_pending(client->output, TRUE);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainenunsigned int clients_get_count(void)
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainenstatic const struct var_expand_table *
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen static struct var_expand_table static_tab[] = {
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen unsigned int i;
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen tab[1].value = t_strcut(client->virtual_user, '@');
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen tab[2].value = strchr(client->virtual_user, '@');
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen for (i = 0; i < 3; i++)
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen tab[i].value = str_sanitize(tab[i].value, 80);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen tab[5].value = net_ip2addr(&client->local_ip);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen tab[8].value = client->auth_mech_name == NULL ? NULL :
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;
return t_strdup_printf(
const char *text)
return FALSE;
return FALSE;
return TRUE;
return TRUE;