repo: ngircd
action: commit
revision: 
path_from: 
revision_from: 456eea6f1896528dad344ed2c254fd07bdc3a4b1:
path_to: 
revision_to: 
git.thebackupbox.net
ngircd
git clone git://git.thebackupbox.net/ngircd
commit 456eea6f1896528dad344ed2c254fd07bdc3a4b1
Author: Alexander Barton 
Date:   Wed Nov 28 14:13:09 2018 +0100

    Implement new configuration option "MaxPenaltyTime" (#251)

    This option configures the maximum penalty time increase in seconds, per
    penalty event. Set to -1 for no limit (the default), 0 to disable
    penalties altogether. ngIRCd doesn't use penalty increases higher than 2
    seconds during normal operation, so values higher than 1 rarely make
    sense.

    Disabling (or reducing) penalties can greatly speed up "make check" runs
    for example, see below, but are mostly a debugging feature and normally
    not meant to be used on production systems!

    Some example timings running "make check" from my macOS workstation:

    - MaxPenaltyTime not set: 4:41,79s
    - "MaxPenaltyTime = 1":   3:14,71s
    - "MaxPenaltyTime = 0":     25,46s

    Closes #249.

diff --git a/doc/sample-ngircd.conf.tmpl b/doc/sample-ngircd.conf.tmpl
index 3f9ba0884dee843eb494a59c98f397e6bb26f5cb..
index ..bd2d4080117b5efa49338c9e69554998cb1ed5b2 100644
--- a/doc/sample-ngircd.conf.tmpl
+++ b/doc/sample-ngircd.conf.tmpl
@@ -117,6 +117,12 @@
 	# maximum nickname length!
 	;MaxNickLength = 9

+	# Maximum penalty time increase in seconds, per penalty event. Set to -1
+	# for no limit (the default), 0 to disable penalties altogether. The
+	# daemon doesn't use penalty increases higher than 2 seconds during
+	# normal operation, so values greater than 1 rarely make sense.
+	;MaxPenaltyTime = -1
+
 	# Maximum number of channels returned in response to a /list
 	# command (0: unlimited):
 	;MaxListSize = 100
diff --git a/man/ngircd.conf.5.tmpl b/man/ngircd.conf.5.tmpl
index b8d4ddd956048c759a6b40af8d43167c323df6a6..
index ..0c0cd3494c84c9686e5f4754e994c5052472e9d8 100644
--- a/man/ngircd.conf.5.tmpl
+++ b/man/ngircd.conf.5.tmpl
@@ -201,6 +201,12 @@ Maximum length of an user nickname (Default: 9, as in RFC 2812). Please
 note that all servers in an IRC network MUST use the same maximum nickname
 length!
 .TP
+\fBMaxPenaltyTime\fR (number)
+Maximum penalty time increase in seconds, per penalty event. Set to -1 for no
+limit (the default), 0 to disable penalties altogether. ngIRCd doesn't use
+penalty increases higher than 2 seconds during normal operation, so values
+greater than 1 rarely make sense.
+.TP
 \fBMaxListSize\fR (number)
 Maximum number of channels returned in response to a LIST command. Default: 100.
 .TP
diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c
index 3a796f038c00ead7b6a650d320a90a57f875e7f1..
index ..3f2e01546dc69779d4cf8d22b748a9d45e0993ba 100644
--- a/src/ngircd/conf.c
+++ b/src/ngircd/conf.c
@@ -388,6 +388,7 @@ Conf_Test( void )
 	printf("  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP);
 	printf("  MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
 	printf("  MaxNickLength = %u\n", Conf_MaxNickLength - 1);
+	printf("  MaxPenaltyTime = %ld\n", Conf_MaxPenaltyTime);
 	printf("  MaxListSize = %d\n", Conf_MaxListSize);
 	printf("  PingTimeout = %d\n", Conf_PingTimeout);
 	printf("  PongTimeout = %d\n", Conf_PongTimeout);
@@ -765,6 +766,7 @@ Set_Defaults(bool InitServers)
 	Conf_MaxConnectionsIP = 5;
 	Conf_MaxJoins = 10;
 	Conf_MaxNickLength = CLIENT_NICK_LEN_DEFAULT;
+	Conf_MaxPenaltyTime = -1;
 	Conf_MaxListSize = 100;
 	Conf_PingTimeout = 120;
 	Conf_PongTimeout = 20;
@@ -1641,6 +1643,12 @@ Handle_LIMITS(const char *File, int Line, char *Var, char *Arg)
 			Config_Error_NaN(File, Line, Var);
 		return;
 	}
+	if (strcasecmp(Var, "MaxPenaltyTime") == 0) {
+		Conf_MaxPenaltyTime = atol(Arg);
+		if (Conf_MaxPenaltyTime < -1)
+			Conf_MaxPenaltyTime = -1;	/* "unlimited" */
+		return;
+	}
 	if (strcasecmp(Var, "PingTimeout") == 0) {
 		Conf_PingTimeout = atoi(Arg);
 		if (Conf_PingTimeout < 5) {
@@ -2281,6 +2289,11 @@ Validate_Config(bool Configtest, bool Rehash)
 			     "This server uses PAM, \"Password\" in [Global] section will be ignored!");
 #endif

+	if (Conf_MaxPenaltyTime != -1)
+		Config_Error(LOG_WARNING,
+			     "Maximum penalty increase ('MaxPenaltyTime') is set to %ld, this is not recommended!",
+			     Conf_MaxPenaltyTime);
+
 #ifdef DEBUG
 	servers = servers_once = 0;
 	for (i = 0; i < MAX_SERVERS; i++) {
diff --git a/src/ngircd/conf.h b/src/ngircd/conf.h
index 7203b86a3b630ce559a6693d7af26234cd1fa84d..
index ..4b73b547f8759e5eefc80e4a8e5de236ba3bcc9d 100644
--- a/src/ngircd/conf.h
+++ b/src/ngircd/conf.h
@@ -239,6 +239,9 @@ GLOBAL unsigned int Conf_MaxNickLength;
 /** Maximum number of channels returned to /list */
 GLOBAL int Conf_MaxListSize;

+/** Maximium seconds to add per "penalty". -1 = unlimited. */
+GLOBAL time_t Conf_MaxPenaltyTime;
+
 #ifndef STRICT_RFC

 /** Require "AUTH PING-PONG" on login */
diff --git a/src/ngircd/conn-func.c b/src/ngircd/conn-func.c
index ed58f7280254bfad8b647fe57c2383253cbcd3c4..
index ..72d38b8621ff559c9c93903989e7c091b018be79 100644
--- a/src/ngircd/conn-func.c
+++ b/src/ngircd/conn-func.c
@@ -26,6 +26,7 @@
 #endif
 #include "conn.h"

+#include "conf.h"
 #include "conn-func.h"

 /**
@@ -97,6 +98,14 @@ Conn_SetPenalty(CONN_ID Idx, time_t Seconds)
 	assert(Idx > NONE);
 	assert(Seconds >= 0);

+	/* Limit new penalty to maximum configured, when less than 10 seconds. *
+	   The latter is used to limit brute force attacks, therefore we don't *
+	   want to limit that! */
+	if (Conf_MaxPenaltyTime >= 0
+	    && Seconds > Conf_MaxPenaltyTime
+	    && Seconds < 10)
+		Seconds = Conf_MaxPenaltyTime;
+
 	t = time(NULL);
 	if (My_Connections[Idx].delaytime < t)
 		My_Connections[Idx].delaytime = t;
diff --git a/src/testsuite/ngircd-test1.conf b/src/testsuite/ngircd-test1.conf
index 5cb7db7c7ad45dab1c4fc28e80e8527eb1872e8b..
index ..ab240a7c4aa285fb68c55923fb49458031207504 100644
--- a/src/testsuite/ngircd-test1.conf
+++ b/src/testsuite/ngircd-test1.conf
@@ -12,6 +12,7 @@
 [Limits]
 	MaxConnectionsIP = 0
 	MaxJoins = 4
+	MaxPenaltyTime = 1

 [Options]
 	OperCanUseMode = yes
diff --git a/src/testsuite/ngircd-test2.conf b/src/testsuite/ngircd-test2.conf
index 0d24c4a45abf2f3f51863df0a8570968b6024c6c..
index ..40d881d483a84a0c726c3d27f689530c561cb37b 100644
--- a/src/testsuite/ngircd-test2.conf
+++ b/src/testsuite/ngircd-test2.conf
@@ -12,6 +12,7 @@
 [Limits]
 	MaxConnectionsIP = 0
 	MaxJoins = 4
+	MaxPenaltyTime = 1

 [Options]
 	OperCanUseMode = yes

-----END OF PAGE-----