client-common.c revision 8372fc7efb6d64dff2e5f55fb4a3822c56869cfe
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
46552a931924c2d743f045e95b08c3ce6beda91aTimo Sirainen#include "common.h"
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen#include "hostpid.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "llist.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "str.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen#include "str-sanitize.h"
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen#include "var-expand.h"
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include "ssl-proxy.h"
45155bb1250cf5a120278f349465aded513a100fTimo Sirainen#include "client-common.h"
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen#include <stdlib.h>
e3a838c80f54f024115fade93c6c87a0998f1fabTimo Sirainen
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainenstruct client *clients = NULL;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainenstatic unsigned int clients_count = 0;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainenvoid client_link(struct client *client)
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen{
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen DLLIST_PREPEND(&clients, client);
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen clients_count++;
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen}
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainenvoid client_unlink(struct client *client)
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen{
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen i_assert(clients_count > 0);
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen clients_count--;
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen DLLIST_REMOVE(&clients, client);
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen}
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainenunsigned int clients_get_count(void)
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen{
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen return clients_count;
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen}
493123e38ca1f27b07ac30dcbc59663c5fcdcba2Timo Sirainen
493123e38ca1f27b07ac30dcbc59663c5fcdcba2Timo Sirainenstatic const struct var_expand_table *
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainenget_var_expand_table(struct client *client)
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen{
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen static struct var_expand_table static_tab[] = {
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen { 'u', NULL, "user" },
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen { 'n', NULL, "username" },
89795c6bbbc52bb382e88bc8617d22092223e9a5Timo Sirainen { 'd', NULL, "domain" },
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen { 's', NULL, "service" },
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen { 'h', NULL, "home" },
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen { 'l', NULL, "lip" },
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen { 'r', NULL, "rip" },
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen { 'p', NULL, "pid" },
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen { 'm', NULL, "mech" },
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen { 'a', NULL, "lport" },
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen { 'b', NULL, "rport" },
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen { 'c', NULL, "secured" },
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen { 'k', NULL, "ssl_security" },
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen { 'e', NULL, "mail_pid" },
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen { '\0', NULL, NULL }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen };
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen struct var_expand_table *tab;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen unsigned int i;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen tab = t_malloc(sizeof(static_tab));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (client->virtual_user != NULL) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen tab[0].value = client->virtual_user;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen tab[1].value = t_strcut(client->virtual_user, '@');
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen tab[2].value = strchr(client->virtual_user, '@');
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if (tab[2].value != NULL) tab[2].value++;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen for (i = 0; i < 3; i++)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[i].value = str_sanitize(tab[i].value, 80);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen }
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen tab[3].value = login_protocol;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[4].value = getenv("HOME");
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen tab[5].value = net_ip2addr(&client->local_ip);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[6].value = net_ip2addr(&client->ip);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[7].value = my_pid;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen tab[8].value = client->auth_mech_name == NULL ? NULL :
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen tab[9].value = dec2str(client->local_port);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen tab[10].value = dec2str(client->remote_port);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if (!client->tls) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[11].value = client->secured ? "secured" : NULL;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[12].value = "";
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen } else {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen const char *ssl_state = ssl_proxy_is_handshaked(client->proxy) ?
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen "TLS" : "TLS handshaking";
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen const char *ssl_error = ssl_proxy_get_last_error(client->proxy);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen tab[11].value = ssl_error == NULL ? ssl_state :
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen t_strdup_printf("%s: %s", ssl_state, ssl_error);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen tab[12].value = ssl_proxy_get_security_string(client->proxy);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen tab[13].value = dec2str(client->mail_pid);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return tab;
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen}
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenstatic bool have_key(const struct var_expand_table *table, const char *str)
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen{
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen char key;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen unsigned int i;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen key = var_get_key(str);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen for (i = 0; table[i].key != '\0'; i++) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (table[i].key == key) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen return table[i].value != NULL &&
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen table[i].value[0] != '\0';
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen }
3cb26db7f4756b71ba06c6e4950fa4f8ce7fad66Timo Sirainen }
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainen return FALSE;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen}
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
53d564c421ca7292d7b1bd945f86894a34b75370Timo Sirainenstatic const char *
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainenclient_get_log_str(struct client *client, const char *msg)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen{
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen static struct var_expand_table static_tab[3] = {
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen { 's', NULL, NULL },
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen { '$', NULL, NULL },
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen { '\0', NULL, NULL }
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen };
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen const struct var_expand_table *var_expand_table;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen struct var_expand_table *tab;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen const char *p, *const *e;
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen string_t *str;
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen var_expand_table = get_var_expand_table(client);
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen tab = t_malloc(sizeof(static_tab));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen str = t_str_new(256);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen for (e = log_format_elements; *e != NULL; e++) {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen for (p = *e; *p != '\0'; p++) {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (*p != '%' || p[1] == '\0')
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen continue;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen p++;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (have_key(var_expand_table, p)) {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen if (str_len(str) > 0)
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_append(str, ", ");
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen var_expand(str, *e, var_expand_table);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen break;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen }
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen }
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen }
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen tab[0].value = t_strdup(str_c(str));
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen tab[1].value = msg;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen str_truncate(str, 0);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen var_expand(str, log_format, tab);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen return str_c(str);
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen}
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainenvoid client_syslog(struct client *client, const char *msg)
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen{
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen T_BEGIN {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen i_info("%s", client_get_log_str(client, msg));
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen } T_END;
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen}
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainenvoid client_syslog_err(struct client *client, const char *msg)
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen{
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen T_BEGIN {
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen i_error("%s", client_get_log_str(client, msg));
be71a9de88d1266597eb8c5e0b6f519d90e14397Timo Sirainen } T_END;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenbool client_is_trusted(struct client *client)
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen{
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen const char *const *net;
ba90e657bc68a72ab3b3021e2f4a874fac9965baTimo Sirainen struct ip_addr net_ip;
feb665db52583259a1f42037c6e8a22852aa8889Timo Sirainen unsigned int bits;
9bc0204ec8bda657ce2e96e6ae715e4034f1538bTimo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (trusted_networks == NULL)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen return FALSE;
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen net = t_strsplit_spaces(trusted_networks, ", ");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (; *net != NULL; net++) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (net_parse_range(*net, &net_ip, &bits) < 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen i_error("login_trusted_networks: "
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen "Invalid network '%s'", *net);
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen break;
8372fc7efb6d64dff2e5f55fb4a3822c56869cfeTimo Sirainen }
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (net_is_in_network(&client->ip, &net_ip, bits))
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen return TRUE;
27d50b3aa143964143e4bef66c0bfe3c72aea233Timo Sirainen }
27d50b3aa143964143e4bef66c0bfe3c72aea233Timo Sirainen return FALSE;
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen}
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainenconst char *client_get_extra_disconnect_reason(struct client *client)
9c47edf0d1aa8afa6d05dde93e7aa5169059c94aTimo Sirainen{
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen if (ssl_require_client_cert && client->proxy != NULL) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (ssl_proxy_has_broken_client_cert(client->proxy))
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen return "(client sent an invalid cert)";
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (!ssl_proxy_has_valid_client_cert(client->proxy))
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen return "(client didn't send a cert)";
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
f30577ff7cf29858f1878abe963b4f40a436434fTimo Sirainen
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if (client->auth_attempts == 0)
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return "(no auth attempts)";
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* some auth attempts without SSL/TLS */
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen if (client->auth_tried_disabled_plaintext)
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return "(tried to use disabled plaintext auth)";
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (ssl_require_client_cert)
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return "(cert required, client didn't start TLS)";
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen
e95dba8921087afebb8a92c592af3b8ca22ae796Timo Sirainen return t_strdup_printf("(auth failed, %u attempts)",
3612ee5c737954d5fb88fd1775aad80f7bf1dc4eTimo Sirainen client->auth_attempts);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen}
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen