client-common.c revision 7cb128dc4cae2a03a742f63ba7afee23c78e3af0
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "login-common.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "hostpid.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "llist.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "istream.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "ostream.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "iostream-rawlog.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "process-title.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "buffer.h"
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen#include "str.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "base64.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "str-sanitize.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "safe-memset.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "var-expand.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "master-interface.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "master-service.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "master-service-ssl-settings.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "master-auth.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "auth-client.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "dsasl-client.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "login-proxy.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "ssl-proxy.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "client-common.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <stdlib.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstruct client *clients = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic struct client *last_client = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic unsigned int clients_count = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void client_idle_disconnect_timeout(struct client *client)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *user_reason, *destroy_reason;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int secs;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (client->master_tag != 0) {
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen secs = ioloop_time - client->auth_finished;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen user_reason = "Timeout while finishing login.";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen destroy_reason = t_strdup_printf(
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Timeout while finishing login (waited %u secs)", secs);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_log_err(client, destroy_reason);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else if (client->auth_request != NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen user_reason =
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen "Disconnected for inactivity during authentication.";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen destroy_reason =
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "Disconnected: Inactivity during authentication";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else if (client->login_proxy != NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen secs = ioloop_time - client->created;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen user_reason = "Timeout while finishing login.";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen destroy_reason = t_strdup_printf(
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "proxy: Logging in to %s:%u timed out "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "(state=%u, duration=%us)",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen login_proxy_get_host(client->login_proxy),
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen login_proxy_get_port(client->login_proxy),
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->proxy_state, secs);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_log_err(client, destroy_reason);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen user_reason = "Disconnected for inactivity.";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen destroy_reason = "Disconnected: Inactivity";
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_notify_disconnect(client, CLIENT_DISCONNECT_TIMEOUT, user_reason);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_destroy(client, destroy_reason);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstatic void client_open_streams(struct client *client)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen client->input =
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen i_stream_create_fd(client->fd, LOGIN_MAX_INBUF_SIZE, FALSE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->output =
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen o_stream_create_fd(client->fd, LOGIN_MAX_OUTBUF_SIZE, FALSE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen o_stream_set_no_error_handling(client->output, TRUE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (login_rawlog_dir != NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (iostream_rawlog_create(login_rawlog_dir, &client->input,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen &client->output) < 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen login_rawlog_dir = NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic bool client_is_trusted(struct client *client)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *const *net;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct ip_addr net_ip;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int bits;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (client->set->login_trusted_networks == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen net = t_strsplit_spaces(client->set->login_trusted_networks, ", ");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (; *net != NULL; net++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (net_parse_range(*net, &net_ip, &bits) < 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("login_trusted_networks: "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "Invalid network '%s'", *net);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (net_is_in_network(&client->ip, &net_ip, bits))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstruct client *
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenclient_create(int fd, bool ssl, pool_t pool,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const struct login_settings *set,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct master_service_ssl_settings *ssl_set,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen void **other_sets,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct ip_addr *local_ip, const struct ip_addr *remote_ip)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct client *client;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(fd != -1);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen client = login_binary->client_vfuncs->alloc(pool);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen client->v = *login_binary->client_vfuncs;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (client->v.auth_send_challenge == NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen client->v.auth_send_challenge = client_auth_send_challenge;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (client->v.auth_parse_response == NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->v.auth_parse_response = client_auth_parse_response;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen client->created = ioloop_time;
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen client->refcount = 1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen client->pool = pool;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->set = set;
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen client->ssl_set = ssl_set;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->real_local_ip = client->local_ip = *local_ip;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->real_remote_ip = client->ip = *remote_ip;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->fd = fd;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->tls = ssl;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen client->trusted = client_is_trusted(client);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen client->secured = ssl || client->trusted ||
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen net_ip_compare(remote_ip, local_ip);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen client->proxy_ttl = LOGIN_PROXY_TTL;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (last_client == NULL)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen last_client = client;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen DLLIST_PREPEND(&clients, client);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen clients_count++;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen client->to_disconnect =
d22301419109ed4a38351715e6760011421dadecTimo Sirainen timeout_add(CLIENT_LOGIN_TIMEOUT_MSECS,
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen client_idle_disconnect_timeout, client);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen client_open_streams(client);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen client->v.create(client, other_sets);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (auth_client_is_connected(auth_client))
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_notify_auth_ready(client);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen else
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_set_auth_waiting(client);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen login_refresh_proctitle();
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return client;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid client_destroy(struct client *client, const char *reason)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (client->destroyed)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->destroyed = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!client->login_success && reason != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen reason = t_strconcat(reason, " ",
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_get_extra_disconnect_reason(client), NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (reason != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_log(client, reason);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen if (last_client == client)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen last_client = client->prev;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen DLLIST_REMOVE(&clients, client);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen if (client->output != NULL)
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen o_stream_uncork(client->output);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!client->login_success && client->ssl_proxy != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ssl_proxy_destroy(client->ssl_proxy);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->input != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_stream_close(client->input);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->output != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen o_stream_close(client->output);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->master_tag != 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(client->auth_request == NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(client->authenticating);
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen i_assert(client->refcount > 1);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen client->authenticating = FALSE;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen master_auth_request_abort(master_auth, client->master_tag);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->refcount--;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen } else if (client->auth_request != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(client->authenticating);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sasl_server_auth_abort(client);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(!client->authenticating);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->io != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen io_remove(&client->io);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->to_disconnect != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen timeout_remove(&client->to_disconnect);
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen if (client->to_auth_waiting != NULL)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen timeout_remove(&client->to_auth_waiting);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->auth_response != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen str_free(&client->auth_response);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->fd != -1) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen net_disconnect(client->fd);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen client->fd = -1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->proxy_password != NULL) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen safe_memset(client->proxy_password, 0,
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen strlen(client->proxy_password));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free_and_null(client->proxy_password);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->proxy_sasl_client != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen dsasl_client_free(&client->proxy_sasl_client);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->login_proxy != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen login_proxy_free(&client->login_proxy);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->v.destroy != NULL)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen client->v.destroy(client);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (client_unref(&client) && initial_service_count == 1) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* as soon as this connection is done with proxying
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen (or whatever), the process will die. there's no need for
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen authentication anymore, so close the connection.
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen do this only with initial service_count=1, in case there
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen are other clients with pending authentications */
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen auth_client_disconnect(auth_client, "unnecessary connection");
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen login_client_destroyed();
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen login_refresh_proctitle();
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainenvoid client_destroy_success(struct client *client, const char *reason)
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->login_success = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_destroy(client, reason);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid client_destroy_internal_failure(struct client *client)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen client_notify_disconnect(client, CLIENT_DISCONNECT_INTERNAL_ERROR,
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen "Internal login failure. "
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen "Refer to server log for more information.");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_destroy(client, t_strdup_printf(
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen "Internal login failure (pid=%s id=%u)",
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen my_pid, client->master_auth_id));
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid client_ref(struct client *client)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->refcount++;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenbool client_unref(struct client **_client)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct client *client = *_client;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen i_assert(client->refcount > 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (--client->refcount > 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen *_client = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(client->destroyed);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(client->login_proxy == NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->ssl_proxy != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ssl_proxy_free(&client->ssl_proxy);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->input != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_stream_unref(&client->input);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->output != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen o_stream_unref(&client->output);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->proxy_user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->proxy_master_user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->virtual_user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->virtual_user_orig);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->virtual_auth_user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->auth_mech_name);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->master_data_prefix);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen pool_unref(&client->pool);
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(clients_count > 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen clients_count--;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen master_service_client_connection_destroyed(master_service);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen login_refresh_proctitle();
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid client_destroy_oldest(void)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct client *client;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen if (last_client == NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* we have no clients */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* destroy the last client that hasn't successfully authenticated yet.
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen this is usually the last client, but don't kill it if it's just
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen waiting for master to finish its job. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (client = last_client; client != NULL; client = client->prev) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->master_tag == 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client == NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client = last_client;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_notify_disconnect(client, CLIENT_DISCONNECT_RESOURCE_CONSTRAINT,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Connection queue full");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_destroy(client, "Disconnected: Connection queue full");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid clients_destroy_all_reason(const char *reason)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct client *client, *next;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (client = clients; client != NULL; client = next) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen next = client->next;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_notify_disconnect(client,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen CLIENT_DISCONNECT_SYSTEM_SHUTDOWN, reason);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_destroy(client, reason);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid clients_destroy_all(void)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen clients_destroy_all_reason("Disconnected: Shutting down");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainenstatic void client_start_tls(struct client *client)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int fd_ssl;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_ref(client);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!client_unref(&client) || client->destroyed)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen fd_ssl = ssl_proxy_alloc(client->fd, &client->ip, client->pool,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->set, client->ssl_set,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen &client->ssl_proxy);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (fd_ssl == -1) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_notify_disconnect(client,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen CLIENT_DISCONNECT_INTERNAL_ERROR,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "TLS initialization failed.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_destroy(client,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "Disconnected: TLS initialization failed.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ssl_proxy_set_client(client->ssl_proxy, client);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ssl_proxy_start(client->ssl_proxy);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->starttls = TRUE;
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen client->tls = TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->secured = TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen login_refresh_proctitle();
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->fd = fd_ssl;
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_stream_unref(&client->input);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen o_stream_unref(&client->output);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_open_streams(client);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->v.starttls(client);
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen}
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainenstatic int client_output_starttls(struct client *client)
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen{
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen int ret;
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen if ((ret = o_stream_flush(client->output)) < 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_destroy(client, "Disconnected");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return 1;
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen }
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen if (ret > 0) {
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen o_stream_unset_flush_callback(client->output);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_start_tls(client);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid client_cmd_starttls(struct client *client)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (client->tls) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->v.notify_starttls(client, FALSE, "TLS is already active.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!client_is_tls_enabled(client)) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->v.notify_starttls(client, FALSE, "TLS support isn't enabled.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* remove input handler, SSL proxy gives us a new fd. we also have to
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen remove it in case we have to wait for buffer to be flushed */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (client->io != NULL)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen io_remove(&client->io);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->v.notify_starttls(client, TRUE, "Begin TLS negotiation now.");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* uncork the old fd */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen o_stream_uncork(client->output);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (o_stream_flush(client->output) <= 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* the buffer has to be flushed */
4182d8cd818e76856a5a1e25b343fe5ddf69fd8eTimo Sirainen o_stream_set_flush_pending(client->output, TRUE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen o_stream_set_flush_callback(client->output,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_output_starttls, client);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else {
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen client_start_tls(client);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenunsigned int clients_get_count(void)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return clients_count;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenconst char *client_get_session_id(struct client *client)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen buffer_t *buf, *base64_buf;
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen struct timeval tv;
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen uint64_t timestamp;
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen unsigned int i;
a406615fbcef37b1d12f0be95a70abf23238c5efTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (client->session_id != NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return client->session_id;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 24);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen base64_buf = buffer_create_dynamic(pool_datastack_create(), 24*2);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (gettimeofday(&tv, NULL) < 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_fatal("gettimeofday(): %m");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen timestamp = tv.tv_usec + (long long)tv.tv_sec * 1000ULL*1000ULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* add lowest 48 bits of the timestamp. this gives us a bit less than
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen 9 years until it wraps */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0; i < 48; i += 8)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append_c(buf, (timestamp >> i) & 0xff);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append_c(buf, client->remote_port & 0xff);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append_c(buf, (client->remote_port >> 16) & 0xff);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen#ifdef HAVE_IPV6
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (IPADDR_IS_V6(&client->ip))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append(buf, &client->ip.u.ip6, sizeof(client->ip.u.ip6));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen else
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#endif
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buffer_append(buf, &client->ip.u.ip4, sizeof(client->ip.u.ip4));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen base64_encode(buf->data, buf->used, base64_buf);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->session_id = p_strdup(client->pool, str_c(base64_buf));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return client->session_id;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic struct var_expand_table login_var_expand_empty_tab[] = {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'u', NULL, "user" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'n', NULL, "username" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'd', NULL, "domain" },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 's', NULL, "service" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'h', NULL, "home" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'l', NULL, "lip" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'r', NULL, "rip" },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { 'p', NULL, "pid" },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { 'm', NULL, "mech" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'a', NULL, "lport" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'b', NULL, "rport" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'c', NULL, "secured" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { 'k', NULL, "ssl_security" },
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen { 'e', NULL, "mail_pid" },
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen { '\0', NULL, "session" },
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen { '\0', NULL, "real_lip" },
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen { '\0', NULL, "real_rip" },
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen { '\0', NULL, "real_lport" },
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen { '\0', NULL, "real_rport" },
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen { '\0', NULL, "orig_user" },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { '\0', NULL, "orig_username" },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { '\0', NULL, "orig_domain" },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { '\0', NULL, "auth_user" },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { '\0', NULL, "auth_username" },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { '\0', NULL, "auth_domain" },
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen { '\0', NULL, NULL }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen};
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainenget_var_expand_users(struct var_expand_table *tab, const char *user)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int i;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen tab[0].value = user;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen tab[1].value = t_strcut(user, '@');
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen tab[2].value = strchr(user, '@');
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (tab[2].value != NULL) tab[2].value++;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0; i < 3; i++)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen tab[i].value = str_sanitize(tab[i].value, 80);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen}
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic const struct var_expand_table *
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenget_var_expand_table(struct client *client)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct var_expand_table *tab;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab = t_malloc(sizeof(login_var_expand_empty_tab));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen memcpy(tab, login_var_expand_empty_tab,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen sizeof(login_var_expand_empty_tab));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (client->virtual_user != NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen get_var_expand_users(tab, client->virtual_user);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[3].value = login_binary->protocol;
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen tab[4].value = getenv("HOME");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[5].value = net_ip2addr(&client->local_ip);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[6].value = net_ip2addr(&client->ip);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[7].value = my_pid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[8].value = client->auth_mech_name == NULL ? NULL :
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[9].value = dec2str(client->local_port);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[10].value = dec2str(client->remote_port);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!client->tls) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[11].value = client->secured ? "secured" : NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[12].value = "";
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else {
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen const char *ssl_state =
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen ssl_proxy_is_handshaked(client->ssl_proxy) ?
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "TLS" : "TLS handshaking";
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const char *ssl_error =
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ssl_proxy_get_last_error(client->ssl_proxy);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen tab[11].value = ssl_error == NULL ? ssl_state :
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen t_strdup_printf("%s: %s", ssl_state, ssl_error);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[12].value =
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ssl_proxy_get_security_string(client->ssl_proxy);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[13].value = client->mail_pid == 0 ? "" :
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen dec2str(client->mail_pid);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[14].value = client_get_session_id(client);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen tab[15].value = net_ip2addr(&client->real_local_ip);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen tab[16].value = net_ip2addr(&client->real_remote_ip);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen tab[17].value = dec2str(client->real_local_port);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen tab[18].value = dec2str(client->real_remote_port);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (client->virtual_user_orig != NULL)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen get_var_expand_users(tab+19, client->virtual_user_orig);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[19].value = tab[0].value;
fb7dd075cf883e5e7defbc0c8fb8326e30bdccdeTimo Sirainen tab[20].value = tab[1].value;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[21].value = tab[2].value;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (client->virtual_auth_user != NULL)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen get_var_expand_users(tab+22, client->virtual_auth_user);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen else {
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen tab[22].value = tab[19].value;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab[23].value = tab[20].value;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen tab[24].value = tab[21].value;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return tab;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic bool have_username_key(const char *str)
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen char key;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen for (; *str != '\0'; str++) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (str[0] == '%' && str[1] != '\0') {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen str++;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen key = var_get_key(str);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (key == 'u' || key == 'n')
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen return TRUE;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return FALSE;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen}
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenstatic const char *
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenclient_get_log_str(struct client *client, const char *msg)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen static struct var_expand_table static_tab[3] = {
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen { 's', NULL, NULL },
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen { '$', NULL, NULL },
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen { '\0', NULL, NULL }
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen };
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen const struct var_expand_table *var_expand_table;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen struct var_expand_table *tab;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen char *const *e;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen string_t *str, *str2;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int pos;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen var_expand_table = get_var_expand_table(client);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen tab = t_malloc(sizeof(static_tab));
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen str = t_str_new(256);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen str2 = t_str_new(128);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen for (e = client->set->log_format_elements_split; *e != NULL; e++) {
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen pos = str_len(str);
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen var_expand(str, *e, var_expand_table);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen if (have_username_key(*e)) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* username is added even if it's empty */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else {
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen str_truncate(str2, 0);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen var_expand(str2, *e, login_var_expand_empty_tab);
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen if (strcmp(str_c(str)+pos, str_c(str2)) == 0) {
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen /* empty %variables, don't add */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen str_truncate(str, pos);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen continue;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen if (str_len(str) > 0)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen str_append(str, ", ");
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (str_len(str) > 0)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen str_truncate(str, str_len(str)-2);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen tab[0].value = t_strdup(str_c(str));
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen tab[1].value = msg;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen str_truncate(str, 0);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen var_expand(str, client->set->login_log_format, tab);
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen return str_c(str);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid client_log(struct client *client, const char *msg)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen T_BEGIN {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_info("%s", client_get_log_str(client, msg));
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen } T_END;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid client_log_err(struct client *client, const char *msg)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen T_BEGIN {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_error("%s", client_get_log_str(client, msg));
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen } T_END;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenvoid client_log_warn(struct client *client, const char *msg)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen T_BEGIN {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen i_warning("%s", client_get_log_str(client, msg));
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen } T_END;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenbool client_is_tls_enabled(struct client *client)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return ssl_initialized && strcmp(client->ssl_set->ssl, "no") != 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenconst char *client_get_extra_disconnect_reason(struct client *client)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen unsigned int auth_secs = client->auth_first_started == 0 ? 0 :
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen ioloop_time - client->auth_first_started;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->set->auth_ssl_require_client_cert &&
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen client->ssl_proxy != NULL) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (ssl_proxy_has_broken_client_cert(client->ssl_proxy))
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(client sent an invalid cert)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (!ssl_proxy_has_valid_client_cert(client->ssl_proxy))
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(client didn't send a cert)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen if (!client->notified_auth_ready)
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen return t_strdup_printf(
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen "(disconnected before auth was ready, waited %u secs)",
7ab62198bfb9ac210b11ea7a147234e0f72f6448Timo Sirainen (unsigned int)(ioloop_time - client->created));
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->auth_attempts == 0) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(no auth attempts in %u secs)",
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen (unsigned int)(ioloop_time - client->created));
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* some auth attempts without SSL/TLS */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->auth_tried_disabled_plaintext)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(tried to use disallowed plaintext auth)";
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (client->set->auth_ssl_require_client_cert &&
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen client->ssl_proxy == NULL)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(cert required, client didn't start TLS)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->auth_tried_unsupported_mech)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(tried to use unsupported auth mechanism)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->auth_waiting && client->auth_attempts == 1) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(client didn't finish SASL auth, "
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen "waited %u secs)", auth_secs);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (client->auth_request != NULL && client->auth_attempts == 1) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(disconnected while authenticating, "
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen "waited %u secs)", auth_secs);
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen }
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen if (client->authenticating && client->auth_attempts == 1) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(disconnected while finishing login, "
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen "waited %u secs)", auth_secs);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen if (client->auth_try_aborted && client->auth_attempts == 1)
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen return "(aborted authentication)";
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen if (client->auth_process_comm_fail)
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen return "(auth process communication failure)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->proxy_auth_failed)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(proxy dest auth failed)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->auth_successes > 0) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(internal failure, %u successful auths)",
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen client->auth_successes);
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen }
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen if (client->auth_user_disabled)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(user disabled)";
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (client->auth_pass_expired)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return "(password expired)";
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return t_strdup_printf("(auth failed, %u attempts in %u secs)",
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen client->auth_attempts, auth_secs);
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen}
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainenvoid client_notify_disconnect(struct client *client,
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen enum client_disconnect_reason reason,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen const char *text)
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen{
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (!client->notified_disconnect) {
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen if (client->v.notify_disconnect != NULL)
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen client->v.notify_disconnect(client, reason, text);
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen client->notified_disconnect = TRUE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenvoid client_notify_auth_ready(struct client *client)
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (!client->notified_auth_ready) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (client->v.notify_auth_ready != NULL)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen client->v.notify_auth_ready(client);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen client->notified_auth_ready = TRUE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenvoid client_notify_status(struct client *client, bool bad, const char *text)
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen{
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (client->v.notify_status != NULL)
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen client->v.notify_status(client, bad, text);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen}
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainenvoid client_send_raw_data(struct client *client, const void *data, size_t size)
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen ssize_t ret;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen ret = o_stream_send(client->output, data, size);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (ret < 0 || (size_t)ret != size) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* either disconnection or buffer full. in either case we want
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen this connection destroyed. however destroying it here might
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen break things if client is still tried to be accessed without
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen being referenced.. */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_stream_close(client->input);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid client_send_raw(struct client *client, const char *data)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen client_send_raw_data(client, data, strlen(data));
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenbool client_read(struct client *client)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen switch (i_stream_read(client->input)) {
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen case -2:
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen /* buffer full */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen client_notify_disconnect(client,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen CLIENT_DISCONNECT_RESOURCE_CONSTRAINT,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen "Input buffer full, aborting");
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen client_destroy(client, "Disconnected: Input buffer full");
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return FALSE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen case -1:
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* disconnected */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen client_destroy(client, "Disconnected");
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return FALSE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen case 0:
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* nothing new read */
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen return TRUE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen default:
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* something was read */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return TRUE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid client_input(struct client *client)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen client->v.input(client);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen