From e7cea7b8c15f4e91c6bb360b85fe053d0add320a Mon Sep 17 00:00:00 2001 From: Bron Gondwana Date: Wed, 24 Dec 2008 23:26:30 +1100 Subject: [PATCH] calculate a global "sessionid" for every connection or login This patch exists to support our 'auditlog' infrastructure, which allows tracing every action back to the login that caused it. The sessionid is returned in the login response or lmtp delivery response, and is logged all the way back through the proxy/filter chain, so we can follow every message end-to-end. =================================================================== --- imap/global.c | 29 +++++++++++++++++++++++++++++ imap/global.h | 4 ++++ imap/imapd.c | 7 ++++++- imap/lmtpd.c | 2 ++ imap/lmtpengine.c | 6 +++--- imap/pop3d.c | 12 ++++++++---- 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/imap/global.c b/imap/global.c index 0a3ec32..b83b67b 100644 --- a/imap/global.c +++ b/imap/global.c @@ -99,6 +99,11 @@ struct cyrusdb_backend *config_tlscache_db; struct cyrusdb_backend *config_ptscache_db; struct cyrusdb_backend *config_statuscache_db; +#define MAX_SESSIONID_SIZE 256 +char session_id_buf[MAX_SESSIONID_SIZE]; +int session_id_time = 0; +int session_id_count = 0; + /* Called before a cyrus application starts (but after command line parameters * are read) */ int cyrus_init(const char *alt_config, const char *ident, unsigned flags) @@ -740,3 +745,27 @@ char *find_free_partition(unsigned long *tavail) if (tavail) *tavail = stats.tavail; return stats.name; } + +/* Set up the Session ID Buffer */ +void session_new_id() +{ + const char *base; + int now = time(NULL); + if (now != session_id_time) { + session_id_time = now; + session_id_count = 0; + } + ++session_id_count; + base = config_getstring(IMAPOPT_SYSLOG_PREFIX); + if (!base) base = config_getstring(IMAPOPT_SERVERNAME); + snprintf(session_id_buf, MAX_SESSIONID_SIZE, "%s-%d-%d-%d", + base, getpid(), session_id_time, session_id_count); +} + +/* Return the session id */ +const char *session_id() +{ + if (!session_id_count) + session_new_id(); + return (const char *)session_id_buf; +} diff --git a/imap/global.h b/imap/global.h index a38e15a..50dbf78 100644 --- a/imap/global.h +++ b/imap/global.h @@ -159,4 +159,8 @@ extern struct cyrusdb_backend *config_tlscache_db; extern struct cyrusdb_backend *config_ptscache_db; extern struct cyrusdb_backend *config_statuscache_db; +/* Session ID */ +extern void session_new_id(); +extern const char *session_id(); + #endif /* INCLUDED_GLOBAL_H */ diff --git a/imap/imapd.c b/imap/imapd.c index 4f2b430..57462bb 100644 --- a/imap/imapd.c +++ b/imap/imapd.c @@ -733,6 +733,8 @@ int service_main(int argc __attribute__((unused)), int niflags; int imapd_haveaddr = 0; + session_new_id(); + signals_poll(); #ifdef ID_SAVE_CMDLINE @@ -2017,6 +2019,7 @@ void cmdloop() void cmd_login(char *tag, char *user) { char userbuf[MAX_MAILBOX_BUFFER]; + char replybuf[MAX_MAILBOX_BUFFER]; unsigned userlen; const char *canon_user = userbuf; const void *val; @@ -2140,7 +2143,9 @@ void cmd_login(char *tag, char *user) return; } - reply = "User logged in"; + snprintf(replybuf, sizeof(replybuf), + "User logged in SESSIONID=<%s>", session_id()); + reply = replybuf; imapd_userid = xstrdup((const char *) val); snmp_increment_args(AUTHENTICATION_YES, 1, VARIABLE_AUTH, 0 /*hash_simple("LOGIN") */, diff --git a/imap/lmtpd.c b/imap/lmtpd.c index aee3d84..b38b967 100644 --- a/imap/lmtpd.c +++ b/imap/lmtpd.c @@ -262,6 +262,8 @@ int service_main(int argc, char **argv, { int opt, r; + session_new_id(); + sync_log_init(); deliver_in = prot_new(0, 0); diff --git a/imap/lmtpengine.c b/imap/lmtpengine.c index eff3e50..fc34055 100644 --- a/imap/lmtpengine.c +++ b/imap/lmtpengine.c @@ -173,7 +173,7 @@ static void send_lmtp_error(struct protstream *pout, int r) { switch (r) { case 0: - prot_printf(pout, "250 2.1.5 Ok\r\n"); + prot_printf(pout, "250 2.1.5 Ok SESSIONID=<%s>\r\n", session_id()); break; case IMAP_IOERROR: @@ -213,10 +213,10 @@ static void send_lmtp_error(struct protstream *pout, int r) case IMAP_QUOTA_EXCEEDED: if(config_getswitch(IMAPOPT_LMTP_OVER_QUOTA_PERM_FAILURE)) { /* Not Default - Perm Failure */ - prot_printf(pout, "552 5.2.2 Over quota\r\n"); + prot_printf(pout, "552 5.2.2 Over quota SESSIONID=<%s>\r\n", session_id()); } else { /* Default - Temp Failure */ - prot_printf(pout, "452 4.2.2 Over quota\r\n"); + prot_printf(pout, "452 4.2.2 Over quota SESSIONID=<%s>\r\n", session_id()); } break; diff --git a/imap/pop3d.c b/imap/pop3d.c index ed5008e..c1419c3 100644 --- a/imap/pop3d.c +++ b/imap/pop3d.c @@ -485,6 +485,8 @@ int service_main(int argc __attribute__((unused)), int niflags; sasl_security_properties_t *secprops=NULL; + session_new_id(); + signals_poll(); sync_log_init(); @@ -1365,9 +1367,9 @@ void cmd_pass(char *pass) } popd_userid = xstrdup((const char *) val); - syslog(LOG_NOTICE, "login: %s %s%s plaintext%s %s", popd_clienthost, + syslog(LOG_NOTICE, "login: %s %s%s plaintext%s %s SESSIONID=<%s>", popd_clienthost, popd_userid, popd_subfolder ? popd_subfolder : "", - popd_starttls_done ? "+TLS" : "", "User logged in"); + popd_starttls_done ? "+TLS" : "", "User logged in", session_id()); if ((plaintextloginpause = config_getint(IMAPOPT_PLAINTEXTLOGINPAUSE)) != 0) { @@ -1739,8 +1741,10 @@ int openinbox(void) /* Create telemetry log */ popd_logfd = telemetry_log(popd_userid, popd_in, popd_out, 0); - prot_printf(popd_out, "+OK%s", - statusline ? statusline : " Mailbox locked and ready\r\n"); + if (statusline) + prot_printf(popd_out, "+OK%s", statusline); + else + prot_printf(popd_out, "+OK Mailbox locked and ready SESSIONID=<%s>\r\n", session_id()); prot_flush(popd_out); return 0; -- 1.5.6.5