client-common.c revision 2454dfa32c93c20a8522c6ed42fe057baaac9f9a
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic unsigned int clients_count = 0;
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzstatic void empty_login_client_allocated_hook(struct client *client ATTR_UNUSED)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic login_client_allocated_func_t *hook_client_allocated =
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzlogin_client_allocated_hook_set(login_client_allocated_func_t *new_hook)
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz login_client_allocated_func_t *old_hook = hook_client_allocated;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzstatic void client_idle_disconnect_timeout(struct client *client)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz user_reason = "Timeout while finishing login.";
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz "Timeout while finishing login (waited %u secs)", secs);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz } else if (client->auth_request != NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz "Disconnected for inactivity during authentication.";
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz "Disconnected: Inactivity during authentication";
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz user_reason = "Timeout while finishing login.";
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz "proxy: Logging in to %s:%u timed out "
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz "(state=%u, duration=%us)",
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz user_reason = "Disconnected for inactivity.";
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz destroy_reason = "Disconnected: Inactivity";
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz client_notify_disconnect(client, CLIENT_DISCONNECT_TIMEOUT, user_reason);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzstatic void client_open_streams(struct client *client)
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz client->input = i_stream_create_fd(client->fd, LOGIN_MAX_INBUF_SIZE);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->output = o_stream_create_fd(client->fd, LOGIN_MAX_OUTBUF_SIZE);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz o_stream_set_no_error_handling(client->output, TRUE);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (iostream_rawlog_create(login_rawlog_dir, &client->input,
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzstatic bool client_is_trusted(struct client *client)
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz const char *const *net;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (client->set->login_trusted_networks == NULL)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz net = t_strsplit_spaces(client->set->login_trusted_networks, ", ");
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (net_parse_range(*net, &net_ip, &bits) < 0) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (net_is_in_network(&client->ip, &net_ip, bits))
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzclient_create(int fd, bool ssl, pool_t pool,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const struct master_service_connection *conn,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz const struct master_service_ssl_settings *ssl_set,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client = login_binary->client_vfuncs->alloc(pool);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (client->v.auth_send_challenge == NULL)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->v.auth_send_challenge = client_auth_send_challenge;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (client->v.auth_parse_response == NULL)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->v.auth_parse_response = client_auth_parse_response;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz p_array_init(&client->module_contexts, client->pool, 5);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->real_local_ip = conn->real_local_ip;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->real_local_port = conn->real_local_port;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->real_remote_ip = conn->real_remote_ip;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->real_remote_port = conn->real_remote_port;
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->listener_name = p_strdup(client->pool, conn->name);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->trusted = client_is_trusted(client);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client->secured = ssl || client->trusted ||
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz net_ip_compare(&conn->real_remote_ip, &conn->real_local_ip);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (auth_client_is_connected(auth_client))
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarzvoid client_destroy(struct client *client, const char *reason)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (!client->login_success && reason != NULL) {
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz client_get_extra_disconnect_reason(client), NULL);
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz if (!client->login_success && client->ssl_proxy != NULL)
f6fb60c7dcfc88895c8c45514c3fc424d3126336Michael Slusarz master_auth_request_abort(master_auth, client->master_tag);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz } else if (client->auth_request != NULL) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz dsasl_client_free(&client->proxy_sasl_client);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz if (client_unref(&client) && initial_service_count == 1) {
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz /* as soon as this connection is done with proxying
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz (or whatever), the process will die. there's no need for
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz authentication anymore, so close the connection.
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz do this only with initial service_count=1, in case there
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz are other clients with pending authentications */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz auth_client_disconnect(auth_client, "unnecessary connection");
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarzvoid client_destroy_success(struct client *client, const char *reason)
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarzvoid client_destroy_internal_failure(struct client *client)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client_notify_disconnect(client, CLIENT_DISCONNECT_INTERNAL_ERROR,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz "Internal login failure. "
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz "Refer to server log for more information.");
e7e9ca33af09b6ab77633bcafe27d751adf09c93Michael Slusarz "Internal login failure (pid=%s id=%u)",
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz master_service_client_connection_destroyed(master_service);
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* we have no clients */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz /* destroy the last client that hasn't successfully authenticated yet.
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz this is usually the last client, but don't kill it if it's just
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz waiting for master to finish its job. */
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz for (client = last_client; client != NULL; client = client->prev) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client_notify_disconnect(client, CLIENT_DISCONNECT_RESOURCE_CONSTRAINT,
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz "Connection queue full");
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz client_destroy(client, "Disconnected: Connection queue full");
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarzvoid clients_destroy_all_reason(const char *reason)
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz for (client = clients; client != NULL; client = next) {
51ed197520dd9ea534fbc3bc1790ebe3cb5421e2Michael M Slusarz CLIENT_DISCONNECT_SYSTEM_SHUTDOWN, reason);
void clients_destroy_all(void)
int fd_ssl;
int ret;
if (ret > 0) {
unsigned int clients_get_count(void)
return clients_count;
static const struct var_expand_table *
sizeof(login_var_expand_empty_tab));
const char *ssl_state =
const char *ssl_error =
return tab;
char key;
str++;
return TRUE;
return FALSE;
const char **value_r,
field_name_len) == 0 &&
const char *error;
unsigned int pos;
*e, error);
if (have_username_key(*e)) {
&error) <= 0) {
T_BEGIN {
} T_END;
T_BEGIN {
} T_END;
T_BEGIN {
} T_END;
return t_strdup_printf(
return t_strdup_printf(
const char *text)
return FALSE;
return FALSE;
return TRUE;
return TRUE;