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