From 7eeaeb0b92c7cb219335784c4dea521e1b75d1e4 Mon Sep 17 00:00:00 2001
From: "Rob Swindell (on Windows 11)" <rob@synchro.net>
Date: Thu, 14 Dec 2023 21:25:24 -0800
Subject: [PATCH] Log notice-level message for > 1 consecutive unique login
 attempts

The log format and details might need some adjustment, but this is a start.

Also, don't delay 3 seconds before disconnecting socket when mail server has
reached maximum number of clients - we should immediately release resources
(the socket) and be able to accept another connection ASAP instead.

Deal with new CID 470557 and 470554 in mail server: resource (file*)
leaks in error paths (corner case).

Set minimum severity of TLS messages in web sever to INFO. Debug-level would
hide some common TLS session errors.
---
 src/sbbs3/ftpsrvr.c  |  2 ++
 src/sbbs3/login.cpp  |  2 ++
 src/sbbs3/mailsrvr.c | 20 +++++++++++---------
 src/sbbs3/services.c |  2 ++
 src/sbbs3/websrvr.c  |  6 +++++-
 5 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index f738916a5d..6b8f5a5531 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -1771,6 +1771,8 @@ static BOOL badlogin(SOCKET sock, CRYPT_SESSION sess, ulong* login_attempts
 
 	if(addr!=NULL) {
 		count=loginFailure(startup->login_attempt_list, addr, client->protocol, user, passwd);
+		if (count > 1)
+			lprintf(LOG_NOTICE, "%04d [%s] !CONSECUTIVE UNIQUE LOGIN ATTEMPT #%lu", sock, client->addr, count);
 		mqtt_user_login_fail(&mqtt, client, user);
 		if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold)
 			ftp_hacklog("FTP LOGIN", user, passwd, client->host, addr);
diff --git a/src/sbbs3/login.cpp b/src/sbbs3/login.cpp
index c90d8d18ec..80ccbf63a2 100644
--- a/src/sbbs3/login.cpp
+++ b/src/sbbs3/login.cpp
@@ -143,6 +143,8 @@ void sbbs_t::badlogin(const char* user, const char* passwd, const char* protocol
 	socklen_t addr_len = sizeof(*addr);
 	SAFEPRINTF(reason,"%s LOGIN", protocol);
 	count=loginFailure(startup->login_attempt_list, addr, protocol, user, passwd);
+	if (count > 1)
+		lprintf(LOG_NOTICE, "!CONSECUTIVE UNIQUE LOGIN ATTEMPT #%lu", count);
 	mqtt_user_login_fail(mqtt, &client, user);
 	if(user!=NULL && startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
 		getnameinfo(&addr->addr, addr_len, host_name, sizeof(host_name), NULL, 0, NI_NAMEREQD);
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 68814c500b..95cfe2ff8f 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -976,6 +976,8 @@ static void badlogin(SOCKET sock, CRYPT_SESSION sess, const char* resp
 	if(addr!=NULL) {
 		SAFEPRINTF(reason,"%s LOGIN", client->protocol);
 		count=loginFailure(startup->login_attempt_list, addr, client->protocol, user, passwd);
+		if (count > 1)
+			lprintf(LOG_NOTICE, "%04d %s [%s] !CONSECUTIVE UNIQUE LOGIN ATTEMPT #%lu", sock, client->protocol, client->addr, count);
 		mqtt_user_login_fail(&mqtt, client, user);
 		if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
 			hacklog(&scfg, &mqtt, reason, user, passwd, client->host, addr);
@@ -3090,14 +3092,6 @@ static bool smtp_client_thread(smtp_t* smtp)
 		return false;
 	}
 
-	if(trashcan(&scfg,host_name,"smtpspy")
-		|| trashcan(&scfg,host_ip,"smtpspy")) {
-		SAFECOPY(str, client.protocol);
-		strlwr(str);
-		SAFEPRINTF2(path,"%s%sspy.txt", scfg.logs_dir, str);
-		spy=fopen(path,"a");
-	}
-
 	/* Initialize client display */
 	client.size=sizeof(client);
 	client.time=time32(NULL);
@@ -3117,11 +3111,20 @@ static bool smtp_client_thread(smtp_t* smtp)
 
 	BOOL* mailproc_to_match = calloc(sizeof(*mailproc_to_match), mailproc_count);
 	if(mailproc_to_match == NULL) {
+		fclose(rcptlst);
 		lprintf(LOG_CRIT,"%04d %s !ERROR allocating memory for mailproc_to_match", socket, client.protocol);
 		sockprintf(socket,client.protocol,session,smtp_error, "malloc failure");
 		return false;
 	}
 
+	if(trashcan(&scfg,host_name,"smtpspy")
+		|| trashcan(&scfg,host_ip,"smtpspy")) {
+		SAFECOPY(str, client.protocol);
+		strlwr(str);
+		SAFEPRINTF2(path,"%s%sspy.txt", scfg.logs_dir, str);
+		spy=fopen(path,"a");
+	}
+
 	/* SMTP session active: */
 
 	sockprintf(socket,client.protocol,session,"220 %s Synchronet %s Server %s%c-%s Ready"
@@ -6322,7 +6325,6 @@ void mail_server(void* arg)
 					lprintf(LOG_WARNING,"%04d %s [%s] !MAXIMUM CLIENTS (%u) reached, access denied (%lu total)"
 						,client_socket, servprot, host_ip, startup->max_clients, ++stats.connections_refused);
 					sockprintf(client_socket, servprot, session, is_smtp ? smtp_error : pop_error, "Maximum active clients reached");
-					mswait(3000);
 					mail_close_socket(&client_socket, &session);
 					continue;
 				}
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 512f266096..f4b29c2c0f 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -340,6 +340,8 @@ static void badlogin(SOCKET sock, char* user, char* passwd, client_t* client, un
 
 	SAFEPRINTF(reason,"%s LOGIN", client->protocol);
 	count=loginFailure(startup->login_attempt_list, addr, client->protocol, user, passwd);
+	if (count > 1)
+		lprintf(LOG_NOTICE, "%04d %s [%s] !CONSECUTIVE UNIQUE LOGIN ATTEMPT #%lu", sock, client->protocol, client->addr, count);
 	mqtt_user_login_fail(&mqtt, client, user);
 	if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
 		hacklog(&scfg, &mqtt, reason, user, passwd, client->host, addr);
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 433ec09b1a..4120df9aa9 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -415,8 +415,10 @@ enum  {
 	int GCES_level;                                                                 \
 	get_crypt_error_string(status, sess->tls_sess, &GCES_estr, action, &GCES_level);\
 	if (GCES_estr) {                                                                \
-		if(GCES_level < startup->tls_error_level)                                   \
+		if (GCES_level < startup->tls_error_level)                                  \
 			GCES_level = startup->tls_error_level;                                  \
+		if (GCES_level > LOG_INFO)													\
+			GCES_level = LOG_INFO;                                                  \
 		lprintf(GCES_level, "%04d TLS %s", sess->socket, GCES_estr);                \
 		free_crypt_attrstr(GCES_estr);                                              \
 	}                                                                               \
@@ -1894,6 +1896,8 @@ static void badlogin(SOCKET sock, const char* user, const char* passwd, client_t
 
 	SAFEPRINTF(reason,"%s LOGIN", client->protocol);
 	count=loginFailure(startup->login_attempt_list, addr, client->protocol, user, passwd);
+	if (count > 1)
+		lprintf(LOG_NOTICE, "%04d %s [%s] !CONSECUTIVE UNIQUE LOGIN ATTEMPT #%lu", sock, client->protocol, client->addr, count);
 	mqtt_user_login_fail(&mqtt, client, user);
 	if(startup->login_attempt.hack_threshold && count>=startup->login_attempt.hack_threshold) {
 		hacklog(&scfg, &mqtt, reason, user, passwd, client->host, addr);
-- 
GitLab