client-common.c revision 19e8adccba16ff419f5675b1575358c2956dce83
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hostpid.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "llist.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
e8bdf1be00aec45d0c6dd72ad9c8be02a3dfc778Timo Sirainen#include "str-sanitize.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "var-expand.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ssl-proxy.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "client-common.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdlib.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstruct client *clients = NULL;
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenunsigned int clients_count = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid client_link(struct client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen DLLIST_PREPEND(&clients, client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen clients_count++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainenvoid client_unlink(struct client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(clients_count > 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen clients_count--;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen DLLIST_REMOVE(&clients, client);
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenunsigned int clients_get_count(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return clients_count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainenstatic const struct var_expand_table *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenget_var_expand_table(struct client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen static struct var_expand_table static_tab[] = {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { 'u', NULL },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { 'n', NULL },
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen { 'd', NULL },
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen { 's', NULL },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { 'h', NULL },
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen { 'l', NULL },
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen { 'r', NULL },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { 'p', NULL },
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen { 'm', NULL },
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen { 'a', NULL },
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen { 'b', NULL },
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen { 'c', NULL },
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen { '\0', NULL }
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen };
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen struct var_expand_table *tab;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen unsigned int i;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen tab = t_malloc(sizeof(static_tab));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen if (client->virtual_user != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[0].value = client->virtual_user;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[1].value = t_strcut(client->virtual_user, '@');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[2].value = strchr(client->virtual_user, '@');
8cab30d26412f21e814dba57814fa4b57b1d36e7Timo Sirainen if (tab[2].value != NULL) tab[2].value++;
8cab30d26412f21e814dba57814fa4b57b1d36e7Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < 3; i++)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[i].value = str_sanitize(tab[i].value, 80);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[3].value = login_protocol;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen tab[4].value = getenv("HOME");
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen tab[5].value = net_ip2addr(&client->local_ip);
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen tab[6].value = net_ip2addr(&client->ip);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[7].value = my_pid;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[8].value = client->auth_mech_name == NULL ? NULL :
55773f17bccf6361d6599ffcbe072d7c9fe205bfTimo Sirainen str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen tab[9].value = dec2str(client->local_port);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen tab[10].value = dec2str(client->remote_port);
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (!client->tls) {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen tab[11].value = client->secured ? "secured" : NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab[11].value = client->proxy != NULL &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ssl_proxy_is_handshaked(client->proxy) ? "TLS" :
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "TLS handshaking";
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen }
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return tab;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenstatic bool have_key(const struct var_expand_table *table, const char *str)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen{
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen char key;
b6a7e0a7899e7f5d60c23cdaa50e025e4c67d05fTimo Sirainen unsigned int i;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen key = var_get_key(str);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen for (i = 0; table[i].key != '\0'; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (table[i].key == key) {
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen return table[i].value != NULL &&
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen table[i].value[0] != '\0';
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen }
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen }
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen return FALSE;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen}
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenstatic void client_syslog_real(struct client *client, const char *msg)
c11155a446dbdc9f6cd5b954f09073a9019e27b2Timo Sirainen{
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen static struct var_expand_table static_tab[3] = {
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen { 's', NULL },
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen { '$', NULL },
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen { '\0', NULL }
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen };
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen const struct var_expand_table *var_expand_table;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen struct var_expand_table *tab;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *p, *const *e;
8000c86be02008b74acc71fa422444dc432e2c01Timo Sirainen string_t *str;
8000c86be02008b74acc71fa422444dc432e2c01Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen var_expand_table = get_var_expand_table(client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen tab = t_malloc(sizeof(static_tab));
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen memcpy(tab, static_tab, sizeof(static_tab));
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen str = t_str_new(256);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen for (e = log_format_elements; *e != NULL; e++) {
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen for (p = *e; *p != '\0'; p++) {
a63bc30f167a221691ad0a3fe5cd45c57444411eTimo Sirainen if (*p != '%' || p[1] == '\0')
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen continue;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen p++;
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (have_key(var_expand_table, p)) {
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen if (str_len(str) > 0)
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen str_append(str, ", ");
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen var_expand(str, *e, var_expand_table);
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen break;
a63bc30f167a221691ad0a3fe5cd45c57444411eTimo Sirainen }
a63bc30f167a221691ad0a3fe5cd45c57444411eTimo Sirainen }
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen }
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainen tab[0].value = t_strdup(str_c(str));
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen tab[1].value = msg;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_truncate(str, 0);
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen var_expand(str, log_format, tab);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_info("%s", str_c(str));
b142deb9a831c89b1bb9129ada655f3e56b9d4ccTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
641f0c0900ee6e7cf9667f4b40ed95cec7d0cdcaTimo Sirainenvoid client_syslog(struct client *client, const char *msg)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen T_BEGIN {
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen client_syslog_real(client, msg);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } T_END;
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen}
d67fde1a8ebc1d85704c5986d8f93aae97eccef3Timo Sirainen