Implement new configuration option "MaxPenaltyTime" (#251)
authorAlexander Barton <alex@barton.de>
Wed, 28 Nov 2018 13:13:09 +0000 (14:13 +0100)
committerGitHub <noreply@github.com>
Wed, 28 Nov 2018 13:13:09 +0000 (14:13 +0100)
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.

doc/sample-ngircd.conf.tmpl
man/ngircd.conf.5.tmpl
src/ngircd/conf.c
src/ngircd/conf.h
src/ngircd/conn-func.c
src/testsuite/ngircd-test1.conf
src/testsuite/ngircd-test2.conf

index 3f9ba08..bd2d408 100644 (file)
        # 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
index b8d4ddd..0c0cd34 100644 (file)
@@ -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
index 3a796f0..3f2e015 100644 (file)
@@ -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++) {
index 7203b86..4b73b54 100644 (file)
@@ -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 */
index ed58f72..72d38b8 100644 (file)
@@ -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;
index 5cb7db7..ab240a7 100644 (file)
@@ -12,6 +12,7 @@
 [Limits]
        MaxConnectionsIP = 0
        MaxJoins = 4
+       MaxPenaltyTime = 1
 
 [Options]
        OperCanUseMode = yes
index 0d24c4a..40d881d 100644 (file)
@@ -12,6 +12,7 @@
 [Limits]
        MaxConnectionsIP = 0
        MaxJoins = 4
+       MaxPenaltyTime = 1
 
 [Options]
        OperCanUseMode = yes