Mercurial > dovecot > original-hg > dovecot-1.2
changeset 3384:3b75956d20c4 HEAD
Added configurable logging for login process. Added configurable pop3 logout
string. Based on a patch by Andrey Panin.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 14 May 2005 23:32:03 +0300 |
parents | bfba2219b586 |
children | fe4a297379fc |
files | dovecot-example.conf src/imap-login/client-authenticate.c src/imap-login/client.c src/login-common/client-common.c src/login-common/client-common.h src/login-common/common.h src/login-common/main.c src/login-common/sasl-server.c src/master/login-process.c src/master/mail-process.c src/master/master-settings.c src/master/master-settings.h src/pop3-login/client-authenticate.c src/pop3-login/client.c src/pop3/client.c src/pop3/client.h src/pop3/commands.c src/pop3/common.h src/pop3/main.c |
diffstat | 19 files changed, 258 insertions(+), 60 deletions(-) [+] |
line wrap: on
line diff
--- a/dovecot-example.conf Sat May 14 20:17:29 2005 +0300 +++ b/dovecot-example.conf Sat May 14 23:32:03 2005 +0300 @@ -128,6 +128,15 @@ # Greeting message for clients. #login_greeting = Dovecot ready. +# Space-separated list of elements we want to log. The elements which have +# a non-empty variable value are joined together to form a comma-separated +# string. +#login_log_format_elements = user=<%u> method=%m rip=%r lip=%l %c + +# Login log format. %$ contains login_log_format_elements string, %s contains +# the data we want to log. +#login_log_format = %$: %s + ## ## Mail processes ## @@ -464,6 +473,16 @@ # idea to change this. %08Xu%08Xv should be pretty fail-safe. #pop3_uidl_format = %v.%u + # POP3 logout format string: + # %t - number of TOP commands + # %T - number of bytes sent to client as a result of TOP command + # %r - number of RETR commands + # %R - number of bytes sent to client as a result of RETR command + # %d - number of deleted messages + # %m - number of messages (before deletion) + # %s - mailbox size in bytes (before deletion) + #pop3_logout_format = top=%t/%T, retr=%r/%R, del=%d/%m, size=%s + # Support for dynamically loadable modules. #mail_use_modules = no #mail_modules = /usr/lib/dovecot/pop3
--- a/src/imap-login/client-authenticate.c Sat May 14 20:17:29 2005 +0300 +++ b/src/imap-login/client-authenticate.c Sat May 14 23:32:03 2005 +0300 @@ -116,7 +116,9 @@ if (imap_proxy_new(client, host, port, destuser, pass) < 0) client_destroy_internal_failure(client); return TRUE; - } else if (host != NULL) { + } + + if (host != NULL) { /* IMAP referral [nologin] referral host=.. [port=..] [destuser=..] @@ -142,6 +144,10 @@ "this server instead."); } client_send_tagline(client, str_c(reply)); + if (!nologin) { + client_destroy(client, "Login with referral"); + return TRUE; + } } else if (nologin) { /* Authentication went ok, but for some reason user isn't allowed to log in. Shouldn't probably happen. */ @@ -158,16 +164,12 @@ return FALSE; } - if (!nologin) { - client_destroy(client, t_strconcat( - "Login: ", client->common.virtual_user, NULL)); - } else { - /* get back to normal client input. */ - if (client->io != NULL) - io_remove(client->io); - client->io = io_add(client->common.fd, IO_READ, - client_input, client); - } + i_assert(nologin); + + /* get back to normal client input. */ + if (client->io != NULL) + io_remove(client->io); + client->io = io_add(client->common.fd, IO_READ, client_input, client); return TRUE; } @@ -187,8 +189,7 @@ } client_send_tagline(client, "OK Logged in."); - client_destroy(client, t_strconcat( - "Login: ", client->common.virtual_user, NULL)); + client_destroy(client, "Login"); break; case SASL_SERVER_REPLY_AUTH_FAILED: if (args != NULL) {
--- a/src/imap-login/client.c Sat May 14 20:17:29 2005 +0300 +++ b/src/imap-login/client.c Sat May 14 23:32:03 2005 +0300 @@ -43,6 +43,8 @@ # error client idle timeout must be smaller than authentication timeout #endif +const char *login_protocol = "IMAP"; + static struct hash_table *clients; static struct timeout *to_idle; @@ -443,7 +445,7 @@ client->destroyed = TRUE; if (reason != NULL) - client_syslog(&client->common, "%s", reason); + client_syslog(&client->common, reason); hash_remove(clients, client); @@ -496,8 +498,7 @@ { client_send_line(client, "* BYE Internal login failure. " "Refer to server log for more information."); - client_destroy(client, t_strconcat("Internal login failure: ", - client->common.virtual_user, NULL)); + client_destroy(client, "Internal login failure"); } void client_ref(struct imap_client *client)
--- a/src/login-common/client-common.c Sat May 14 20:17:29 2005 +0300 +++ b/src/login-common/client-common.c Sat May 14 23:32:03 2005 +0300 @@ -1,20 +1,108 @@ -/* Copyright (C) 2002 Timo Sirainen */ +/* Copyright (C) 2002-2005 Timo Sirainen */ #include "common.h" +#include "hostpid.h" +#include "str.h" +#include "str-sanitize.h" +#include "var-expand.h" #include "client-common.h" -void client_syslog(struct client *client, const char *format, ...) +#include <stdlib.h> + +static const struct var_expand_table * +get_var_expand_table(struct client *client) { - const char *addr; - va_list args; + static struct var_expand_table static_tab[] = { + { 'u', NULL }, + { 'n', NULL }, + { 'd', NULL }, + { 's', NULL }, + { 'h', NULL }, + { 'l', NULL }, + { 'r', NULL }, + { 'p', NULL }, + { 'm', NULL }, + { 'c', NULL }, + { '\0', NULL } + }; + struct var_expand_table *tab; + + tab = t_malloc(sizeof(static_tab)); + memcpy(tab, static_tab, sizeof(static_tab)); - addr = net_ip2addr(&client->ip); - if (addr == NULL) - addr = "??"; + if (client->virtual_user != NULL) { + tab[0].value = client->virtual_user; + tab[1].value = t_strcut(client->virtual_user, '@'); + tab[2].value = strchr(client->virtual_user, '@'); + if (tab[2].value != NULL) tab[2].value++; + } + tab[3].value = login_protocol; + tab[4].value = getenv("HOME"); + tab[5].value = net_ip2addr(&client->local_ip); + tab[6].value = net_ip2addr(&client->ip); + tab[7].value = my_pid; + tab[8].value = client->auth_mech_name == NULL ? NULL : + str_sanitize(client->auth_mech_name, MAX_MECH_NAME); + tab[9].value = client->tls ? "TLS" : client->secured ? "SSL" : NULL; + + return tab; +} + +static int have_key(const struct var_expand_table *table, const char *str) +{ + char key; + unsigned int i; + + key = var_get_key(str); + for (i = 0; table[i].key != '\0'; i++) { + if (table[i].key == key) { + return table[i].value != NULL && + table[i].value[0] != '\0'; + } + } + return FALSE; +} + +void client_syslog(struct client *client, const char *msg) +{ + static struct var_expand_table static_tab[3] = { + { 's', NULL }, + { '$', NULL }, + { '\0', NULL } + }; + const struct var_expand_table *var_expand_table; + struct var_expand_table *tab; + const char *p, *const *e; + string_t *str; t_push(); - va_start(args, format); - i_info("%s [%s]", t_strdup_vprintf(format, args), addr); - va_end(args); + var_expand_table = get_var_expand_table(client); + + tab = t_malloc(sizeof(static_tab)); + memcpy(tab, static_tab, sizeof(static_tab)); + + str = t_str_new(256); + for (e = log_format_elements; *e != NULL; e++) { + for (p = *e; *p != '\0'; p++) { + if (*p != '%' || p[1] == '\0') + continue; + + p++; + if (have_key(var_expand_table, p)) { + if (str_len(str) > 0) + str_append(str, ", "); + var_expand(str, *e, var_expand_table); + break; + } + } + } + + tab[0].value = t_strdup(str_c(str)); + tab[1].value = msg; + str_truncate(str, 0); + + var_expand(str, log_format, tab); + i_info("%s", str_c(str)); + t_pop(); }
--- a/src/login-common/client-common.h Sat May 14 20:17:29 2005 +0300 +++ b/src/login-common/client-common.h Sat May 14 23:32:03 2005 +0300 @@ -29,8 +29,7 @@ struct client *client_create(int fd, int ssl, const struct ip_addr *local_ip, const struct ip_addr *ip); -void client_syslog(struct client *client, const char *format, ...) - __attr_format__(2, 3); +void client_syslog(struct client *client, const char *msg); unsigned int clients_get_count(void); void clients_notify_auth_connected(void);
--- a/src/login-common/common.h Sat May 14 20:17:29 2005 +0300 +++ b/src/login-common/common.h Sat May 14 23:32:03 2005 +0300 @@ -3,12 +3,18 @@ #include "lib.h" +/* Used only for string sanitization */ +#define MAX_MECH_NAME 64 + #define AUTH_FAILED_MSG "Authentication failed." #define AUTH_TEMP_FAILED_MSG "Temporary authentication failure." +extern const char *login_protocol; + extern int disable_plaintext_auth, process_per_connection, greeting_capability; extern int verbose_proctitle, verbose_ssl, verbose_auth; -char *greeting; +extern const char *greeting, *log_format; +extern const char *const *log_format_elements; extern unsigned int max_logging_users; extern unsigned int login_process_uid; extern struct auth_client *auth_client;
--- a/src/login-common/main.c Sat May 14 20:17:29 2005 +0300 +++ b/src/login-common/main.c Sat May 14 23:32:03 2005 +0300 @@ -20,7 +20,8 @@ int disable_plaintext_auth, process_per_connection, greeting_capability; int verbose_proctitle, verbose_ssl, verbose_auth; -char *greeting; +const char *greeting, *log_format; +const char *const *log_format_elements; unsigned int max_logging_users; unsigned int login_process_uid; struct auth_client *auth_client; @@ -170,6 +171,15 @@ greeting = PACKAGE" ready."; greeting_capability = getenv("GREETING_CAPABILITY") != NULL; + value = getenv("LOG_FORMAT_ELEMENTS"); + if (value == NULL) + value = "user=<%u> method=%m rip=%r lip=%l %c : %$"; + log_format_elements = t_strsplit(value, " "); + + log_format = getenv("LOG_FORMAT"); + if (log_format == NULL) + log_format = "%$: %s"; + value = getenv("PROCESS_UID"); if (value == NULL) i_fatal("BUG: PROCESS_UID environment not given");
--- a/src/login-common/sasl-server.c Sat May 14 20:17:29 2005 +0300 +++ b/src/login-common/sasl-server.c Sat May 14 23:32:03 2005 +0300 @@ -9,9 +9,6 @@ #include "client-common.h" #include "master.h" -/* Used only for string sanitization while verbose_auth is set. */ -#define MAX_MECH_NAME 64 - static enum auth_request_flags client_get_auth_flags(struct client *client) { @@ -154,9 +151,11 @@ void sasl_server_auth_cancel(struct client *client, const char *reason) { if (verbose_auth && reason != NULL) { - client_syslog(client, "Authenticate %s failed: %s", - str_sanitize(client->auth_mech_name, - MAX_MECH_NAME), reason); + const char *auth_name = + str_sanitize(client->auth_mech_name, MAX_MECH_NAME); + client_syslog(client, + t_strdup_printf("Authenticate %s failed: %s", + auth_name, reason)); } client->authenticating = FALSE;
--- a/src/master/login-process.c Sat May 14 20:17:29 2005 +0300 +++ b/src/master/login-process.c Sat May 14 23:32:03 2005 +0300 @@ -439,6 +439,9 @@ env_put(t_strconcat("PROCESS_UID=", dec2str(pid), NULL)); env_put(t_strconcat("GREETING=", set->login_greeting, NULL)); + env_put(t_strconcat("LOG_FORMAT_ELEMENTS=", + set->login_log_format_elements, NULL)); + env_put(t_strconcat("LOG_FORMAT=", set->login_log_format, NULL)); if (set->login_greeting_capability) env_put("GREETING_CAPABILITY=1"); }
--- a/src/master/mail-process.c Sat May 14 20:17:29 2005 +0300 +++ b/src/master/mail-process.c Sat May 14 23:32:03 2005 +0300 @@ -205,6 +205,8 @@ set->pop3_uidl_format, NULL)); env_put(t_strconcat("POP3_CLIENT_WORKAROUNDS=", set->pop3_client_workarounds, NULL)); + env_put(t_strconcat("POP3_LOGOUT_FORMAT=", + set->pop3_logout_format, NULL)); if (set->mail_save_crlf) env_put("MAIL_SAVE_CRLF=1");
--- a/src/master/master-settings.c Sat May 14 20:17:29 2005 +0300 +++ b/src/master/master-settings.c Sat May 14 23:32:03 2005 +0300 @@ -69,6 +69,8 @@ DEF(SET_STR, login_executable), DEF(SET_STR, login_user), DEF(SET_STR, login_greeting), + DEF(SET_STR, login_log_format_elements), + DEF(SET_STR, login_log_format), DEF(SET_BOOL, login_process_per_connection), DEF(SET_BOOL, login_chroot), @@ -131,6 +133,7 @@ DEF(SET_BOOL, pop3_enable_last), DEF(SET_STR, pop3_uidl_format), DEF(SET_STR, pop3_client_workarounds), + DEF(SET_STR, pop3_logout_format), { 0, NULL, 0 } }; @@ -258,6 +261,8 @@ MEMBER(login_executable) NULL, MEMBER(login_user) "dovecot", MEMBER(login_greeting) "Dovecot ready.", + MEMBER(login_log_format_elements) "user=<%u> method=%m rip=%r lip=%l %c", + MEMBER(login_log_format) "%$: %s", MEMBER(login_process_per_connection) TRUE, MEMBER(login_chroot) TRUE, @@ -324,6 +329,7 @@ MEMBER(pop3_enable_last) FALSE, MEMBER(pop3_uidl_format) "%v.%u", MEMBER(pop3_client_workarounds) NULL, + MEMBER(pop3_logout_format) "top=%t/%T, retr=%r/%R, del=%d/%m, size=%s", /* .. */ MEMBER(login_uid) 0,
--- a/src/master/master-settings.h Sat May 14 20:17:29 2005 +0300 +++ b/src/master/master-settings.h Sat May 14 23:32:03 2005 +0300 @@ -40,6 +40,8 @@ const char *login_executable; const char *login_user; const char *login_greeting; + const char *login_log_format_elements; + const char *login_log_format; int login_process_per_connection; int login_chroot; @@ -100,6 +102,7 @@ int pop3_enable_last; const char *pop3_uidl_format; const char *pop3_client_workarounds; + const char *pop3_logout_format; /* .. */ uid_t login_uid;
--- a/src/pop3-login/client-authenticate.c Sat May 14 20:17:29 2005 +0300 +++ b/src/pop3-login/client-authenticate.c Sat May 14 23:32:03 2005 +0300 @@ -160,8 +160,7 @@ } client_send_line(client, "+OK Logged in."); - client_destroy(client, t_strconcat( - "Login: ", client->common.virtual_user, NULL)); + client_destroy(client, "Login"); break; case SASL_SERVER_REPLY_AUTH_FAILED: if (args != NULL) {
--- a/src/pop3-login/client.c Sat May 14 20:17:29 2005 +0300 +++ b/src/pop3-login/client.c Sat May 14 23:32:03 2005 +0300 @@ -41,6 +41,8 @@ # error client idle timeout must be smaller than authentication timeout #endif +const char *login_protocol = "POP3"; + static struct hash_table *clients; static struct timeout *to_idle; @@ -343,7 +345,7 @@ client->destroyed = TRUE; if (reason != NULL) - client_syslog(&client->common, "%s", reason); + client_syslog(&client->common, reason); hash_remove(clients, client); @@ -394,8 +396,7 @@ { client_send_line(client, "-ERR [IN-USE] Internal login failure. " "Refer to server log for more information."); - client_destroy(client, t_strconcat("Internal login failure: ", - client->common.virtual_user, NULL)); + client_destroy(client, "Internal login failure"); } void client_ref(struct pop3_client *client)
--- a/src/pop3/client.c Sat May 14 20:17:29 2005 +0300 +++ b/src/pop3/client.c Sat May 14 23:32:03 2005 +0300 @@ -7,6 +7,7 @@ #include "istream.h" #include "ostream.h" #include "str.h" +#include "var-expand.h" #include "mail-storage.h" #include "commands.h" #include "mail-search.h" @@ -156,12 +157,12 @@ i_error("Couldn't open INBOX: %s", mail_storage_get_last_error(storage, &syntax_error)); client_send_line(client, "-ERR No INBOX for user."); - client_destroy(client); + client_destroy(client, "No INBOX for user."); return NULL; } if (!init_mailbox(client)) { - client_destroy(client); + client_destroy(client, "Mailbox init failed"); return NULL; } @@ -173,8 +174,42 @@ return client; } -void client_destroy(struct client *client) +static const char *client_stats(struct client *client) { + static struct var_expand_table static_tab[] = { + { 'T', NULL }, + { 't', NULL }, + { 'R', NULL }, + { 'r', NULL }, + { 'd', NULL }, + { 'm', NULL }, + { 's', NULL }, + { '\0', NULL } + }; + struct var_expand_table *tab; + string_t *str; + + tab = t_malloc(sizeof(static_tab)); + memcpy(tab, static_tab, sizeof(static_tab)); + + tab[0].value = dec2str(client->top_bytes); + tab[1].value = dec2str(client->top_count); + tab[2].value = dec2str(client->retr_bytes); + tab[3].value = dec2str(client->retr_count); + tab[4].value = dec2str(client->deleted_count); + tab[5].value = dec2str(client->messages_count); + tab[6].value = dec2str(client->total_size); + + str = t_str_new(128); + var_expand(str, logout_format, tab); + return str_c(str); +} + +void client_destroy(struct client *client, const char *reason) +{ + if (reason != NULL) + i_info("%s %s", reason, client_stats(client)); + if (client->cmd != NULL) { /* deinitialize command */ i_stream_close(client->input); @@ -204,8 +239,11 @@ io_loop_stop(ioloop); } -void client_disconnect(struct client *client) +void client_disconnect(struct client *client, const char *reason) { + if (reason != NULL) + i_info("%s %s", reason, client_stats(client)); + (void)o_stream_flush(client->output); i_stream_close(client->input); @@ -266,7 +304,7 @@ if (mailbox_is_inconsistent(client->mailbox)) { client_send_line(client, "-ERR Mailbox is in inconsistent " "state, please relogin."); - client_disconnect(client); + client_disconnect(client, "Mailbox is in inconsistent state."); return; } @@ -295,12 +333,12 @@ switch (i_stream_read(client->input)) { case -1: /* disconnected */ - client_destroy(client); + client_destroy(client, "Disconnected"); return; case -2: /* line too long, kill it */ client_send_line(client, "-ERR Input line too long."); - client_destroy(client); + client_destroy(client, "Input line too long."); return; } @@ -323,13 +361,13 @@ } } else if (++client->bad_counter > CLIENT_MAX_BAD_COMMANDS) { client_send_line(client, "-ERR Too many bad commands."); - client_disconnect(client); + client_disconnect(client, "Too many bad commands."); } } o_stream_uncork(client->output); if (client->output->closed) - client_destroy(client); + client_destroy(client, NULL); } static int client_output(void *context) @@ -338,7 +376,7 @@ int ret; if ((ret = o_stream_flush(client->output)) < 0) { - client_destroy(client); + client_destroy(client, NULL); return 1; } @@ -374,13 +412,13 @@ if (my_client->cmd != NULL) { if (ioloop_time - my_client->last_output >= CLIENT_OUTPUT_TIMEOUT) - client_destroy(my_client); + client_destroy(my_client, "Disconnected for inactivity."); } else { if (ioloop_time - my_client->last_input >= CLIENT_IDLE_TIMEOUT) { client_send_line(my_client, "-ERR Disconnected for inactivity."); - client_destroy(my_client); + client_destroy(my_client, "Disconnected for inactivity."); } } } @@ -395,7 +433,7 @@ { if (my_client != NULL) { client_send_line(my_client, "-ERR Server shutting down."); - client_destroy(my_client); + client_destroy(my_client, "Server shutting down."); } timeout_remove(to_idle);
--- a/src/pop3/client.h Sat May 14 20:17:29 2005 +0300 +++ b/src/pop3/client.h Sat May 14 23:32:03 2005 +0300 @@ -30,6 +30,14 @@ uoff_t deleted_size; uint32_t last_seen; + uoff_t top_bytes; + uoff_t retr_bytes; + unsigned int top_count; + unsigned int retr_count; + + uoff_t *byte_counter; + uoff_t byte_counter_offset; + unsigned char *deleted_bitmask; unsigned int deleted:1; @@ -39,10 +47,10 @@ /* Create new client with specified input/output handles. socket specifies if the handle is a socket. */ struct client *client_create(int hin, int hout, struct mail_storage *storage); -void client_destroy(struct client *client); +void client_destroy(struct client *client, const char *reason); /* Disconnect client connection */ -void client_disconnect(struct client *client); +void client_disconnect(struct client *client, const char *reason); /* Send a line of data to client */ int client_send_line(struct client *client, const char *fmt, ...)
--- a/src/pop3/commands.c Sat May 14 20:17:29 2005 +0300 +++ b/src/pop3/commands.c Sat May 14 23:32:03 2005 +0300 @@ -217,7 +217,7 @@ if (client->deleted) { if (!expunge_mails(client)) { client_send_storage_error(client); - client_disconnect(client); + client_disconnect(client, "Storage error during logout."); return TRUE; } } @@ -230,7 +230,7 @@ else client_send_line(client, "+OK Logging out, messages deleted."); - client_disconnect(client); + client_disconnect(client, "Logout."); return TRUE; } @@ -342,6 +342,10 @@ (void)o_stream_send(client->output, "\r\n", 2); } + *client->byte_counter += + client->output->offset - client->byte_counter_offset; + client->byte_counter = NULL; + client_send_line(client, "."); fetch_deinit(ctx); client->cmd = NULL; @@ -405,6 +409,10 @@ if (client->last_seen <= msgnum) client->last_seen = msgnum+1; + client->retr_count++; + client->byte_counter = &client->retr_bytes; + client->byte_counter_offset = client->output->offset; + fetch(client, msgnum, (uoff_t)-1); return TRUE; } @@ -468,6 +476,10 @@ if (get_size(client, args, &max_lines) == NULL) return FALSE; + client->top_count++; + client->byte_counter = &client->top_bytes; + client->byte_counter_offset = client->output->offset; + fetch(client, msgnum, max_lines); return TRUE; }
--- a/src/pop3/common.h Sat May 14 20:17:29 2005 +0300 +++ b/src/pop3/common.h Sat May 14 23:32:03 2005 +0300 @@ -19,7 +19,7 @@ extern struct ioloop *ioloop; extern enum client_workarounds client_workarounds; extern int enable_last_command, no_flag_updates; -extern const char *uidl_format; +extern const char *uidl_format, *logout_format; extern enum uidl_keys uidl_keymask; extern void (*hook_mail_storage_created)(struct mail_storage **storage);
--- a/src/pop3/main.c Sat May 14 20:17:29 2005 +0300 +++ b/src/pop3/main.c Sat May 14 23:32:03 2005 +0300 @@ -41,7 +41,7 @@ enum client_workarounds client_workarounds = 0; int enable_last_command = FALSE; int no_flag_updates = FALSE; -const char *uidl_format; +const char *uidl_format, *logout_format; enum uidl_keys uidl_keymask; static void sig_quit(int signo __attr_unused__) @@ -178,6 +178,9 @@ uidl_format = getenv("POP3_UIDL_FORMAT"); if (uidl_format == NULL) uidl_format = "%v.%u"; + logout_format = getenv("POP3_LOGOUT_FORMAT"); + if (logout_format == NULL) + logout_format = "top=%t/%T, retr=%r/%R, del=%d/%m, size=%s"; uidl_keymask = parse_uidl_keymask(uidl_format); flags = 0;