commit 7b6e26628a884a768863c753a3fdff00116c0eed from: Alexander Barton date: Wed Nov 05 23:24:48 2003 UTC Fixed and enhanced penalty handling; changed internal time resoluiton of the server to one second. Code cleanup. commit - 2981fe9eb707b340107b5131018805ee2a469950 commit + 7b6e26628a884a768863c753a3fdff00116c0eed blob - 7e173e3c56bb12f1e43a0b492568d055a6e9b450 blob + a59923c579cff259a958b2f08f569cca1a856cff --- ChangeLog +++ ChangeLog @@ -12,6 +12,9 @@ ngIRCd CVS-HEAD + - Fixed and enhanced the "penalty handling" of the server: commands that + require more resources block the client for a short time. + - Changed the internal time resolution to one second. - New configuration variable "MaxConnectionsIP" to limit the number of simultaneous connections from a single IP that the server will accept. This configuration options lowers the risk of denial of service attacks @@ -472,4 +475,4 @@ ngIRCd 0.0.1, 31.12.2001 -- -$Id: ChangeLog,v 1.214 2003/11/05 21:41:01 alex Exp $ +$Id: ChangeLog,v 1.215 2003/11/05 23:24:48 alex Exp $ blob - 172784b660f4a650cd731b49e8ad9bcfa0e52fb3 blob + 591804b1910aafa565ade56f2a09e9b2ba47ad97 --- src/ngircd/conn-func.c +++ src/ngircd/conn-func.c @@ -16,10 +16,11 @@ #include "portab.h" -static char UNUSED id[] = "$Id: conn-func.c,v 1.1 2002/12/30 17:14:28 alex Exp $"; +static char UNUSED id[] = "$Id: conn-func.c,v 1.2 2003/11/05 23:24:48 alex Exp $"; #include "imp.h" #include +#include #include "conn.h" @@ -69,7 +70,7 @@ Conn_SetPenalty( CONN_ID Idx, time_t Seconds ) assert( Idx > NONE ); assert( Seconds >= 0 ); - + t = time( NULL ) + Seconds; if( t > My_Connections[Idx].delaytime ) My_Connections[Idx].delaytime = t; } /* Conn_SetPenalty */ blob - 2c65f26e1f52204cffd87e16b60407d482326c6c blob + 317171ea1ddb3e833f592238beb9fc0ac321c0f0 --- src/ngircd/conn.c +++ src/ngircd/conn.c @@ -16,7 +16,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: conn.c,v 1.126 2003/11/05 21:41:02 alex Exp $"; +static char UNUSED id[] = "$Id: conn.c,v 1.127 2003/11/05 23:24:48 alex Exp $"; #include "imp.h" #include @@ -120,7 +120,9 @@ Conn_Init( VOID ) Log( LOG_EMERG, "Can't allocate memory! [Conn_Init]" ); exit( 1 ); } +#ifdef DEBUG Log( LOG_DEBUG, "Allocated connection pool for %d items (%ld bytes).", Pool_Size, sizeof( CONNECTION ) * Pool_Size ); +#endif /* zu Beginn haben wir keine Verbindungen */ FD_ZERO( &My_Listeners ); @@ -147,7 +149,9 @@ Conn_Exit( VOID ) CONN_ID idx; INT i; +#ifdef DEBUG Log( LOG_DEBUG, "Shutting down all connections ..." ); +#endif #ifdef RENDEZVOUS Rendezvous_UnregisterListeners( ); @@ -165,12 +169,16 @@ Conn_Exit( VOID ) if( FD_ISSET( i, &My_Listeners )) { close( i ); +#ifdef DEBUG Log( LOG_DEBUG, "Listening socket %d closed.", i ); +#endif } else if( FD_ISSET( i, &My_Connects )) { close( i ); +#ifdef DEBUG Log( LOG_DEBUG, "Connection %d closed during creation (socket %d).", idx, i ); +#endif } else if( idx < Pool_Size ) { @@ -225,7 +233,9 @@ Conn_ExitListeners( VOID ) if( FD_ISSET( i, &My_Sockets ) && FD_ISSET( i, &My_Listeners )) { close( i ); +#ifdef DEBUG Log( LOG_DEBUG, "Listening socket %d closed.", i ); +#endif } } } /* Conn_ExitListeners */ @@ -368,10 +378,13 @@ Conn_Handler( VOID ) Check_Servers( ); Check_Connections( ); + t = time( NULL ); + /* noch volle Lese-Buffer suchen */ for( i = 0; i < Pool_Size; i++ ) { - if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].rdatalen > 0 )) + if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].rdatalen > 0 ) && + ( My_Connections[i].delaytime < t )) { /* Kann aus dem Buffer noch ein Befehl extrahiert werden? */ if( Handle_Buffer( i )) timeout = FALSE; @@ -400,7 +413,6 @@ Conn_Handler( VOID ) } /* von welchen Sockets koennte gelesen werden? */ - t = time( NULL ); read_sockets = My_Sockets; for( i = 0; i < Pool_Size; i++ ) { @@ -431,7 +443,7 @@ Conn_Handler( VOID ) /* Timeout initialisieren */ tv.tv_usec = 0; - if( timeout ) tv.tv_sec = TIME_RES; + if( timeout ) tv.tv_sec = 1; else tv.tv_sec = 0; /* Auf Aktivitaet warten */ @@ -545,7 +557,9 @@ Conn_Write( CONN_ID Idx, CHAR *Data, INT Len ) * In diesem Fall wird hier einfach ein Fehler geliefert. */ if( My_Connections[Idx].sock <= NONE ) { +#ifdef DEBUG Log( LOG_DEBUG, "Skipped write on closed socket (connection %d).", Idx ); +#endif return FALSE; } @@ -854,7 +868,9 @@ Handle_Write( CONN_ID Idx ) return FALSE; } +#ifdef DEBUG Log( LOG_DEBUG, "Connection %d with \"%s:%d\" established, now sendig PASS and SERVER ...", Idx, My_Connections[Idx].host, Conf_Server[Conf_GetServer( Idx )].port ); +#endif /* PASS und SERVER verschicken */ Conn_WriteStr( Idx, "PASS %s %s", Conf_Server[Conf_GetServer( Idx )].pwd_out, NGIRCd_ProtoID ); @@ -995,9 +1011,13 @@ New_Connection( INT Sock ) /* Struktur umkopieren ... */ memcpy( ptr, My_Connections, sizeof( CONNECTION ) * Pool_Size ); +#ifdef DEBUG Log( LOG_DEBUG, "Allocated new connection pool for %ld items (%ld bytes). [malloc()/memcpy()]", new_size, sizeof( CONNECTION ) * new_size ); +#endif } +#ifdef DEBUG else Log( LOG_DEBUG, "Allocated new connection pool for %ld items (%ld bytes). [realloc()]", new_size, sizeof( CONNECTION ) * new_size ); +#endif /* Adjust pointer to new block */ My_Connections = ptr; @@ -1061,7 +1081,9 @@ Socket2Index( INT Sock ) { /* die Connection wurde vermutlich (wegen eines * Fehlers) bereits wieder abgebaut ... */ +#ifdef DEBUG Log( LOG_DEBUG, "Socket2Index: can't get connection for socket %d!", Sock ); +#endif return NONE; } else return idx; @@ -1164,6 +1186,9 @@ Handle_Buffer( CONN_ID Idx ) result = FALSE; do { + /* Check penalty */ + if( My_Connections[Idx].delaytime > time( NULL )) return result; + #ifdef USE_ZLIB /* ggf. noch unkomprimiete Daten weiter entpacken */ if( My_Connections[Idx].options & CONN_ZIP ) @@ -1243,7 +1268,9 @@ Handle_Buffer( CONN_ID Idx ) memcpy( My_Connections[Idx].zip.rbuf, My_Connections[Idx].rbuf, My_Connections[Idx].rdatalen ); My_Connections[Idx].zip.rdatalen = My_Connections[Idx].rdatalen; My_Connections[Idx].rdatalen = 0; +#ifdef DEBUG Log( LOG_DEBUG, "Moved already received data (%d bytes) to uncompression buffer.", My_Connections[Idx].zip.rdatalen ); +#endif } } #endif @@ -1280,14 +1307,18 @@ Check_Connections( VOID ) if( My_Connections[i].lastping < time( NULL ) - Conf_PongTimeout ) { /* Timeout */ +#ifdef DEBUG Log( LOG_DEBUG, "Connection %d: Ping timeout: %d seconds.", i, Conf_PongTimeout ); +#endif Conn_Close( i, NULL, "Ping timeout", TRUE ); } } else if( My_Connections[i].lastdata < time( NULL ) - Conf_PingTimeout ) { /* es muss ein PING gesendet werden */ +#ifdef DEBUG Log( LOG_DEBUG, "Connection %d: sending PING ...", i ); +#endif My_Connections[i].lastping = time( NULL ); Conn_WriteStr( i, "PING :%s", Client_ID( Client_ThisServer( ))); } @@ -1298,7 +1329,9 @@ Check_Connections( VOID ) if( My_Connections[i].lastdata < time( NULL ) - Conf_PingTimeout ) { /* Timeout */ +#ifdef DEBUG Log( LOG_DEBUG, "Connection %d timed out ...", i ); +#endif Conn_Close( i, NULL, "Timeout", FALSE ); } } @@ -1354,7 +1387,9 @@ Check_Servers( VOID ) Log( LOG_ALERT, "Can't establist server connection: connection limit reached (%d)!", Pool_Size ); return; } +#ifdef DEBUG Log( LOG_DEBUG, "Preparing connection %d for \"%s\" ...", idx, Conf_Server[i].host ); +#endif /* Verbindungs-Struktur initialisieren */ Init_Conn_Struct( idx ); @@ -1466,7 +1501,9 @@ New_Server( INT Server, CONN_ID Idx ) FD_SET( new_sock, &My_Connects ); if( new_sock > Conn_MaxFD ) Conn_MaxFD = new_sock; +#ifdef DEBUG Log( LOG_DEBUG, "Registered new connection %d on socket %d.", Idx, My_Connections[Idx].sock ); +#endif } /* New_Server */ @@ -1563,11 +1600,15 @@ Read_Resolver_Result( INT r_fd ) /* Opsa! Keine passende Connection gefunden!? Vermutlich * wurde sie schon wieder geschlossen. */ close( r_fd ); +#ifdef DEBUG Log( LOG_DEBUG, "Resolver: Got result for unknown connection!?" ); +#endif return; } +#ifdef DEBUG Log( LOG_DEBUG, "Resolver: %s is \"%s\".", My_Connections[i].host, result ); +#endif /* Aufraeumen */ close( My_Connections[i].res_stat->pipe[0] ); blob - 57f82b69ad51489d0af0e2c21e54e65c29e26b1a blob + e4865e1a762a6d9504ade6a9a288754712fff511 --- src/ngircd/defines.h +++ src/ngircd/defines.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: defines.h,v 1.42 2003/02/23 12:03:39 alex Exp $ + * $Id: defines.h,v 1.43 2003/11/05 23:24:48 alex Exp $ * * Global defines of ngIRCd. */ @@ -19,8 +19,6 @@ #define NONE -1 -#define TIME_RES 2 /* Zeit-Aufloesung des Servers in Sekunden */ - #define FNAME_LEN 256 /* max. Laenge eines Dateinamen */ #define LINE_LEN 256 /* max. Laenge einer Konfigurationszeile */ blob - 3bc6904f5dc1efe3d5d9ee60cc9a2929ad2e8cf9 blob + e4d1c7fcc3fbcd93dd4dacff65aac44242b737dc --- src/ngircd/irc-info.c +++ src/ngircd/irc-info.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-info.c,v 1.17 2003/06/06 20:46:11 alex Exp $"; +static char UNUSED id[] = "$Id: irc-info.c,v 1.18 2003/11/05 23:24:48 alex Exp $"; #include "imp.h" #include @@ -77,6 +77,7 @@ IRC_ADMIN(CLIENT *Client, REQUEST *Req ) if( ! IRC_WriteStrClient( Client, RPL_ADMINLOC2_MSG, Client_ID( prefix ), Conf_ServerAdmin2 )) return DISCONNECTED; if( ! IRC_WriteStrClient( Client, RPL_ADMINEMAIL_MSG, Client_ID( prefix ), Conf_ServerAdminMail )) return DISCONNECTED; + IRC_SetPenalty( Client, 1 ); return CONNECTED; } /* IRC_ADMIN */ @@ -161,7 +162,8 @@ IRC_LINKS( CLIENT *Client, REQUEST *Req ) } c = Client_Next( c ); } - + + IRC_SetPenalty( target, 1 ); return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask ); } /* IRC_LINKS */ @@ -197,6 +199,7 @@ IRC_LUSERS( CLIENT *Client, REQUEST *Req ) IRC_Send_LUSERS( target ); + IRC_SetPenalty( target, 1 ); return CONNECTED; } /* IRC_LUSERS */ @@ -230,6 +233,7 @@ IRC_MOTD( CLIENT *Client, REQUEST *Req ) } } + IRC_SetPenalty( from, 3 ); return IRC_Show_MOTD( from ); } /* IRC_MOTD */ @@ -324,6 +328,7 @@ IRC_NAMES( CLIENT *Client, REQUEST *Req ) if( ! IRC_WriteStrClient( from, "%s", rpl )) return DISCONNECTED; } + IRC_SetPenalty( from, 1 ); return IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), "*" ); } /* IRC_NAMES */ @@ -402,6 +407,7 @@ IRC_STATS( CLIENT *Client, REQUEST *Req ) break; } + IRC_SetPenalty( from, 2 ); return IRC_WriteStrClient( from, RPL_ENDOFSTATS_MSG, Client_ID( from ), query ); } /* IRC_STATS */ @@ -517,6 +523,7 @@ IRC_VERSION( CLIENT *Client, REQUEST *Req ) } /* mit Versionsinfo antworten */ + IRC_SetPenalty( Client, 1 ); #ifdef CVSDATE strlcpy( ver, CVSDATE, sizeof( ver )); strncpy( ver + 4, ver + 5, 2 ); blob - 280923a798856413fef87fa036aeaa20125fe3b2 blob + b4b489f5a8dc0f67e189cc2c21371d977e956eaf --- src/ngircd/irc-login.c +++ src/ngircd/irc-login.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-login.c,v 1.34 2003/03/31 15:54:21 alex Exp $"; +static char UNUSED id[] = "$Id: irc-login.c,v 1.35 2003/11/05 23:24:48 alex Exp $"; #include "imp.h" #include @@ -223,6 +223,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req ) /* neuen Client-Nick speichern */ Client_SetID( target, Req->argv[0] ); + IRC_SetPenalty( target, 2 ); } return CONNECTED; @@ -457,6 +458,9 @@ Hello_User( CLIENT *Client ) if( ! IRC_Send_LUSERS( Client )) return DISCONNECTED; if( ! IRC_Show_MOTD( Client )) return DISCONNECTED; + /* Suspend the client for a second ... */ + IRC_SetPenalty( Client, 1 ); + return CONNECTED; } /* Hello_User */ blob - cf6354171df7a454dbd704163b0a146e90673729 blob + 5586989ca75e8cca7895c2252effbf86bf3c0610 --- src/ngircd/irc-mode.c +++ src/ngircd/irc-mode.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-mode.c,v 1.31 2003/01/21 21:04:16 alex Exp $"; +static char UNUSED id[] = "$Id: irc-mode.c,v 1.32 2003/11/05 23:24:48 alex Exp $"; #include "imp.h" #include @@ -230,7 +230,8 @@ client_exit: } Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( Target ), Client_Modes( Target )); } - + + IRC_SetPenalty( Client, 1 ); return ok; } /* Client_Mode */ @@ -598,6 +599,7 @@ chan_exit: } } + IRC_SetPenalty( Client, 1 ); return CONNECTED; } /* Channel_Mode */ blob - b8a5e28d6eaa1095f5291e6c478a09c539638a95 blob + 9127ef11e2ab1c47ee8532ca4124d827af4b1bf3 --- src/ngircd/irc-write.c +++ src/ngircd/irc-write.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc-write.c,v 1.14 2002/12/30 17:15:42 alex Exp $"; +static char UNUSED id[] = "$Id: irc-write.c,v 1.15 2003/11/05 23:24:48 alex Exp $"; #include "imp.h" #include @@ -395,6 +395,21 @@ va_dcl } /* IRC_WriteStrRelatedPrefix */ +GLOBAL VOID +IRC_SetPenalty( CLIENT *Client, INT Seconds ) +{ + CONN_ID c; + + assert( Client != NULL ); + assert( Seconds > 0 ); + + if( Client_Type( Client ) == CLIENT_SERVER ) return; + + c = Client_Conn( Client ); + if( c > NONE ) Conn_SetPenalty( c, Seconds ); +} /* IRC_SetPenalty */ + + LOCAL CHAR * Get_Prefix( CLIENT *Target, CLIENT *Client ) { blob - 7d70d696c1b520a9a80b1ecc87717ac0b18f7c43 blob + 41e2f2e7359e2316ee31f6358e2c1d2a06362058 --- src/ngircd/irc-write.h +++ src/ngircd/irc-write.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-write.h,v 1.5 2002/12/12 12:23:43 alex Exp $ + * $Id: irc-write.h,v 1.6 2003/11/05 23:24:48 alex Exp $ * * Sending IRC commands over the network (header) */ @@ -18,19 +18,21 @@ #define __irc_write_h__ -GLOBAL BOOLEAN IRC_WriteStrClient PARAMS((CLIENT *Client, CHAR *Format, ... )); -GLOBAL BOOLEAN IRC_WriteStrClientPrefix PARAMS((CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )); +GLOBAL BOOLEAN IRC_WriteStrClient PARAMS(( CLIENT *Client, CHAR *Format, ... )); +GLOBAL BOOLEAN IRC_WriteStrClientPrefix PARAMS(( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )); -GLOBAL BOOLEAN IRC_WriteStrChannel PARAMS((CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )); -GLOBAL BOOLEAN IRC_WriteStrChannelPrefix PARAMS((CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )); +GLOBAL BOOLEAN IRC_WriteStrChannel PARAMS(( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )); +GLOBAL BOOLEAN IRC_WriteStrChannelPrefix PARAMS(( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )); -GLOBAL VOID IRC_WriteStrServers PARAMS((CLIENT *ExceptOf, CHAR *Format, ... )); -GLOBAL VOID IRC_WriteStrServersPrefix PARAMS((CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )); -GLOBAL VOID IRC_WriteStrServersPrefixFlag PARAMS((CLIENT *ExceptOf, CLIENT *Prefix, CHAR Flag, CHAR *Format, ... )); +GLOBAL VOID IRC_WriteStrServers PARAMS(( CLIENT *ExceptOf, CHAR *Format, ... )); +GLOBAL VOID IRC_WriteStrServersPrefix PARAMS(( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )); +GLOBAL VOID IRC_WriteStrServersPrefixFlag PARAMS(( CLIENT *ExceptOf, CLIENT *Prefix, CHAR Flag, CHAR *Format, ... )); -GLOBAL BOOLEAN IRC_WriteStrRelatedPrefix PARAMS((CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )); +GLOBAL BOOLEAN IRC_WriteStrRelatedPrefix PARAMS(( CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )); +GLOBAL VOID IRC_SetPenalty PARAMS(( CLIENT *Client, INT Seconds )); + #endif blob - 1c1212af38d83c06cff1ecb59a3b6f4fc63e5f2e blob + eb32afdd134a9988fc17a0fe7282c4d4b82236ef --- src/ngircd/irc.c +++ src/ngircd/irc.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: irc.c,v 1.121 2003/04/29 12:19:20 alex Exp $"; +static char UNUSED id[] = "$Id: irc.c,v 1.122 2003/11/05 23:24:48 alex Exp $"; #include "imp.h" #include @@ -265,6 +265,7 @@ IRC_TRACE( CLIENT *Client, REQUEST *Req ) /* Some information about us */ if( ! IRC_WriteStrClient( from, RPL_TRACESERVER_MSG, Client_ID( from ), Conf_ServerName, Client_Mask( Client_ThisServer( )), Option_String( Client_Conn( Client )))) return DISCONNECTED; + IRC_SetPenalty( Client, 3 ); return IRC_WriteStrClient( from, RPL_TRACEEND_MSG, Client_ID( from ), Conf_ServerName, PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_DebugLevel ); } /* IRC_TRACE */ @@ -286,6 +287,8 @@ IRC_HELP( CLIENT *Client, REQUEST *Req ) if( ! IRC_WriteStrClient( Client, "NOTICE %s :%s", Client_ID( Client ), cmd->name )) return DISCONNECTED; cmd++; } + + IRC_SetPenalty( Client, 2 ); return CONNECTED; } /* IRC_HELP */