From ccfb0f023ae523474c04bf3fbcdb1248d6f9a04a Mon Sep 17 00:00:00 2001
From: "Rob Swindell (on Windows 11)" <rob@synchro.net>
Date: Fri, 29 Dec 2023 01:46:46 -0800
Subject: [PATCH] Every sever has a configurable "Login Requirements" (AR
 String)

The Global Login Requirements (default: blank) are used for any sever that doesn't have it explicitly set.

This resolves issue #666 (the issue of the beast) for Keyop
---
 src/sbbs3/ftpsrvr.c       |  7 +++++++
 src/sbbs3/logon.cpp       | 13 ++++++++++--
 src/sbbs3/mailsrvr.c      | 18 ++++++++++++++++
 src/sbbs3/sbbs_ini.c      | 44 +++++++++++++++++++++++++++++++++++++++
 src/sbbs3/scfg/scfgsrvr.c | 39 +++++++++++++++++++++++++++-------
 src/sbbs3/services.c      |  8 +++++++
 src/sbbs3/startup.h       |  2 ++
 src/sbbs3/websrvr.c       | 14 +++++++++++++
 8 files changed, 136 insertions(+), 9 deletions(-)

diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index 2eed49d40c..4c5378a207 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -2538,6 +2538,13 @@ static void ctrl_thread(void* arg)
 				user.number=0;
 				continue;
 			}
+			if(!chk_ars(&scfg, startup->login_ars, &user, &client)) {
+				lprintf(LOG_NOTICE,"%04d <%s> !Insufficient server access: %s"
+					,sock, user.alias, startup->login_ars);
+				sockprintf(sock,sess,"530 Insufficient server access.");
+				user.number=0;
+				continue;
+			}
 
 			SAFEPRINTF2(sys_pass,"%s:%s",user.pass,scfg.sys_pass);
 			if(!user.pass[0]) {	/* Guest/Anonymous */
diff --git a/src/sbbs3/logon.cpp b/src/sbbs3/logon.cpp
index d9db5d8252..3c944fff48 100644
--- a/src/sbbs3/logon.cpp
+++ b/src/sbbs3/logon.cpp
@@ -91,10 +91,19 @@ bool sbbs_t::logon()
 		useron.shell=cfg.new_shell; 
 	}
 
+	if(!chk_ars(startup->login_ars, &useron, &client)) {
+		bputs(text[NoNodeAccess]);
+		safe_snprintf(str, sizeof str, "(%04u)  %-25s  Insufficient server access: %s"
+			,useron.number, useron.alias, startup->login_ars);
+		logline(LOG_NOTICE, "+!", str);
+		hangup();
+		return false; 
+	}
+
 	if(!chk_ar(cfg.node_ar,&useron,&client)) {
 		bputs(text[NoNodeAccess]);
-		safe_snprintf(str, sizeof(str), "(%04u)  %-25s  Insufficient node access"
-			,useron.number,useron.alias);
+		safe_snprintf(str, sizeof(str), "(%04u)  %-25s  Insufficient node access: %s"
+			,useron.number, useron.alias, cfg.node_arstr);
 		logline(LOG_NOTICE,"+!",str);
 		hangup();
 		return(false); 
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 947b1e6123..05cb138b4b 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -1301,6 +1301,12 @@ static bool pop3_client_thread(pop3_t* pop3)
 			badlogin(socket, session, pop_auth_error, username, password, &client, &pop3->client_addr);
 			break;
 		}
+		if(!chk_ars(&scfg, startup->login_ars, &user, &client)) {
+			lprintf(LOG_NOTICE,"%04d %s [%s] <%s> !Insufficient server access: %s"
+				,socket, client.protocol, host_ip, username, startup->login_ars);
+			badlogin(socket, session, pop_auth_error, username, NULL, &client, &pop3->client_addr);
+			break;
+		}
 
 		if(user.pass[0]) {
 			loginSuccess(startup->login_attempt_list, &pop3->client_addr);
@@ -4172,6 +4178,12 @@ static bool smtp_client_thread(smtp_t* smtp)
 				badlogin(socket, session, badauth_rsp, user_name, user_pass, &client, &smtp->client_addr);
 				break;
 			}
