This patch written by Andrew Richards 2010. For more details, documentation etc. please see http://free.acrconsulting.co.uk/ diff -Nru ucspi-tcp-0.88/Makefile ucspi-tcp-0.88_logmsg/Makefile --- ucspi-tcp-0.88/Makefile 2000-03-18 15:18:42.000000000 +0000 +++ ucspi-tcp-0.88_logmsg/Makefile 2010-02-09 14:58:53.000000000 +0000 @@ -151,6 +151,10 @@ > choose chmod 755 choose +clean: \ +TARGETS + rm -f `cat TARGETS` + commands.o: \ compile commands.c buffer.h stralloc.h gen_alloc.h str.h case.h \ commands.h diff -Nru ucspi-tcp-0.88/rblsmtpd.c ucspi-tcp-0.88_logmsg/rblsmtpd.c --- ucspi-tcp-0.88/rblsmtpd.c 2000-03-18 15:18:42.000000000 +0000 +++ ucspi-tcp-0.88_logmsg/rblsmtpd.c 2010-07-23 10:41:35.000000000 +0100 @@ -27,6 +27,9 @@ char *ip_env; static stralloc ip_reverse; +static stralloc addr = {0}; +static stralloc foo = {0}; +static char pid_str[FMT_ULONG]="?PID?"; void ip_init(void) { @@ -48,6 +51,101 @@ } } +void eout(s1) char *s1; {buffer_puts(buffer_2,s1);} +void eout2(s1,s2) char *s1,*s2; {buffer_puts(buffer_2,s1);buffer_puts(buffer_2,s2);} +void eout3(s1,s2,s3) char *s1,*s2,*s3; {buffer_puts(buffer_2,s1);buffer_puts(buffer_2,s2);buffer_puts(buffer_2,s3);} + +void epid() +{ + if (*pid_str == '?') /* not yet set from getpid() */ + pid_str[fmt_ulong(pid_str,getpid())] = 0; + eout(pid_str); +} + +/* Choose your log format here, */ + +/* rblsmtpd: 192.168.1.1 pid 1234: log msg */ +/* void enew() { eout3("rblsmtpd: ",ip_env," pid "); epid(); eout(": "); } */ + +/* rblsmtpd: pid 1234 from 192.168.1.1: log msg */ +void enew() { eout("rblsmtpd: pid "); epid(); eout2(" from ", ip_env); eout(": "); } + +void eflush() { buffer_flush(buffer_2); } + +/* The functions below here come from qmail's qsutil.c with minor changes */ +void eoutsa(sa) stralloc *sa; { buffer_put(buffer_2,sa->s,sa->len); } /* no flush here */ + +static int issafe(ch) char ch; +{ /* Differs from qsutil.c version: space and % permitted */ + if (ch == ':') return 0; /* Replace since used as delimiter in logs */ + if (ch == '<') return 0; /* Replace since used around addresses in logs */ + if (ch == '>') return 0; /* Replace since used around addresses in logs */ + if (ch < 32) return 0; /* Note that space (32) is permitted */ + if (ch > 126) return 0; + return 1; +} + +void eoutclean(s) char *s; +{ + int i; + while (!stralloc_copys(&foo,s)) nomem(); + for (i = 0;i < foo.len;++i) + if (foo.s[i] == '\n') + foo.s[i] = '/'; + else + if (!issafe(foo.s[i])) + foo.s[i] = '_'; + eoutsa(&foo); +} + +/* Adapted from qmail-smtpd.c, only needed so we can log the envelope addresses: */ +int addrparse(arg) +char *arg; +{ + int i; + char ch; + char terminator; + int flagesc; + int flagquoted; + + terminator = '>'; + i = str_chr(arg,'<'); + if (arg[i]) + arg += i + 1; + else { /* partner should go read rfc 821 */ + terminator = ' '; + arg += str_chr(arg,':'); + if (*arg == ':') ++arg; + while (*arg == ' ') ++arg; + } + + /* strip source route */ + if (*arg == '@') while (*arg) if (*arg++ == ':') break; + + if (!stralloc_copys(&addr,"")) nomem(); + flagesc = 0; + flagquoted = 0; + for (i = 0;ch = arg[i];++i) { /* copy arg to addr, stripping quotes */ + if (flagesc) { + if (!stralloc_append(&addr,&ch)) nomem(); + flagesc = 0; + } + else { + if (!flagquoted && (ch == terminator)) break; + switch(ch) { + case '\\': flagesc = 1; break; + case '"': flagquoted = !flagquoted; break; + default: if (!stralloc_append(&addr,&ch)) nomem(); + } + } + } + /* could check for termination failure here, but why bother? */ + if (!stralloc_append(&addr,"")) nomem(); + + if (addr.len > 900) return 0; + return 1; +} + unsigned long timeout = 60; int flagrblbounce = 0; int flagfailclosed = 0; @@ -93,7 +191,6 @@ decision = 1; } -char strnum[FMT_ULONG]; static stralloc message; char inspace[64]; buffer in = BUFFER_INIT(read,0,inspace,sizeof inspace); @@ -102,17 +199,43 @@ void reject() { buffer_putflush(&out,message.s,message.len); } void accept() { buffer_putsflush(&out,"250 rblsmtpd.local\r\n"); } void greet() { buffer_putsflush(&out,"220 rblsmtpd.local\r\n"); } -void quit() { buffer_putsflush(&out,"221 rblsmtpd.local\r\n"); _exit(0); } -void drop() { _exit(0); } +void quit() { buffer_putsflush(&out,"221 rblsmtpd.local\r\n"); enew(); eout("Remote end QUIT: quitting\n"); eflush(); _exit(0); } +void drop() { enew(); eout("Session timed out: quitting\n"); eflush(); _exit(0); } +void err_vrfy() { buffer_putsflush(&out,"252 rblsmtpd.local\r\n"); } + +void smtp_mail(arg) char *arg; +{ + enew(); + if (!addrparse(arg)) { eout("MAIL with too long address\n"); } + else { eout("Sender <"); eoutclean(addr.s); eout(">\n"); } + eflush(); + accept(); +} + +void smtp_rcpt(arg) char *arg; +{ + enew(); + if (!addrparse(arg)) { eout("RCPT with too long address\n"); } + else { eout("Recipient <"); eoutclean(addr.s); eout(">\n"); } + eflush(); + reject(); +/* + * We now have the envelope info for logging, assuming sender address + * already supplied - to be thorough we could check that the sender + * was supplied using the same logic as in qmail-smtpd.c + */ +} struct commands smtpcommands[] = { { "quit", quit, 0 } , { "helo", accept, 0 } , { "ehlo", accept, 0 } -, { "mail", accept, 0 } +, { "mail", smtp_mail, 0 } , { "rset", accept, 0 } +, { "vrfy", err_vrfy, 0 } /* Needed in a minimal SMTP implementation */ , { "noop", accept, 0 } -, { 0, reject, 0 } +, { "rcpt", smtp_rcpt, 0 } +, { 0, reject, 0 } /* Including DATA */ } ; void rblsmtpd(void) @@ -131,14 +254,11 @@ if ((message.s[i] < 32) || (message.s[i] > 126)) message.s[i] = '?'; - buffer_puts(buffer_2,"rblsmtpd: "); - buffer_puts(buffer_2,ip_env); - buffer_puts(buffer_2," pid "); - buffer_put(buffer_2,strnum,fmt_ulong(strnum,getpid())); - buffer_puts(buffer_2,": "); - buffer_put(buffer_2,message.s,message.len); - buffer_puts(buffer_2,"\n"); - buffer_flush(buffer_2); + enew(); + eout("RBL message is "); + eoutsa(&message); + eout("\n"); + eflush(); if (!stralloc_cats(&message,"\r\n")) nomem(); @@ -150,6 +270,9 @@ greet(); commands(&in,smtpcommands); } + enew(); + eout("Session terminated: quitting\n"); /* Normally client disconnecting */ + eflush(); _exit(0); }