Package: xinetd
Version: 2.3.14-7
Severity: wishlist
Tags: patch

I wanted options cpm, cph (connections per minute and per hour),
to better protect services like telnet and ssh where the "normal"
turnaround time is several seconds (so cps is useless). The patch
below may implement these. This includes the patch for bug#523956.

Cheers,

Paul Szabo   p...@maths.usyd.edu.au   http://www.maths.usyd.edu.au/u/psz/
School of Mathematics and Statistics   University of Sydney    Australia



--- xinetd-2.3.14/xinetd/access.c.ORIG  2005-10-06 03:15:33.000000000 +1000
+++ xinetd-2.3.14/xinetd/access.c       2009-04-15 12:11:32.000000000 +1000
@@ -62,6 +62,8 @@
    { "libwrap",                  (int) AC_LIBWRAP         },
    { "load",                     (int) AC_LOAD            },
    { "connections per second",   (int) AC_CPS             },
+   { "connections per minute",   (int) AC_CPM             },
+   { "connections per hour",     (int) AC_CPH             },
    { CHAR_NULL,                  1                        },
    { "UNKNOWN",                  0                        }
 } ;
@@ -113,6 +115,54 @@
    xtimer_add(cps_service_restart, SC_TIME_WAIT(scp));
 }
 
+void cpm_service_stop(struct service *sp, const char *reason)
+{
+   struct service_config   *scp = SVC_CONF( sp ) ; 
+   time_t nowtime;
+   time_t waittime;
+
+   svc_deactivate( sp );
+   nowtime = time(NULL);
+   waittime = SC_TIME_CPM_WAIT(scp);
+   /* Check that reenable will not be within this same minute */
+   if( (int)((nowtime+waittime)/60) == SC_TIME_CPM_LIMIT(scp) ) {
+       int x;
+       x = (SC_TIME_CPM_LIMIT(scp) + 1)*60 - nowtime;
+       if( x > waittime ) {    /* Paranoia... */
+               waittime = x;
+       }
+   }
+   msg(LOG_ERR, "service_stop", 
+       "Deactivating service %s due to %s.  Restarting in %d seconds.", 
+       SC_NAME(scp), reason, (int)waittime);
+   SC_TIME_REENABLE(scp) = nowtime + waittime;
+   xtimer_add(cps_service_restart, waittime);
+}
+
+void cph_service_stop(struct service *sp, const char *reason)
+{
+   struct service_config   *scp = SVC_CONF( sp ) ; 
+   time_t nowtime;
+   time_t waittime;
+
+   svc_deactivate( sp );
+   nowtime = time(NULL);
+   waittime = SC_TIME_CPH_WAIT(scp);
+   /* Check that reenable will not be within this same hour */
+   if( (int)((nowtime+waittime)/3600) == SC_TIME_CPH_LIMIT(scp) ) {
+       int x;
+       x = (SC_TIME_CPH_LIMIT(scp) + 1)*3600 - nowtime;
+       if( x > waittime ) {    /* Paranoia... */
+               waittime = x;
+       }
+   }
+   msg(LOG_ERR, "service_stop", 
+       "Deactivating service %s due to %s.  Restarting in %d seconds.", 
+       SC_NAME(scp), reason, (int)waittime);
+   SC_TIME_REENABLE(scp) = nowtime + waittime;
+   xtimer_add(cps_service_restart, waittime);
+}
+
 
 /*
  * Returns OK if the IP address in sinp is acceptable to the access control
@@ -286,18 +336,13 @@
 
    /* CPS handler */
    if( SC_TIME_CONN_MAX(scp) != 0 ) {
-      int time_diff;
       nowtime = time(NULL);
-      time_diff = nowtime - SC_TIME_LIMIT(scp) ;
 
-      if( SC_TIME_CONN(scp) == 0 ) {
+      if( nowtime == SC_TIME_LIMIT(scp) && SC_TIME_CONN(scp) > 0 ) {
+         /* Count connections during this very same second */
          SC_TIME_CONN(scp)++;
-         SC_TIME_LIMIT(scp) = nowtime;
-      } else if( time_diff < SC_TIME_CONN_MAX(scp) ) {
-         SC_TIME_CONN(scp)++;
-         if( time_diff == 0 ) time_diff = 1;
-         if( SC_TIME_CONN(scp)/time_diff > SC_TIME_CONN_MAX(scp) ) {
-            cps_service_stop(sp, "excessive incoming connections");
+         if( SC_TIME_CONN(scp) > SC_TIME_CONN_MAX(scp) ) {
+            cps_service_stop(sp, "excessive incoming connections per second");
             return(AC_CPS);
          }
       } else {
@@ -306,6 +351,38 @@
       }
    }
 
+   /* CPM handler */
+   if( SC_TIME_CPM_CONN_MAX(scp) != 0 ) {
+      nowtime = (int)(time(NULL)/60);
+      if( nowtime == SC_TIME_CPM_LIMIT(scp) && SC_TIME_CPM_CONN(scp) > 0 ) {
+         /* Count connections during this very same minute */
+         SC_TIME_CPM_CONN(scp)++;
+         if( SC_TIME_CPM_CONN(scp) > SC_TIME_CPM_CONN_MAX(scp) ) {
+            cpm_service_stop(sp, "excessive incoming connections per minute");
+            return(AC_CPM);
+         }
+      } else {
+         SC_TIME_CPM_LIMIT(scp) = nowtime;
+         SC_TIME_CPM_CONN(scp) = 1;
+      }
+   }
+
+   /* CPH handler */
+   if( SC_TIME_CPH_CONN_MAX(scp) != 0 ) {
+      nowtime = (int)(time(NULL)/3600);
+      if( nowtime == SC_TIME_CPH_LIMIT(scp) && SC_TIME_CPH_CONN(scp) > 0 ) {
+         /* Count connections during this very same hour */
+         SC_TIME_CPH_CONN(scp)++;
+         if( SC_TIME_CPH_CONN(scp) > SC_TIME_CPH_CONN_MAX(scp) ) {
+            cph_service_stop(sp, "excessive incoming connections per hour");
+            return(AC_CPH);
+         }
+      } else {
+         SC_TIME_CPH_LIMIT(scp) = nowtime;
+         SC_TIME_CPH_CONN(scp) = 1;
+      }
+   }
+
 #ifdef HAVE_LOADAVG
    if ( SC_MAX_LOAD(scp) != 0 ) {
       if ( xgetloadavg() >= SC_MAX_LOAD(scp) ) {
--- xinetd-2.3.14/xinetd/access.h.ORIG  2004-01-03 08:07:42.000000000 +1100
+++ xinetd-2.3.14/xinetd/access.h       2009-04-15 12:11:30.000000000 +1000
@@ -39,7 +39,9 @@
       AC_PROCESS_LIMIT,    /* total process limit would be exceeded        */
       AC_LIBWRAP,
       AC_LOAD,
-      AC_CPS
+      AC_CPS,
+      AC_CPM,
+      AC_CPH
    } access_e ;
 
 
@@ -48,6 +50,8 @@
 
 extern const struct name_value access_code_names[];
 void cps_service_stop(struct service *sp, const char *reason);
+void cpm_service_stop(struct service *sp, const char *reason);
+void cph_service_stop(struct service *sp, const char *reason);
 access_e access_control(struct service *sp,
        const connection_s *cp,const mask_t *check_mask);
 access_e parent_access_control(struct service *sp,const connection_s *cp);
--- xinetd-2.3.14/xinetd/attr.h.ORIG    2005-10-06 03:15:33.000000000 +1000
+++ xinetd-2.3.14/xinetd/attr.h 2009-04-15 12:11:29.000000000 +1000
@@ -48,19 +48,21 @@
 #define A_BANNER_FAIL      30
 #define A_MAX_LOAD         31
 #define A_CPS              32
-#define A_SVCDISABLE       33
-#define A_RLIMIT_AS        34
-#define A_RLIMIT_CPU       35
-#define A_RLIMIT_DATA      36
-#define A_RLIMIT_RSS       37
-#define A_RLIMIT_STACK     38
-#define A_V6ONLY           39
-#define A_DENY_TIME        40
-#define A_UMASK            41
-#define A_ENABLED          42
-#define A_DISABLED         43
-#define A_MDNS             44
-#define A_LIBWRAP          45
+#define A_CPM              33
+#define A_CPH              34
+#define A_SVCDISABLE       35
+#define A_RLIMIT_AS        36
+#define A_RLIMIT_CPU       37
+#define A_RLIMIT_DATA      38
+#define A_RLIMIT_RSS       39
+#define A_RLIMIT_STACK     40
+#define A_V6ONLY           41
+#define A_DENY_TIME        42
+#define A_UMASK            43
+#define A_ENABLED          44
+#define A_DISABLED         45
+#define A_MDNS             46
+#define A_LIBWRAP          47
 
 /*
  * SERVICE_ATTRIBUTES is the number of service attributes and also
--- xinetd-2.3.14/xinetd/confparse.c.ORIG       2009-04-14 09:17:39.000000000 
+1000
+++ xinetd-2.3.14/xinetd/confparse.c    2009-04-15 12:14:16.000000000 +1000
@@ -191,6 +191,20 @@
       SC_TIME_REENABLE(scp) = 0;
    }
 
+   /* Would not these be zero anyway? */
+   if ( ! SC_SPECIFIED( scp, A_CPM ) ) 
+   {
+      SC_TIME_CPM_CONN_MAX(scp) = 0;
+      SC_TIME_CPM_WAIT(scp) = 0;
+   }
+
+   /* Would not these be zero anyway? */
+   if ( ! SC_SPECIFIED( scp, A_CPH ) ) 
+   {
+      SC_TIME_CPH_CONN_MAX(scp) = 0;
+      SC_TIME_CPH_WAIT(scp) = 0;
+   }
+
 #ifdef HAVE_LOADAVG
    if ( ! SC_SPECIFIED( scp, A_MAX_LOAD ) ) {
       SC_MAX_LOAD(scp) = SC_SPECIFIED( def, A_MAX_LOAD ) ? SC_MAX_LOAD(def) : 
0;
--- xinetd-2.3.14/xinetd/parse.c.ORIG   2005-10-06 03:15:33.000000000 +1000
+++ xinetd-2.3.14/xinetd/parse.c        2009-04-15 12:11:26.000000000 +1000
@@ -79,6 +79,8 @@
    { "banner_success", A_BANNER_SUCCESS, 1,  banner_success_parser  },
    { "banner_fail",    A_BANNER_FAIL,    1,  banner_fail_parser     },
    { "cps",            A_CPS,            2,  cps_parser             },
+   { "cpm",            A_CPM,            2,  cpm_parser             },
+   { "cph",            A_CPH,            2,  cph_parser             },
    { "disable",        A_SVCDISABLE,     1,  svcdisable_parser      },
 #ifdef HAVE_LOADAVG
    { "max_load",       A_MAX_LOAD,       1,  max_load_parser        },
--- xinetd-2.3.14/xinetd/parsers.c.ORIG 2005-10-06 07:45:41.000000000 +1000
+++ xinetd-2.3.14/xinetd/parsers.c      2009-04-15 12:11:25.000000000 +1000
@@ -580,6 +580,80 @@
    return(OK);
 }
 
+status_e cpm_parser( pset_h values, 
+                     struct service_config *scp, 
+                     enum assign_op op )
+{
+   char *cpm = (char *) pset_pointer(values, 0);
+   char *waittime = (char *) pset_pointer(values, 1);
+   unsigned int waittime_int, conn_max;
+
+   if( cpm == NULL || waittime == NULL ) {
+      parsemsg(LOG_ERR, "cpm_parser", "NULL options specified in cpm");
+      return( FAILED );
+   }
+   if( parse_ubase10(cpm, &conn_max) ) {
+      parsemsg(LOG_ERR, "cpm_parser", "cpm argument not a number");
+      SC_TIME_CPM_CONN_MAX(scp) = 0;
+      SC_TIME_CPM_WAIT(scp) = 0;
+      return( FAILED );
+   }
+   if( parse_ubase10(waittime, &waittime_int) ) {
+      parsemsg(LOG_ERR, "cpm_parser", "cpm time argument not a number");
+      SC_TIME_CPM_CONN_MAX(scp) = 0;
+      SC_TIME_CPM_WAIT(scp) = 0;
+      return( FAILED );
+   }
+   SC_TIME_CPM_WAIT(scp) = waittime_int;
+   SC_TIME_CPM_CONN_MAX(scp) = conn_max;
+
+   if( SC_TIME_CPM_CONN_MAX(scp) < 0 || SC_TIME_CPM_WAIT(scp) < 0 ) {
+      parsemsg(LOG_ERR, "cpm_parser", "cpm arguments invalid");
+      SC_TIME_CPM_CONN_MAX(scp) = 0;
+      SC_TIME_CPM_WAIT(scp) = 0;
+      return( FAILED );
+   }
+
+   return(OK);
+}
+
+status_e cph_parser( pset_h values, 
+                     struct service_config *scp, 
+                     enum assign_op op )
+{
+   char *cph = (char *) pset_pointer(values, 0);
+   char *waittime = (char *) pset_pointer(values, 1);
+   unsigned int waittime_int, conn_max;
+
+   if( cph == NULL || waittime == NULL ) {
+      parsemsg(LOG_ERR, "cph_parser", "NULL options specified in cph");
+      return( FAILED );
+   }
+   if( parse_ubase10(cph, &conn_max) ) {
+      parsemsg(LOG_ERR, "cph_parser", "cph argument not a number");
+      SC_TIME_CPH_CONN_MAX(scp) = 0;
+      SC_TIME_CPH_WAIT(scp) = 0;
+      return( FAILED );
+   }
+   if( parse_ubase10(waittime, &waittime_int) ) {
+      parsemsg(LOG_ERR, "cph_parser", "cph time argument not a number");
+      SC_TIME_CPH_CONN_MAX(scp) = 0;
+      SC_TIME_CPH_WAIT(scp) = 0;
+      return( FAILED );
+   }
+   SC_TIME_CPH_WAIT(scp) = waittime_int;
+   SC_TIME_CPH_CONN_MAX(scp) = conn_max;
+
+   if( SC_TIME_CPH_CONN_MAX(scp) < 0 || SC_TIME_CPH_WAIT(scp) < 0 ) {
+      parsemsg(LOG_ERR, "cph_parser", "cph arguments invalid");
+      SC_TIME_CPH_CONN_MAX(scp) = 0;
+      SC_TIME_CPH_WAIT(scp) = 0;
+      return( FAILED );
+   }
+
+   return(OK);
+}
+
 status_e id_parser( pset_h values, 
                     struct service_config *scp, 
                     enum assign_op op )
--- xinetd-2.3.14/xinetd/parsers.h.ORIG 2005-10-06 03:15:33.000000000 +1000
+++ xinetd-2.3.14/xinetd/parsers.h      2009-04-15 12:11:24.000000000 +1000
@@ -43,6 +43,8 @@
 status_e banner_success_parser(pset_h, struct service_config *, enum 
assign_op) ;
 status_e banner_fail_parser(pset_h, struct service_config *, enum assign_op) ;
 status_e cps_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e cpm_parser(pset_h, struct service_config *, enum assign_op) ;
+status_e cph_parser(pset_h, struct service_config *, enum assign_op) ;
 status_e enabled_parser(pset_h, struct service_config *, enum assign_op) ;
 status_e svcdisable_parser(pset_h, struct service_config *, enum assign_op);
 #ifdef HAVE_LOADAVG
--- xinetd-2.3.14/xinetd/sconf.c.ORIG   2005-10-06 03:15:33.000000000 +1000
+++ xinetd-2.3.14/xinetd/sconf.c        2009-04-15 12:11:22.000000000 +1000
@@ -314,6 +314,14 @@
       tabprint( fd, tab_level+1, "CPS = max conn:%lu wait:%lu\n", 
          SC_TIME_CONN_MAX(scp), SC_TIME_WAIT(scp) );
 
+   if ( SC_SPECIFIED( scp, A_CPM ) )
+      tabprint( fd, tab_level+1, "CPM = max conn:%lu wait:%lu\n", 
+         SC_TIME_CPM_CONN_MAX(scp), SC_TIME_CPM_WAIT(scp) );
+
+   if ( SC_SPECIFIED( scp, A_CPH ) )
+      tabprint( fd, tab_level+1, "CPH = max conn:%lu wait:%lu\n", 
+         SC_TIME_CPH_CONN_MAX(scp), SC_TIME_CPH_WAIT(scp) );
+
    if ( SC_SPECIFIED( scp, A_PER_SOURCE ) )
       tabprint( fd, tab_level+1, "PER_SOURCE = %d\n", 
          SC_PER_SOURCE(scp) );
--- xinetd-2.3.14/xinetd/sconf.h.ORIG   2005-10-06 03:15:33.000000000 +1000
+++ xinetd-2.3.14/xinetd/sconf.h        2009-04-15 12:11:20.000000000 +1000
@@ -139,6 +139,14 @@
    time_t               sc_time_conn_max ;
    time_t               sc_time_wait ;
    time_t               sc_time_reenable ;
+   time_t               sc_time_cpm_limit ;
+   time_t               sc_time_cpm_conn ;
+   time_t               sc_time_cpm_conn_max ;
+   time_t               sc_time_cpm_wait ;
+   time_t               sc_time_cph_limit ;
+   time_t               sc_time_cph_conn ;
+   time_t               sc_time_cph_conn_max ;
+   time_t               sc_time_cph_wait ;
    rlim_t               sc_rlim_as;
    rlim_t               sc_rlim_cpu;
    rlim_t               sc_rlim_data;
@@ -212,6 +220,15 @@
 #define SC_TIME_CONN_MAX( scp )  (scp)->sc_time_conn_max
 #define SC_TIME_WAIT( scp )      (scp)->sc_time_wait
 #define SC_TIME_REENABLE( scp )  (scp)->sc_time_reenable
+#define SC_TIME_CPM_LIMIT( scp ) (scp)->sc_time_cpm_limit
+#define SC_TIME_CPM_CONN( scp )  (scp)->sc_time_cpm_conn
+#define SC_TIME_CPM_CONN_MAX( scp )  (scp)->sc_time_cpm_conn_max
+#define SC_TIME_CPM_WAIT( scp )  (scp)->sc_time_cpm_wait
+#define SC_TIME_CPH_LIMIT( scp ) (scp)->sc_time_cph_limit
+#define SC_TIME_CPH_CONN( scp )  (scp)->sc_time_cph_conn
+#define SC_TIME_CPH_CONN_MAX( scp )  (scp)->sc_time_cph_conn_max
+#define SC_TIME_CPH_WAIT( scp )  (scp)->sc_time_cph_wait
+
 #define SC_UMASK( scp )          (scp)->sc_umask
 #define SC_DENY_TIME( scp )      (scp)->sc_deny_time
 #define SC_MDNS_NAME( scp )      (scp)->sc_mdns_name
--- xinetd-2.3.14/xinetd/xinetd.conf.man.ORIG   2009-04-14 09:17:39.000000000 
+1000
+++ xinetd-2.3.14/xinetd/xinetd.conf.man        2009-04-15 12:14:16.000000000 
+1000
@@ -490,13 +490,41 @@
 also be specified in the defaults section.
 .TP
 .B cps
-Limits the rate of incoming connections.  Takes two arguments.  
+Limits the rate of incoming connections per second.  Takes two arguments.  
 The first argument is the number of connections per second to handle.
 If the rate of incoming connections is higher than this, the service
 will be temporarily disabled.  The second argument is the number of
 seconds to wait before re-enabling the service after it has been disabled.
-The default for this setting is 50 incoming connections and the interval
-is 10 seconds.
+Connections are counted within each wall-clock second, from any
+sources.  Service is disabled for all sources.
+The default for this setting is 50 incoming connections per second and
+the interval is 10 seconds.
+.TP
+.B cpm
+Limits the rate of incoming connections per minute.  Takes two arguments.
+The first argument is the number of connections per minute to handle.
+If the rate of incoming connections is higher than this, the service
+will be temporarily disabled.  The second argument is the number of
+seconds to wait before re-enabling the service after it has been
+disabled.
+Connections are counted within each wall-clock minute, from any
+sources.  Time to disable is given in seconds, and will be increased
+if would re-enable within the same wall-clock minute; service
+is disabled for all sources.
+There is no default cpm limit (i.e. is unlimited).
+.TP
+.B cph
+Limits the rate of incoming connections per hour.  Takes two arguments.
+The first argument is the number of connections per hour to handle.
+If the rate of incoming connections is higher than this, the service
+will be temporarily disabled.  The second argument is the number of
+seconds to wait before re-enabling the service after it has been
+disabled.
+Connections are counted within each wall-clock hour, from any
+sources.  Time to disable is given in seconds, and will be increased
+if would re-enable within the same wall-clock hour; service
+is disabled for all sources.
+There is no default cph limit (i.e. is unlimited).
 .TP
 .B max_load
 Takes a floating point value as the load at which the service will 



-- System Information:
Debian Release: 4.0
  APT prefers oldstable
  APT policy: (500, 'oldstable')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.24-pk03.03-svr
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to