+			if(!chk_ars(&scfg, startup->login_ars, &relay_user, &client)) {
+				lprintf(LOG_NOTICE,"%04d %s [%s] <%s> !Insufficient server access: %s"
+					,socket, client.protocol, client_id, user_name, startup->login_ars);
+				badlogin(socket, session, badauth_rsp, user_name, NULL, &client, &smtp->client_addr);
+				break;
+			}
 
 			if(relay_user.pass[0]) {
 				loginSuccess(startup->login_attempt_list, &smtp->client_addr);
@@ -4271,6 +4283,12 @@ static bool smtp_client_thread(smtp_t* smtp)
 				badlogin(socket, session, badauth_rsp, user_name, p, &client, &smtp->client_addr);
 				break;
 			}
+			if(!chk_ars(&scfg, startup->login_ars, &relay_user, &client)) {
+				lprintf(LOG_NOTICE,"%04d %s [%s] <%s> !Insufficient server access: %s"
+					,socket, client.protocol, client_id, user_name, startup->login_ars);
+				badlogin(socket, session, badauth_rsp, user_name, NULL, &client, &smtp->client_addr);
+				break;
+			}
 
 			if(relay_user.pass[0]) {
 				loginSuccess(startup->login_attempt_list, &smtp->client_addr);
diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c
index 2e0f34426b..0d4a05687c 100644
--- a/src/sbbs3/sbbs_ini.c
+++ b/src/sbbs3/sbbs_ini.c
@@ -61,6 +61,7 @@ static const char*	strLoginAttemptTempBanThreshold="LoginAttemptTempBanThreshold
 static const char*	strLoginAttemptTempBanDuration="LoginAttemptTempBanDuration";
 static const char*	strLoginAttemptFilterThreshold="LoginAttemptFilterThreshold";
 static const char*	strLoginAttemptFilterDuration="LoginAttemptFilterDuration";
+static const char*	strLoginRequirements="LoginRequirements";
 static const char*	strJavaScriptMaxBytes		="JavaScriptMaxBytes";
 static const char*	strJavaScriptTimeLimit		="JavaScriptTimeLimit";
 static const char*	strJavaScriptGcInterval		="JavaScriptGcInterval";
@@ -280,6 +281,8 @@ static void get_ini_globals(str_list_t list, global_startup_t* global)
 	if(*p)
         SAFECOPY(global->host_name,value);
 
+	SAFECOPY(global->login_ars, iniGetString(list, section, strLoginRequirements, nulstr, value));
+
 	global->sem_chk_freq=(uint16_t)iniGetDuration(list,section,strSemFileCheckFrequency,DEFAULT_SEM_CHK_FREQ);
 	global->interfaces=iniGetStringList(list,section,strInterfaces, ",", "0.0.0.0,::");
 	global->outgoing4.s_addr=iniGetIpAddress(list,section,strOutgoing4,INADDR_ANY);
@@ -463,6 +466,9 @@ void sbbs_read_ini(
 		SAFECOPY(bbs->temp_dir
 			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
 
+		SAFECOPY(bbs->login_ars
+			,iniGetString(list, section, strLoginRequirements, global->login_ars, value));
+
 		bbs->default_term_width = iniGetUInteger(list, section, "DefaultTermWidth", TERM_COLS_DEFAULT);
 		bbs->default_term_height = iniGetUInteger(list, section, "DefaultTermHeight", TERM_ROWS_DEFAULT);
 
@@ -564,6 +570,9 @@ void sbbs_read_ini(
 		SAFECOPY(ftp->temp_dir
 			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
 
+		SAFECOPY(ftp->login_ars
+			,iniGetString(list, section, strLoginRequirements, global->login_ars, value));
+
 		ftp->log_level
 			=iniGetLogLevel(list,section,strLogLevel,global->log_level);
 		ftp->options
@@ -631,6 +640,9 @@ void sbbs_read_ini(
 		SAFECOPY(mail->temp_dir
 			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
 
+		SAFECOPY(mail->login_ars
+			,iniGetString(list, section, strLoginRequirements, global->login_ars, value));
+
 		SAFECOPY(mail->relay_server
 			,iniGetString(list,section,"RelayServer",nulstr,value));
 		SAFECOPY(mail->relay_user
@@ -702,6 +714,9 @@ void sbbs_read_ini(
 		SAFECOPY(services->temp_dir
 			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
 
+		SAFECOPY(services->login_ars
+			,iniGetString(list, section, strLoginRequirements, global->login_ars, value));
+
 		SAFECOPY(services->services_ini
 			,iniGetString(list, section, strIniFileName, "services.ini", value));
 
@@ -750,6 +765,9 @@ void sbbs_read_ini(
 		SAFECOPY(web->temp_dir
 			,iniGetString(list,section,strTempDirectory,global->temp_dir,value));
 
+		SAFECOPY(web->login_ars
+			,iniGetString(list, section, strLoginRequirements, global->login_ars, value));
+
 		SAFECOPY(web->root_dir
 			,iniGetString(list,section,"RootDirectory",WEB_DEFAULT_ROOT_DIR,value));
 		SAFECOPY(web->error_dir
@@ -849,6 +867,7 @@ BOOL sbbs_write_ini(
 		iniSetString(lp,section,strCtrlDirectory,global->ctrl_dir,&style);
 		iniSetString(lp,section,strTempDirectory,global->temp_dir,&style);
 		iniSetString(lp,section,strHostName,global->host_name,&style);
+		iniSetString(lp,section,strLoginRequirements, global->login_ars, &style);
 		iniSetDuration(lp,section,strSemFileCheckFrequency,global->sem_chk_freq,&style);
 		if(global->outgoing4.s_addr != INADDR_ANY)
 			iniSetIpAddress(lp,section,strOutgoing4,global->outgoing4.s_addr,&style);
@@ -950,6 +969,11 @@ BOOL sbbs_write_ini(
 		else if(!iniSetString(lp,section,strTempDirectory,bbs->temp_dir,&style))
 			break;
 
+		if(stricmp(bbs->login_ars, global->login_ars) == 0)
+			iniRemoveKey(lp, section, strLoginRequirements);
+		else if(!iniSetString(lp, section, strLoginRequirements, bbs->login_ars, &style))
+			break;
+
 		iniSetUInteger(lp, section, "DefaultTermWidth", bbs->default_term_width, &style);
 		iniSetUInteger(lp, section, "DefaultTermHeight", bbs->default_term_height, &style);
 
@@ -1052,6 +1076,11 @@ BOOL sbbs_write_ini(
 		else if(!iniSetString(lp,section,strTempDirectory,ftp->temp_dir,&style))
 			break;
 
+		if(stricmp(ftp->login_ars, global->login_ars) == 0)
+			iniRemoveKey(lp, section, strLoginRequirements);
+		else if(!iniSetString(lp, section, strLoginRequirements, ftp->login_ars, &style))
+			break;
+
 		if(!iniSetString(lp,section,"IndexFileName",ftp->index_file_name,&style))
 			break;
 
@@ -1151,6 +1180,11 @@ BOOL sbbs_write_ini(
 		else if(!iniSetString(lp,section,strTempDirectory,mail->temp_dir,&style))
 			break;
 
+		if(stricmp(mail->login_ars, global->login_ars) == 0)
+			iniRemoveKey(lp, section, strLoginRequirements);
+		else if(!iniSetString(lp, section, strLoginRequirements, mail->login_ars, &style))
+			break;
+
 		if(!iniSetString(lp,section,"RelayServer",mail->relay_server,&style))
 			break;
 		if(!iniSetString(lp,section,"RelayUsername",mail->relay_user,&style))
@@ -1245,6 +1279,11 @@ BOOL sbbs_write_ini(
 		else if(!iniSetString(lp,section,strTempDirectory,services->temp_dir,&style))
 			break;
 
+		if(stricmp(services->login_ars, global->login_ars) == 0)
+			iniRemoveKey(lp, section, strLoginRequirements);
+		else if(!iniSetString(lp, section, strLoginRequirements, services->login_ars, &style))
+			break;
+
 		if(!sbbs_set_sound_settings(lp, section, &services->sound, &global->sound, &style))
 			break;
 
@@ -1321,6 +1360,11 @@ BOOL sbbs_write_ini(
 		else if(!iniSetString(lp,section,strTempDirectory,web->temp_dir,&style))
 			break;
 
+		if(stricmp(web->login_ars, global->login_ars) == 0)
+			iniRemoveKey(lp, section, strLoginRequirements);
+		else if(!iniSetString(lp, section, strLoginRequirements, web->login_ars, &style))
+			break;
+
 		if(!iniSetString(lp,section,"RootDirectory",web->root_dir,&style))
 			break;
 		if(!iniSetString(lp,section,"ErrorDirectory",web->error_dir,&style))
diff --git a/src/sbbs3/scfg/scfgsrvr.c b/src/sbbs3/scfg/scfgsrvr.c
index 4f801d351b..e397023bfb 100644
--- a/src/sbbs3/scfg/scfgsrvr.c
+++ b/src/sbbs3/scfg/scfgsrvr.c
@@ -226,6 +226,7 @@ static void global_cfg(void)
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Bind Retry Count", threshold(startup.bind_retry_count));
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Bind Retry Delay", vduration(startup.bind_retry_delay));
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Sem File Check Interval", vduration(startup.sem_chk_freq));
+		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Login Requirements", startup.login_ars);
 		strcpy(opt[i++], "JavaScript Settings...");
 		strcpy(opt[i++], "Failed Login Attempts...");
 		opt[i][0] = '\0';
@@ -235,8 +236,9 @@ static void global_cfg(void)
 			"\n"
 			"Settings that are shared among multiple Synchronet servers.\n"
 			"\n"
-			"These settings can be over-ridden on a per-server basis by editing the\n"
-			"corresponding keys in each `[server]` section of the `ctrl/sbbs.ini` file.\n"
+			"These settings can be over-ridden on a per-server basis via other SCFG\n"
+			"Server Configuration menus or by editing the corresponding keys in each\n"
+			"`[server]` section of the `ctrl/sbbs.ini` file.\n"
 		;
 		switch(uifc.list(WIN_ACT|WIN_RHT|WIN_SAV|WIN_ESC, 0, 0, 0, &cur, &bar
 			,"Global Server Settings",opt)) {
@@ -275,9 +277,12 @@ static void global_cfg(void)
 					startup.sem_chk_freq = (uint16_t)parse_duration(str);
 				break;
 			case 7:
-				js_startup_cfg(&startup.js);
+				getar("Global Server Login", startup.login_ars);
 				break;
 			case 8:
+				js_startup_cfg(&startup.js);
+				break;
+			case 9:
 				login_attempt_cfg(&startup.login_attempt);
 				break;
 			default:
@@ -392,6 +397,7 @@ static void termsrvr_cfg(void)
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Execute QWK-related Events"
 			,startup.options & BBS_OPT_NO_EVENTS ? "N/A" : startup.options & BBS_OPT_NO_QWK_EVENTS ? "No" : "Yes");
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Lookup Client Hostname", startup.options & BBS_OPT_NO_HOST_LOOKUP ? "No" : "Yes");
+		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Login Requirements", startup.login_ars);
 		strcpy(opt[i++], "JavaScript Settings...");
 		strcpy(opt[i++], "Failed Login Attempts...");
 		opt[i][0] = '\0';
@@ -534,9 +540,12 @@ static void termsrvr_cfg(void)
 				startup.options ^= BBS_OPT_NO_HOST_LOOKUP;
 				break;
 			case 28:
-				js_startup_cfg(&startup.js);
+				getar("Terminal Server Login", startup.login_ars);
 				break;
 			case 29:
+				js_startup_cfg(&startup.js);
+				break;
+			case 30:
 				login_attempt_cfg(&startup.login_attempt);
 				break;
 			default:
@@ -647,6 +656,7 @@ static void websrvr_cfg(void)
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "CGI File Extensions", strListCombine(startup.cgi_ext, tmp, sizeof(tmp), ", "));
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "CGI Default Content-Type", startup.default_cgi_content);
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "CGI Max Inactivity", vduration(startup.max_cgi_inactivity));
+		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Login Requirements", startup.login_ars);
 		strcpy(opt[i++], "JavaScript Settings...");
 		strcpy(opt[i++], "Failed Login Attempts...");
 		opt[i][0] = '\0';
@@ -800,9 +810,12 @@ static void websrvr_cfg(void)
 					startup.max_cgi_inactivity = (uint16_t)parse_duration(str);
 				break;
 			case 27:
-				js_startup_cfg(&startup.js);
+				getar("Web Server Login", startup.login_ars);
 				break;
 			case 28:
+				js_startup_cfg(&startup.js);
+				break;
+			case 29:
 				login_attempt_cfg(&startup.login_attempt);
 				break;
 			default:
@@ -898,6 +911,7 @@ static void ftpsrvr_cfg(void)
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Sysop File System Access", startup.options & FTP_OPT_NO_LOCAL_FSYS ? "No" : "Yes");
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Allow Bounce Transfers", startup.options & FTP_OPT_ALLOW_BOUNCE ? "Yes" : "No");
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Lookup Client Hostname", startup.options & BBS_OPT_NO_HOST_LOOKUP ? "No" : "Yes");
+		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Login Requirements", startup.login_ars);
 		strcpy(opt[i++], "Failed Login Attempts...");
 
 		opt[i][0] = '\0';
@@ -1002,6 +1016,9 @@ static void ftpsrvr_cfg(void)
 				startup.options ^= BBS_OPT_NO_HOST_LOOKUP;
 				break;
 			case 15:
+				getar("FTP Server Login", startup.login_ars);
+				break;
+			case 16:
 				login_attempt_cfg(&startup.login_attempt);
 				break;
 			default:
@@ -1243,6 +1260,7 @@ static void mailsrvr_cfg(void)
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Hash DNS-Blacklisted Msgs", startup.options & MAIL_OPT_DNSBL_SPAMHASH ? "Yes" : "No");
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Kill SPAM When Read", startup.options & MAIL_OPT_KILL_READ_SPAM ? "Yes": "No");
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "SendMail Thread...", startup.options & MAIL_OPT_NO_SENDMAIL ? strDisabled : "");
+		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Login Requirements", startup.login_ars);
 		strcpy(opt[i++], "JavaScript Settings...");
 		strcpy(opt[i++], "Failed Login Attempts...");
 		opt[i][0] = '\0';
@@ -1421,9 +1439,12 @@ static void mailsrvr_cfg(void)
 				sendmail_cfg(&startup);
 				break;
 			case 31:
-				js_startup_cfg(&startup.js);
+				getar("Mail Server Login", startup.login_ars);
 				break;
 			case 32:
+				js_startup_cfg(&startup.js);
+				break;
+			case 33:
 				login_attempt_cfg(&startup.login_attempt);
 				break;
 			default:
@@ -1508,6 +1529,7 @@ static void services_cfg(void)
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Network Interfaces", strListCombine(startup.interfaces, tmp, sizeof(tmp), ", "));
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Lookup Client Hostname", startup.options & BBS_OPT_NO_HOST_LOOKUP ? "No" : "Yes");
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Configuration File", startup.services_ini);
+		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Login Requirements", startup.login_ars);
 		strcpy(opt[i++], "JavaScript Settings...");
 		strcpy(opt[i++], "Failed Login Attempts...");
 		opt[i][0] = '\0';
@@ -1542,9 +1564,12 @@ static void services_cfg(void)
 				uifc.input(WIN_MID|WIN_SAV, 0, 0, "Services Configuration File", startup.services_ini, sizeof(startup.services_ini)-1, K_EDIT);
 				break;
 			case 5:
-				js_startup_cfg(&startup.js);
+				getar("Services Login", startup.login_ars);
 				break;
 			case 6:
+				js_startup_cfg(&startup.js);
+				break;
+			case 7:
 				login_attempt_cfg(&startup.login_attempt);
 				break;
 			default:
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index bc573f5c19..c23d18b0db 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -425,6 +425,14 @@ js_login(JSContext *cx, uintN argc, jsval *arglist)
 		JS_RESUMEREQUEST(cx, rc);
 		return(JS_TRUE);
 	}
+	if(!chk_ars(&scfg, startup->login_ars, &client->user, client->client)) {
+		lprintf(LOG_NOTICE,"%04d %s <%s> !Insufficient server access: %s"
+			,client->socket, client->service->protocol, client->user.alias, startup->login_ars);
+		badlogin(client->socket, user, NULL, client->client, &client->addr);
+		JS_RESUMEREQUEST(cx, rc);
+		return(JS_TRUE);
+	}
+
 	JS_RESUMEREQUEST(cx, rc);
 
 	if(argc>2)
diff --git a/src/sbbs3/startup.h b/src/sbbs3/startup.h
index 90bc800e54..28d4ad9e2f 100644
--- a/src/sbbs3/startup.h
+++ b/src/sbbs3/startup.h
@@ -67,6 +67,7 @@ typedef struct {
 	char	ctrl_dir[INI_MAX_VALUE_LEN];
 	char	temp_dir[INI_MAX_VALUE_LEN];
 	char	host_name[INI_MAX_VALUE_LEN];
+	char	login_ars[LEN_ARSTR + 1];
 	uint16_t sem_chk_freq;
 	struct in_addr	outgoing4;
 	struct in6_addr	outgoing6;
@@ -88,6 +89,7 @@ typedef struct {
 	int			type; \
     uint32_t	options; \
 	int			log_level; \
+	char		login_ars[LEN_ARSTR + 1]; \
 	void*	cbdata; \
 	int 	(*lputs)(void*, int level, const char*); \
 	void	(*errormsg)(void*, int level, const char* msg); \
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index ccc0168388..653babeb26 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -2041,6 +2041,13 @@ static BOOL check_ars(http_session_t * session)
 			break;
 	}
 
+	if(!chk_ars(&scfg, startup->login_ars, &thisuser, &session->client)) {
+		lprintf(LOG_NOTICE, "%04d <%s> !Insufficient server access: %s"
+			,session->socket, thisuser.alias, startup->login_ars);
+		badlogin(session->socket, thisuser.alias, NULL, &session->client, &session->addr);
+		return FALSE;
+	}
+
 	if(i != session->last_user_num) {
 		http_logoff(session,session->socket,__LINE__);
 		session->user.number=i;
@@ -5621,6 +5628,13 @@ js_login(JSContext *cx, uintN argc, jsval *arglist)
 		}
 	}
 
+	if(!chk_ars(&scfg, startup->login_ars, &user, &session->client)) {
+		lprintf(LOG_NOTICE, "%04d <%s> !Insufficient server access: %s"
+			,session->socket, user.alias, startup->login_ars);
+		badlogin(session->socket, username, NULL, &session->client, &session->addr);
+		return JS_TRUE;
+	}
+
 	if(argc>2)
 		JS_ValueToBoolean(cx,argv[2],&inc_logons);
 
-- 
GitLab