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