Commit e5da08ed authored by rswindell's avatar rswindell
Browse files

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.
parent 3c14a4fe
......@@ -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);
}
......
......@@ -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*);
......
......@@ -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)
......
......@@ -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*);
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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*);
......
......@@ -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*);
......
......@@ -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);
}
......
......@@ -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*);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment