From e5da08ed5c1af5e3fda15b4cf4d08ee1b1507d9d Mon Sep 17 00:00:00 2001 From: rswindell <> Date: Sun, 25 Oct 2009 03:05:58 +0000 Subject: [PATCH] Added errormsg callback function pointer to all startup structures to allow error counting/logging/messages to be handled by front-end (e.g. control panel) regardless of log_level setting. Mail server now filters blocked-subjects before applying DNSBL tag. Received message header TO and FROM fields are no longer checked against the email.can file for SMTP-authenticated clients. SMTP MAIL FROM and RCTP TO addresses are no longer checked against the email.can file for SMTP-authenticated clients. Statistics are displayed in a more legible manner when the mail server is terminated. The msgs_received stats counter now includes blocked and ignored messages too. --- src/sbbs3/ftpsrvr.c | 10 ++++-- src/sbbs3/ftpsrvr.h | 5 +-- src/sbbs3/mailsrvr.c | 86 +++++++++++++++++++++++++++----------------- src/sbbs3/mailsrvr.h | 3 +- src/sbbs3/main.cpp | 29 ++++++++++----- src/sbbs3/services.c | 5 ++- src/sbbs3/services.h | 5 +-- src/sbbs3/startup.h | 3 +- src/sbbs3/websrvr.c | 10 ++++-- src/sbbs3/websrvr.h | 5 +-- 10 files changed, 105 insertions(+), 56 deletions(-) diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c index 3783d31726..5d8c9d329c 100644 --- a/src/sbbs3/ftpsrvr.c +++ b/src/sbbs3/ftpsrvr.c @@ -138,8 +138,11 @@ static int lprintf(int level, const char *fmt, ...) sbuf[sizeof(sbuf)-1]=0; va_end(argptr); - if(level <= LOG_ERR) + if(level <= LOG_ERR) { errorlog(&scfg, startup==NULL ? NULL:startup->host_name, sbuf); + if(startup!=NULL && startup->errormsg!=NULL) + startup->errormsg(startup->cbdata,level,sbuf); + } if(startup==NULL || startup->lputs==NULL || level > startup->log_level) return(0); @@ -4585,8 +4588,9 @@ static void cleanup(int code, int line) thread_down(); status("Down"); if(terminate_server || code) - lprintf(LOG_INFO,"#### FTP Server thread terminated (%u threads remain, %lu clients served)" - ,thread_count, served); + lprintf(LOG_INFO,"#### FTP Server thread terminated (%lu clients served)", served); + if(thread_count) + lprintf(LOG_ERR,"#### !FTP Server threads (%u) remain active after termination", thread_count); if(startup!=NULL && startup->terminated!=NULL) startup->terminated(startup->cbdata,code); } diff --git a/src/sbbs3/ftpsrvr.h b/src/sbbs3/ftpsrvr.h index 24d072e1fd..8dc59d2198 100644 --- a/src/sbbs3/ftpsrvr.h +++ b/src/sbbs3/ftpsrvr.h @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2009 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -57,7 +57,8 @@ typedef struct { void* cbdata; /* Private data passed to callbacks */ /* Callbacks (NULL if unused) */ - int (*lputs)(void*, int, const char*); + int (*lputs)(void*, int level, const char* msg); + void (*errormsg)(void*, int level, const char* msg); void (*status)(void*, const char*); void (*started)(void*); void (*recycle)(void*); diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c index 1f5b80ac6f..dde736617f 100644 --- a/src/sbbs3/mailsrvr.c +++ b/src/sbbs3/mailsrvr.c @@ -151,8 +151,11 @@ static int lprintf(int level, const char *fmt, ...) sbuf[sizeof(sbuf)-1]=0; va_end(argptr); - if(level <= LOG_ERR) + if(level <= LOG_ERR) { errorlog(&scfg,startup==NULL ? NULL:startup->host_name,sbuf), stats.errors++; + if(startup!=NULL && startup->errormsg!=NULL) + startup->errormsg(startup->cbdata,level,sbuf); + } if(level <= LOG_CRIT) stats.crit_errors++; @@ -2438,6 +2441,8 @@ static void smtp_thread(void* arg) lprintf(LOG_INFO,"%04d SMTP End of message (body: %lu lines, %lu bytes, header: %lu lines, %lu bytes)" , socket, lines, ftell(msgtxt)-hdr_len, hdr_lines, hdr_len); + stats.msgs_received++; + /* Twit-listing (sender's name and e-mail addresses) here */ SAFEPRINTF(path,"%stwitlist.cfg",scfg.ctrl_dir); if(fexist(path) && (findstr(sender,path) || findstr(sender_addr,path))) { @@ -2668,24 +2673,38 @@ static void smtp_thread(void* arg) if((p=get_header_field(buf, field, sizeof(field)))!=NULL) { if(stricmp(field, "SUBJECT")==0) { - if(relay_user.number==0 && dnsbl_result.s_addr && startup->dnsbl_tag[0] && !(startup->options&MAIL_OPT_DNSBL_IGNORE)) { - safe_snprintf(str,sizeof(str),"%.*s: %.*s" - ,(int)sizeof(str)/2, startup->dnsbl_tag - ,(int)sizeof(str)/2, p); - p=str; - lprintf(LOG_NOTICE,"%04d SMTP TAGGED MAIL SUBJECT from blacklisted server with: %s" - ,socket, startup->dnsbl_tag); + /* SPAM Filtering/Logging */ + if(relay_user.number==0) { + if(trashcan(&scfg,p,"subject")) { + lprintf(LOG_NOTICE,"%04d !SMTP BLOCKED SUBJECT (%s) from: %s (%u total)" + ,socket, p, reverse_path, ++stats.msgs_refused); + SAFEPRINTF2(tmp,"Blocked subject (%s) from: %s" + ,p, reverse_path); + spamlog(&scfg, "SMTP", "REFUSED" + ,tmp, host_name, host_ip, rcpt_addr, reverse_path); + errmsg="554 Subject not allowed."; + smb_error=SMB_FAILURE; + break; + } + if(dnsbl_result.s_addr && startup->dnsbl_tag[0] && !(startup->options&MAIL_OPT_DNSBL_IGNORE)) { + safe_snprintf(str,sizeof(str),"%.*s: %.*s" + ,(int)sizeof(str)/2, startup->dnsbl_tag + ,(int)sizeof(str)/2, p); + p=str; + lprintf(LOG_NOTICE,"%04d SMTP TAGGED MAIL SUBJECT from blacklisted server with: %s" + ,socket, startup->dnsbl_tag); + } } smb_hfield_str(&msg, SUBJECT, p); continue; } - if(stricmp(field, "FROM")==0 + if(relay_user.number==0 && stricmp(field, "FROM")==0 && !chk_email_addr(socket,p,host_name,host_ip,rcpt_addr,reverse_path,"FROM")) { errmsg="554 Sender not allowed."; smb_error=SMB_FAILURE; break; } - if(stricmp(field, "TO")==0 && !spam_bait_result + if(relay_user.number==0 && stricmp(field, "TO")==0 && !spam_bait_result && !chk_email_addr(socket,p,host_name,host_ip,rcpt_addr,reverse_path,"TO")) { errmsg="550 Unknown user."; smb_error=SMB_FAILURE; @@ -2717,18 +2736,6 @@ static void smtp_thread(void* arg) ,sender ,sizeof(sender)-1 ,sender_addr,sizeof(sender_addr)-1); } - - /* SPAM Filtering/Logging */ - if(relay_user.number==0 && msg.subj!=NULL && trashcan(&scfg,msg.subj,"subject")) { - lprintf(LOG_NOTICE,"%04d !SMTP BLOCKED SUBJECT (%s) from: %s (%u total)" - ,socket, msg.subj, reverse_path, ++stats.msgs_refused); - SAFEPRINTF2(tmp,"Blocked subject (%s) from: %s" - ,msg.subj, reverse_path); - spamlog(&scfg, "SMTP", "REFUSED" - ,tmp, host_name, host_ip, rcpt_addr, reverse_path); - sockprintf(socket, "554 Subject not allowed."); - continue; - } dnsbl_recvhdr=FALSE; if(startup->options&MAIL_OPT_DNSBL_CHKRECVHDRS) { for(i=0;!dnsbl_result.s_addr && i<msg.total_hfields;i++) { @@ -2827,7 +2834,6 @@ static void smtp_thread(void* arg) ,socket, sender_addr, scfg.sub[subnum]->sname); sockprintf(socket,ok_rsp); signal_smtp_sem(); - stats.msgs_received++; } free(msgbuf); smb_close(&smb); @@ -3015,7 +3021,6 @@ static void smtp_thread(void* arg) smb_incmsg_dfields(&smb,&msg,(ushort)(rcpt_count-1)); sockprintf(socket,ok_rsp); signal_smtp_sem(); - stats.msgs_received++; } #if 0 /* This shouldn't be necessary here */ smb_close_da(&smb); @@ -3368,7 +3373,8 @@ static void smtp_thread(void* arg) || !strnicmp(buf,"SAML FROM:",10) /* Send AND Mail a Message to a local user */ ) { p=buf+10; - if(!chk_email_addr(socket,p,host_name,host_ip,NULL,NULL,"REVERSE PATH")) { + if(relay_user.number==0 + && !chk_email_addr(socket,p,host_name,host_ip,NULL,NULL,"REVERSE PATH")) { sockprintf(socket, "554 Sender not allowed."); break; } @@ -3503,7 +3509,8 @@ static void smtp_thread(void* arg) } /* Check for blocked recipients */ - if(!chk_email_addr(socket,rcpt_addr,host_name,host_ip,rcpt_addr,reverse_path,"RECIPIENT")) { + if(relay_user.number==0 + && !chk_email_addr(socket,rcpt_addr,host_name,host_ip,rcpt_addr,reverse_path,"RECIPIENT")) { sockprintf(socket, "550 Unknown User:%s", buf+8); continue; } @@ -4599,12 +4606,27 @@ static void cleanup(int code) thread_down(); status("Down"); - if(terminate_server || code) - lprintf(LOG_INFO,"#### Mail Server thread terminated (connections served: %u, refused: %u, ignored: %u, sessions refused: %u, messages received: %u, refused: %u, ignored: %u, errors: %u, critical: %u)" - ,stats.connections_served, stats.connections_refused, stats.connections_ignored - ,stats.sessions_refused - ,stats.msgs_received, stats.msgs_refused, stats.msgs_ignored - ,stats.errors, stats.crit_errors); + if(terminate_server || code) { + char str[1024]; + sprintf(str,"%u connections served", stats.connections_served); + if(stats.connections_refused) + sprintf(str+strlen(str),", %u refused", stats.connections_refused); + if(stats.connections_ignored) + sprintf(str+strlen(str),", %u ignored", stats.connections_refused); + if(stats.sessions_refused) + sprintf(str+strlen(str),", %u sessions refused", stats.sessions_refused); + sprintf(str+strlen(str),", %u messages received", stats.msgs_received); + if(stats.msgs_refused) + sprintf(str+strlen(str),", %u refused", stats.msgs_refused); + if(stats.msgs_ignored) + sprintf(str+strlen(str),", %u ignored", stats.msgs_ignored); + if(stats.errors) + sprintf(str+strlen(str),", %u errors", stats.errors); + if(stats.crit_errors) + sprintf(str+strlen(str),", %u critcal", stats.crit_errors); + + lprintf(LOG_INFO,"#### Mail Server thread terminated (%s)",str); + } if(thread_count) lprintf(LOG_ERR,"#### !Mail Server threads (%u) remain active after termination", thread_count); if(startup!=NULL && startup->terminated!=NULL) diff --git a/src/sbbs3/mailsrvr.h b/src/sbbs3/mailsrvr.h index 7a3c6adba3..50cb36a6aa 100644 --- a/src/sbbs3/mailsrvr.h +++ b/src/sbbs3/mailsrvr.h @@ -62,7 +62,8 @@ typedef struct { void* cbdata; /* Private data passed to callbacks */ /* Callbacks (NULL if unused) */ - int (*lputs)(void*, int, const char*); + int (*lputs)(void*, int level, const char* msg); + void (*errormsg)(void*, int level, const char* msg); void (*status)(void*, const char*); void (*started)(void*); void (*recycle)(void*); diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp index 4b684f0915..ac4c7afa76 100644 --- a/src/sbbs3/main.cpp +++ b/src/sbbs3/main.cpp @@ -151,8 +151,11 @@ static void thread_down() int lputs(int level, const char* str) { - if(level <= LOG_ERR) + if(level <= LOG_ERR) { errorlog(&scfg,startup==NULL ? NULL:startup->host_name, str); + if(startup!=NULL && startup->errormsg!=NULL) + startup->errormsg(startup->cbdata,level,str); + } if(startup==NULL || startup->lputs==NULL || str==NULL || level > startup->log_level) return(0); @@ -182,13 +185,20 @@ int eprintf(int level, const char *fmt, ...) va_list argptr; char sbuf[1024]; - if(startup==NULL || startup->event_lputs==NULL || level > startup->log_level) - return(0); - va_start(argptr,fmt); vsnprintf(sbuf,sizeof(sbuf),fmt,argptr); sbuf[sizeof(sbuf)-1]=0; va_end(argptr); + + if(level <= LOG_ERR) { + errorlog(&scfg,startup==NULL ? NULL:startup->host_name, sbuf); + if(startup!=NULL && startup->errormsg!=NULL) + startup->errormsg(startup->cbdata,level,sbuf); + } + + if(startup==NULL || startup->event_lputs==NULL || level > startup->log_level) + return(0); + strip_ctrl(sbuf, sbuf); return(startup->event_lputs(startup->event_cbdata,level,sbuf)); } @@ -4199,7 +4209,7 @@ void DLLCALL bbs_terminate(void) static void cleanup(int code) { - lputs(LOG_INFO,"BBS System thread terminating"); + lputs(LOG_INFO,"Terminal Server thread terminating"); if(telnet_socket!=INVALID_SOCKET) { close_socket(telnet_socket); @@ -4252,8 +4262,9 @@ static void cleanup(int code) status("Down"); thread_down(); if(terminate_server || code) - lprintf(LOG_INFO,"BBS System thread terminated (%u threads remain, %lu clients served)" - ,thread_count, served); + lprintf(LOG_INFO,"Terminal Server thread terminated (%lu clients served)", served); + if(thread_count) + lprintf(LOG_ERR,"!Terminal Server threads (%u) remain active after termination", thread_count); if(startup->terminated!=NULL) startup->terminated(startup->cbdata,code); } @@ -4665,7 +4676,7 @@ NO_SSH: #endif sbbs = new sbbs_t(0, server_addr.sin_addr.s_addr - ,"BBS System", telnet_socket, &scfg, text, NULL); + ,"Terminal Server", telnet_socket, &scfg, text, NULL); sbbs->online = 0; if(sbbs->init()==false) { lputs(LOG_CRIT,"!BBS initialization failed"); @@ -4791,7 +4802,7 @@ NO_SSH: if(startup->started!=NULL) startup->started(startup->cbdata); - lprintf(LOG_INFO,"BBS System thread started for nodes %d through %d", first_node, last_node); + lprintf(LOG_INFO,"Terminal Server thread started for nodes %d through %d", first_node, last_node); while(!terminate_server) { diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c index 0771e096a8..db08d50cba 100644 --- a/src/sbbs3/services.c +++ b/src/sbbs3/services.c @@ -124,8 +124,11 @@ static int lprintf(int level, const char *fmt, ...) sbuf[sizeof(sbuf)-1]=0; va_end(argptr); - if(level <= LOG_ERR) + if(level <= LOG_ERR) { errorlog(&scfg,startup==NULL ? NULL:startup->host_name, sbuf); + if(startup!=NULL && startup->errormsg!=NULL) + startup->errormsg(startup->cbdata,level,sbuf); + } if(startup==NULL || startup->lputs==NULL || level > startup->log_level) return(0); diff --git a/src/sbbs3/services.h b/src/sbbs3/services.h index 5df4291a29..ccaea048e6 100644 --- a/src/sbbs3/services.h +++ b/src/sbbs3/services.h @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2009 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -50,7 +50,8 @@ typedef struct { void* cbdata; /* Private data passed to callbacks */ /* Callbacks (NULL if unused) */ - int (*lputs)(void*, int, const char*); /* Log - put string */ + int (*lputs)(void*, int level, const char*); /* Log - put string */ + void (*errormsg)(void*, int level, const char* msg); void (*status)(void*, const char*); void (*started)(void*); void (*recycle)(void*); diff --git a/src/sbbs3/startup.h b/src/sbbs3/startup.h index 1d1c2459cb..a56337bb21 100644 --- a/src/sbbs3/startup.h +++ b/src/sbbs3/startup.h @@ -92,8 +92,9 @@ typedef struct { void* event_cbdata; /* Private data passed to event_lputs callback */ /* Callbacks (NULL if unused) */ - int (*lputs)(void*, int, const char*); /* Log - put string */ + int (*lputs)(void*, int , const char*); /* Log - put string */ int (*event_lputs)(void*, int, const char*); /* Event log - put string */ + void (*errormsg)(void*, int level, const char* msg); void (*status)(void*, const char*); void (*started)(void*); void (*recycle)(void*); diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c index 36936bd56a..ac28ad75f8 100644 --- a/src/sbbs3/websrvr.c +++ b/src/sbbs3/websrvr.c @@ -490,8 +490,11 @@ static int lprintf(int level, const char *fmt, ...) sbuf[sizeof(sbuf)-1]=0; va_end(argptr); - if(level <= LOG_ERR) + if(level <= LOG_ERR) { errorlog(&scfg,startup==NULL ? NULL:startup->host_name, sbuf); + if(startup!=NULL && startup->errormsg!=NULL) + startup->errormsg(startup->cbdata,level,sbuf); + } if(startup==NULL || startup->lputs==NULL || level > startup->log_level) return(0); @@ -5177,8 +5180,9 @@ static void cleanup(int code) thread_down(); status("Down"); if(terminate_server || code) - lprintf(LOG_INFO,"#### Web Server thread terminated (%u threads remain, %lu clients served)" - ,thread_count, served); + lprintf(LOG_INFO,"#### Web Server thread terminated (%lu clients served)", served); + if(thread_count) + lprintf(LOG_ERR,"#### !Web Server threads (%u) remain active after termination", thread_count); if(startup!=NULL && startup->terminated!=NULL) startup->terminated(startup->cbdata,code); } diff --git a/src/sbbs3/websrvr.h b/src/sbbs3/websrvr.h index 461a8d4079..e1fb11981e 100644 --- a/src/sbbs3/websrvr.h +++ b/src/sbbs3/websrvr.h @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2009 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -55,7 +55,8 @@ typedef struct { void* cbdata; /* Private data passed to callbacks */ /* Callbacks (NULL if unused) */ - int (*lputs)(void*, int, const char*); + int (*lputs)(void*, int level, const char* msg); + void (*errormsg)(void*, int level, const char* msg); void (*status)(void*, const char*); void (*started)(void*); void (*recycle)(void*); -- GitLab