client-common.c revision 7c849dbc7be089175c1a83a84ee7249ed695810d
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstruct client *clients = NULL, *last_client = NULL;
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic unsigned int clients_count = 0;
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic void client_idle_disconnect_timeout(struct client *client)
6a90041707f1290c8970a3bacb0f8f928aeaaba6Stephan Bosch client_send_line(client, CLIENT_CMD_REPLY_BYE,
6a90041707f1290c8970a3bacb0f8f928aeaaba6Stephan Bosch "Disconnected for inactivity.");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client_destroy(client, "Disconnected: Inactivity");
feba5e502b2131c9a1c766b7ef9ff041dbf71d1dStephan Boschstatic void client_open_streams(struct client *client)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_stream_create_fd(client->fd, LOGIN_MAX_INBUF_SIZE, FALSE);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch o_stream_create_fd(client->fd, LOGIN_MAX_OUTBUF_SIZE, FALSE);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch if (iostream_rawlog_create(login_rawlog_dir, &client->input,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const struct login_settings *set, void **other_sets,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const struct ip_addr *local_ip, const struct ip_addr *remote_ip)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client = login_binary->client_vfuncs->alloc(pool);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client->v.auth_send_challenge = client_auth_send_challenge;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client->v.auth_parse_response = client_auth_parse_response;
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid client_destroy(struct client *client, const char *reason)
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen if (!client->login_success && reason != NULL) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client_get_extra_disconnect_reason(client), NULL);
d08e49550aa890e71a5f10b7de43347ec44473acTimo Sirainen master_auth_request_abort(master_auth, client->master_tag);
d08e49550aa890e71a5f10b7de43347ec44473acTimo Sirainen if (client_unref(&client) && initial_service_count == 1) {
d08e49550aa890e71a5f10b7de43347ec44473acTimo Sirainen /* as soon as this connection is done with proxying
d08e49550aa890e71a5f10b7de43347ec44473acTimo Sirainen (or whatever), the process will die. there's no need for
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch authentication anymore, so close the connection.
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch do this only with initial service_count=1, in case there
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch are other clients with pending authentications */
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Boschvoid client_destroy_success(struct client *client, const char *reason)
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Boschvoid client_destroy_internal_failure(struct client *client)
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch "Internal login failure. "
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch "Refer to server log for more information.");
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch "Internal login failure (pid=%s id=%u)",
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch master_service_client_connection_destroyed(master_service);
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch /* we have no clients */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* destroy the last client that hasn't successfully authenticated yet.
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch this is usually the last client, but don't kill it if it's just
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch waiting for master to finish its job. */
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch for (client = last_client; client != NULL; client = client->prev) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client_destroy(client, "Disconnected: Connection queue full");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch for (client = clients; client != NULL; client = next) {
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen client_destroy(client, "Disconnected: Shutting down");
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic void client_start_tls(struct client *client)
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch if (!client_unref(&client) || client->destroyed)
b72c3363092b73cab1da2de4a9d75592e7d8fd6bTimo Sirainen fd_ssl = ssl_proxy_alloc(client->fd, &client->ip,
2a8454fe986d4a881d3612eebb39101be1d6db94Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_BYE,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "TLS initialization failed.");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "Disconnected: TLS initialization failed.");
7af70f7646264a2f52b361f9ca78f08681acc4e2Stephan Bosch ssl_proxy_set_client(client->ssl_proxy, client);
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch client->io = io_add(client->fd, IO_READ, client_input, client);
7af70f7646264a2f52b361f9ca78f08681acc4e2Stephan Boschstatic int client_output_starttls(struct client *client)
7af70f7646264a2f52b361f9ca78f08681acc4e2Stephan Bosch if ((ret = o_stream_flush(client->output)) < 0) {
7af70f7646264a2f52b361f9ca78f08681acc4e2Stephan Bosch o_stream_unset_flush_callback(client->output);
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid client_cmd_starttls(struct client *client)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch client_send_line(client, CLIENT_CMD_REPLY_BAD,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "TLS is already active.");
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch client_send_line(client, CLIENT_CMD_REPLY_BAD,
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch "TLS support isn't enabled.");
c177bc7c153dd4d00dfa719f8a93c81129c4235eStephan Bosch /* remove input handler, SSL proxy gives us a new fd. we also have to
c177bc7c153dd4d00dfa719f8a93c81129c4235eStephan Bosch remove it in case we have to wait for buffer to be flushed */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "Begin TLS negotiation now.");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* uncork the old fd */
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch /* the buffer has to be flushed */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch o_stream_set_flush_pending(client->output, TRUE);
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Boschunsigned int clients_get_count(void)
6a90041707f1290c8970a3bacb0f8f928aeaaba6Stephan Boschstatic const struct var_expand_table *
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch static struct var_expand_table static_tab[] = {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch unsigned int i;
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch tab[1].value = t_strcut(client->virtual_user, '@');
208dcaf62332b80b220c8c66e776f7cc0c39253bStephan Bosch tab[2].value = strchr(client->virtual_user, '@');
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch for (i = 0; i < 3; i++)
7af70f7646264a2f52b361f9ca78f08681acc4e2Stephan Bosch tab[i].value = str_sanitize(tab[i].value, 80);
7af70f7646264a2f52b361f9ca78f08681acc4e2Stephan Bosch tab[5].value = net_ip2addr(&client->local_ip);
7af70f7646264a2f52b361f9ca78f08681acc4e2Stephan Bosch tab[8].value = client->auth_mech_name == NULL ? NULL :
7af70f7646264a2f52b361f9ca78f08681acc4e2Stephan Bosch str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
7af70f7646264a2f52b361f9ca78f08681acc4e2Stephan Bosch tab[11].value = client->secured ? "secured" : NULL;
6a90041707f1290c8970a3bacb0f8f928aeaaba6Stephan Bosch tab[11].value = ssl_error == NULL ? ssl_state :
6a90041707f1290c8970a3bacb0f8f928aeaaba6Stephan Bosch t_strdup_printf("%s: %s", ssl_state, ssl_error);
6a90041707f1290c8970a3bacb0f8f928aeaaba6Stephan Bosch ssl_proxy_get_security_string(client->ssl_proxy);
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic bool have_key(const struct var_expand_table *table, const char *str)
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;